Shaders on Atlas Terrain
by Adam Schofield · in Torque Game Engine Advanced · 10/11/2005 (5:08 am) · 10 replies
Rather than reviving this thread I thought I'd start an Atlas specific one.
Is it possible to add pixel shaders or normal mapping to an Atlas terrain? or does it only support precalculated texture data?
I noticed the terrainV.hlsl and terrainP.hlsl in /example/shader but they are used for Legacy terrain right? so is it possible to add shaders to the Legacy Terrain then?
Is it possible to add pixel shaders or normal mapping to an Atlas terrain? or does it only support precalculated texture data?
I noticed the terrainV.hlsl and terrainP.hlsl in /example/shader but they are used for Legacy terrain right? so is it possible to add shaders to the Legacy Terrain then?
About the author
#2
The problem being the water shader reflecting the space below the terrain at the shore line, Possibly a pure black back side texture to the terrain to remidy this, please excuse my un beknownst knowledge of Atlas.
10/12/2005 (9:21 am)
Arr (pirate style) do you mean 'these things' as in Legacy or Atlas? I have no interest in Legacy anymore BTW as Atlas is a far more advanced utility without size limitations. Shaders in the Atlas terrain could solve the shore line problem (can't find the link right now)The problem being the water shader reflecting the space below the terrain at the shore line, Possibly a pure black back side texture to the terrain to remidy this, please excuse my un beknownst knowledge of Atlas.
#3
the main thing your looking for is: GFX->setPixelShaderConstF and GFX->setVertexShaderConstF. This is how you set params in the engine to be used by your shaders.
I submitted an generic resource on adding shaders to a tse class, but it has yet to be approved..:)
goodluck
10/12/2005 (10:18 am)
Enhancing shaders on atlas or any other torque class is very easy..the main thing your looking for is: GFX->setPixelShaderConstF and GFX->setVertexShaderConstF. This is how you set params in the engine to be used by your shaders.
I submitted an generic resource on adding shaders to a tse class, but it has yet to be approved..:)
goodluck
#5
show someone in this thread
Took me all of 5 minutes... it is really quite easy...
~neo
11/27/2005 (5:08 am)
I changed the atlas shaders a couple of months ago to add normal mapping toshow someone in this thread
Took me all of 5 minutes... it is really quite easy...
~neo
#6
01/06/2006 (4:47 am)
Hey, guys, take a look here : www.garagegames.com/mg/forums/result.thread.php?qt=38460
#7
06/14/2006 (12:37 pm)
OK you shader monkeys :^) I keep finding posts in the "It's easy I did it in 5 minutes!" vein - are there any actually POSTED shaders for Atlas terrain that do normal/bump mapping?
#8
How To Add Basic Normal Maps To Atlas Terrain
The first thing you need to do is somehow get a normal map texture available for the shader. There are two ways you can do this: either just use the already existing detailTexture, or modify the Atlas code to add an additional texture for the normal map. To keep this simple, I'm going to just use the existing detail material to specify what normal map image the shader should use.
To do this, open up your mission file in a text editor, and find the AtlasInstance definition. It will look something like this...
Now as mentioned above, we're going to stick the normal map image into the detail texture. If you don't have a normal map, you'll need to create one. If you just need a basic noise texture, there's one in the TSE demo already named "noise02.png". It looks like this...

So for this example let's just use the noise normal image. Go ahead and edit your mission file so that the detailTexture now points to the normal map...
OK - now we've set up our mission file to know about the normal map image we want to use.
The next step is to modify the shader used to "paint" the terrain. Go ahead and open up the pixel shader file in shaders/atlasSurfaceP.hlsl. The main section of shader code in all it's uncommented glory looks like this...
So before I get into modifying the shader to add the normal map support, let me do a little explaining about how this code works. Shaders are pretty confusing to some people (like me!) so this may help you.
OK first of all, you should understand that this little piece of code in the Pixel shader gets run for every single pixel on your game screen that is Atlas terrain. Every pixel, every time your screen refreshes. All this little bit of code has to do is return a color value (RGB). The graphics card is going to use that color value to paint the specific pixel just calculated.
Now normally, the default shader grabs a single pixel color value off of the TQT image and uses it. It's stored in the variable named "diffuseColor". Then it grabs a pixel out of the detailMap texture (the detailTexture value set in the mission file) and merges it onto the base TQT texture. Lastly, it uses the "lerp" function (for Linear Interpolation) to make the terrain color turn into the fog color when it's farther away from the player's (or camera's) eye. Here is the same code but with comments...
(continued on next post)...
06/16/2006 (2:10 pm)
Psh - fine! I did it myself and HERE IS THE CODE! :^)How To Add Basic Normal Maps To Atlas Terrain
The first thing you need to do is somehow get a normal map texture available for the shader. There are two ways you can do this: either just use the already existing detailTexture, or modify the Atlas code to add an additional texture for the normal map. To keep this simple, I'm going to just use the existing detail material to specify what normal map image the shader should use.
To do this, open up your mission file in a text editor, and find the AtlasInstance definition. It will look something like this...
new AtlasInstance(Tillamook) {
position = "0 0 -56.2";
rotation = "1 0 0 0";
scale = "1 1 1";
chunkFile = "~/data/terrains/raw/tillamook_10meter_1025_noflip_l3dt_r1.chu";
// generateTQT ("gnnviz/data/terrains/canopy_cover_rgb_gauss2_90cw.jpg", "gnnviz/data/terrains/canopy_cover_rgb_gauss2_90cw.tqt", 5, 512);
tqtFile = "~/data/terrains/canopy_cover_rgb_gauss2_90cw.tqt";
materialName = "AtlasMaterial";
// a detail texture
detailTexture = "~/data/terrains/details/detailtexture.png";
};Now as mentioned above, we're going to stick the normal map image into the detail texture. If you don't have a normal map, you'll need to create one. If you just need a basic noise texture, there's one in the TSE demo already named "noise02.png". It looks like this...

So for this example let's just use the noise normal image. Go ahead and edit your mission file so that the detailTexture now points to the normal map...
// This used to be the detail texture, but we're going to stick a normal map in here // instead. The AtlasTerrain shader has been modifed to use this normal map and // apply it to the ground. detailTexture = "~/data/textures/noise02.png";
OK - now we've set up our mission file to know about the normal map image we want to use.
The next step is to modify the shader used to "paint" the terrain. Go ahead and open up the pixel shader file in shaders/atlasSurfaceP.hlsl. The main section of shader code in all it's uncommented glory looks like this...
Fragout main( ConnectData IN,
uniform sampler2D diffuseMap : register(S0),
uniform sampler2D fogMap : register(S1),
uniform sampler2D detailMap : register(S2),
uniform sampler2D detailMap2 : register(S3)
)
{
Fragout OUT;
float4 diffuseColor = tex2D(diffuseMap, IN.texCoord) * IN.shading;
float4 fogCol = tex2D(fogMap, IN.fogCoord);
float4 detailCol = tex2D(detailMap, IN.detailCoord);
detailCol *= tex2D(detailMap2, IN.detailCoord2);
OUT.col = lerp( diffuseColor * (detailCol + 0.6), fogCol, fogCol.a );
return OUT;
}So before I get into modifying the shader to add the normal map support, let me do a little explaining about how this code works. Shaders are pretty confusing to some people (like me!) so this may help you.
OK first of all, you should understand that this little piece of code in the Pixel shader gets run for every single pixel on your game screen that is Atlas terrain. Every pixel, every time your screen refreshes. All this little bit of code has to do is return a color value (RGB). The graphics card is going to use that color value to paint the specific pixel just calculated.
Now normally, the default shader grabs a single pixel color value off of the TQT image and uses it. It's stored in the variable named "diffuseColor". Then it grabs a pixel out of the detailMap texture (the detailTexture value set in the mission file) and merges it onto the base TQT texture. Lastly, it uses the "lerp" function (for Linear Interpolation) to make the terrain color turn into the fog color when it's farther away from the player's (or camera's) eye. Here is the same code but with comments...
Fragout main( ConnectData IN,
uniform sampler2D diffuseMap : register(S0),
uniform sampler2D fogMap : register(S1),
uniform sampler2D detailMap : register(S2),
uniform sampler2D detailMap2 : register(S3)
)
{
// -----------------------------------------------------------------------------
// OUT will contain the color to be drawn at this pixel. This bit of code's job
// is to set that color value!
// -----------------------------------------------------------------------------
Fragout OUT;
// -----------------------------------------------------------------------------
// Get a single pixel (red, green, blue value) from the base TQT image that should be drawn
// at this point on the player's screen.
// -----------------------------------------------------------------------------
float4 diffuseColor = tex2D(diffuseMap, IN.texCoord) * IN.shading;
// -----------------------------------------------------------------------------
// Get the color of the fog. If the map were 100% foggy, this is the color you would see.
// Normally it's some kind of grey color etc.
// -----------------------------------------------------------------------------
float4 fogCol = tex2D(fogMap, IN.fogCoord);
// -----------------------------------------------------------------------------
// Get a single pixel (red, green, blue value) from the detail texture. We'll multiply
// the diffuseColor by this value to add some "detail" noise to the ground.
// -----------------------------------------------------------------------------
float4 detailCol = tex2D(detailMap, IN.detailCoord);
// -----------------------------------------------------------------------------
// Combine the base texture color and the detail color
// -----------------------------------------------------------------------------
float4 finalCol = diffuseColor * (detailCol + 0.6);
// -----------------------------------------------------------------------------
// Linearly interpolate between the ground color (finalCol) and the
// full fog color (fogCol). The value fogCol.a varies from 0.0 to
// 1.0 depending on how far away the terrain pixel is from the viewer.
// If the terrain is directly in front of the viewer, then the value
// will be 0.0 (no fog). If the point is at or beyond the maximum fog
// distance, then the value will be 1.0 (full fog).
// -----------------------------------------------------------------------------
OUT.col = lerp( finalCol, fogCol, fogCol.a );
// -----------------------------------------------------------------------------
// Note that if you want to just show the ground color and have no fog, you
// could just use the following line instead. Uncomment it and you will have
// no fog.
// OUT.col = finalCol;
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Return the OUT structure, which contains the color to be drawn at this point
// -----------------------------------------------------------------------------
return OUT;
}(continued on next post)...
#9
OK! So now that we get how this shader works a bit better, back to adding normal map support. Recall that we've now got a normal map image in the detail texture instead of just a detail texture. If we didn't modify the shader at all, we'd get some sort of strange bluish look to the ground texture.
Using the above commented source code as your base, find the line that defines the finalCol value and comment it out. Replace it with the following code. The comments should hopefully explain what it's doing.
Now save the shader file, and you should have normal map support in the Atlas terrain shader. Here's a screenshot of terrain without normal maps...

and here is a shot with a normal map. Note this is NOT the noise02.png shader, but a different one I made.

Note the normal maps done't really line up with anything on the terrain texture, so it's not that sexy really. But none the less, it's there.
06/16/2006 (2:11 pm)
(continued from previous post)OK! So now that we get how this shader works a bit better, back to adding normal map support. Recall that we've now got a normal map image in the detail texture instead of just a detail texture. If we didn't modify the shader at all, we'd get some sort of strange bluish look to the ground texture.
Using the above commented source code as your base, find the line that defines the finalCol value and comment it out. Replace it with the following code. The comments should hopefully explain what it's doing.
// -----------------------------------------------------------------------------
// First, get the appropriate pixel from the detail texture
// -----------------------------------------------------------------------------
float4 bumpNormal = tex2D(detailMap, IN.detailCoord);
// -----------------------------------------------------------------------------
// Next, we need to set a vector that represents the DIRECTION that the light is
// shining. Note that we REALLY should be grabbing this value from the "Sun"
// entry in the mission file. It has a light direction value.
// -----------------------------------------------------------------------------
float4 lightVector = { 0.6f, 0.6f, -0.5f, 1.0f };
// -----------------------------------------------------------------------------
// Scale the light vector so it varies from -1 to 1 instead of 0.0 to 1.0. I am
// I confess not sure why you do this, but I saw it in an example so I'm doing it
// here, and it seems to work! :^)
// -----------------------------------------------------------------------------
lightVector = lightVector * 2.0 - 1.0;
// -----------------------------------------------------------------------------
// Compute how much extra light or shadow we should apply to this pixel based on the
// angle between the light and this particular spot on the normal map.
// -----------------------------------------------------------------------------
float4 bumpDot = saturate (dot (bumpNormal.xyz * 2.0 - 1.0, lightVector.xyz));
// -----------------------------------------------------------------------------
// Lastly, apply this extra light or shadow value to the pixel we're going
// -----------------------------------------------------------------------------
float4 finalCol = diffuseColor * bumpDot;Now save the shader file, and you should have normal map support in the Atlas terrain shader. Here's a screenshot of terrain without normal maps...

and here is a shot with a normal map. Note this is NOT the noise02.png shader, but a different one I made.

Note the normal maps done't really line up with anything on the terrain texture, so it's not that sexy really. But none the less, it's there.
#10
07/13/2006 (2:45 am)
Do you think about porting it to Atlas 2?
Associate Kyle Carter