Textured Atlas Terrain
by Vincent BILLET · in Torque Game Engine Advanced · 01/06/2006 (3:19 am) · 3 replies
The main issue (In my opinion) for Atlas is textured terrains.
For this I made a simple shader, and some code modifications. But before coding, you must understand How it works.
Texture Library
Each Pixel of the terrain (in TQT file) represent a texture. I wanted 64 textures for my terrain. So I made big texture(2048x2048) filled with 8x8 texture of 256x256 pixel size.
Blending Texture
I made a texture for blending terrain. The idea is to use this "blending texture" as 4 alpha channels.
You can call this procedure from where you want.
Atlas update
In void AtlasInstance::renderObject(SceneState *state, SceneRenderImage *image)
For this I made a simple shader, and some code modifications. But before coding, you must understand How it works.
Texture Library
Each Pixel of the terrain (in TQT file) represent a texture. I wanted 64 textures for my terrain. So I made big texture(2048x2048) filled with 8x8 texture of 256x256 pixel size.
Blending Texture
I made a texture for blending terrain. The idea is to use this "blending texture" as 4 alpha channels.
void createBlend()
{
GBitmap tmp(512, 512, false, GFXFormatR8G8B8A8);
FileStream fsP;
if(!ResourceManager->openFileForWrite(fsP, "AW/data/blend.png", File::Write))
{
Con::errorf("SavePNG - failed to open output file!");
return ;
}
ColorI Color;
int rr,gg,bb,aa;
rr=255;
aa=0;
for (int yy=0;yy<512;yy++)
{
gg=255;
bb=0;
for (int xx=0;xx<512;xx++)
{
if (rr>0) {Color.red=rr;} else {Color.red=0;}
if (gg>0) {Color.green=gg;} else {Color.green=0;}
if (bb>0) {Color.blue=bb;} else {Color.blue=0;}
if (aa>0) {Color.alpha=aa;} else {Color.alpha=0;}
tmp.setColor(xx,yy,Color);
if (gg>=0) {gg--;} else {bb++;}
}
if (rr>=0) {rr--;} else {aa++;}
}
tmp.writePNG(fsP);
fsP.close();
}You can call this procedure from where you want.
Atlas update
In void AtlasInstance::renderObject(SceneState *state, SceneRenderImage *image)
void AtlasInstance::renderObject(SceneState *state, SceneRenderImage *image)
{
PROFILE_START(ChunkInstance_renderObject);
GFX->pushState();
// Set up rendering state
GFX->disableShaders();
GFX->setTextureStageColorOp( 0, GFXTOPModulate );
GFX->setTextureStageColorOp( 1, GFXTOPModulate );
GFX->setTextureStageColorOp( 2, GFXTOPModulate );
GFX->setTextureStageColorOp( 3, GFXTOPModulate );
GFX->setTextureStageColorOp( 4, GFXTOPDisable );
GFX->setAlphaBlendEnable(false);just after GFX->setAlphaBlendEnable(false);GFX->setTextureStageMagFilter(0, GFXTextureFilterPoint );//<=========Terrain GFX->setTextureStageMinFilter(0, GFXTextureFilterPoint ); GFX->setTextureStageMipFilter(0, GFXTextureFilterPoint); GFX->setTextureStageMagFilter(1, GFXTextureFilterLinear );//<=========Fog GFX->setTextureStageMinFilter(1, GFXTextureFilterLinear ); GFX->setTextureStageMipFilter(1, GFXTextureFilterLinear); GFX->setTextureStageMagFilter(2, GFXTextureFilterLinear );//<=========Detail GFX->setTextureStageMinFilter(2, GFXTextureFilterLinear ); GFX->setTextureStageMipFilter(2, GFXTextureFilterLinear); GFX->setTextureStageMagFilter(3, GFXTextureFilterLinear );//<=========Texture Library (2048x2048) GFX->setTextureStageMinFilter(3, GFXTextureFilterLinear ); GFX->setTextureStageMipFilter(3, GFXTextureFilterLinear); GFX->setTextureStageMagFilter(4, GFXTextureFilterLinear );//<=========Blending texture (made with createBlend) GFX->setTextureStageMinFilter(4, GFXTextureFilterLinear ); GFX->setTextureStageMipFilter(4, GFXTextureFilterLinear); GFX->setTextureStageAddressModeU( 0, GFXAddressClamp ); GFX->setTextureStageAddressModeV( 0, GFXAddressClamp ); // ^=- This texture is set by the quad tree as we recurse. GFX->setTextureStageAddressModeU( 1, GFXAddressClamp ); GFX->setTextureStageAddressModeV( 1, GFXAddressClamp ); GFX->setTexture(1, gClientSceneGraph->getFogTexture()); // And the detail textures... GFX->setTextureStageAddressModeU( 2, GFXAddressWrap ); GFX->setTextureStageAddressModeV( 2, GFXAddressWrap ); GFX->setTexture(2, mDetailTex); GFX->setTextureStageAddressModeU( 3, GFXAddressClamp ); GFX->setTextureStageAddressModeV( 3, GFXAddressClamp ); GFX->setTexture(3, mDetailTex1); GFX->setTextureStageAddressModeU( 4, GFXAddressWrap ); GFX->setTextureStageAddressModeV( 4, GFXAddressWrap ); GFX->setTexture(4, mDetailTex2);
#2
Shaders
Here are the shaders I used : atlasSurfaceV.hlsl
atlasSurfaceP.hlsl
01/06/2006 (3:20 am)
Continued due to post limit.Shaders
Here are the shaders I used : atlasSurfaceV.hlsl
#define IN_HLSL
#include "shdrConsts.h"
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct VertData
{
float4 position : POSITION;
float2 texCoord : TEXCOORD0;
// float3 normal : NORMAL;
};
struct ConnectData
{
float4 hpos : POSITION;
float2 texCoord : TEXCOORD0;
float2 fogCoord : TEXCOORD1;
float2 detailCoord : TEXCOORD2;
float2 detailCoord2 : TEXCOORD3;
};
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
ConnectData main( VertData IN,
uniform float4x4 modelview : register(VC_WORLD_PROJ),
uniform float4x4 objTrans : register(VC_OBJ_TRANS),
uniform float3 eyePos : register(VC_EYE_POS),
uniform float3 fogData : register(VC_FOGDATA),
uniform float4 texGen : register(C44),
uniform float4 scaleOff : register(C45),
uniform float4 morphInfo : register(C46)
)
{
ConnectData OUT;
// Do positional transform on the heightfield data, and apply morph.
float4 realPos;
realPos.x = IN.position.x * scaleOff.z + scaleOff.x;
realPos.y = IN.position.y * scaleOff.z + scaleOff.y;
realPos.z = IN.position.z + IN.texCoord.x * morphInfo.x;
realPos.w = IN.position.w;
OUT.hpos = mul(modelview, realPos);
float3 worldPos = mul(objTrans, realPos.xyz);
float3 worldEye = mul(objTrans, eyePos);
/// Generate texture co-ords.
OUT.texCoord.y = realPos.x * texGen.z + texGen.x;
OUT.texCoord.x = realPos.y * texGen.z + texGen.y;
// And fog texture co-ords.
OUT.fogCoord.x = 1.0 - ( distance( worldPos, worldEye ) / fogData.z );
OUT.fogCoord.y = (worldPos.z - fogData.x) * fogData.y;
// And detail texture co-ords.
OUT.detailCoord = realPos / 8;
OUT.detailCoord2 = realPos /8;
return OUT;
}atlasSurfaceP.hlsl
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct ConnectData
{
float2 texCoord : TEXCOORD0;
float2 fogCoord : TEXCOORD1;
float2 detailCoord : TEXCOORD2;
float2 detailCoord2 : TEXCOORD3;
};
struct Fragout
{
float4 col : COLOR0;
};
float4 Couleur(float4 diffuseColor, sampler2D detailMap1, float2 TC)
{
float num,num1;
float2 CoordVB;
num = int(diffuseColor.r*20);//-1.0;
num1 = int(diffuseColor.b*20);//-1.0;
CoordVB.x = (TC.x-int(TC.x))/8.0;
CoordVB.y = (TC.y-int(TC.y))/8.0;
if (CoordVB.x<=1/2) {CoordVB.x +=1/512;} else {CoordVB.x -=1/512;}
if (CoordVB.y<=1/2) {CoordVB.y +=1/512;} else {CoordVB.y -=1/512;}
CoordVB.x += num/8.0;
CoordVB.y += num1/8.0;
return tex2D(detailMap1, CoordVB);
}
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
Fragout main( ConnectData IN,
uniform sampler2D diffuseMap : register(S0),
uniform sampler2D fogMap : register(S1),
uniform sampler2D detailMap : register(S2),
uniform sampler2D detailMap1 : register(S3),
uniform sampler2D detailMap2 : register(S4),
uniform sampler2D detailMap3 : register(S5),
uniform sampler2D detailMap4 : register(S6),
uniform sampler2D detailMap5 : register(S7)
)
{
Fragout OUT;
float Offset = 1.0/512.0;
float4 color,colorU,colorD,colorR,colorL,couleur;
float4 diffuseColor = tex2D(diffuseMap,IN.texCoord);
color = Couleur(diffuseColor, detailMap1, IN.detailCoord2);
diffuseColor = tex2D(diffuseMap,float2(IN.texCoord.x,IN.texCoord.y+Offset));
colorU = Couleur(diffuseColor, detailMap1, IN.detailCoord2);
diffuseColor = tex2D(diffuseMap,float2(IN.texCoord.x,IN.texCoord.y-Offset));
colorD = Couleur(diffuseColor, detailMap1, IN.detailCoord2);
diffuseColor = tex2D(diffuseMap,float2(IN.texCoord.x+Offset,IN.texCoord.y));
colorL = Couleur(diffuseColor, detailMap1, IN.detailCoord2);
diffuseColor = tex2D(diffuseMap,float2(IN.texCoord.x-Offset,IN.texCoord.y));
colorR = Couleur(diffuseColor, detailMap1, IN.detailCoord2);
float4 coulb = tex2D(detailMap2,IN.detailCoord*4)/2;
color = lerp(color,colorR,coulb.r);
color = lerp(color,colorD,coulb.g);
color = lerp(color,colorU,coulb.b);
color = lerp(color,colorL,coulb.a);
float4 fogCol = tex2D(fogMap, IN.fogCoord);
float4 detailCol = tex2D(detailMap, IN.detailCoord);
OUT.col = lerp( color *(diffuseColor.g*2+0.4), fogCol, fogCol.a );
return OUT;
}
#3
How to use this code with HTC ?
Go to the texture window. Select a colorset (for example the first). set the colors to 10 40 0 - 20 40 0 - 30 40 0 - etc.. Select the second colorset and the the colors : 10 40 10 - 20 40 10 - 30 40 10 - etc.. and so on for each textureset. Set Bumping to 0. Create your texture Library with texture of equivalent color.

Final Words
You must understand, as I said in beginning of this post, that each color represent a texture. Red component is the "x" Texture coordinate in Library, blue is the "y" coordinate. e.g. I want to paint the texture placed in 2,3 in my texture library. The color is equal to 20,?,30.
The green component is used to make shadows. the less this value is, the more shadows are.
I Hope this migth help some of you, and perhaps some gives some ideas to improve this.
01/06/2006 (3:22 am)
Continued due to post limit.How to use this code with HTC ?
Go to the texture window. Select a colorset (for example the first). set the colors to 10 40 0 - 20 40 0 - 30 40 0 - etc.. Select the second colorset and the the colors : 10 40 10 - 20 40 10 - 30 40 10 - etc.. and so on for each textureset. Set Bumping to 0. Create your texture Library with texture of equivalent color.

Final Words
You must understand, as I said in beginning of this post, that each color represent a texture. Red component is the "x" Texture coordinate in Library, blue is the "y" coordinate. e.g. I want to paint the texture placed in 2,3 in my texture library. The color is equal to 20,?,30.
The green component is used to make shadows. the less this value is, the more shadows are.
I Hope this migth help some of you, and perhaps some gives some ideas to improve this.
Torque Owner Vincent BILLET
Default Studio Name
In bool AtlasInstance::onAdd(). Just after mDetailTex1.set(mDetailName1, &GFXDefaultStaticDiffuseProfile);
mDetailTex1.set(mDetailName2, &GFXDefaultStaticDiffuseProfile); mDetailTex2.set(mDetailName2, &GFXDefaultStaticDiffuseProfile);In AtlasInstance::AtlasInstance(), add just after mDetailName1 = StringTable->insert("terrain_water_demo/data/terrains/details/detail1");
mDetailName1 = StringTable->insert("terrain_water_demo/data/terrains/details/detail1"); mDetailName2 = StringTable->insert("terrain_water_demo/data/terrains/details/detail1");In void AtlasInstance::initPersistFields(), just add before the end
addField("detailTexture1", TypeFilename, Offset(mDetailName1, AtlasInstance), "Texture Library."); addField("detailTexture2", TypeFilename, Offset(mDetailName2, AtlasInstance), "Blending.");In U32 AtlasInstance::packUpdate(NetConnection * conn, U32 mask, BitStream *stream) just add
In void AtlasInstance::unpackUpdate(NetConnection * conn, BitStream *stream) just add
In atlasInstance.h, just after GFXTexHandle mDetailTex; add: