/****************************************************************************** HLSL Eye Shader by Rob Galanakis robg@robg3d.com www.robg3d.com The metal shader simulates reflective metals. It has a 24-bit specular map, dual specular highlights (one tight and saturated, one broad and duller), and a mask for reflection (shinier areas get non-blurry reflections). Despite the number of maps required, this is a relatively cheap shader. diffuseLight Texture: This is your color texture, it should be mostly void of lighting detail. It holds an ambient occlusion map in the alpha. norm Texture: This is a norm map. specularRefl Texture: This is the 24-bit specular. It should be quite saturated in color. The alpha holds the reflection mask, where lighter tones correspond to higher reflectivity. ambCube Texture: This is a diffusely convolved cube map, for ambient lighting. reflCube Texture: This a "regular" cube map, for reflections in the ambient lighting pass. specColor: This is the color of the specular highlights. ******************************************************************************/ sampler2D normalSampler : register(s0); sampler2D specReflSampler : register(s1); sampler2D diffuseLightSampler : register(s2); samplerCUBE ambCubeSampler : register(s3); samplerCUBE reflCubeSampler : register(s4); /////Tweakables///////////// //controls the level of ambient/reflection cube blending float envBlendFactor; //shininess of the inner highlight float glossInner; //shininess of the outer highlight float glossOuter; //multiplier for specular Texture float specMultInner; float specMultOuter; //Controls how much diffuse lighting there is (1 is none at all) float diffuseFactor; /************** light info **************/ float4 ambColor; float4 light0Color; float4 light1Color; float4 light2Color; //---------------------------------- float4x4 wvp; float4x4 world; float4x4 worldIT; // input from application struct a2v { float4 pos : POSITION; float2 texCoord : TEXCOORD0; float3 tan : TANGENT; float3 binorm : BINORMAL; float3 norm : NORMAL; }; // output to fragment program struct v2f { float4 pos : POSITION; float2 texCoord : TEXCOORD0; float3 eyeVec : TEXCOORD1; float3 worldNormal : TEXCOORD2; float3 worldTangent : TEXCOORD3; float3 worldBinormal : TEXCOORD4; float3 lightVec0 : TEXCOORD5; float3 lightVec1 : TEXCOORD6; float3 lightVec2 : TEXCOORD7; }; ////////////Ambient Pass/////////////////////////// //Ambient and Self-Illum Pass Vertex Shader v2f av(a2v In, uniform float3 eyePosition) { v2f Out = (v2f)0; //zero out the shader Out.pos = mul(wvp, In.pos); //transform vert pos to homogeneous clip space float3 worldSpacePos = mul(world, In.pos); //world space pos of vertex //Out.eyeVec = viewInv[3] - worldSpacePos; //get the eye vector Out.eyeVec = eyePosition; Out.texCoord.xy = In.texCoord.xy; //Pass through texture coordinates Out.worldNormal = mul(worldIT, float4(In.norm,0.0f)).xyz; //compute world space norm Out.worldBinormal = mul(worldIT, float4(In.binorm,0.0f)).xyz; //compute world space binorm Out.worldTangent = mul(worldIT, float4(In.tan,0.0f)).xyz; //compute world space tan return Out; } //Ambient and Self-Illum Pass Pixel Shader float4 af(v2f In, uniform float4 lightColor) : COLOR { float4 diffuseLightTexture = tex2D(diffuseLightSampler, In.texCoord.xy); float4 specReflTexture = tex2D(specReflSampler, In.texCoord.xy); float4 normalTexture = tex2D(normalSampler, In.texCoord.xy); normalTexture = normalTexture * 2 - 1; //expand to -1 to 1 range float3 Nn = normalize(In.worldNormal); //input the vectors required for tan to world space transform float3 Tn = normalize(In.worldTangent); float3 Bn = normalize(In.worldBinormal); float3 E = normalize(In.eyeVec); //Normalize the eye vector //Perform the tan to world space transformation normalTexture = float4((Nn * normalTexture.z) + (normalTexture.x * Tn + normalTexture.y * -Bn), normalTexture.w); //create a per-pixel norm for Y up float3 N = normalize(normalTexture.rgb); //normalized the norm vector E = -E; //negate eye vector for proper reflections float3 reflVector = reflect(E, N); //Compute the reflection vector float envBlend = pow(specReflTexture.a, envBlendFactor); float3 normalReflection = lerp(N, reflVector, envBlend); float4 ambCubeTexture = texCUBE(ambCubeSampler, normalReflection.xyz); float4 reflCubeTexture = texCUBE(reflCubeSampler, normalReflection.xyz); float3 blendedCubes = lerp(ambCubeTexture.rgb, reflCubeTexture.rgb, envBlend); float3 cubeTexAmb = blendedCubes * ambColor * diffuseLightTexture.rgb * diffuseLightTexture.a; float4 ret = float4(cubeTexAmb, 1); return ret; } ////////////Light (Multi) Pass/////////////////////////// //Multi-pass vertex shader v2f v(a2v In, uniform float3 eyePosition, uniform float3 lightPosition0) { v2f Out = (v2f)0; Out.pos = mul(wvp, In.pos); //transform vert pos to homogeneous clip space Out.texCoord = In.texCoord; //pass through UV coordinates float3 worldSpacePos = mul(world, In.pos); //world space pos of vertex Out.lightVec0 = lightPosition0; //world space light vector (from light, to vertex pos) //Out.eyeVec = viewInv[3] - worldSpacePos; //eye vector in world space (from eye, to vertex pos) Out.eyeVec = eyePosition; Out.worldNormal = mul(worldIT, float4(In.norm,0.0f)).xyz; //compute world space norm Out.worldBinormal = mul(worldIT, float4(In.binorm,0.0f)).xyz; //compute world space binorm Out.worldTangent = mul(worldIT, float4(In.tan,0.0f)).xyz; //compute world space tan Out.worldNormal = mul(In.norm, world).xyz; //compute world space norm by multiplying norm with world matrix return Out; } //Multi-Pass Pixel Shader float4 f(v2f In, uniform float4 lightColor ) : COLOR { //texture declarations float4 diffuseLightTexture = tex2D(diffuseLightSampler, In.texCoord.xy); float4 specReflTexture = tex2D(specReflSampler, In.texCoord.xy); float4 normalTexture = tex2D(normalSampler, In.texCoord.xy); float3 L = normalize(In.lightVec0.xyz); //normalized light vector float3 E = normalize(In.eyeVec.xyz); //normalized eye vector float3 H = normalize(L + E); //Normalized half angle vector //input the vectors required for tan to world space transform float3 Nn = In.worldNormal; float3 Tn = In.worldTangent; float3 Bn = In.worldBinormal; //figure out N (norm) normalTexture = normalTexture * 2 - 1; //expand to -1, 1 normalTexture = float4((Nn * normalTexture.z) + (normalTexture.x * Tn + normalTexture.y * -Bn), 1.0); float3 N = normalize(normalTexture.rgb); //overlay detail texture //diffuse calculations float NdotL = dot(N, L); float NdotLmod = saturate(NdotL - diffuseFactor); float3 diffuseComp = diffuseLightTexture.rgb * NdotLmod; //specular calculations float NdotH = saturate(dot(N, H)); float specularLevelInner = pow(NdotH, glossInner); float3 specInner = specularLevelInner * specMultInner * specReflTexture.rgb; float specularLevelOuter = pow(NdotH, glossOuter); float3 specOuter = specularLevelOuter * specMultOuter * diffuseLightTexture.rgb; float3 specComp = (specInner + specOuter) * specularLevelOuter; //lightTexture and final addition float3 diffuseSpec = diffuseComp + specComp; float3 diffuseSpecLight = diffuseSpec * light0Color * diffuseLightTexture.a; float4 ret = float4(diffuseSpecLight.xyz, 1); //Sets w value of the float4 to 1 (a float 4 must be the output of the pixel shader) return ret; } ////////////Light (Multi) Pass/////////////////////////// //Multi-pass vertex shader v2f v3(a2v In, uniform float3 eyePosition, uniform float3 lightPosition0, uniform float3 lightPosition1, uniform float3 lightPosition2) { v2f Out = (v2f)0; Out.pos = mul(wvp, In.pos); //transform vert pos to homogeneous clip space Out.texCoord = In.texCoord; //pass through UV coordinates float3 worldSpacePos = mul(world, In.pos); //world space pos of vertex Out.lightVec0 = lightPosition0; //world space light vector (from light, to vertex pos) Out.lightVec1 = lightPosition1; //world space light vector (from light, to vertex pos) Out.lightVec2= lightPosition2; //world space light vector (from light, to vertex pos) //Out.eyeVec = viewInv[3] - worldSpacePos; //eye vector in world space (from eye, to vertex pos) Out.eyeVec = eyePosition; Out.worldNormal = mul(worldIT, float4(In.norm,0.0f)).xyz; //compute world space norm Out.worldBinormal = mul(worldIT, float4(In.binorm,0.0f)).xyz; //compute world space binorm Out.worldTangent = mul(worldIT, float4(In.tan,0.0f)).xyz; //compute world space tan Out.worldNormal = mul(In.norm, world).xyz; //compute world space norm by multiplying norm with world matrix return Out; } //Multi-Pass Pixel Shader float4 f3(v2f In, uniform float4 lightColor ) : COLOR { //texture declarations float4 diffuseLightTexture = tex2D(diffuseLightSampler, In.texCoord.xy); float4 specReflTexture = tex2D(specReflSampler, In.texCoord.xy); float4 normalTexture = tex2D(normalSampler, In.texCoord.xy); float3 L0 = normalize(In.lightVec0.xyz); //normalized light vector float3 L1 = normalize(In.lightVec1.xyz); //normalized light vector float3 L2 = normalize(In.lightVec2.xyz); //normalized light vector float3 E = normalize(In.eyeVec.xyz); //normalized eye vector float3 H0 = normalize(L0 + E); //Normalized half angle vector float3 H1 = normalize(L1 + E); //Normalized half angle vector float3 H2 = normalize(L2 + E); //Normalized half angle vector //input the vectors required for tan to world space transform float3 Nn = In.worldNormal; float3 Tn = In.worldTangent; float3 Bn = In.worldBinormal; //figure out N (norm) normalTexture = normalTexture * 2 - 1; //expand to -1, 1 normalTexture = float4((Nn * normalTexture.z) + (normalTexture.x * Tn + normalTexture.y * -Bn), 1.0); float3 N = normalize(normalTexture.rgb); //overlay detail texture //diffuse calculations float NdotL0 = dot(N, L0); float NdotL1 = dot(N, L1); float NdotL2 = dot(N, L2); float NdotLmod0 = saturate(NdotL0 - diffuseFactor); float NdotLmod1 = saturate(NdotL1 - diffuseFactor); float NdotLmod2 = saturate(NdotL2 - diffuseFactor); float3 diffuseComp = (diffuseLightTexture.rgb * NdotLmod0) + (diffuseLightTexture.rgb * NdotLmod1) + (diffuseLightTexture.rgb * NdotLmod2); //specular calculations float NdotH0 = saturate(dot(N, H0)); float NdotH1 = saturate(dot(N, H1)); float NdotH2 = saturate(dot(N, H2)); float specularLevelInner0 = pow(NdotH0, glossInner); float specularLevelInner1 = pow(NdotH1, glossInner); float specularLevelInner2 = pow(NdotH2, glossInner); float3 specInner = ((specularLevelInner0 + specularLevelInner1 + specularLevelInner2) * specMultInner * specReflTexture.rgb); float specularLevelOuter0 = pow(NdotH0, glossOuter); float specularLevelOuter1 = pow(NdotH1, glossOuter); float specularLevelOuter2 = pow(NdotH2, glossOuter); float3 specOuter = ((specularLevelOuter0 + specularLevelOuter1 + specularLevelOuter2) * specMultOuter * diffuseLightTexture.rgb); float3 specComp = (specInner + specOuter); specComp *= specularLevelOuter0; specComp *= specularLevelOuter1; specComp *= specularLevelOuter2; //lightTexture and final addition float3 diffuseSpec = diffuseComp + specComp; float3 diffuseSpecLight = diffuseSpec * (light0Color + light1Color + light2Color) * diffuseLightTexture.a; float4 ret = float4(diffuseSpecLight.xyz, 1); //Sets w value of the float4 to 1 (a float 4 must be the output of the pixel shader) return ret; } ////////////Light (Multi) Pass/////////////////////////// //Multi-pass vertex shader v2f v2(a2v In, uniform float3 eyePosition, uniform float3 lightPosition0, uniform float3 lightPosition1) { v2f Out = (v2f)0; Out.pos = mul(wvp, In.pos); //transform vert pos to homogeneous clip space Out.texCoord = In.texCoord; //pass through UV coordinates float3 worldSpacePos = mul(world, In.pos); //world space pos of vertex Out.lightVec0 = lightPosition0; //world space light vector (from light, to vertex pos) Out.lightVec1 = lightPosition1; //world space light vector (from light, to vertex pos) //Out.eyeVec = viewInv[3] - worldSpacePos; //eye vector in world space (from eye, to vertex pos) Out.eyeVec = eyePosition; Out.worldNormal = mul(worldIT, float4(In.norm,0.0f)).xyz; //compute world space norm Out.worldBinormal = mul(worldIT, float4(In.binorm,0.0f)).xyz; //compute world space binorm Out.worldTangent = mul(worldIT, float4(In.tan,0.0f)).xyz; //compute world space tan Out.worldNormal = mul(In.norm, world).xyz; //compute world space norm by multiplying norm with world matrix return Out; } //Multi-Pass Pixel Shader float4 f2(v2f In, uniform float4 lightColor ) : COLOR { //texture declarations float4 diffuseLightTexture = tex2D(diffuseLightSampler, In.texCoord.xy); float4 specReflTexture = tex2D(specReflSampler, In.texCoord.xy); float4 normalTexture = tex2D(normalSampler, In.texCoord.xy); float3 L0 = normalize(In.lightVec0.xyz); //normalized light vector float3 L1 = normalize(In.lightVec1.xyz); //normalized light vector float3 E = normalize(In.eyeVec.xyz); //normalized eye vector float3 H0 = normalize(L0 + E); //Normalized half angle vector float3 H1 = normalize(L1 + E); //Normalized half angle vector //input the vectors required for tan to world space transform float3 Nn = In.worldNormal; float3 Tn = In.worldTangent; float3 Bn = In.worldBinormal; //figure out N (norm) normalTexture = normalTexture * 2 - 1; //expand to -1, 1 normalTexture = float4((Nn * normalTexture.z) + (normalTexture.x * Tn + normalTexture.y * -Bn), 1.0); float3 N = normalize(normalTexture.rgb); //overlay detail texture //diffuse calculations float NdotL0 = dot(N, L0); float NdotL1 = dot(N, L1); float NdotLmod0 = saturate(NdotL0 - diffuseFactor); float NdotLmod1 = saturate(NdotL1 - diffuseFactor); float3 diffuseComp = (diffuseLightTexture.rgb * NdotLmod0) + (diffuseLightTexture.rgb * NdotLmod1); //specular calculations float NdotH0 = saturate(dot(N, H0)); float NdotH1 = saturate(dot(N, H1)); float specularLevelInner0 = pow(NdotH0, glossInner); float specularLevelInner1 = pow(NdotH1, glossInner); float3 specInner = ((specularLevelInner0 + specularLevelInner1) * specMultInner * specReflTexture.rgb); float specularLevelOuter0 = pow(NdotH0, glossOuter); float specularLevelOuter1 = pow(NdotH1, glossOuter); float3 specOuter = ((specularLevelOuter0 + specularLevelOuter1) * specMultOuter * diffuseLightTexture.rgb); float3 specComp = (specInner + specOuter); specComp *= specularLevelOuter0; specComp *= specularLevelOuter1; //lightTexture and final addition float3 diffuseSpec = diffuseComp + specComp; float3 diffuseSpecLight = diffuseSpec * (light0Color + light1Color) * diffuseLightTexture.a; float4 ret = float4(diffuseSpecLight.xyz, 1); //Sets w value of the float4 to 1 (a float 4 must be the output of the pixel shader) return ret; }