TSE/Shaders/Parallax Shader
From TDN
'Guide to implementing Parallax Shader with TSE.'
This is a TDN conversion of information based on a community post by Emmanuel Nwankwo about implementing Parallax Shader Effect in TSE. The shader files where created by Jacob Dankovchik and Kevin Johnson.
Requires Shader Model 2.0 hardware and drivers.
Create 2 HLSL files one for the Vertex and one for the Pixel shader." These go into the /shader directory.'
parallaxV.hlsl
//-----------------------------------------------------------------------------
// Parallax Vertex Shader - For TSE EA
// By: Jacob Dankovchik and Kevin Johnson
//-----------------------------------------------------------------------------
struct VertData
{
float4 texCoord : TEXCOORD0;
float2 lmCoord : TEXCOORD1;
float3 T : TEXCOORD2;
float3 B : TEXCOORD3;
float3 N : TEXCOORD4;
float3 normal : NORMAL;
float4 position : POSITION;
};
struct ConnectData
{
float4 hpos : POSITION;
float2 outTexCoord : TEXCOORD0;
float2 bumpCoord : TEXCOORD1;
float3 outLightVec : TEXCOORD2;
float3 tangenteye: TEXCOORD3;
float2 lightmap: TEXCOORD4;
};
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
ConnectData main( VertData IN,
uniform float4x4 modelview : register(C0),
uniform float4x4 texMat : register(C4),
uniform float3 inLightVec : register(C24),
uniform float3 eyePos : register(C20),
uniform float4x4 objTrans : register(C12)
)
{
ConnectData OUT;
OUT.hpos = mul(modelview, IN.position);
OUT.outTexCoord = mul(texMat, IN.texCoord);
OUT.bumpCoord = OUT.outTexCoord;
float3x3 objToTangentSpace;
objToTangentSpace[0] = IN.T;
objToTangentSpace[1] = IN.B;
objToTangentSpace[2] = IN.N;
OUT.outLightVec.xyz = -inLightVec;
OUT.outLightVec.xyz = mul(objToTangentSpace, OUT.outLightVec);
OUT.outLightVec = OUT.outLightVec / 2.0 + 0.5;
float3 objectspace_view_vector = mul( texMat, eyePos ) - IN.position;
OUT.tangenteye = mul( objToTangentSpace, objectspace_view_vector );
OUT.lightmap = IN.lmCoord;
return OUT;
}
And parallaxP.hlsl
//-----------------------------------------------------------------------------
// Parallax Pixel Shader - For Garagegames TSE EA
// By: Jacob Dankovchik and Kevin Johnson
//-----------------------------------------------------------------------------
struct ConnectData
{
float2 texCoord : TEXCOORD0;
float2 bumpCoord : TEXCOORD1;
float3 lightVec : TEXCOORD2;
float3 tangenteye: TEXCOORD3;
float2 TEX1: TEXCOORD4;
};
struct Fragout
{
float4 col : COLOR0;
};
float2 ParallaxTexCoord(float2 oldcoord, sampler2D heightmap, float3 eye_vect, float parallax_amount)
{
return (tex2D(heightmap, oldcoord)
* parallax_amount - parallax_amount * 0.5)
* eye_vect + oldcoord;
}
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
Fragout main( ConnectData IN,
uniform sampler2D diffuseMap : register(S0),
uniform sampler2D bumpMap : register(S1),
uniform sampler2D height_map : register(S2),
uniform float4 ambient : register(C2),
uniform sampler2D lightMap : register(S3)
)
{
Fragout OUT;
float3 eyevect = normalize(IN.tangenteye);
float2 modified_texcoord = ParallaxTexCoord(IN.texCoord, height_map, eyevect, 0.1);
OUT.col = tex2D(diffuseMap, modified_texcoord)* tex2D(lightMap, IN.TEX1);
float4 bumpNormal = tex2D(bumpMap, modified_texcoord);
IN.lightVec = IN.lightVec * 2.0 - 1.0;
float4 bumpDot = saturate( dot(bumpNormal.xyz * 2.0 - 1.0, IN.lightVec.xyz) );
OUT.col *= bumpDot + ambient;
return OUT;
}
Next defining the shader entry for TSE to be aware and compile.
At the end of /client/scripts/shaders.cs add the following.
new ShaderData ( Parallax )
{
DXVertexShaderFile ="shaders/parallaxV.hlsl";
DXPixelShaderFile ="shaders/parallaxP.hlsl";
pixVersion = 2.0;
};
Now you're ready to apply the shader to materials.
This is where the fun begins. Here is my example materials.cs, I was using the test cube that comes with the TSE SDK demo.
new Material(BoxEdge)
{
mapTo = box_edge;
baseTex[0] = "box_edge";
bumpTex[0] = "knot3bump";
shader = Parallax;
version = 2.0;
pixelSpecular[0] = true;
specular[0] = "1.0 1.0 1.0 1.0";
specularPower[0] = 32.0;
};
new Material(ParallaxFive )
{
mapTo = five;
baseTex[0] = "five";
bumpTex[0] = "metalcrate_bump";
shader = Parallax;
version = 2.0;
pixelSpecular[0] = true;
specular[0] = "0.8 0.8 0.8 0.8";
specularPower[0] = 16.0;
animFlags[0] = $rotate | $wave;
rotPivotOffset[0] = "-0.5 -0.5";
rotSpeed[0] = 1.0;
waveType[0] = Sin;
waveFreq[0] = 0.25;
waveAmp[0] = 1.0;
};
new CustomMaterial(SixBump)
{
mapTo = six;
texture[0] = "metalcrate_bump";
texture[1] = "six";
texture[3] = "$cubemap";
shader = Parallax;
version = 2.0;
specular = "1.0 1.0 1.0 0.0";
specularPower = 20.0;
};



