//======================================================================================// // filename: FixedFuncShader.fx // // // // author: Pedro V. Sander // // ATI Research, Inc. // // 3D Application Research Group // // email: psander@ati.com // // // // Description: A programmable shader that emulates the fixed function pipeline // // hg Modified & optimized // // //======================================================================================// // (C) 2003 ATI Research, Inc. All rights reserved. // //======================================================================================// #define PI 3.14f #define LIGHT_TYPE_NONE 0 #define LIGHT_TYPE_POINT 1 #define LIGHT_TYPE_SPOT 2 #define LIGHT_TYPE_DIRECTIONAL 3 #define LIGHT_NUM_TYPES 4 #define FOG_TYPE_NONE 0 #define FOG_TYPE_EXP 1 #define FOG_TYPE_EXP2 2 #define FOG_TYPE_LINEAR 3 #define FOG_NUM_TYPES 4 #define TEX_TYPE_NONE 0 #define TEX_TYPE_CUBEMAP 1 #define TEX_NUM_TYPES 2 #define TEXGEN_TYPE_NONE 0 #define TEXGEN_TYPE_CAMERASPACENORMAL 1 #define TEXGEN_TYPE_CAMERASPACEPOSITION 2 #define TEXGEN_TYPE_CAMERASPACEREFLECTIONVECTOR 3 #define TEXGEN_NUM_TYPES 4 // Structs and variables with default values float4 vMaterialColor = float4(128.f/255.f, 128.f/255.f, 128.f/255.f, 1.f); float fMaterialPower = 16.f; float4 vAmbientColor = float4(0.f/255.f, 0.f/255.f, 0.f/255.f, 1.f); static const bool bSpecular : register(b0) = false; static const bool bTweening = false; static const bool bAtten = false;// hg do we need atten ? static const float fTweenFactor = 0.f; //fog settings static const int iFogType = FOG_TYPE_NONE; static const float4 vFogColor = float4(0.0f, 0.0f, 0.0f, 0.0f); static const float fFogStart = 10.f; static const float fFogEnd = 25.f; static const float fFogDensity = .02f; static const bool bFogRange = false; static const int iTexType = TEX_TYPE_NONE; static const int iTexGenType = TEXGEN_TYPE_NONE; struct CLight { int iType; float3 vPos; float3 vDir; float4 vAmbient; float4 vDiffuse; float4 vSpecular; float fRange; float3 vAttenuation; //1, D, D^2; float3 vSpot; //cos(theta/2), cos(phi/2), falloff }; #if 1 // angusface #define NUM_LIGHTS 3 //initial and range of directional, point and spot lights within the light array static const int iLightDirIni=0; static const int iLightDirNum=0; static const int iLightPointIni=0; static const int iLightPointNum=3; static const int iLightSpotIni=0; static const int iLightSpotNum=0; static const CLight lights[5] = { //NUM_LIGHTS == 5 { LIGHT_TYPE_POINT, //type float3(1278.48, 0, -372.605), //position float3(2.0f,-3.0f, 4.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(0.953, 0.604, 0.533, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 2000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) }, { LIGHT_TYPE_POINT, //type float3(-359.253, 0, 330.632), //position float3(-20.0f,-30.0f, -40.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(0.824, 0.878, 0.898, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 2000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) }, { LIGHT_TYPE_POINT, //type float3(399.419, 0, 327.643), //position float3(0.0f, 0.0f, 0.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(0.941, 0.537, 0.318, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 2000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) }, { LIGHT_TYPE_NONE, //type float3(20.0f, 30.0f, 40.0f), //position float3(0.0f, 0.0f, 0.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(1.0f, 1.0f, 1.0f, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 1000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) }, { LIGHT_TYPE_NONE, //type float3(20.0f, 30.0f, 40.0f), //position float3(0.0f, 0.0f, 0.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(1.0f, 1.0f, 1.0f, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 1000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) } }; #else #define NUM_LIGHTS 2 //initial and range of directional, point and spot lights within the light array static const int iLightDirIni=0; static const int iLightDirNum=1; static const int iLightPointIni=0; static const int iLightPointNum=0; static const int iLightSpotIni=0; static const int iLightSpotNum=0; static const CLight lights[5] = { //NUM_LIGHTS == 5 { LIGHT_TYPE_DIRECTIONAL, //type float3(0.0f, 0.0f, 0.0f), //position float3(2.0f,-3.0f, 4.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(1.0f, 1.0f, 1.0f, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 1000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) }, { LIGHT_TYPE_NONE, //type float3(20.0f, 30.0f, 40.0f), //position float3(-20.0f,-30.0f, -40.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(1.0f, 1.0f, 1.0f, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 1000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) }, { LIGHT_TYPE_NONE, //type float3(20.0f, 30.0f, 40.0f), //position float3(0.0f, 0.0f, 0.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(1.0f, 1.0f, 1.0f, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 1000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) }, { LIGHT_TYPE_NONE, //type float3(20.0f, 30.0f, 40.0f), //position float3(0.0f, 0.0f, 0.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(1.0f, 1.0f, 1.0f, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 1000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) }, { LIGHT_TYPE_NONE, //type float3(20.0f, 30.0f, 40.0f), //position float3(0.0f, 0.0f, 0.0f), //direction float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(1.0f, 1.0f, 1.0f, 1.0f), //diffuse float4(1.0f, 1.0f, 1.0f, 1.0f), //specular 1000.f, //range float3(1.f, 0.f, 0.f), //attenuation float3(.999f, .996f, 1) //spot (theta=PI/50, phi=PI/20) } }; #endif //transformation matrices float4x4 matWorldViewProj : WORLDVIEWPROJECTIONTRANSPOSE; float4x4 matWorldView : WORLDVIEWTRANSPOSE; float4x4 matWorld : WORLDTRANSPOSE; float4x4 matWorldViewIT :viewinverse; // transpose; float4x4 matViewIT : worldviewinverse; // transpose; //function output structures struct VS_OUTPUT { float4 Pos : POSITION; float4 Color : COLOR0; float4 ColorSpec : COLOR1; float4 Tex0 : TEXCOORD0; float Fog : FOG; }; struct COLOR_PAIR { float4 Color : COLOR0; float4 ColorSpec : COLOR1; }; //----------------------------------------------------------------------------- // Name: DoDirLight() // Desc: Directional light computation //----------------------------------------------------------------------------- COLOR_PAIR DoDirLight(float3 N, float3 V, int i) { COLOR_PAIR Out; float3 L = mul((float3x3)matViewIT, -normalize(lights[i].vDir)); float NdotL = dot(N, L); Out.Color = lights[i].vAmbient; Out.ColorSpec = 0; if(NdotL > 0.f) { //compute diffuse color Out.Color += NdotL * lights[i].vDiffuse; //add specular component if(bSpecular) { float3 H = normalize(L + V); //half vector Out.ColorSpec = pow(max(0, dot(H, N)), fMaterialPower) * lights[i].vSpecular; } } return Out; } //----------------------------------------------------------------------------- // Name: DoPointLight() // Desc: Point light computation //----------------------------------------------------------------------------- COLOR_PAIR DoPointLight(float4 vPosition, float3 N, float3 V, int i) { float3 L = mul((float3x3)matViewIT, normalize((lights[i].vPos-(float3)mul(matWorld,vPosition)))); COLOR_PAIR Out; float NdotL = dot(N, L); Out.Color = lights[i].vAmbient; Out.ColorSpec = 0; float fAtten = 1.f; if(NdotL >= 0.f) { //compute diffuse color Out.Color += NdotL * lights[i].vDiffuse; //add specular component if(bSpecular) { float3 H = normalize(L + V); //half vector Out.ColorSpec = pow(max(0, dot(H, N)), fMaterialPower) * lights[i].vSpecular; } if (bAtten) // hg do we need atten ? { float LD = length(lights[i].vPos-(float3)mul(matWorld,vPosition)); if(LD > lights[i].fRange) { fAtten = 0.f; } else { fAtten *= 1.f/(lights[i].vAttenuation.x + lights[i].vAttenuation.y*LD + lights[i].vAttenuation.z*LD*LD); } Out.Color *= fAtten; Out.ColorSpec *= fAtten; } } return Out; } //----------------------------------------------------------------------------- // Name: DoSpotLight() // Desc: Spot light computation //----------------------------------------------------------------------------- COLOR_PAIR DoSpotLight(float4 vPosition, float3 N, float3 V, int i) { float3 L = mul((float3x3)matViewIT, normalize((lights[i].vPos-(float3)mul(matWorld,vPosition)))); COLOR_PAIR Out; float NdotL = dot(N, L); Out.Color = lights[i].vAmbient; Out.ColorSpec = 0; float fAttenSpot = 1.f; if(NdotL >= 0.f) { //compute diffuse color Out.Color += NdotL * lights[i].vDiffuse; //add specular component if(bSpecular) { float3 H = normalize(L + V); //half vector Out.ColorSpec = pow(max(0, dot(H, N)), fMaterialPower) * lights[i].vSpecular; } if (bAtten) // hg do we need atten ? { float LD = length(lights[i].vPos-(float3)mul(matWorld,vPosition)); if(LD > lights[i].fRange) { fAttenSpot = 0.f; } else { fAttenSpot *= 1.f/(lights[i].vAttenuation.x + lights[i].vAttenuation.y*LD + lights[i].vAttenuation.z*LD*LD); } } //spot cone computation float3 L2 = mul((float3x3)matViewIT, -normalize(lights[i].vDir)); float rho = dot(L, L2); fAttenSpot *= pow(saturate((rho - lights[i].vSpot.y)/(lights[i].vSpot.x - lights[i].vSpot.y)), lights[i].vSpot.z); Out.Color *= fAttenSpot; Out.ColorSpec *= fAttenSpot; } return Out; } //----------------------------------------------------------------------------- // Name: vs_main() // Desc: The vertex shader //----------------------------------------------------------------------------- VS_OUTPUT vs_main (float4 vPosition : POSITION0, float4 vPosition2 : POSITION1, float3 vNormal : NORMAL0, float3 vNormal2 : NORMAL1, float2 tc : TEXCOORD0) { VS_OUTPUT Out = (VS_OUTPUT) 0; if(bTweening) { vPosition = (1.f-fTweenFactor) * vPosition + fTweenFactor * vPosition2; vNormal = (1.f-fTweenFactor) * normalize(vNormal) + fTweenFactor * normalize(vNormal2); } vNormal = normalize(vNormal); Out.Pos = mul(matWorldViewProj, vPosition); float3 P = mul(matWorldView, vPosition); //position in view space float3 N = mul((float3x3)matWorldViewIT, vNormal); //normal in view space float3 V = -normalize(P); //viewer //automatic texture coordinate generation Out.Tex0 = float4((2.f * dot(V,N) * N - V) * (iTexGenType == TEXGEN_TYPE_CAMERASPACEREFLECTIONVECTOR) + N * (iTexGenType == TEXGEN_TYPE_CAMERASPACENORMAL) + P * (iTexGenType == TEXGEN_TYPE_CAMERASPACEPOSITION), 0); Out.Tex0.xy += tc * (iTexGenType == TEXGEN_TYPE_NONE); //light computation Out.Color = vAmbientColor; Out.ColorSpec = 0; //directional lights for(int i = 0; i < iLightDirNum; i++) { COLOR_PAIR ColOut = DoDirLight(N, V, i+iLightDirIni); Out.Color += ColOut.Color; Out.ColorSpec += ColOut.ColorSpec; } //point lights for(int i = 0; i < iLightPointNum; i++) { COLOR_PAIR ColOut = DoPointLight(vPosition, N, V, i+iLightPointIni); Out.Color += ColOut.Color; Out.ColorSpec += ColOut.ColorSpec; } //spot lights for(int i = 0; i < iLightSpotNum; i++) { COLOR_PAIR ColOut = DoSpotLight(vPosition, N, V, i+iLightSpotIni); Out.Color += ColOut.Color; Out.ColorSpec += ColOut.ColorSpec; } //apply material color Out.Color *= vMaterialColor; Out.ColorSpec *= vMaterialColor; //saturate Out.Color = min(1, Out.Color); Out.ColorSpec = min(1, Out.ColorSpec); //apply fog float d; if(bFogRange) d = length(P); else d = P.z; Out.Fog = 1.f * (iFogType == FOG_TYPE_NONE) + 1.f/exp(d * fFogDensity) * (iFogType == FOG_TYPE_EXP) + 1.f/exp(pow(d * fFogDensity, 2)) * (iFogType == FOG_TYPE_EXP2) + saturate((fFogEnd - d)/(fFogEnd - fFogStart)) * (iFogType == FOG_TYPE_LINEAR); return Out; } // Techniques //the technique for the programmable shader (simply sets the vertex shader) technique basic_with_shader { pass P0 { SPECULARENABLE = (bSpecular); FOGENABLE = (iFogType != FOG_TYPE_NONE); FOGCOLOR = (vFogColor); VertexShader = compile vs_2_0 vs_main(); } } //the technique to set the state for the fixed function shader technique noShader { pass P0 { AMBIENT = (vAmbientColor); SPECULARENABLE = (bSpecular); FOGENABLE = (iFogType != FOG_TYPE_NONE); FOGCOLOR = (vFogColor); } }