varianceshadowreceiverfp.cg
上传用户:xhbjoy
上传日期:2014-10-07
资源大小:38068k
文件大小:4k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // shadowreceiverfp.cg
  4. //
  5. // Hamilton Chong
  6. // (c) 2006
  7. //
  8. // This is an example fragment shader for shadow receiver objects.  
  9. //
  10. /////////////////////////////////////////////////////////////////////////////////
  11. sampler2D ShadowMap : TEXUNIT0;
  12. // Define outputs from vertex shader.
  13. struct Vertex
  14. {
  15.   float4 position       : POSITION;     // fragment position in post projective space
  16.   float4 shadowCoord    : TEXCOORD0;    // fragment position in shadow map coordinates
  17.   float  diffuse        : TEXCOORD1;    // diffuse shading value
  18. };
  19. struct Fragment
  20. {
  21.     float4 color  : COLOR0;
  22. };
  23. Fragment main(Vertex        In, 
  24.               uniform float uSTexWidth,
  25.               uniform float uSTexHeight)
  26. {
  27.     Fragment Out;
  28.     // compute the shadow coordinates for texture lookup
  29.     // NOTE: texture_viewproj_matrix maps z into [0,1] range, not [-1,1], so
  30.     //  have to make sure shadow caster stores depth values with same convention.
  31.     float4 scoord = In.shadowCoord / In.shadowCoord.w;
  32.     // -- Bilinear Filtering of Sample -------------------------------------------- 
  33.     // One could use scoord.xy to look up the shadow map for depth testing, but
  34.     // we'll be implementing a simple "percentage closest filtering" algorithm instead.
  35.     // This mimics the behavior of turning on bilinear filtering on NVIDIA hardware
  36.     // when also performing shadow comparisons.  This causes bilinear filtering of
  37.     // depth tests.  Note that this is NOT the same as bilinear filtering the depth
  38.     // values and then doing the depth comparison.  The two operations are not 
  39.     // commutative.  PCF is explicitly about filtering the test values since
  40.     // testing filtered z values is often meaningless.  
  41.     // Real percentage closest filtering should sample from the entire footprint
  42.     // on the shadow map, not just seek the closest four sample points.  Such 
  43.     // an improvement is for future work.
  44.     
  45.     // NOTE: Assuming OpenGL convention for texture lookups with integers in centers.
  46.     //  DX convention is to have integers mark sample corners
  47.     float2 tcoord;
  48.     tcoord.x = (scoord.x * uSTexWidth) - 0.5;
  49.     tcoord.y = (scoord.y * uSTexHeight) - 0.5;
  50.     float x0 = floor(tcoord.x);
  51.     float x1 = ceil(tcoord.x);
  52.     float fracx = frac(tcoord.x);
  53.     float y0 = floor(tcoord.y);
  54.     float y1 = ceil(tcoord.y);
  55.     float fracy = frac(tcoord.y);
  56.     
  57.     // sample coordinates in [0,1]^2 domain
  58.     float2 t00, t01, t10, t11;
  59.     float invWidth  = 1.0 / uSTexWidth;
  60.     float invHeight = 1.0 / uSTexHeight;
  61.     t00 = float2((x0+0.5) * invWidth, (y0+0.5) * invHeight);
  62.     t10 = float2((x1+0.5) * invWidth, (y0+0.5) * invHeight);
  63.     t01 = float2((x0+0.5) * invWidth, (y1+0.5) * invHeight);
  64.     t11 = float2((x1+0.5) * invWidth, (y1+0.5) * invHeight);
  65.     
  66.     // grab the samples
  67.     float2 z00 = tex2D(ShadowMap, t00).xy;
  68.     float2 z01 = tex2D(ShadowMap, t01).xy;
  69.     float2 z10 = tex2D(ShadowMap, t10).xy;
  70.     float2 z11 = tex2D(ShadowMap, t11).xy;
  71.     // bilinear filter the sample data
  72.     float2 d0 = ((1.0 - fracx) * z00) + (fracx * z10);
  73.     float2 d1 = ((1.0 - fracx) * z01) + (fracx * z11);
  74.     float2 datum = ((1.0 - fracy) * d0) + (fracy * d1);
  75.     // -- Variance Shadow Mapping ---------------------------------------------------
  76.     float zVariance = datum.y - (datum.x * datum.x);
  77.     float zDeviation = scoord.z - datum.x;
  78.     zDeviation = (zDeviation < 0.0) ? 0.0 : zDeviation;
  79.     float visibility = zVariance / (zVariance + (zDeviation * zDeviation));
  80.     float ztest = (scoord.z < datum.x) ? 1.0:0.0;  // filtering depth ok, because used only for small variance
  81.     visibility = (zVariance > 0.0) ? visibility : ztest; // if variance too small, we get garbage
  82.     //0.0000001
  83.     // determine that all geometry within pixel border of shadow map (and outside) is lit
  84.     float filterBorder = max(invWidth, invHeight);
  85.     visibility = (all(abs(scoord.xy-0.5)<=0.5-filterBorder)) ? visibility : 1.0;
  86.     // ------------------------------------------------------------------------------
  87.     visibility *= In.diffuse;
  88.     Out.color = float4(visibility, visibility, visibility, 0.0);
  89.     return Out;
  90. }