/****************************************************************************** HLSL Normal Mapping Shader Copyright 2006 Mark Sararu This file is part of the Renegade scripts.dll The Renegade scripts.dll is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. See the file COPYING for more details. In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence. Only the source code to the module(s) containing the licenced code has to be released. Also, applying this shader to an object does not cause the licence of this file to apply to any other shaders in the game world. This shader requires hardware support for DirectX 9. ******************************************************************************/ float4 light1Direction: Light1Direction < > = {0.0f, 0.0f, 0.0f, 0.0f}; float4 light1Color: Light1Diffuse < > = {0.2f, 0.2f, 0.2f, 1.0f}; float4 light1SpecularColor: Light1Specular < string UIName = "Surface Specular"; > = {0.4f, 0.4f, 0.4f, 1.0f}; float light1SpecExpon: Light1SpecularPower < string UIWidget = "slider"; float UIMin = 1.0; float UIMax = 128.0; float UIStep = 1.0; string UIName = "Specular Power"; > = 60.0; float4 ambiColor: AmbientColor < string UIName = "Ambient Light Color"; > = {-0.1f, -0.1f, -0.1f, 1.0f}; float4 surfColor: SurfaceColor < string UIName = "Surface Color"; > = {1.0f, 1.0f, 1.0f, 1.0f}; texture txDiffuseMap: TextureColor; texture txNormalMap: TextureNormal; sampler2D samDiffuseMap = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; AddressU = Wrap; AddressV = Wrap; }; sampler2D samNormalMap = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; AddressU = Wrap; AddressV = Wrap; }; float4x4 mWorld: World; float4x4 mViewInverse: ViewInverse; float4x4 mWorldInverseTranspose: WorldInverseTranspose; float4x4 mWorldViewProjection: WorldViewProjection; struct VS_INPUT { float4 Position : POSITION; float3 Normal : NORMAL; float2 TexCoord0 : TEXCOORD0; float3 Tangent : TANGENT; //float3 Binormal : BINORMAL; }; struct VS_INPUT_TERRAIN { float4 Position : POSITION; float4 Diffuse : COLOR0; float3 Normal : NORMAL; float2 TexCoord0 : TEXCOORD0; float3 Tangent : TANGENT; //float3 Binormal : BINORMAL; }; struct VS_OUTPUT { float4 Position : POSITION; float4 Diffuse : COLOR0; float2 TexCoord0 : TEXCOORD0; float3 worldNormal : TEXCOORD1; float3 worldTangent : TEXCOORD2; float3 worldBinormal : TEXCOORD3; float3 EyeVec : TEXCOORD4; float FogFactor : TEXCOORD5; }; #define FOGMODE_NONE 0 #define FOGMODE_EXP 1 #define FOGMODE_EXP2 1 #define FOGMODE_LINEAR 3 #define E 2.71828 int g_FogMode : FogMode = 0; float g_FogStart : FogStart = 50.0f; float g_FogEnd : FogEnd = 100.0f; float g_FogDensity : FogDensity = 0.0f; float4 g_FogColor : FogColor = {0.3f,0.3f,0.3f,1.0f}; float CalcFogFactor(float d) { float fogCoeff = 1.0; if(g_FogMode == FOGMODE_LINEAR) { fogCoeff = (g_FogEnd - d)/(g_FogEnd - g_FogStart); } else if(g_FogMode == FOGMODE_EXP) { fogCoeff = 1.0 / pow(E, d*g_FogDensity); } else if(g_FogMode == FOGMODE_EXP2) { fogCoeff = 1.0 / pow(E, d*d*g_FogDensity*g_FogDensity); } return clamp(fogCoeff, 0, 1); } float4 CalculateFog(float4 inputColor, float depth) { float fogFactor = CalcFogFactor(depth); return fogFactor * inputColor + (1.0 - fogFactor) * g_FogColor; } VS_OUTPUT VS_NormalMapping(VS_INPUT In) { VS_OUTPUT Out; Out.Position = mul(In.Position,mWorldViewProjection); Out.worldNormal = mul(In.Normal,mWorldInverseTranspose).xyz; Out.worldTangent = mul(In.Tangent,mWorldInverseTranspose).xyz; Out.worldBinormal = cross(Out.worldNormal,Out.worldTangent).xyz; Out.TexCoord0 = In.TexCoord0; float3 worldEyePos = mViewInverse[3].xyz; float3 worldVertPos = mul(In.Position, mWorld).xyz; Out.EyeVec = mViewInverse[3].xyz - worldVertPos; //eye vector Out.Diffuse = surfColor; Out.FogFactor = Out.Position.w; return Out; } VS_OUTPUT VS_NormalMapping_Terrain(VS_INPUT_TERRAIN In) { VS_OUTPUT Out; Out.Position = mul(In.Position,mWorldViewProjection); Out.worldNormal = mul(In.Normal,mWorldInverseTranspose).xyz; Out.worldTangent = mul(In.Tangent,mWorldInverseTranspose).xyz; Out.worldBinormal = cross(Out.worldNormal,Out.worldTangent).xyz; Out.TexCoord0 = In.TexCoord0; float3 worldEyePos = mViewInverse[3].xyz; float3 worldVertPos = mul(In.Position, mWorld).xyz; Out.EyeVec = mViewInverse[3].xyz - worldVertPos; //eye vector Out.Diffuse = In.Diffuse; Out.FogFactor = Out.Position.w; return Out; } float4 blinn(float3 N,float3 L,float3 V,uniform float4 diffuseColor,uniform float4 specularColor, uniform float shininess) { float3 H = normalize(V+L); float4 lighting = lit(dot(L,N), dot(H,N), shininess); return diffuseColor*lighting.y + specularColor*lighting.z; } float4 diffuse(float3 N,float3 L,uniform float4 diffuseColor) { return diffuseColor*dot(L,N); } float4 PS_NormalMapping(VS_OUTPUT In, uniform float3 lightDirection, uniform float4 lightColor): COLOR { float3 normal = tex2D(samNormalMap, In.TexCoord0.xy).xyz * 2.0 - 1.0; float4 color = tex2D(samDiffuseMap, In.TexCoord0.xy); float3 N = (In.worldNormal * normal.z) + (normal.x * In.worldBinormal) + (normal.y * In.worldTangent); N = normalize(N); float3 L = normalize(lightDirection); float4 output = ambiColor * color; output += lightColor * diffuse(N, L,color*In.Diffuse); output.a = color.a * In.Diffuse.a; return CalculateFog(output,In.FogFactor); } float4 PS_NormalMapping_Spec(VS_OUTPUT In, uniform float3 lightDirection, uniform float4 lightColor, uniform float4 specularColor, uniform float specularExponent): COLOR { float3 normal = tex2D(samNormalMap, In.TexCoord0.xy).xyz * 2.0 - 1.0; float4 color = tex2D(samDiffuseMap, In.TexCoord0.xy); float3 N = (In.worldNormal * normal.z) + (normal.x * In.worldBinormal) + (normal.y * In.worldTangent); N = normalize(N); float3 V = normalize(In.EyeVec); float3 L = normalize(lightDirection); float4 output = ambiColor * color; output += lightColor * blinn(N, L, V, color*In.Diffuse, specularColor*color.a, specularExponent); output.a = color.a * In.Diffuse.a; return CalculateFog(output,In.FogFactor); } technique NormalMapping { pass Light1 { VertexShader = compile vs_2_0 VS_NormalMapping(); PixelShader = compile ps_2_0 PS_NormalMapping(light1Direction,light1Color); } } technique NormalMapping_Terrain { pass Light1 { VertexShader = compile vs_2_0 VS_NormalMapping_Terrain(); PixelShader = compile ps_2_0 PS_NormalMapping(light1Direction,light1Color); } } technique NormalMapping_Spec { pass Light1 { VertexShader = compile vs_2_0 VS_NormalMapping(); PixelShader = compile ps_2_0 PS_NormalMapping_Spec(light1Direction,light1Color,light1SpecularColor,light1SpecExpon); } } technique NormalMapping_Spec_Terrain { pass Light1 { VertexShader = compile vs_2_0 VS_NormalMapping_Terrain(); PixelShader = compile ps_2_0 PS_NormalMapping_Spec(light1Direction,light1Color,light1SpecularColor,light1SpecExpon); } }