float4x4 WorldViewProj : WorldViewProjection; float4x4 WorldInvTrans : WorldInverseTranspose; float4x4 WorldX : World; float4x4 viewIX : ViewInverse; float4x4 viewX : View; float3 cameraPos : WORLDCAMERAPOSITION; struct appData { float4 position : POSITION; float4 color : COLOR0; float4 UV0 : TEXCOORD0; float4 tangent : TANGENT; float4 binormal : BINORMAL; float3 normal : NORMAL; }; struct vertexOutput { float4 position : POSITION; float4 color : COLOR0; float4 UV0 : TEXCOORD0; float4 wpos : TEXCOORD1; float3 normal : TEXCOORD2; float3 tangent : TEXCOORD3; float3 binormal : TEXCOORD4; float3 eyeDir : TEXCOORD5; }; struct pointLight { float3 position; float3 direction; float3 diffuseColor; float diffuseIntensity; float3 specularColor; float specularIntensity; float falloff; }; struct rimLight { float3 direction; float range; }; struct lightingOutput { float4 Diffuse; float4 Specular; }; /////////////////// ///TWEAKABLES /////////////////// float3 lightPosition : POSITION < string UIName = "Light(defaults to 0,0,0)"; string Object = "Omni01"; string Space = "World" ; int RefID = 0; > = {0,0,0}; float4 lightColor : LightColor < int LightRef = 0; > = float4(1.0f, 1.0f, 1.0f, 1.0f); bool attenDistance < string UIName =" Attenuate Distance"; > = false; float lightFalloff < string UIName=" Falloff Distnace"; float UIMin = 0; float UIMax = 10000.0; float UIStep = 0.01; > = 100.0; float4 AmbientColor < string UIName = "Ambient Color"; > = float4(0.3f,0.3f,0.3f,1.0f); float4 AmbientIntensity < string UIName = "Ambient Intensity"; > = float4(0,0,0,0); // Boring o'l Diffuse texture diffuseTex < string UIName = "Diffuse Texture"; >; // Ramp Texture texture rampTex < string UIName = "Ramp Texture"; >; bool smoothRamp = false; // Specular Texture stuff bool useSpecTex = false; texture specularTex < string UIName = " Specular texture"; >; int specularHardness < string UIName = " Specular hardness"; int UIMin = 0; int UIMax = 100; int UIStep = 1; > = 32; // Normal Texture Stuff bool useNormalMap = false; texture normalTex < string UIName = " Normal Map"; >; bool swapRG = false; bool flipR = false; bool flipG = false; // Rim Light Settings. bool doRimLight = false; bool rimLight_top = false; float3 rimLightColor = float3(1,1,1); float rimLightIntensity = 1.0; float rimLightSize = 0.5; /////////////////// ///SAMPLERS /////////////////// sampler s_diffuseTex = sampler_state { texture = ; }; sampler s_specularTex = sampler_state { texture = ; }; sampler s_normalTex = sampler_state { texture = ; }; sampler s_rampTex = sampler_state { texture = ; AddressU = Clamp; AddressV = Clamp; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; }; /////////////////// ///Lighting functions /////////////////// float3 rimLighting(rimLight lightdata, float3 normal, float3 color) { // transform the normal to view space float3 curNormal = mul(normal, viewX); // the rim light is the one-minus a light directly cast upon the view vector. float NdotV = clamp(1 - dot(lightdata.direction, curNormal) - (1 - rimLightSize), 0.0, 1); // add the rim light to the base color; color += NdotV * (rimLightColor * rimLightIntensity); return color; } lightingOutput blinnPhong(pointLight theLight, float3 pos3D, float3 eyeDir, float3 normal) { // initialize output struct lightingOutput lighting_out; // determine light position data. float3 lightDir = theLight.position - pos3D; float distance = length(lightDir); lightDir = normalize(lightDir); // diffuse attenuation float i = clamp(dot(lightDir, normal), 0, 1); if (attenDistance) { lighting_out.Diffuse.a = i / (distance/theLight.falloff); lighting_out.Diffuse.rgb = (i * theLight.diffuseColor * theLight.diffuseIntensity) / (distance/theLight.falloff); } else { lighting_out.Diffuse.a = i; lighting_out.Diffuse.rgb = (i * theLight.diffuseColor * theLight.diffuseIntensity); } // specular section float3 halfVector = normalize(lightDir + eyeDir); //specular attenuation. i = pow(clamp(dot(normal, halfVector), 0, 1), specularHardness); if (attenDistance) { lighting_out.Specular.a = i / (distance/theLight.falloff); lighting_out.Specular.rgb = i * (theLight.specularColor * theLight.specularIntensity) / (distance/theLight.falloff); } else { lighting_out.Specular.a = i; lighting_out.Specular.rgb = i * (theLight.specularColor * theLight.specularIntensity); } return lighting_out; } /////////////////// ///Vert Shader /////////////////// vertexOutput vertShader(appData in_appData) { vertexOutput vertex_output; vertex_output.position = mul(in_appData.position, WorldViewProj); vertex_output.wpos = mul(in_appData.position, WorldX); vertex_output.color = AmbientColor * AmbientIntensity; vertex_output.normal = in_appData.normal; vertex_output.tangent = in_appData.tangent; vertex_output.binormal = in_appData.binormal; vertex_output.UV0 = in_appData.UV0; vertex_output.eyeDir = normalize(viewIX[3].xyz - vertex_output.wpos); vertex_output.color.a = 1; return vertex_output; } /////////////////// ///Pixel Shader /////////////////// float4 pixShader(vertexOutput vert_in) : COLOR0 { float4 outputColor; // build our tan to worldspace matrix for normals. float3x3 tanToWorldSpace; tanToWorldSpace[0].xyz = normalize(mul(vert_in.binormal, (float3x3)WorldX)); tanToWorldSpace[1].xyz = normalize(mul(-vert_in.tangent, (float3x3)WorldX)); tanToWorldSpace[2].xyz = normalize(mul(vert_in.normal, (float3x3)WorldX)); float3 curNormal; if (useNormalMap ) { float3 normalTex = tex2D(s_normalTex, vert_in.UV0); if (swapRG) normalTex.rg = float2(normalTex.g, normalTex.r); if (flipR) normalTex.r = 1 - normalTex.r; if (flipG) normalTex.g = 1 - normalTex.g; curNormal = mul((normalTex * 2 - 1), tanToWorldSpace); } else { curNormal = mul(float3(0.5, 0.5, 1) * 2 - 1, tanToWorldSpace); } // just create a generic light from our struct. pointLight aLight; aLight.position = lightPosition; aLight.direction = float3 (0, -1, 0); // not used //aLight.diffuseColor = float3(1,1,1); aLight.diffuseColor = lightColor.rgb; aLight.diffuseIntensity = lightColor.a; aLight.specularColor = lightColor.rgb; aLight.specularIntensity = 1.0f; aLight.falloff = lightFalloff; // initialize lighting output struct. lightingOutput bp_lighting; // do blinn phong lighting. bp_lighting = blinnPhong(aLight, vert_in.wpos, vert_in.eyeDir, curNormal); float3 difRampTex = tex2D(s_rampTex, bp_lighting.Diffuse.a); // take a few offset samples of the ramp texture to average out the slope. usefull for low-resolution ramp textures. if (smoothRamp) { float3 sample1 = tex2D(s_rampTex, bp_lighting.Diffuse.a + 0.05); float3 sample2 = tex2D(s_rampTex, bp_lighting.Diffuse.a - 0.05); difRampTex += sample1 + sample2; difRampTex /= 3; } outputColor.rgb = (vert_in.color + bp_lighting.Diffuse.rgb) * (tex2D(s_diffuseTex, vert_in.UV0) * difRampTex); outputColor.rgb = tex2D(s_diffuseTex, vert_in.UV0) * difRampTex; // modulate the specular amount by the texture if we're using one. if (useSpecTex) outputColor.rgb += bp_lighting.Specular.rgb * tex2D(s_specularTex, vert_in.UV0); else outputColor.rgb = saturate(outputColor.rgb + bp_lighting.Specular.rgb); // add in the rimlight, that is, if we're using one. if (doRimLight) { rimLight rl; rl.direction = float3(0,0,-1); rl.range = .4; if (rimLight_top) rl.direction = float3(0,-.5,-1); outputColor.rgb = rimLighting(rl, curNormal, outputColor); } // simplicity's sake, alpha = 1; outputColor.a = 1; return outputColor; } technique rampshader { pass p0 { CullMode = None; VertexShader = compile vs_3_0 vertShader(); PixelShader = compile ps_3_0 pixShader(); AlphaBlendEnable = false; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; } }