jchmack
20-12-2008 02:08:29
I knew i should have just posted the all of the shaders in the first place. For the level I use the monster shader:
monster.material
material MonsterExample
{
receive_shadows off
transparency_casts_shadows off
technique Map #13
{
pass Map #14
{
ambient 0.698039 0.698039 0.698039 1
diffuse 0.698039 0.698039 0.698039 1
specular 0.898039 0.898039 0.898039 1 20
emissive 0 0 0 1
scene_blend one zero
depth_check on
depth_write on
depth_func less_equal
depth_bias 0 0
alpha_rejection always_pass 0
cull_hardware clockwise
cull_software back
lighting on
shading gouraud
polygon_mode solid
colour_write on
max_lights 8
start_light 0
iteration once
vertex_program_ref monster_vs
{
param_named_auto eyePosition camera_position_object_space
param_named_auto lightPosition0 light_position_object_space 0
//param_named scale float 2//orginal
param_named scale float 1
param_named_auto worldviewproj worldviewproj_matrix
}
fragment_program_ref monster_ps
{
param_named ambient float4 0 0 0 1
param_named_auto atten0 light_attenuation 0
param_named_auto lightDiffuse0 light_diffuse_colour 0
//param_named scaleBias float4 0.04 -0.02 1 0 //orginal
param_named scaleBias float4 0 0 0 1
//param_named exponent0 float 127
param_named exponent0 float 256
param_named_auto lightSpecular0 light_specular_colour 0
}
texture_unit Normal
{
texture Rockwall_NH.png 2d unlimited
binding_type fragment
tex_coord_set 0
tex_address_mode wrap wrap wrap
//tex_address_mode border border border
tex_border_colour 0 0 0 1
filtering trilinear
max_anisotropy 1
mipmap_bias 0
colour_op_ex modulate src_texture src_current 1 1 1 1 1 1 1
alpha_op_ex modulate src_texture src_current 1 1 1
colour_op_multipass_fallback one zero
env_map off
//scroll_anim 1 1
}
texture_unit Diffuse
{
texture Rockwall.png 2d unlimited
binding_type fragment
tex_coord_set 0
tex_address_mode wrap wrap wrap
//tex_address_mode border border border
tex_border_colour 0 0 0 1
filtering trilinear
max_anisotropy 1
mipmap_bias 0
colour_op_ex modulate src_texture src_current 1 1 1 1 1 1 1
alpha_op_ex modulate src_texture src_current 1 1 1
colour_op_multipass_fallback one zero
env_map off
//scroll_anim 1 1
}
}
}
}
material TestMonsterForge: MonsterExample
{
set_texture_alias Diffuse forge_diffuse.tga
set_texture_alias Normal forge_normal.tga
}
monster.program
vertex_program monster_vs cg
{
source monster.source
default_params
{
param_named_auto lightPosition0 light_position_object_space 0
param_named_auto lightPosition1 light_position_object_space 1
param_named_auto lightPosition2 light_position_object_space 2
param_named_auto eyePosition camera_position_object_space
param_named_auto worldviewproj worldviewproj_matrix
param_named scale float 2
}
entry_point monster_vs
profiles vs_1_1 arbvp1
//profiles vs_3_0 arbvp1
//includes_skeletal_animation true
}
fragment_program monster_ps cg
{
source monster.source
default_params
{
param_named_auto lightDiffuse0 light_diffuse_colour 0
param_named_auto lightDiffuse1 light_diffuse_colour 1
param_named_auto lightDiffuse2 light_diffuse_colour 2
param_named_auto lightSpecular0 light_specular_colour 0
param_named_auto lightSpecular1 light_specular_colour 1
param_named_auto lightSpecular2 light_specular_colour 2
param_named_auto atten0 light_attenuation 0
param_named_auto atten1 light_attenuation 1
param_named_auto atten2 light_attenuation 2
param_named exponent0 float 127
param_named scaleBias float4 0.04 -0.02 1 0
//param_named ambient float4 0.0 0.0 0.0 1.0
param_named ambient float4 0.0 0.0 0.0 0.0
}
entry_point monster_ps
profiles ps_2_0 arbfp1
//includes_skeletal_animation true
}
monster.source
//TWEAK HERE
#define FADING 0
//fading is buggy, experimental guarantees :)
#define ATTENUATION 0
#define LIGHT0_IS_DIRECTIONAL 0
//if u have directional light (suppose a healthy 1 only), it is always light0
//(regarding that you turn off lights in RECOMMENDED ORDER of 2,1,0)
//so do not attenuate it, but then we have power to attenuate light1, and light2
//even with offset mapping on !
#define ANY_TEXTURE 1
#define DIFFUSE_TEXTURE 1
#define AT_LEAST_PERPIXEL 1
#define AT_LEAST_NORMAL_MAPPING 1
#define OFFSET_MAPPING 0
#define AMBIENT 1
#define DIFFUSE 1
#define SPECULAR 1
#define LIGHT0 1
#define LIGHT1 1
#define LIGHT2 1
//#define Skinned 0
/////////////////////////////////////////////////////////////////////////////////////////////////
// VERT COMES
/////////////////////////////////////////////////////////////////////////////////////////////////
//quite chaotic form, maybe more logical arrangement possible
void monster_vs
(
float4 position : POSITION,
float3 normal : NORMAL,
out float4 oPosition : POSITION,
#if ANY_TEXTURE
float2 uv : TEXCOORD0,
out float2 oUv : TEXCOORD0,
uniform float scale,
#endif
#if AT_LEAST_NORMAL_MAPPING
float3 tangent : TEXCOORD1,
#elif AT_LEAST_PERPIXEL //just normal perpixel, use texcoord7 to transmit to frag (holds eyedir in offset case)
out float3 oNorm : TEXCOORD7,
#endif
// Still in frag shader!
// #if AMBIENT
// uniform float4 ambient,
// out float4 oColor : COLOR,
// #endif
#if LIGHT0
uniform float4 lightPosition0, // object space
#if DIFFUSE
out float3 oLightDir0 : TEXCOORD1,
#endif
#if SPECULAR
out float3 oHalfAngle0 : TEXCOORD4,
#endif
#endif
#if LIGHT1
uniform float4 lightPosition1, // object space
#if DIFFUSE
out float3 oLightDir1 : TEXCOORD2,
#endif
#if SPECULAR
out float3 oHalfAngle1 : TEXCOORD5,
#endif
#endif
#if LIGHT2
uniform float4 lightPosition2, // object space
#if DIFFUSE
out float3 oLightDir2 : TEXCOORD3,
#endif
#endif
#if ATTENUATION
out float4 dist : TEXCOORD6, // .x, .y, and .z is used for light distances
#elif SPECULAR
out float3 oHalfAngle2 : TEXCOORD6,
#endif
#if OFFSET_MAPPING //needs eye no matter specular
uniform float3 eyePosition, // object space
out float3 oEyeDir : TEXCOORD7,
#elif SPECULAR //no need to output eye, even if normal-mapping is on
uniform float3 eyePosition, // object space
#elif FADING
uniform float3 eyePosition, // object space
//Fading will modify alpha, and will be passed to frag in COLOR,
//though I could do it with dist.w, which is unmodified even with atten
//but I do not use dist without atten, anyway. Dunno which is faster.
#endif
#if FADING
out float4 oFadeColor : COLOR,
uniform float4 fadefirst,
uniform float4 fadesecond,
#endif
//#if Skinned
// float blendIdx : BLENDINDICES,
// uniform float3x4 worldMatrix3x4Array[24],
// uniform float4x4 viewProjectionMatrix,
//#endif
uniform float4x4 worldviewproj
)
{
//#if Skinned
// transform by indexed matrix
// float4 blendPos = float4(mul(worldMatrix3x4Array[blendIdx], position).xyz, 1.0);
// view / projection
// oPosition = mul(viewProjectionMatrix, blendPos);
// transform normal
// float3 norm = mul((float3x3)worldMatrix3x4Array[blendIdx], normal);
// Lighting - support point and directional
// float3 lightDir0 = normalize(
// lightPos[0].xyz - (blendPos.xyz * lightPos[0].w));
// float3 lightDir1 = normalize(
// lightPos[1].xyz - (blendPos.xyz * lightPos[1].w));
//#else
oPosition = mul(worldviewproj , position);
//#endif
#if ANY_TEXTURE
oUv = uv * scale;
#endif
#if AT_LEAST_NORMAL_MAPPING
float3 binormal = cross(tangent, normal);
float3x3 rotation = float3x3(tangent, binormal, normal);
#elif AT_LEAST_PERPIXEL
oNorm = normal;
#endif
#if OFFSET_MAPPING //no matter specular, I need eye for offsetting
float3 eyeDir = eyePosition - position.xyz;
eyeDir = normalize(mul(rotation, eyeDir));
oEyeDir = eyeDir;
#elif SPECULAR //I need eye only if specular other than offset, plus no eye output now
float3 eyeDir = normalize(eyePosition - position.xyz);
#if AT_LEAST_NORMAL_MAPPING //eye needs adjustment if normal-mapping
eyeDir = normalize(mul(rotation, eyeDir));
#endif
#endif
//if DIFFUSE is commented out, we only need temp_lightDirX for oHalfAngle
//and if both DIFFUSE and SPECULAR is out, we shall not calculate any lighting
#if LIGHT0
#if ATTENUATION
#if LIGHT0_IS_DIRECTIONAL
// light0 is directional, atten is on, but we do not atten light0
float3 temp_lightDir0 = normalize(lightPosition0.xyz - (position * lightPosition0.w));
dist.x = 0;
//I need dist.x even I do not use it now. Compiler blah-blah about continous oTex6.
#else
float3 temp_lightDir0 = lightPosition0.xyz - (position * lightPosition0.w);
dist.x = length(temp_lightDir0);
temp_lightDir0 = temp_lightDir0 / dist.x; //normalize it this way
// oatten.x = 1/(atten.y + dist0*atten.z + dist0*dist0*atten.w);
// Attenuation calc, could be even much faster if it could be done in vertex shader.
// Think about leaving kl component only, and calculating atten value here,
// instead doing only distance here, and calculating atten in frag shader.
#endif
#else
float3 temp_lightDir0 = normalize(lightPosition0.xyz - (position * lightPosition0.w));
#endif
#if AT_LEAST_NORMAL_MAPPING
temp_lightDir0 = normalize(mul(rotation, temp_lightDir0));
#if DIFFUSE
oLightDir0 = temp_lightDir0;
#endif
#elif DIFFUSE //just normal perpixel
oLightDir0 = temp_lightDir0;
#endif
#if SPECULAR
oHalfAngle0 = normalize(eyeDir + temp_lightDir0);
#endif
#endif
#if LIGHT1
#if ATTENUATION
float3 temp_lightDir1 = lightPosition1.xyz - (position * lightPosition1.w);
dist.y = length(temp_lightDir1);
temp_lightDir1 = temp_lightDir1 / dist.y; //normalize it this way
#else
float3 temp_lightDir1 = normalize(lightPosition1.xyz - (position * lightPosition1.w));
#endif
#if AT_LEAST_NORMAL_MAPPING
temp_lightDir1 = normalize(mul(rotation, temp_lightDir1));
#if DIFFUSE
oLightDir1 = temp_lightDir1;
#endif
#elif DIFFUSE //just normal perpixel
oLightDir1 = temp_lightDir1;
#endif
#if SPECULAR
oHalfAngle1 = normalize(eyeDir + temp_lightDir1);
#endif
#endif
#if LIGHT2
#if ATTENUATION
float3 temp_lightDir2 = lightPosition2.xyz - (position * lightPosition2.w);
dist.z = length(temp_lightDir2);
temp_lightDir2 = temp_lightDir2 / dist.z; //normalize it this way
#else
float3 temp_lightDir2 = normalize(lightPosition2.xyz - (position * lightPosition2.w));
#if SPECULAR
oHalfAngle2 = normalize(eyeDir + temp_lightDir2);
#endif
#endif
#if AT_LEAST_NORMAL_MAPPING
temp_lightDir2 = normalize(mul(rotation, temp_lightDir2));
#if DIFFUSE
oLightDir2 = temp_lightDir2;
#endif
#elif DIFFUSE //just normal perpixel
oLightDir2 = temp_lightDir2;
#endif
#endif
#if FADING
float ratio = saturate(1-(distance(eyePosition, position.xyz)-fadefirst) / fadesecond);
oFadeColor = float4(0,0,0,ratio);
#endif
}
// Helper: Expand a range-compressed vector
float3 expand(float3 v)
{
return (v - 0.5) * 2;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// FRAG COMES
/////////////////////////////////////////////////////////////////////////////////////////////////
void monster_ps(
#if DIFFUSE_TEXTURE
uniform sampler2D diffuseMap : register(s1),
float2 uv : TEXCOORD0,
#elif ANY_TEXTURE
float2 uv : TEXCOORD0,
#endif
#if LIGHT0
#if DIFFUSE
float3 LightDir0 : TEXCOORD1,
uniform float4 lightDiffuse0,
#endif
#if SPECULAR
float3 HalfAngle0 : TEXCOORD4,
uniform float4 lightSpecular0,
#endif
#endif
#if LIGHT1
#if DIFFUSE
float3 LightDir1 : TEXCOORD2,
uniform float4 lightDiffuse1,
#endif
#if SPECULAR
float3 HalfAngle1 : TEXCOORD5,
uniform float4 lightSpecular1,
#endif
#endif
#if LIGHT2
#if DIFFUSE
float3 LightDir2 : TEXCOORD3,
uniform float4 lightDiffuse2,
#endif
#endif
#if OFFSET_MAPPING
float3 EyeDir : TEXCOORD7,
uniform float4 scaleBias,
uniform sampler2D normalHeightMap : register(s0),
#elif AT_LEAST_NORMAL_MAPPING
uniform sampler2D normalHeightMap : register(s0),
#elif AT_LEAST_PERPIXEL //no normal-mapping, use standard normal, in eyedir's place
float3 normalvec : TEXCOORD7,
#endif
#if SPECULAR
uniform float exponent0,
// uniform float exponent1,
// uniform float exponent2,
#endif
#if AMBIENT
uniform float4 ambient,
#endif
#if ATTENUATION //if on, supposed to have light0 on as well, OR light0_directional!
float4 dist : TEXCOORD6,
#if !LIGHT0_IS_DIRECTIONAL
uniform float4 atten0,
#endif
#if LIGHT1
uniform float4 atten1,
#endif
#if LIGHT2
uniform float4 atten2,
#endif
#elif SPECULAR
#if LIGHT2
float3 HalfAngle2 : TEXCOORD6,
uniform float4 lightSpecular2,
#endif
#endif
#if FADING
float4 inFadeColor : COLOR,
#endif
out float4 oColor : COLOR
)
{
#if OFFSET_MAPPING
float height = tex2D(normalHeightMap, uv).a;
float scale = scaleBias.x;
float bias = scaleBias.y;
float displacement = (height * scale) + bias;
float3 uv2 = float3(uv, 1);
float2 newTexCoord = ((EyeDir * displacement) + uv2).xy;
float3 bumpVec = expand(tex2D(normalHeightMap, newTexCoord ).xyz);
// float3 bumpVec = tex2D(normalHeightMap, newTexCoord ).xyz;
float3 N = normalize(bumpVec);
#if DIFFUSE_TEXTURE
float3 diffusetex = tex2D(diffuseMap, newTexCoord).xyz;
#endif
#elif AT_LEAST_NORMAL_MAPPING
float3 bumpVec = expand(tex2D(normalHeightMap, uv).xyz);
// float3 N = tex2D(normalHeightMap, uv).xyz;
float3 N = normalize(bumpVec);
#if DIFFUSE_TEXTURE
float3 diffusetex = tex2D(diffuseMap, uv).xyz;
#endif
#elif AT_LEAST_PERPIXEL
float3 N = normalize(normalvec);
#if DIFFUSE_TEXTURE
float3 diffusetex = tex2D(diffuseMap, uv).xyz;
#endif
#elif DIFFUSE_TEXTURE
float3 diffusetex = tex2D(diffuseMap, uv).xyz;
#endif
//If different exponents for different specular-lights, change 3 places here!
#if LIGHT0
#if DIFFUSE
float NdotL0 = dot(normalize(LightDir0), N);
#if SPECULAR //both
float NdotH0 = dot(normalize(HalfAngle0), N);
float4 Lit0 = lit(NdotL0,NdotH0,exponent0);
#else //just diffuse
float4 Lit0;
Lit0.y = saturate(NdotL0);
#endif
#elif SPECULAR //just specular
float NdotH0 = dot(normalize(HalfAngle0), N);
float4 Lit0;
Lit0.z = pow(saturate(NdotH0),exponent0);
#endif
#endif
#if LIGHT1
#if DIFFUSE
float NdotL1 = dot(normalize(LightDir1), N);
#if SPECULAR //both
float NdotH1 = dot(normalize(HalfAngle1), N);
float4 Lit1 = lit(NdotL1,NdotH1,exponent0);
#else //just diffuse
float4 Lit1;
Lit1.y = saturate(NdotL1);
#endif
#elif SPECULAR //just specular
float NdotH1 = dot(normalize(HalfAngle1), N);
float4 Lit1;
Lit1.z = pow(saturate(NdotH1),exponent0);
#endif
#endif
#if LIGHT2
#if DIFFUSE
float NdotL2 = dot(normalize(LightDir2), N);
#if SPECULAR //both
#if !ATTENUATION
float NdotH2 = dot(normalize(HalfAngle2), N);
float4 Lit2 = lit(NdotL2,NdotH2,exponent0);
#else
float4 Lit2;
Lit2.y = saturate(NdotL2);
#endif
#else //just diffuse
float4 Lit2;
Lit2.y = saturate(NdotL2);
#endif
#elif SPECULAR //just specular
#if !ATTENUATION
float NdotH2 = dot(normalize(HalfAngle2), N);
float4 Lit2;
Lit2.z = pow(saturate(NdotH2),exponent0);
#else
float4 Lit2;
Lit2 = float4(1,0,0,1);
#endif
#endif
#endif
oColor =
#if ATTENUATION //since usage rules specify it, we have at least light0 on with at least either
//diffuse or specular also on !
// - if you want no lighting, just textures, turn attenuation off!
//But yes, you can have diffusetex with just specular :)
//Note that you can't have specular of light2 with attenuation on. See docs.
// Final color formula with atten
// oColor = atten0 * (diffusetex * lightDiffuse0 * Lit0.y + lightSpecular0 * Lit0.z)
// atten1 * (diffusetex * lightDiffuse1 * Lit1.y + lightSpecular1 * Lit1.z)
// atten2 * (diffusetex * lightDiffuse2 * Lit2.y + lightSpecular2 * Lit2.z)
// + ambient;
#if !DIFFUSE //we start with the no diffuse just diffusetex case, here only spec is attenuated
#if DIFFUSE_TEXTURE
float4(diffusetex,1) +
#endif
#endif
// 1/(atten0.y + atten0.z*dist.x + atten0.w*dist.x*dist.x)* (
// use simpler formular instead: counts much in FPS!
#if !LIGHT0_IS_DIRECTIONAL
1/(1 + atten0.z*dist.x)* (
#else
( //for syntax
#endif
//we always have light0 on here, and spec0 or diffuse0 with it
#if SPECULAR
lightSpecular0 * Lit0.z
#if DIFFUSE
+
#else //light0 has only spec, light0 done
)
#endif
#endif
#if DIFFUSE
lightDiffuse0 * Lit0.y //without + sign, we are good at no specular case as well
#if DIFFUSE_TEXTURE
* float4(diffusetex,1)) //light0 done
#else
) //light0 done
#endif
#endif
#if LIGHT1 //optional, but if we have it, we have either diff1 or spec1, difftex can be 0/1
// + 1/(atten1.y + atten1.z*dist.y + atten1.w*dist.y*dist.y) * (
// use simpler formula instead
+ 1/(1 + atten1.z*dist.y) * (
#if SPECULAR
lightSpecular1 * Lit1.z
#if DIFFUSE
+
#else //light1 has only spec, light1 done
)
#endif
#endif
#if DIFFUSE
lightDiffuse1 * Lit1.y //without + sign here, we are good at no specular case as well
#if DIFFUSE_TEXTURE
* float4(diffusetex,1)) //light1 done
#else
) //light1 done
#endif
#endif
#endif
#if LIGHT2 //ditto goes for diff2, and difftex (no specular here)
// + 1/(atten2.y + atten2.z*dist.z + atten2.w*dist.z*dist.z) * (
// use simpler formula instead
+ 1/(1 + atten2.z*dist.z) * (
#if DIFFUSE
lightDiffuse2 * Lit2.y //without + sign here, we are good at no specular case as well
#if DIFFUSE_TEXTURE
* float4(diffusetex,1)) //light2 done
#else
) //light2 done
#endif
#endif
#endif
#else
// And wo. atten
// oColor = diffusetex
// * (lightDiffuse0 * Lit0.y + lightDiffuse1 * Lit1.y + lightDiffuse2 * Lit2.y)
// + lightSpecular0 * Lit0.z + lightSpecular1 * Lit1.z + lightSpecular2 * Lit2.z
// + ambient;
float4(0,0,0,0) //this is needed to simplify preprocessor stuff, no FPS cost :)
#if DIFFUSE_TEXTURE //at least diffuse texture, no lighting yet
+ float4(diffusetex,1)
#if DIFFUSE //modulate texture with lighting
*(
#if LIGHT0
lightDiffuse0 * Lit0.y
#endif
#if LIGHT1
+ lightDiffuse1 * Lit1.y
#endif
#if LIGHT2
+ lightDiffuse2 * Lit2.y
#endif
)
#endif
#elif DIFFUSE //just diffuse lighting, no modulation
#if LIGHT0
+ lightDiffuse0 * Lit0.y
#endif
#if LIGHT1
+ lightDiffuse1 * Lit1.y
#endif
#if LIGHT2
+ lightDiffuse2 * Lit2.y
#endif
#endif
#if SPECULAR
#if LIGHT0
+ lightSpecular0 * Lit0.z
#endif
#if LIGHT1
+ lightSpecular1 * Lit1.z
#endif
#if LIGHT2
+ lightSpecular2 * Lit2.z
#endif
#endif
#endif
#if AMBIENT
+ ambient
#endif
;
#if FADING
//WARNING: this will eat up all original/computed alpha!
oColor = float4(oColor.x, oColor.y, oColor.z, inFadeColor.w);
#endif
}
jchmack
20-12-2008 02:13:34
And for the Character i use this shader:
animatedNormalSpecular.material
vertex_program AnimatedNormalSpecular_VP hlsl
{
source animatedNormalSpecular.hlsl
entry_point main_vp
target vs_2_0
//target vs_2_x
//target vs_3_0
// target vs_2_a
column_major_matrices false //required for hlsl skinning
includes_skeletal_animation true
default_params
{
param_named_auto worldviewprojmatrix worldviewproj_matrix
param_named_auto light_position light_position_object_space 0
param_named_auto eye_position camera_position_object_space
param_named_auto worldMatrix3x4Array world_matrix_array_3x4
param_named_auto viewProjectionMatrix viewproj_matrix
param_named_auto invworldmatrix inverse_world_matrix
}
}
fragment_program AnimatedNormalSpecular_FP hlsl
{
source animatedNormalSpecular.hlsl
entry_point main_fp
target ps_2_0
default_params
{
param_named_auto lightDiffuse light_diffuse_colour 0
param_named_auto ambientLight ambient_light_colour
param_named_auto specularLight light_specular_colour 0
param_named specular_power float 64
param_named bumpiness float 1
}
}
vertex_program Ogre/HardwareSkinningTwoWeightsShadowCasterCg cg
{
source animatedNormalSpecular.cg
entry_point hardwareSkinningTwoWeightsCaster_vp
//profiles vs_1_1 arbvp1
profiles vs_2_0 arbvp1
includes_skeletal_animation true
}
vertex_program Ogre/HardwareSkinningTwoWeightsShadowCasterGLSL glsl
{
source animatedNormalSpecular.glsl
includes_skeletal_animation true
}
material animatedNormalSpecular
{
technique
{
pass Single Pass
{
vertex_program_ref AnimatedNormalSpecular_VP
{
}
fragment_program_ref AnimatedNormalSpecular_FP
{
}
//shadow_caster_vertex_program_ref HardwareSkinningFourShadow //this part is in the ogre samples somewhere
shadow_caster_vertex_program_ref Ogre/HardwareSkinningTwoWeightsShadowCasterCg
//shadow_caster_vertex_program_ref Ogre/HardwareSkinningTwoWeightsShadowCasterGLSL
{
param_named_auto worldMatrix3x4Array world_matrix_array_3x4
param_named_auto viewProjectionMatrix viewproj_matrix
param_named_auto ambient ambient_light_colour
}
//diffuse map
texture_unit
{
texture_alias DiffuseMap
texture diffuse.tga
filtering linear linear linear
}
//normal map
texture_unit
{
texture_alias NormalMap
texture diffuse_normal.tga
filtering linear linear linear
}
// specular map
texture_unit
{
texture_alias SpecularMap
texture specular.png
}
}
}
}
material ForgeHighQuality: animatedNormalSpecular
{
set_texture_alias DiffuseMap forge_diffuse.tga
set_texture_alias NormalMap forge_normal.tga
set_texture_alias SpecularMap forge_spec.tga
}
animatedNormalSpecular.hlsl
void main_vp(
float4 position : POSITION,
float2 uv : TEXCOORD0,
float3 normal : NORMAL,
float3 tangent : TANGENT0,
float4 blendIdx : BLENDINDICES,
float4 blendWgt : BLENDWEIGHT,
out float4 oPosition : POSITION,
out float2 oUV : TEXCOORD0,
out float3 oLightVector : TEXCOORD1,
out float3 oHalfAngle : TEXCOORD2,
uniform float4x4 worldviewprojmatrix,
uniform float4 light_position,
uniform float4 eye_position,
uniform float3x4 worldMatrix3x4Array[61],
uniform float4x4 viewProjectionMatrix,
uniform float4x4 invworldmatrix
) {
// Calculate the pixel position using the perspective matrix.
oUV = uv;
// transform by indexed matrix
float4 blendPos = float4(0,0,0,0);
int i;
for (i = 0; i < 3; ++i)
{
blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * blendWgt[i];
}
// view / projection
oPosition = mul(viewProjectionMatrix, blendPos);
// transform normal
float3 newnormal = float3(0,0,0);
for (i = 0; i < 3; ++i)
{
newnormal += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], normal) * blendWgt[i];
}
newnormal = mul((float3x3)invworldmatrix, newnormal);
newnormal = normalize(newnormal);
// transform tangent
float3 newtangent = float3(0,0,0);
for (i = 0; i < 3; ++i)
{
newtangent += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], tangent) * blendWgt[i];
}
newtangent = mul((float3x3)invworldmatrix, newtangent);
newtangent = normalize(newtangent);
float3 binormal = cross(newtangent, newnormal);
float3x3 rotation = float3x3(newtangent, binormal, newnormal);
// Calculate the light vector in object space,
// and then transform it into texture space.
float3 temp_lightDir0 = normalize(light_position.xyz - (blendPos * light_position.w));
temp_lightDir0 = normalize(mul(rotation, temp_lightDir0));
oLightVector = temp_lightDir0;
// Calculate the view vector in object space,
// and then transform it into texture space.
float3 eyeDir = normalize(eye_position - blendPos);
eyeDir = normalize(mul(rotation, eyeDir.xyz));
// Calculate the half angle
oHalfAngle = oLightVector + eyeDir;
}
float4 lightDiffuse ;
float4 ambientLight;
float4 specularLight;
float specular_power;
float bumpiness;
sampler base_map;
sampler bump_map;
sampler specular_map;
struct PS_INPUT_STRUCT
{
float2 uv: TEXCOORD0;
float3 light_vector: TEXCOORD1;
float3 half_angle: TEXCOORD2;
};
struct PS_OUTPUT_STRUCT
{
float4 color0: COLOR0;
};
PS_OUTPUT_STRUCT main_fp( PS_INPUT_STRUCT psInStruct )
{
PS_OUTPUT_STRUCT psOutStruct;
float3 base = tex2D( base_map, psInStruct.uv );
float3 bump = tex2D( bump_map, psInStruct.uv );
float specularLevel = tex2D(specular_map, psInStruct.uv).r;
//normalise
float3 normalized_light_vector = normalize( psInStruct.light_vector );
float3 normalized_half_angle = normalize( psInStruct.half_angle );
// "Smooth out" the bump based on the bumpiness parameter.
// This is simply a linear interpolation between a "flat"
// normal and a "bumped" normal. Note that this "flat"
// normal is based on the texture space coordinate basis.
float3 smooth = { 0.5f, 0.5f, 1.0f };
bump = lerp( smooth, bump, bumpiness );
bump = normalize( ( bump * 2.0f ) - 1.0f );
// These dot products are used for the lighting model
// equations. The surface normal dotted with the light
// vector is denoted by n_dot_l. The normal vector
// dotted with the half angle vector is denoted by n_dot_h.
float4 n_dot_l = dot( bump, normalized_light_vector );
float4 n_dot_h = dot( bump, normalized_half_angle );
// Calculate the resulting pixel color,
// based on our lighting model.
// Ambient + Diffuse + Specular
psOutStruct.color0.rgb =
( base * ambientLight) +
( base * lightDiffuse * max( 0, n_dot_l ) ) +
( specularLight * specularLevel * pow( max( 0, n_dot_h ), specular_power ) );
psOutStruct.color0.a = 1.0f; //** Set the alpha component manually
return psOutStruct;
}
animatedNormalSpecular.cg
/*
Two-weight-per-vertex hardware skinning, shadow caster pass
*/
void hardwareSkinningTwoWeightsCaster_vp(
float4 position : POSITION,
float3 normal : NORMAL,
float2 uv : TEXCOORD0,
float4 blendIdx : BLENDINDICES,
float4 blendWgt : BLENDWEIGHT,
out float4 oPosition : POSITION,
out float4 colour : COLOR,
// Support up to 24 bones of float3x4
// vs_1_1 only supports 96 params so more than this is not feasible
uniform float3x4 worldMatrix3x4Array[24],
uniform float4x4 viewProjectionMatrix,
uniform float4 ambient)
{
// transform by indexed matrix
float4 blendPos = float4(0,0,0,0);
int i;
for (i = 0; i < 2; ++i)
{
blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * blendWgt[i];
}
// view / projection
oPosition = mul(viewProjectionMatrix, blendPos);
colour = ambient;
}
animatedNormalSpecular.glsl
// Example GLSL program for skinning with two bone weights per vertex
attribute vec4 vertex;
attribute vec4 uv0;
attribute vec4 blendIndices;
attribute vec4 blendWeights;
// 3x4 matrix, passed as vec4's for compatibility with GL 2.0
// GL 2.0 supports 3x4 matrices
// Support 24 bones ie 24*3, but use 72 since our parser can pick that out for sizing
uniform vec4 worldMatrix3x4Array[72];
uniform mat4 viewProjectionMatrix;
uniform vec4 ambient;
void main()
{
vec3 blendPos = vec3(0,0,0);
for (int bone = 0; bone < 2; ++bone)
{
// perform matrix multiplication manually since no 3x4 matrices
// ATI GLSL compiler can't handle indexing an array within an array so calculate the inner index first
int idx = int(blendIndices[bone]) * 3;
// ATI GLSL compiler can't handle unrolling the loop so do it manually
// ATI GLSL has better performance when mat4 is used rather than using individual dot product
// There is a bug in ATI mat4 constructor (Cat 7.2) when indexed uniform array elements are used as vec4 parameter so manually assign
mat4 worldMatrix;
worldMatrix[0] = worldMatrix3x4Array[idx];
worldMatrix[1] = worldMatrix3x4Array[idx + 1];
worldMatrix[2] = worldMatrix3x4Array[idx + 2];
worldMatrix[3] = vec4(0);
// now weight this into final
blendPos += (vertex * worldMatrix).xyz * blendWeights[bone];
}
// apply view / projection to position
gl_Position = viewProjectionMatrix * vec4(blendPos, 1);
gl_FrontSecondaryColor = vec4(0,0,0,0);
gl_FrontColor = ambient;
gl_TexCoord[0] = uv0;
}
hlsl for the vp/fp and cg for the shadows. As you can see i tried changing the shadows to glsl but I get the same results.