///////////////////////////////////////////////////////////////////////////////// // // shadowcasterfp.cg // // Hamilton Chong // (c) 2006 // // This is an example fragment shader for shadow caster objects. // ///////////////////////////////////////////////////////////////////////////////// // Define outputs from vertex shader. struct VertexOut { float4 position : POSITION; // can't rely on access to this float4 pos : TEXCOORD0; // position of fragment (in homogeneous coordinates) float4 normal : TEXCOORD1; // un-normalized normal in object space float4 modelPos : TEXCOORD2; // coordinates of model in object space at this point }; struct FragmentOut { float4 color : COLOR0; }; FragmentOut main( VertexOut In, // fragment to process uniform float uDepthOffset, // offset amount (constant in eye space) uniform float4x4 uProjection // projection matrix ) { FragmentOut Out; // compute the "normalized device coordinates" (no viewport applied yet) float4 postproj = In.pos / In.pos.w; // get the normalized normal of the geometry seen at this point float4 normal = normalize(In.normal); // -- Computing Depth Bias Quantities ----------------------------- // We now compute the change in z that would signify a push in the z direction // by 1 unit in eye space. Note that eye space z is related in a nonlinear way to // screen space z, so this is not just a constant. // ddepth below is how much screen space z at this point would change for that push. // NOTE: computation of ddepth likely differs from OpenGL's glPolygonOffset "unit" // computation, which is allowed to be vendor specific. float4 dpwdz = mul(uProjection, float4(0.0, 0.0, 1.0, 0.0)); float4 dpdz = (dpwdz - (postproj * dpwdz.w)) / In.pos.w; float ddepth = abs(dpdz.z); // -- End depth bias helper section -------------------------------- // We now compute the depth of the fragment. This is the actual depth value plus // our depth bias. The depth bias depends on how uncertain we are about the z value // plus some constant push in the z direction. The exact coefficients to use are // up to you, but at least it should be somewhat intuitive now what the tradeoffs are. float depthval = postproj.z /* + (0.5 * dzlen)*/ + (uDepthOffset * ddepth); depthval = (0.5 * depthval) + 0.5; // put into [0,1] range instead of [-1,1] Out.color = float4(depthval, depthval * depthval, depthval, 0.0); return Out; }