Game Development Community

HLSL Grass shader

by mb · in Torque Game Engine Advanced · 05/01/2008 (10:19 am) · 21 replies

I found a HLSL shader that creates realistic looking grass on terrain. I was wondering how or if it would be possible (I know anythings possible if you can code it) to get it working in TGEA 1.7. I don't know enough about making or converting shaders for TGEA. This is the link www.cg.tuwien.ac.at/research/publications/2007/Habel_2007_IAG/

Can someone with knowledge of shaders take a look at it and let me know if it's feasable? And if you can convert it for TGEA it would be great.. and I could possibly pay (but let me beforehand how much such a thing would cost).

File here: www.cg.tuwien.ac.at/research/publications/2007/Habel_2007_IAG/#Additional%20File...

Thanks!
Page «Previous 1 2
#1
05/01/2008 (10:27 am)
Something along these lines is what I'd like to accomplish, but without using Ogre and python.
www.garagegames.com/blogs/4280/14036
#2
05/01/2008 (11:07 am)
Those in the PrairieGames shot are billboard textures, much like whats in tge/tgea now but maybe handling more objects ;)

The grass shader is very nice...
#3
05/01/2008 (12:39 pm)
Yeh I was hoping to make some dts objects with lod and use the shape replicator but I don't know if it can handle that much or not so I'm looking for alternatives.
#4
05/02/2008 (1:18 am)
@mb: I'd use the groundcover feature that is currently available in 1.7. It doesn't work out of the box with megaterrains or with atlas, but it does work on legacy, there is an atlas port in another thread on the forums, and it wouldn't be too hard to rig it up to support multiple terrain blocks for megaterrains. It supports both billboards and multiple different shapes (supports lod), has a much better performance than the shape or foliage replicators, uses lightmaps for shading of billboards, and can easily be expanded to exclude certain areas from having foliage or colormapping (there's some code for this in the atlas port thread). It also supports wind and has a lot of configuration options. All in all it was a very nice addition with 1.7, but I don't think a lot of people even realize that it's in there.
#5
05/02/2008 (6:04 am)
Thanks J.C. I did see that but, I didn't realize there was an Atlas port. I'll go search for that now. Thanks again.
#6
05/02/2008 (1:29 pm)
I'm trying to convert the grass shader now. I don't know a huge amount about shaders, but I'm learning fast!
#7
05/02/2008 (1:37 pm)
...
#8
05/03/2008 (1:45 am)
This is what I've come up with for the vertex shader... I really don't know what I'm doing. Does this look close?

//-----------------------------------------------------------------------------
// Structures 
//-----------------------------------------------------------------------------
struct VertData
{
	float4 position	: POSITION,
	float3 normal	   : NORMAL,	
	float2 texCoord	: TEXCOORD0,
	float2 texCoord2  : TEXCOORD1,
	float3 tangent    : TEXCOORD2,
};

struct ConnectData
{
	float4 vertColor              : COLOR, //In this implementation a per vertex lightmap is used

	out float4 oVertColor         : COLOR,
	out float2 oTexCoord	  	      : TEXCOORD0,
	out float2 oTexCoord2	  	   : TEXCOORD1,
	out float4 oPosition	   	   : POSITION,
	out float3 oEyeDirTan      	: TEXCOORD2,
	out float4 oPositionViewProj	: TEXCOORD3,

};


//-----------------------------------------------------------------------------
// Main 
//-----------------------------------------------------------------------------
ConnectData main( VertexIn_PNTTTB IN,
	uniform float4x4 worldViewProj,
	uniform float3 eyePositionO,
	uniform float time //Runs from 0 to 10 per second.
)
{
ConnectData OUT;

OUT.hpos = mul(worldViewProj, position); //oPosition must be output to satisy pipeline.
OUT.oTexCoord = IN.texCoord;
OUT.oTexCoord2 = float2((texCoord2.x+time*0.2)/2,(texCoord2.y+time*0.2)/2); // offset second texture coordinate
                                                                           // according to time for wind texture
                                                                           
OUT.oVertColor = vertColor;

float3 eyeDirO = -(eyePositionO-position) ; //eye vector in object space
float3 binormal = cross(tangent,normal);
float3x3 TBNMatrix = float3x3(tangent,binormal,normal); 


OUT.oEyeDirTan = normalize(mul(TBNMatrix,eyeDirO)); // eye vector in tangent space

return OUT;
}
#9
05/03/2008 (9:36 pm)
I have it basically done. There are still two issues, though. The first is that it's somewhat slow. I don't know a whole lot about optimizing shaders, so someone else will have to sort this out. The second is that there are minor rendering artifacts at the top of the grass billboards. I'm not totally sure yet what causes them.

grassV.hlsl
#define IN_HLSL
#include "shdrConsts.h"
#include "hlslStructs.h"

//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------

struct ConnectData
{
	float2 texCoord	  	: TEXCOORD0;
	float2 texCoord2	: TEXCOORD1;
	float4 position	   	: POSITION;
	float3 eyeDirTan      	: TEXCOORD2;
	float4 positionViewProj	: TEXCOORD3;
	float4x4 modelView : TEXCOORD4;
};

//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
ConnectData main( VertexIn_PNTTTB IN,
                  uniform float4x4 modelview       : register(C0),
                  uniform float4x4 texMat          : register(C4),
                  uniform float3   eyePos          : register(C20)
)
{
   ConnectData OUT;

    OUT.modelView = modelview;

    OUT.position = mul(modelview, IN.pos); //oPosition must be output to satisy pipeline.
    OUT.positionViewProj = OUT.position;

    OUT.texCoord = IN.uv0;
    OUT.texCoord2 = IN.uv1;

    OUT.eyeDirTan = mul( float3x3(IN.T,IN.B,IN.normal), IN.pos - eyePos);

   return OUT;
}

continued...
#10
05/03/2008 (9:36 pm)
GrassP.hlsl
#define IN_HLSL
#include "shdrConsts.h"

//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------

//Set everything which is constant in the fragment shader, the values used are for the moderate height data set.

#define MAX_RAYDEPTH 5 //Number of iterations.

#define PLANE_NUM 16.0 //Number of grass slice grid planes per unit in tangent space.

#define PLANE_NUM_INV (1.0/PLANE_NUM)
#define PLANE_NUM_INV_DIV2 (PLANE_NUM_INV/2)

#define GRASS_SLICE_NUM 8 // Number of grass slices in texture grassblades.

#define GRASS_SLICE_NUM_INV (1.0/GRASS_SLICE_NUM)
#define GRASS_SLICE_NUM_INV_DIV2 (GRASS_SLICE_NUM_INV/2)

#define GRASSDEPTH GRASS_SLICE_NUM_INV //Depth set to inverse of number of grass slices so no stretching occurs.

#define TC1_TO_TC2_RATIO 8 //Ratio of texture coordinate set 1 to texture coordinate set 2, used for the animation lookup.

#define PREMULT (GRASS_SLICE_NUM_INV*PLANE_NUM) //Saves a multiply in the shader.

#define AVERAGE_COLOR float4(0.32156,0.513725,0.0941176,1.0) //Used to fill remaining opacity, can be replaced by a texture lookup.

//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------

struct ConnectData
{
	float2 texCoord	  	: TEXCOORD0;
	float2 texCoord2	: TEXCOORD1;
	float4 position	   	: POSITION;
	float3 eyeDirTan      	: TEXCOORD2;
	float4 positionViewProj	: TEXCOORD3;
	float4x4 modelView : TEXCOORD4;
};

struct Fragout
{
   float4 col : COLOR0;
   float depth : DEPTH;
};

//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
Fragout main( ConnectData IN,
			uniform sampler2D grassblades      : register(S0),
			uniform sampler2D ground         : register(S1),
			uniform sampler2D windnoise      : register(S2),
			 uniform sampler2D lightMap       : register(S3),
             uniform float accumTime	  : register(C4),
             uniform float4    ambient         : register(C2)
)
{
   Fragout OUT;

	//Initialize increments/decrements and per fragment constants
	OUT.col = float4(0.0,0.0,0.0,0.0);

 	float2 plane_offset = float2(0.0,0.0);
 	float3 rayEntry = float3(IN.texCoord.xy,0.0);
	float zOffset = 0.0;
	bool zFlag = 1;

	float2 windCoord = float2((accumTime*0.1),(accumTime*0.1));


 	//The signs of eyeDirTan determines if we increment or decrement along the tangent space axis
	//plane_correct, planemod and pre_dir_correct are used to avoid unneccessary if-conditions.

 	float2 sgn = float2(sign(IN.eyeDirTan.x),sign(IN.eyeDirTan.y));
 	float2 plane_correct = float2((sgn.x+1)*GRASS_SLICE_NUM_INV_DIV2,
 	                              (sgn.y+1)*GRASS_SLICE_NUM_INV_DIV2);
 	float2 planemod = float2(floor(rayEntry.x*PLANE_NUM)/PLANE_NUM,
 	                         floor(rayEntry.y*PLANE_NUM)/PLANE_NUM);
	float2 pre_dir_correct = float2((sgn.x+1)*PLANE_NUM_INV_DIV2,
	                                (sgn.y+1)*PLANE_NUM_INV_DIV2);

	float2 dir_correct;
	float2 distance;
	float3 rayHitpointX;
	float3 rayHitpointY;
	float distanceZ;
	float3 rayHitpointZ;
	float2 orthoLookupZ;
 	float2 orthoLookup; //Will contain texture lookup coordinates for grassblades texture.
 	float4 windX;
 	float lookupX;
 	float4 windY;
 	float lookupY;


	int hitcount;
 	for(hitcount =0; hitcount < MAX_RAYDEPTH % (MAX_RAYDEPTH+1); hitcount++) // %([MAX_RAYDEPTH]+1) speeds up compilation.
										 // It may proof to be faster to early exit this loop
										 // depending on the hardware used.
 	{

		//Calculate positions of the intersections with the next grid planes on the u,v tangent space axis independently.

 		dir_correct = float2(sgn.x*plane_offset.x+pre_dir_correct.x,
 		                            sgn.y*plane_offset.y+pre_dir_correct.y);
		distance = float2((planemod.x + dir_correct.x - rayEntry.x)/(IN.eyeDirTan.x),
		                         (planemod.y + dir_correct.y - rayEntry.y)/(IN.eyeDirTan.y));

 		rayHitpointX = rayEntry + IN.eyeDirTan *distance.x;
  		rayHitpointY = rayEntry + IN.eyeDirTan *distance.y;

		//Check if we hit the ground. If so, calculate the intersection and look up the ground texture and blend colors.

  		if ((rayHitpointX.z <= -GRASSDEPTH)&& (rayHitpointY.z <= -GRASSDEPTH))
  		{
  			distanceZ = (-GRASSDEPTH)/IN.eyeDirTan.z; // rayEntry.z is 0.0 anyway

  			rayHitpointZ = rayEntry + IN.eyeDirTan *distanceZ;
			orthoLookupZ = rayHitpointZ.xy; //float2(rayHitpointZ.x,rayHitpointZ.y);

  			OUT.col = (OUT.col)+((1.0-OUT.col.w) * tex2D(ground,orthoLookupZ));
  			if(zFlag ==1) zOffset = distanceZ; // write the distance from rayEntry to intersection
  			zFlag = 0; //Early exit here if faster.
  		}
  		else
 		{
 			//check if we hit a u or v plane, calculate lookup accordingly with wind shear displacement.
			if(distance.x <= distance.y)
 			{
 				windX = (tex2D(windnoise,windCoord+rayHitpointX.xy/TC1_TO_TC2_RATIO)-0.5)/2;

				lookupX = -(rayHitpointX.z+(planemod.x+sgn.x*plane_offset.x)*PREMULT)-plane_correct.x;
				orthoLookup=float2(rayHitpointX.y+windX.x*(GRASSDEPTH+rayHitpointX.z)*.25,lookupX);

				plane_offset.x += PLANE_NUM_INV; // increment/decrement to next grid plane on u axis
				if(zFlag==1) zOffset = distance.x;
			}
			else {
				windY = (tex2D(windnoise,windCoord+rayHitpointY.xy/TC1_TO_TC2_RATIO)-0.5)/2;

				lookupY = -(rayHitpointY.z+(planemod.y+sgn.y*plane_offset.y)*PREMULT)-plane_correct.y;
				orthoLookup = float2(rayHitpointY.x+windY.y*(GRASSDEPTH+rayHitpointY.z)*.25 ,lookupY);

				plane_offset.y += PLANE_NUM_INV;  // increment/decrement to next grid plane on v axis
				if(zFlag==1) zOffset = distance.y;

  			}

 	 		OUT.col += (1.0-OUT.col.w)*tex2D(grassblades,orthoLookup);

 	 		if(OUT.col.w >= 0.49){zFlag = 0;}	//Early exit here if faster.
  		}
	}

     OUT.col += (1.0-OUT.col.w)*AVERAGE_COLOR; //Fill remaining transparency in case there is some left. Can be replaced by a texture lookup
					   //into a fully opaque grass slice using orthoLookup.


     OUT.col.xyz *= tex2D(lightMap, IN.texCoord2); //(vertColor.xyz); //Modulate with per vertex lightmap,as an alternative, modulate with N*L for dynamic lighting.

     OUT.col += ambient;

     //zOffset is along eye direction, transform and add to vertex position to get correct z-value.
     IN.positionViewProj += mul(IN.modelView,IN.eyeDirTan.xzy*zOffset);

     //Divide by homogenous part.
     OUT.depth = IN.positionViewProj.z/IN.positionViewProj.w;

   return OUT;
}

ShaderData
new ShaderData( GrassShader )
{
   DXVertexShaderFile   = "shaders/grassV.hlsl";
   DXPixelShaderFile    = "shaders/grassP.hlsl";
   pixVersion = 3.0;
};

Material (using the textures from the article)
new CustomMaterial(Grass1)
{
   mapTo = "[texture]";
   texture[0] = "m_grassblades";
   texture[1] = "m_grass_ground";
   texture[2] = "windnoise";
   texture[3] = "$lightmap";
   shader = GrassShader;
   version = 3.0;
};
#11
05/03/2008 (11:37 pm)
Good work !!!
#12
05/05/2008 (3:36 pm)
Very nice. I haven't been able to get it working for me though. How are you testing it? I made a box with uv map and exported to dts and used your material.cs above and changed the mapTo to my texture. I also copied the .tga files into the same folder as my dts and material.cs.

My log:
GFXTextureManager::createTexture - Unable to load Texture: C:/Torque/TGEA_1_7_0/GameExamples/Copy of Stronghold/game/scriptsAndAssets/data/shapes/grass/m_grass_ground
GFXTextureManager::createTexture - Unable to load Texture: C:/Torque/TGEA_1_7_0/GameExamples/Copy of Stronghold/game/scriptsAndAssets/data/shapes/grass/m_grass_ground
GFXTextureManager::createTexture - Unable to load Texture: scriptsAndAssets/data/shapes/grass/m_grassblades
GFXTextureManager::createTexture - Unable to load Texture: scriptsAndAssets/data/shapes/grass/m_grass_ground
GFXTextureManager::createTexture - Unable to load Texture: scriptsAndAssets/data/shapes/grass/windnoise
Tried to get the object for item 222, which is not InspectorData!
Tried to get the object for item 222, which is not InspectorData!
GFXTextureManager::createTexture - Unable to load Texture: C:/Torque/TGEA_1_7_0/GameExamples/Copy of Stronghold/game/scriptsAndAssets/data/shapes/grass/m_grass_ground
GFXTextureManager::createTexture - Unable to load Texture: C:/Torque/TGEA_1_7_0/GameExamples/Copy of Stronghold/game/scriptsAndAssets/data/shapes/grass/m_grass_ground
#13
05/05/2008 (5:57 pm)
You need to convert from tga to png or jpg. Torque doesn't support tga.
#14
05/05/2008 (7:01 pm)
Thanks Dan. I converted them and I still can't get it working. What texture do you use for the ground, and are you using a dts? I made a box in blender and I uv mapped the m_grass_ground texture to it. Is this right?

Sorry for all the questions. Thanks for your help.
#15
05/06/2008 (6:55 am)
Hi, I managed to port their HLSL shader to RenderMonkey and from RenderMonkey to TGEA. Below is the finalized shader model 3 HLSL code for the grass shader.

i63.photobucket.com/albums/h138/eternaldark112/grassShader.png
i63.photobucket.com/albums/h138/eternaldark112/grassShader2.png
grassV.hlsl
struct VertData
{
   float4 texCoord        : TEXCOORD0;
   float3 normal          : NORMAL;
   float4 position        : POSITION;
};


struct ConnectData
{
   float4 hpos            : POSITION;
   float2 TexCoord		  : TEXCOORD0;
   float3 Eye			  : TEXCOORD1;
   float4 Position	      : TEXCOORD2;
};

//-----------------------------------------------------------------------------
// Main                                                                        
//-----------------------------------------------------------------------------
ConnectData main( VertData IN,
                  uniform float4x4 modelview       : register(C0),
                  uniform float3   eyePos          : register(C20)
)
{
   ConnectData OUT;

   OUT.hpos = mul(modelview, IN.position);
   OUT.TexCoord = IN.texCoord;
   float3 tangent = float3(0,1,0);
   float3 binormal = cross(tangent,IN.normal);
   float3x3 TBNMatrix = float3x3(tangent,binormal,IN.normal); 
   float3 eyeDirO = -(eyePos-IN.position) ; //eye vector in object space
   OUT.Eye = normalize(mul(TBNMatrix,eyeDirO));
   OUT.Position = OUT.hpos;

   return OUT;
}

grassP.hlsl
#define IN_HLSL
#include "shdrConsts.h"

//Set everything which is constant in the fragment shader, the values used are for the moderate height data set.

#define MAX_RAYDEPTH 5 //Number of iterations.

#define PLANE_NUM 16.0 //Number of grass slice grid planes per unit in tangent space.

#define PLANE_NUM_INV (1.0/PLANE_NUM)
#define PLANE_NUM_INV_DIV2 (PLANE_NUM_INV/2)

#define GRASS_SLICE_NUM 8 // Number of grass slices in texture grassblades.

#define GRASS_SLICE_NUM_INV (1.0/GRASS_SLICE_NUM)
#define GRASS_SLICE_NUM_INV_DIV2 (GRASS_SLICE_NUM_INV/2)

#define GRASSDEPTH GRASS_SLICE_NUM_INV //Depth set to inverse of number of grass slices so no stretching occurs.

#define TC1_TO_TC2_RATIO 8 //Ratio of texture coordinate set 1 to texture coordinate set 2, used for the animation lookup.

#define PREMULT (GRASS_SLICE_NUM_INV*PLANE_NUM) //Saves a multiply in the shader.

#define AVERAGE_COLOR float4(0.32156,0.513725,0.0941176,1.0) //Used to fill remaining opacity, can be replaced by a texture lookup.

struct ConnectData
{
   float4 hpos            : POSITION;
   float2 texCoord		  : TEXCOORD0;
   float3 Eye			  : TEXCOORD1;
   float4 Position	      : TEXCOORD2;
};

struct Fragout
{
   float4 col : COLOR0;
};

//-----------------------------------------------------------------------------
// Main                                                                        
//-----------------------------------------------------------------------------
Fragout main( ConnectData IN,
              uniform sampler2D Grass			: register(S0),
              uniform sampler2D Ground          : register(S1),
              uniform sampler2D windnoise		: register(S2),
              uniform float time				: register(PC_ACCUM_TIME)
              
)			  
{
   Fragout OUT;
 //Initialize increments/decrements and per fragment constants
   float4 color = float4(0.0,0.0,0.0,0.0);
   float2 texCoord2 = float2((IN.texCoord.x+time*0.2)/2,(IN.texCoord.y+time*0.2)/2);
    float2 plane_offset = float2(0.0,0.0);               
    float3 rayEntry = float3(IN.texCoord.xy,0.0);
   float zOffset = 0.0;
   bool zFlag = 1;


    //The signs of eyeDirTan determines if we increment or decrement along the tangent space axis
   //plane_correct, planemod and pre_dir_correct are used to avoid unneccessary if-conditions. 
   
    float2 sign = float2(sign(IN.Eye.x),sign(IN.Eye.y));   
    float2 plane_correct = float2((sign.x+1)*GRASS_SLICE_NUM_INV_DIV2,
                                  (sign.y+1)*GRASS_SLICE_NUM_INV_DIV2);
    float2 planemod = float2(floor(rayEntry.x*PLANE_NUM)/PLANE_NUM,
                             floor(rayEntry.y*PLANE_NUM)/PLANE_NUM);
   float2 pre_dir_correct = float2((sign.x+1)*PLANE_NUM_INV_DIV2,
                                   (sign.y+1)*PLANE_NUM_INV_DIV2);


   int hitcount;
    for(hitcount =0; hitcount < MAX_RAYDEPTH % (MAX_RAYDEPTH+1); hitcount++) // %([MAX_RAYDEPTH]+1) speeds up compilation.
                               // It may proof to be faster to early exit this loop
                               // depending on the hardware used.
    {

      //Calculate positions of the intersections with the next grid planes on the u,v tangent space axis independently.

       float2 dir_correct = float2(sign.x*plane_offset.x+pre_dir_correct.x,
                                   sign.y*plane_offset.y+pre_dir_correct.y);         
      float2 distance = float2((planemod.x + dir_correct.x - rayEntry.x)/(IN.Eye.x),
                               (planemod.y + dir_correct.y - rayEntry.y)/(IN.Eye.y));
                
       float3 rayHitpointX = rayEntry + IN.Eye *distance.x;   
        float3 rayHitpointY = rayEntry + IN.Eye *distance.y;
      
      //Check if we hit the ground. If so, calculate the intersection and look up the ground texture and blend colors.

        if ((rayHitpointX.z <= -GRASSDEPTH)&& (rayHitpointY.z <= -GRASSDEPTH))    
        {
           float distanceZ = (-GRASSDEPTH)/IN.Eye.z; // rayEntry.z is 0.0 anyway 

           float3 rayHitpointZ = rayEntry + IN.Eye *distanceZ;
         float2 orthoLookupZ = float2(rayHitpointZ.x,rayHitpointZ.y);
                  
           color = (color)+((1.0-color.w) * tex2D(Ground,orthoLookupZ));
           if(zFlag ==1) zOffset = distanceZ; // write the distance from rayEntry to intersection
           zFlag = 0; //Early exit here if faster.      
        }  
        else
       {
          
          float2 orthoLookup; //Will contain texture lookup coordinates for grassblades texture.

          //check if we hit a u or v plane, calculate lookup accordingly with wind shear displacement.
         if(distance.x <= distance.y)
          {
             float4 windX = (tex2D(windnoise,texCoord2+rayHitpointX.xy/TC1_TO_TC2_RATIO)-0.5)/2;
            
            float lookupX = -(rayHitpointX.z+(planemod.x+sign.x*plane_offset.x)*PREMULT)-plane_correct.x;
            orthoLookup=float2(rayHitpointX.y+windX.x*(GRASSDEPTH+rayHitpointX.z),lookupX); 
            
            plane_offset.x += PLANE_NUM_INV; // increment/decrement to next grid plane on u axis
            if(zFlag==1) zOffset = distance.x;
         }
         else {
            float4 windY = (tex2D(windnoise,texCoord2+rayHitpointY.xy/TC1_TO_TC2_RATIO)-0.5)/2;
          
            float lookupY = -(rayHitpointY.z+(planemod.y+sign.y*plane_offset.y)*PREMULT)-plane_correct.y;
            orthoLookup = float2(rayHitpointY.x+windY.y*(GRASSDEPTH+rayHitpointY.z) ,lookupY);
          
            plane_offset.y += PLANE_NUM_INV;  // increment/decrement to next grid plane on v axis
            if(zFlag==1) zOffset = distance.y;
               
           }
            
           color += (1.0-color.w)*tex2D(Grass,orthoLookup);
    
           if(color.w >= 0.49){zFlag = 0;}   //Early exit here if faster.
        }
   }   

   color += (1.0-color.w)*AVERAGE_COLOR; //Fill remaining transparency in case there is some left. Can be replaced by a texture lookup
                  //into a fully opaque grass slice using orthoLookup.
   OUT.col = color;
   return OUT;
}

Matt Vitelli
#16
05/06/2008 (7:05 am)
Wow, so we have two versions! You guys rock! I wish I knew how to convert these better I'd make a few myself.

You guys have a list of what the commands are in tgea vs the commands in HLSL or render monkey?
#17
05/06/2008 (4:01 pm)
Well, they're basically the same. RenderMonkey has a ton of predefined vectors, but most shaders end up using world matrices, projection matrices, inverse world matrices. TGEA supports those as well as surface normals. TGEA out of the box is not setup to take binormals or tangents into account, though you can easily compensate for this using some simple calculations. Basically the sky's the limit. I write shaders in RenderMonkey and then once they're finalized I port them over.

One neat thing to have would be correct normal calculations for Legacy Terrain. As it currently stands, the normals appear to flicker and change based on your distance from the object. Perhaps this has to do with the terrain LOD, but I'm really not sure.
#18
05/07/2008 (2:15 pm)
Hi Guys. Sorry to bug you again but I'm still having trouble getting this working. All I can get is either the UV textured box I made or it's completely invisible. I have pixel shader 3.0 on my graphix card.
Here's what I've done:

1. I converted the images to png and put them in data\shapes\grasstest folder where my grass.dts resides.
2.. I UV mapped a box with (I tried different textures listed below)
2a. m_grass_ground.png
2b. s_grass_ground.png

3.. Added the P & V hlsl files to the shaders directory: Copy of Stronghold\game\shaders
4.. Added the shaderdata in game\scriptsAndAssets\client\scripts\shaders.cs from Dans post.
5.. Added the material file (and I tried different variations) from Dans post.
5a. mapTo = "[texture]"; // This will make the UV texture appear...
5b. mapTo = "s_grass_ground"; // This makes everything invisible.

What am I missing? Thanks again for your help. I'm I a complete noob when it comes to shaders.
#19
05/08/2008 (4:33 pm)
Here's my test version. Maybe that will work?
#20
05/08/2008 (5:04 pm)
Awesome thanks! That helps a lot.
Page «Previous 1 2