1). There are some peculiarities... Like when working with certain xyz operations and their orders... Calculating the binormal in the vertex program... Determining which vec_______ will serve the required purpose and sometime negating it. There are more, I suppose.
2). Converting the FX files is needed so that the variables supplied by the engine, that would be supplied by the main.cpp code in a DX project, make it into the shader. Also, some long shaders will crash, at a published run, if they reside in a looooooong effect string in a WDL.
3). DX SDK Documentation I use alot... Seems most books parrot that thing anyhows. I also find very many lessons on the interent. There are a few books that I like. But the names escape me right now as they are out in my service van.
The best thing to do is look at the (2) versions and see what is changed... it will make total sense to you.
First I present a RenderMonkey 1.5 FX dump, we will convert a portion of the
Illumination-Advanced.fx file. This is my 3DGS screen:
//**************************************************************//
// Effect File exported by RenderMonkey
//
// - Although many improvements were made to RenderMonkey FX
// file export, there are still situations that may cause
// compilation problems once the file is exported, such as
// occasional naming conflicts for methods, since FX format
// does not support any notions of name spaces. You need to
// try to create workspaces in such a way as to minimize
// potential naming conflicts on export.
//
// - Note that to minimize resulting name collisions in the FX
// file, RenderMonkey will mangle names for passes, shaders
// and function names as necessary to reduce name conflicts.
//**************************************************************//
//--------------------------------------------------------------//
// Spherical Harmonic Lighting
//--------------------------------------------------------------//
//--------------------------------------------------------------//
// PerPixel
//--------------------------------------------------------------//
//--------------------------------------------------------------//
// Single Pass
//--------------------------------------------------------------//
string Spherical_Harmonic_Lighting_PerPixel_Single_Pass_Teapot : ModelData = "../../../Program Files/ATI Research Inc/RenderMonkey 1.5/Examples/Media/Models/Teapot.3ds";
float4x4 view_proj_matrix : ViewProjection;
float4x4 view_matrix : View;
float4x4 inv_view_matrix;
//------------------------------------------------------------------//
// Spherical harmonic lighting, per-pixel illumination effect //
// //
// (c) Nathaniel Hoffman 2003 //
// //
// Based on 'An Efficient Representation for Irradiance //
// Environment Maps', SIGGRAPH 2001, by Ravi Ramamoorthi and Pat //
// Hanrahan from Stanford University //
//------------------------------------------------------------------//
struct VS_OUTPUT
{
float4 Pos: POSITION;
float4 Tex: TEXCOORD0;
float3 Normal: TEXCOORD1;
float3 Tangent: TEXCOORD2;
float3 Binormal: TEXCOORD3;
};
VS_OUTPUT Spherical_Harmonic_Lighting_PerPixel_Single_Pass_Vertex_Shader_main(
float4 vPosition: POSITION,
float4 vNormal: NORMAL,
float4 vTex: TEXCOORD,
float4 vTangent: TANGENT,
float4 vBinormal: BINORMAL )
{
VS_OUTPUT Out = (VS_OUTPUT) 0;
Out.Pos = mul(view_proj_matrix, vPosition);
Out.Tex = vTex * 2; //Scale factor for tex
// Rotate tangent basis from object/world space to view
// space (in RenderMonkey lights are defined in view space)
float4 nvec = float4(vNormal.x, vNormal.y, vNormal.z, 0.0);
float4 tvec = float4(vTangent.x, vTangent.y, vTangent.z, 0.0);
float4 bvec = float4(vBinormal.x, vBinormal.y, vBinormal.z, 0.0);
Out.Normal = mul(view_matrix, nvec);
Out.Tangent = mul(view_matrix, tvec);
Out.Binormal = mul(view_matrix, bvec);
return Out;
}
float4x4 g_sh_matrix
<
string UIName = "g_sh_matrix";
string UIWidget = "Matrix";
> = ( -0.02, -0.02, 0.09, -0.03, -0.02, 0.02, -0.09, 0.18, 0.09, -0.09, -0.07, -0.09, -0.03, 0.18, -0.09, -0.01 );
float4x4 r_sh_matrix
<
string UIName = "r_sh_matrix";
string UIWidget = "Matrix";
> = ( 0.09, -0.05, 0.24, -0.15, -0.05, -0.09, -0.11, 0.20, 0.24, -0.11, -0.12, -0.17, -0.15, 0.20, -0.17, -0.07 );
float4x4 b_sh_matrix
<
string UIName = "b_sh_matrix";
string UIWidget = "Matrix";
> = ( -0.13, -0.05, 0.06, 0.01, -0.05, 0.13, -0.20, 0.31, 0.06, -0.20, -0.11, -0.14, 0.01, 0.31, -0.14, -0.03 );
texture bump_map_Tex
<
string ResourceName = "..\..\..\Program Files\ATI Research Inc\RenderMonkey 1.5\Examples\Media\Textures\FieldstoneBumpDOT3.tga";
>;
sampler bump_map = sampler_state
{
Texture = (bump_map_Tex);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
texture rgb_map_Tex
<
string ResourceName = "..\..\..\Program Files\ATI Research Inc\RenderMonkey 1.5\Examples\Media\Textures\Fieldstone.tga";
>;
sampler rgb_map = sampler_state
{
Texture = (rgb_map_Tex);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
//------------------------------------------------------------------//
// Spherical harmonic lighting, per-pixel illumination effect //
// //
// (c) Nathaniel Hoffman 2003 //
// //
// Based on 'An Efficient Representation for Irradiance //
// Environment Maps', SIGGRAPH 2001, by Ravi Ramamoorthi and Pat //
// Hanrahan from Stanford University //
//------------------------------------------------------------------//
float4 Spherical_Harmonic_Lighting_PerPixel_Single_Pass_Pixel_Shader_main(
float4 Tex: TEXCOORD0,
float3 Normal: TEXCOORD1,
float3 Tangent: TEXCOORD2,
float3 Binormal: TEXCOORD3 ) : COLOR
{
float4 c;
float3x3 rotation;
float3 normal3;
float4 normal4;
// Matrix to transform from tangent space into light space)
rotation = float3x3(Tangent, Binormal, Normal);
// Get normal
normal3 = tex2D(bump_map, Tex) * 2.0 - 1.0;
// Transform normal into light space
normal3 = mul(normal3, rotation);
normal4 = float4(normal3, 1.0);
// Evaluate spherical harmonic
c.r = dot(mul(r_sh_matrix, normal4), normal4);
c.g = dot(mul(g_sh_matrix, normal4), normal4);
c.b = dot(mul(b_sh_matrix, normal4), normal4);
c.a = 1.0;
// Multiply by rgb factor (and scale by two)
c = c* tex2D(rgb_map, Tex) * 2.0;
return c;
}
//--------------------------------------------------------------//
// Technique Section for Spherical Harmonic Lighting
//--------------------------------------------------------------//
technique PerPixel
{
pass Single_Pass
{
VertexShader = compile vs_1_1 Spherical_Harmonic_Lighting_PerPixel_Single_Pass_Vertex_Shader_main();
PixelShader = compile ps_2_0 Spherical_Harmonic_Lighting_PerPixel_Single_Pass_Pixel_Shader_main();
}
}
//////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
Then here is the converted version:
////////////////////////////////////////////////
// Adaptation of ATI Advanced-Illumination.fx\
// for 3DGS.
// Specifically the Per-Pixel, Spherical Harmonic Lighting
//
material shillum_fx {
Flags = Tangent; // Bring the tangent in on TexCoord2
effect="
//////////////////////////////////////////////
// Variables, etc
//--------------------------------------------
// Change the matrices to the ones
// we are given by the Engine.
// Then check the vs/ps and make the
// necessary replacements as well.
//--------------------------------------------
float4x4 matWorldViewProj;
float4x4 matView;
float4x4 g_sh_matrix= { -0.02, -0.02, 0.09, -0.03,
-0.02, 0.02, -0.09, 0.18,
0.09, -0.09, -0.07, -0.09,
-0.03, 0.18, -0.09, -0.01 };
float4x4 r_sh_matrix= { 0.09, -0.05, 0.24, -0.15,
-0.05, -0.09, -0.11, 0.20,
0.24, -0.11, -0.12, -0.17,
-0.15, 0.20, -0.17, -0.07 };
float4x4 b_sh_matrix = { -0.13, -0.05, 0.06, 0.01,
-0.05, 0.13, -0.20, 0.31,
0.06, -0.20, -0.11, -0.14,
0.01, 0.31, -0.14, -0.03 };
/////////////////////////////////////////////
// Textures
Texture entSkin1;
Texture entSkin2;
sampler rgb_map = sampler_state //Colormap
{
Texture = (entSkin1);
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
MAGFILTER = LINEAR;
};
sampler bump_map = sampler_state
{
Texture = (entSkin2); // Normalmap
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
MAGFILTER = LINEAR;
};
/////////////////////////////////////////////
// Vertex Shader
struct VS_OUTPUT
{
float4 Pos: POSITION;
float4 Tex: TEXCOORD0;
float3 Normal: TEXCOORD1;
float3 Tangent: TEXCOORD2;
float3 Binormal: TEXCOORD3;
};
//--------------------------------------------
// Note the change needed to get the
// Tangent.
//--------------------------------------------
VS_OUTPUT main_vs(
float4 vPosition: POSITION,
float4 vNormal: NORMAL,
float4 vTex: TEXCOORD0,
float4 vTangent: TEXCOORD2)
{
VS_OUTPUT Out;
//--------------------------------------------
// Note the change needed to get our
// object in screen space.
//--------------------------------------------
Out.Pos = mul(vPosition, matWorldViewProj);
Out.Tex = vTex * 2; //Scale factor for tex
//--------------------------------------------
// Note the way we need to get the
// Binormal. Remove the references
// to the Binormal in the main_vs IN.Structs
//--------------------------------------------
float3 vBinormal = cross(vTangent, vNormal);
// Rotate tangent basis from object/world space to view
// space (in RenderMonkey lights are defined in view space)
float4 nvec = float4(vNormal.x, vNormal.y, vNormal.z, 0.0);
float4 tvec = float4(vTangent.x, vTangent.y, vTangent.z, 0.0);
float4 bvec = float4(vBinormal.x, vBinormal.y, vBinormal.z, 0.0);
Out.Normal = mul(matView, nvec);
Out.Tangent = mul(matView, tvec);
Out.Binormal = mul(matView, bvec);
return Out;
}
/////////////////////////////////////////////
// Pixel Shader
float4 main_ps(
float4 Tex: TEXCOORD0,
float3 Normal: TEXCOORD1,
float3 Tangent: TEXCOORD2,
float3 Binormal: TEXCOORD3 ) : COLOR
{
float4 c;
float3x3 rotation;
float3 normal3;
float4 normal4;
// Matrix to transform from tangent space into light space)
rotation = float3x3(Tangent, Binormal, Normal);
// Get normal
normal3 = tex2D(bump_map, Tex) * 2.0 - 1.0;
// Transform normal into light space
normal3 = mul(normal3, rotation);
normal4 = float4(normal3, 1.0);
// Evaluate spherical harmonic
c.r = dot(mul(r_sh_matrix, normal4), normal4);
c.g = dot(mul(g_sh_matrix, normal4), normal4);
c.b = dot(mul(b_sh_matrix, normal4), normal4);
c.a = 1.0;
// Multiply by rgb factor (and scale by two)
c = c* tex2D(rgb_map, Tex) * 2.0;
return c;
}
//--------------------------------------------------------------//
// Technique Section for Spherical Harmonic Lighting
//--------------------------------------------------------------//
technique PerPixel
{
pass Single_Pass
{
VertexShader = compile vs_1_1 main_vs();
PixelShader = compile ps_2_0 main_ps();
}
}
";
}
Action sh_illumination {
my.material = shillum_fx;
my.nofog = on;
}
Good luck!!!!!