Advertisement
Guest User

ssr

a guest
Oct 23rd, 2016
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.45 KB | None | 0 0
  1. // By Morgan McGuire and Michael Mara at Williams College 2014
  2. // Released as open source under the BSD 2-Clause License
  3. // http://opensource.org/licenses/BSD-2-Clause
  4. #define point2 float2
  5. #define point3 float3
  6.  
  7. float distanceSquared(float2 a, float2 b) { a -= b; return dot(a, a); }
  8.  
  9. // Returns true if the ray hit something
  10. bool traceScreenSpaceRay(
  11.  // Camera-space ray origin, which must be within the view volume
  12.  point3 csOrig,
  13.  
  14.  // Unit length camera-space ray direction
  15.  float3 csDir,
  16.  
  17.  // A projection matrix that maps to pixel coordinates (not [-1, +1]
  18.  // normalized device coordinates)
  19.  matrix proj,
  20.  
  21.  // The camera-space Z buffer (all negative values)
  22.  Texture2D csZBuffer,
  23.  
  24.  // Dimensions of csZBuffer
  25.  float2 csZBufferSize,
  26.  
  27.  // Camera space thickness to ascribe to each pixel in the depth buffer
  28.  float zThickness,
  29.  
  30.  // (Negative number)
  31.  float nearPlaneZ,
  32.  
  33.  // Step in horizontal or vertical pixels between samples. This is a float
  34.  // because integer math is slow on GPUs, but should be set to an integer >= 1
  35.  float stride,
  36.  
  37.  // Number between 0 and 1 for how far to bump the ray in stride units
  38.  // to conceal banding artifacts
  39.  float jitter,
  40.  
  41.  // Maximum number of iterations. Higher gives better images but may be slow
  42.  const float maxSteps,
  43.  
  44.  // Maximum camera-space distance to trace before returning a miss
  45.  float maxDistance,
  46.  
  47.  // Pixel coordinates of the first intersection with the scene
  48.  out point2 hitPixel,
  49.  
  50.  // Camera space location of the ray hit
  51.  out point3 hitPoint) {
  52.  
  53.     // Clip to the near plane  
  54.     float rayLength = ((csOrig.z + csDir.z * maxDistance) > nearPlaneZ) ?
  55.         (nearPlaneZ - csOrig.z) / csDir.z : maxDistance;
  56.     point3 csEndPoint = csOrig + csDir * rayLength;
  57.  
  58.     // Project into homogeneous clip space
  59.     float4 H0 = proj * float4(csOrig, 1.0);
  60.     float4 H1 = proj * float4(csEndPoint, 1.0);
  61.     float k0 = 1.0 / H0.w, k1 = 1.0 / H1.w;
  62.  
  63.     // The interpolated homogeneous version of the camera-space points
  64.     point3 Q0 = csOrig * k0, Q1 = csEndPoint * k1;
  65.  
  66.     // Screen-space endpoints
  67.     point2 P0 = H0.xy * k0, P1 = H1.xy * k1;
  68.  
  69.     // If the line is degenerate, make it cover at least one pixel
  70.     // to avoid handling zero-pixel extent as a special case later
  71.     P1 += float2((distanceSquared(P0, P1) < 0.0001) ? 0.01 : 0.0);
  72.     float2 delta = P1 - P0;
  73.  
  74.     // Permute so that the primary iteration is in x to collapse
  75.     // all quadrant-specific DDA cases later
  76.     bool permute = false;
  77.     if (abs(delta.x) < abs(delta.y)) {
  78.         // This is a more-vertical line
  79.         permute = true; delta = delta.yx; P0 = P0.yx; P1 = P1.yx;
  80.     }
  81.  
  82.     float stepDir = sign(delta.x);
  83.     float invdx = stepDir / delta.x;
  84.  
  85.     // Track the derivatives of Q and k
  86.     float3  dQ = (Q1 - Q0) * invdx;
  87.     float dk = (k1 - k0) * invdx;
  88.     float2  dP = float2(stepDir, delta.y * invdx);
  89.  
  90.     // Scale derivatives by the desired pixel stride and then
  91.     // offset the starting values by the jitter fraction
  92.     dP *= stride; dQ *= stride; dk *= stride;
  93.     P0 += dP * jitter; Q0 += dQ * jitter; k0 += dk * jitter;
  94.  
  95.     // Slide P from P0 to P1, (now-homogeneous) Q from Q0 to Q1, k from k0 to k1
  96.     point3 Q = Q0;
  97.  
  98.     // Adjust end condition for iteration direction
  99.     float  end = P1.x * stepDir;
  100.  
  101.     float k = k0, stepCount = 0.0, prevZMaxEstimate = csOrig.z;
  102.     float rayZMin = prevZMaxEstimate, rayZMax = prevZMaxEstimate;
  103.     float sceneZMax = rayZMax + 100;
  104.     for (point2 P = P0;
  105.          ((P.x * stepDir) <= end) && (stepCount < maxSteps) &&
  106.          ((rayZMax < sceneZMax - zThickness) || (rayZMin > sceneZMax)) &&
  107.           (sceneZMax != 0);
  108.          P += dP, Q.z += dQ.z, k += dk, ++stepCount) {
  109.          
  110.         rayZMin = prevZMaxEstimate;
  111.         rayZMax = (dQ.z * 0.5 + Q.z) / (dk * 0.5 + k);
  112.         prevZMaxEstimate = rayZMax;
  113.         if (rayZMin > rayZMax) {
  114.            float t = rayZMin; rayZMin = rayZMax; rayZMax = t;
  115.         }
  116.  
  117.         hitPixel = permute ? P.yx : P;
  118.         // You may need hitPixel.y = csZBufferSize.y - hitPixel.y; here if your vertical axis
  119.         // is different than ours in screen space
  120.        
  121.         //hitPixel.y = csZBufferSize.y - hitPixel.y;
  122.         sceneZMax = csZBuffer.Load(int2(hitPixel), 0);
  123.     }
  124.      
  125.     // Advance Q based on the number of steps
  126.     Q.xy += dQ.xy * stepCount;
  127.     hitPoint = Q * (1.0 / k);
  128.     return (rayZMax >= sceneZMax - zThickness) && (rayZMin < sceneZMax);
  129. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement