//----------------------------------------------------------------------------- // --- GNNViz: VERTEX shader for terrain used in GNNViz with the Torque Shader // --- Engine // --- // --- This is a custom shader derived from the original TSE Atlas Vertex // --- shader code. It has been modified to allow for multiple detail texture // --- scales to remove tiling effects, plus a fade factor to allow terrain // --- to fade from detail texture close up to a "satellite overview" texture // --- for distant terrain. // --- // --- This shader was developed as part of the GNNViz project who's website is // --- at http://www.fsl.orst.edu/lemma/gnnviz/index.php // --- // --- See pixel shader code in GNNVizAtlasSurface.P.hlsl for notes on // --- potential improvements. // --- // --- For more information, contact Tim Holt at tim.holt@oregonstate.edu //----------------------------------------------------------------------------- #define IN_HLSL #include "../shdrConsts.h" //----------------------------------------------------------------------------- // Structures //----------------------------------------------------------------------------- struct VertData { float3 position : POSITION; // Our base position. float2 texCoord : TEXCOORD0; // Our texture co-ordinates. float3 morphCoord : TEXCOORD1; // We have a 3d morph vector, which is scaled by 0..1 and added to position to get our current position. }; struct ConnectData { float4 hpos : POSITION; float2 texCoord : TEXCOORD0; float2 fogCoord : TEXCOORD1; float2 detailCoord : TEXCOORD2; // Detail texture coordinate #1 float2 detailCoord2 : TEXCOORD3; // Detail texture coordinate #2 float2 distCoord : TEXCOORD4; // Fade info for near/far terrain }; //----------------------------------------------------------------------------- // 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 float3 texGen : register(C44), uniform float4 scaleOff : register(C45) ) { ConnectData OUT; // Calculate our morph value. float4 morphOffset; morphOffset.xyz = IN.morphCoord * 0; //scaleOff.w; morphOffset.w = 0; // Calculate our position in objectspace. float4 realPos; realPos.x = IN.position.x; realPos.y = IN.position.y; realPos.z = IN.position.z; realPos.w = 1; // Combine morph and realPos. realPos += morphOffset; OUT.hpos = mul(modelView, realPos); // Pass the texcoord along after scaling + offsetting it. OUT.texCoord.x = IN.texCoord.x * texGen.z + texGen.x; OUT.texCoord.y = IN.texCoord.y * texGen.z + texGen.y; // ------------------------------------------------------------------------ // --- GNNViz: Generate detail coords and shading info. // --- // --- Note that we are generating two different sets of detail texture // --- coordinates here. We use them to apply detail textures to the ground // --- by combining two copies of the same detail texture, one sampled // --- at detailCoord, the other sampled at detailCoord2. Since the two // --- textures have different scales and thus tile differently, the // --- result is a nice ground detail without obvious tiling. // --- // --- Note that dividing the position by a bigger number scales up the // --- detail texture. So that means the /4 version will be finer scale // --- than the /13 version. // ------------------------------------------------------------------------ OUT.detailCoord = realPos / 4; OUT.detailCoord2 = realPos / 13; // ------------------------------------------------------------------------ // --- Fog coordinate generation. // --- // --- Note that we aren't just generating a simple 0..1 fog value here, but // --- rather a set of x/y coordinates, where the X coordinate is based on // --- the range from the players eye to the point we are rendering, and the // --- y coordinate based on the height above the terrain. // --- // --- The pixel render code will use these x/y coordinates to look up the // --- fog intensity value from a texture, which lets us have fog that is // --- more dense at certain altitudes rather than a simple all-pervasive // --- “cheap” fog. // ------------------------------------------------------------------------ float3 worldPos = mul(objTrans, realPos.xyz); OUT.fogCoord.x = 1.0 - ( distance( realPos.xyz, eyePos ) / fogData.z ); OUT.fogCoord.y = (worldPos.z - fogData.x) * fogData.y; // ------------------------------------------------------------------------ // --- GNNViz: Calcualte the distance between the viewer eye and the point // --- being rendered. // --- // --- GNNViz uses this value to blend between close up detail textures and // --- the overlay image drawn on the terrain when viewed from afar. This // --- is how we have GNNViz draw dirt/forest floor type textures on the // --- ground close to the player, and then overlay high resolution // --- satellite images on the terrain when it is viewed from afar. This is // --- very important for rendering forested environments, as from the air // --- you will see just tree tops, whereas on the ground you will see the // --- brown earth. // --- // --- Note that the distance calculation has two factors to control its // --- behavior. The divisor (15 in the below case) controls how fast the // --- the fade transition is between detail and distant textures. The // --- additive value (0.2 below) controls how far away the fade starts and // --- ends. // ------------------------------------------------------------------------ OUT.distCoord.x = clamp(1.0 - distance (worldPos.xyz, eyePos) / 15.0 + 0.2, 0.0, 1.0); OUT.distCoord.y = OUT.distCoord.x; return OUT; }