LightGridCommon.bslinc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. Technique : base("LightGridCommon") =
  2. {
  3. Language = "HLSL11";
  4. Pass =
  5. {
  6. Common =
  7. {
  8. cbuffer GridParams : register(b4)
  9. {
  10. // Offsets at which specific light types begin in gLights buffer
  11. // Assumed directional lights start at 0
  12. // x - offset to point lights, y - offset to spot lights, z - total number of lights
  13. uint3 gLightOffsets;
  14. uint gNumCells;
  15. uint3 gGridSize;
  16. uint gMaxNumLightsPerCell;
  17. uint2 gGridPixelSize;
  18. }
  19. float convertToNDCZ(float viewZ)
  20. {
  21. return -gNDCZToWorldZ.y + (gNDCZToWorldZ.x / viewZ);
  22. }
  23. float calcViewZFromCellZ(uint cellZ)
  24. {
  25. // We don't want to subdivide depth uniformly because XY sizes will be much
  26. // smaller closer to the near plane, and larger towards far plane. We want
  27. // our cells to be as close to cube shape as possible, so that width/height/depth
  28. // are all similar. Ideally we would use either width or height as calculated for
  29. // purposes of the projection matrix, for the depth. But since we'll be splitting
  30. // the depth range into multiple slices, in practice this ends up with many tiny
  31. // cells close to the near plane. Instead we use a square function, which is
  32. // somewhere between the two extremes:
  33. // view = slice^2
  34. // We need it in range [near, far] so we normalize and scale
  35. // view = slice^2 / maxSlices^2 * (far - near) + near
  36. // Note: Some of these calculations could be moved to CPU
  37. float viewZ = (pow(cellZ, 2) / pow(gGridSize.z, 2)) * (gNearFar.y - gNearFar.x) + gNearFar.x;
  38. return -viewZ;
  39. }
  40. uint calcCellZFromViewZ(float viewZ)
  41. {
  42. // Inverse of calculation in calcViewZFromCellZ
  43. uint cellZ = min((uint)floor(sqrt(((-viewZ - gNearFar.x)*pow(gGridSize.z, 2))/(gNearFar.y - gNearFar.x))), gGridSize.z);
  44. return cellZ;
  45. }
  46. uint calcCellIdx(uint2 pixelPos, float deviceZ)
  47. {
  48. // Note: Use bitshift to divide since gGridPixelSize will be a power of 2
  49. uint2 cellXY = pixelPos / gGridPixelSize;
  50. uint cellZ = calcCellZFromViewZ(convertFromDeviceZ(deviceZ));
  51. uint cellIdx = (cellZ * gGridSize.y + cellXY.y) * gGridSize.x + cellXY.x;
  52. return cellIdx;
  53. }
  54. };
  55. };
  56. };
  57. Technique : base("LightGridCommon") =
  58. {
  59. Language = "GLSL";
  60. Pass =
  61. {
  62. Common =
  63. {
  64. layout(binding = 4, std140) uniform GridParams
  65. {
  66. // Offsets at which specific light types begin in gLights buffer
  67. // Assumed directional lights start at 0
  68. // x - offset to point lights, y - offset to spot lights, z - total number of lights
  69. uvec3 gLightOffsets;
  70. uint gNumCells;
  71. uvec3 gGridSize;
  72. uint gMaxNumLightsPerCell;
  73. uvec2 gGridPixelSize;
  74. };
  75. float convertToNDCZ(float viewZ)
  76. {
  77. return -gNDCZToWorldZ.y + (gNDCZToWorldZ.x / viewZ);
  78. }
  79. float calcViewZFromCellZ(uint cellZ)
  80. {
  81. // See HLSL version for reasons behind this formulation
  82. // Note: Some of these calculations could be moved to CPU
  83. float viewZ = (pow(cellZ, 2) / pow(gGridSize.z, 2)) * (gNearFar.y - gNearFar.x) + gNearFar.x;
  84. return -viewZ;
  85. }
  86. uint calcCellZFromViewZ(float viewZ)
  87. {
  88. // Inverse of calculation in calcViewZFromCellZ
  89. uint cellZ = min(uint(floor(sqrt(((-viewZ - gNearFar.x)*pow(gGridSize.z, 2))/(gNearFar.y - gNearFar.x)))), gGridSize.z);
  90. return cellZ;
  91. }
  92. int calcCellIdx(uvec2 pixelPos, float deviceZ)
  93. {
  94. // OpenGL uses lower left for window space origin, we use upper-left
  95. #ifdef OPENGL
  96. pixelPos.y = gViewportRectangle.w - pixelPos.y;
  97. #endif
  98. // Note: Use bitshift to divide since gGridPixelSize will be a power of 2
  99. uvec2 cellXY = pixelPos / gGridPixelSize;
  100. uint cellZ = calcCellZFromViewZ(convertFromDeviceZ(deviceZ));
  101. int cellIdx = int((cellZ * gGridSize.y + cellXY.y) * gGridSize.x + cellXY.x);
  102. return cellIdx;
  103. }
  104. };
  105. };
  106. };