/** * VDM -- View-dependent Displacement Mapping * L. Wang, X. Wang, X. Tong, S. Lin, S. Hu, B. Guo, HY. Shum * * HLSL implementation by Nico Galoppo * :: COMP 236 course project, Spring 2004 * :: University of North Carolina, Chapel Hill */ // Fragment Shader struct v2f { float4 Position : POSITION; // clip space float2 TexCoord0 : TEXCOORD0; float2 TexCoord1 : TEXCOORD1; float3 L : TEXCOORD2; // tangent space float3 H : TEXCOORD3; float3 V : TEXCOORD4; float2 lightAngle : TEXCOORD5; float2 viewAngle : TEXCOORD6; }; half4 VDMPS_3(v2f IN, uniform sampler2D colorTex, uniform sampler2D normalTex, uniform sampler2D phongTex, uniform sampler2D vdmTex, uniform half4 ambientColor, uniform half4 diffuseColor, uniform half4 specularColor ) : COLOR { IN.lightAngle = toSpherical(IN.L); IN.viewAngle = toSpherical(IN.V); // index into composed VDM map ====================================================== int iTheta, iPhi; float tPhi = modf(IN.viewAngle.x / PI * 16, iPhi); float tTheta = modf(IN.viewAngle.y / PI * 16, iTheta); float2 vdm_xy; vdm_xy.x = (iPhi + IN.TexCoord0.x) / 16.0; if (iTheta > 15) vdm_xy.x = vdm_xy.x + 0.5; vdm_xy.y = (iTheta + IN.TexCoord0.y) / 16.0; // view-dependent distance ========================================================== float3 dVDM = tex2D(vdmTex, vdm_xy); #ifdef MIPMAPPING float2 steptexX = float2(1.0/16.0, 0); float2 steptexY = float2(0, 1.0/16.0); float2 steptexXY = float2(1.0/16.0, 1.0/16.0); float3 dVDMPhi1 = (1-tPhi) * tex2D(vdmTex,vdm_xy) + tPhi * tex2D(vdmTex, vdm_xy + steptexX); float3 dVDMPhi2 = (1-tPhi) * tex2D(vdmTex, vdm_xy + steptexY) + tPhi * tex2D(vdmTex, vdm_xy + steptexXY); //dVDM.r = (1-tTheta) * dVDMPhi1.r + tTheta * dVDMPhi2.r; dVDM = (1-tTheta) * dVDMPhi1 + tTheta * dVDMPhi2; #endif // silhouette determination ========================================================= if (dVDM.g > 0.75) clip(-1); // real texture coordinates ========================================================= float2 dT = dScale * dVDM.r * IN.V.xy; // sin(IN.viewAngle.x) * cos(IN.viewAngle.y), // sin(IN.viewAngle.x) * sin(IN.viewAngle.y)); // predefined phong lighting ======================================================== half4 uN = tex2D(normalTex, IN.TexCoord0 - dT); half4 colorMap = tex2D(colorTex, IN.TexCoord0 - dT); half3 N = uN.xyz*2.0 - 1.0; half NdotL = dot(N, IN.L); half NdotH = dot(N, IN.H); half4 light = tex2D(phongTex, half2(NdotL, NdotH)); // shadow determination ============================================================= float height = 1 - uN.a; float2 lightOffset = height * tan(IN.lightAngle.x) * IN.L.xy; float2 lightIntersection = vdm_xy + (lightOffset - dT) / 16.0; // distance to the light float3 dL1 = (1-tPhi) * tex2D(vdmTex, lightIntersection) + tPhi * tex2D(vdmTex, lightIntersection + steptexX); float3 dL2 = (1-tPhi) * tex2D(vdmTex, lightIntersection + steptexY) + tPhi * tex2D(vdmTex, lightIntersection + steptexXY); //dVDM.r = (1-tTheta) * dVDMPhi1.r + tTheta * dVDMPhi2.r; //float dL = (1-tTheta) * dL1 + tTheta * dL2; float dL = tex2D(vdmTex, lightIntersection); int shadow = 1; float distToLightSurface = height / cos(IN.lightAngle.x) - hOffset; if (dL < distToLightSurface) shadow = 0; // output =========================================================================== //return ambientColor*colorMap + light*diffuseColor*colorMap + light.a*specularColor; //return ambientColor + light*diffuseColor + light.a*specularColor; //return half4(dVDM.r * dScale + dVDM.g, 0,0,1); //return half4(length(IN.V.xy), 0, 0, 1); // Debug light offset --------------------------------------------------------------- //return half4(lightOffset, 0, 1); // Debug light offset --------------------------------------------------------------- //return half4(0, IN.lightAngle.y, 0, 1); // Debug heights -------------------------------------------------------------------- //return half4(1 - tex2D(normalTex, IN.TexCoord1 - dT).a, 0, 0, 1); // Debugging full phong lighting ---------------------------------------------------- //return ambientColor*colorMap; shadow = 1; return saturate(1 - dVDM.g) * (ambientColor*colorMap + shadow * (light*diffuseColor*colorMap + light.a*specularColor)); // Debugging specular lighting ------------------------------------------------------ //return light.a*specularColor; // Debugging simple diffuse lighting ------------------------------------------------ //return light*diffuseColor*colorMap; // Debugging normals ---------------------------------------------------------------- //return half4(tex2D(normalTex, IN.TexCoord1 - dT).xyz, 1); // Debugging colors ----------------------------------------------------------------- //return colorMap; // Debugging depths ----------------------------------------------------------------- half4 debug = IN.viewAngle.y / PI2; if (IN.viewAngle.y <0) debug = half4(1, 0, 0, 1); return debug; }