LightGridLLCreation.bsl 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include "$ENGINE$\PerCameraData.bslinc"
  2. #define USE_LIGHT_GRID_INDICES
  3. #include "$ENGINE$\LightingCommon.bslinc"
  4. #include "$ENGINE$\ImageBasedLighting.bslinc"
  5. #include "$ENGINE$\LightGridCommon.bslinc"
  6. Blocks =
  7. {
  8. Block PerCamera : auto("PerCamera");
  9. Block GridParams : auto("GridParams");
  10. };
  11. Technique
  12. : inherits("PerCameraData")
  13. : inherits("LightingCommon")
  14. : inherits("LightGridCommon")
  15. : inherits("ImageBasedLighting") =
  16. {
  17. Pass =
  18. {
  19. Compute =
  20. {
  21. [layout(r32ui)]
  22. RWBuffer<uint> gLightsCounter;
  23. [layout(r32ui)]
  24. RWBuffer<uint> gLightsLLHeads;
  25. RWBuffer<uint4> gLightsLL;
  26. [layout(r32ui)]
  27. RWBuffer<uint> gProbesCounter;
  28. [layout(r32ui)]
  29. RWBuffer<uint> gProbesLLHeads;
  30. RWBuffer<uint2> gProbesLL;
  31. // Generates a an axis aligned bounding box in NDC and transforms it to view space.
  32. // Note: This will overlap other cells, so it might be better to use frustum planes
  33. // instead of AABB, although frustum testing procedure could result in more false positive
  34. void calcCellAABB(uint3 cellIdx, out float3 center, out float3 extent)
  35. {
  36. // Note:: AABB calculation in tiled deferred image based lighting shader uses less instructions than this,
  37. // see if it can be applied here.
  38. // Convert grid XY coordinates to clip coordinates
  39. float2 a = 2.0f / gGridSize.xy;
  40. float3 ndcMin;
  41. float3 ndcMax;
  42. ndcMin.xy = cellIdx.xy * a - float2(1.0f, 1.0f);
  43. ndcMax.xy = (cellIdx.xy + 1) * a - float2(1.0f, 1.0f);
  44. // Flip Y depending on render API, depending if Y in NDC is facing up or down
  45. // (We negate the value because we want NDC with Y flipped, so origin is top left)
  46. float flipY = -sign(gMatProj[1][1]);
  47. ndcMin.y *= flipY;
  48. ndcMax.y *= flipY;
  49. // Because we're viewing along negative Z, farther end is the minimum
  50. float viewZMin = calcViewZFromCellZ(cellIdx.z + 1);
  51. float viewZMax = calcViewZFromCellZ(cellIdx.z);
  52. ndcMin.z = convertToNDCZ(viewZMax);
  53. ndcMax.z = convertToNDCZ(viewZMin);
  54. float4 corner[8];
  55. // Near
  56. corner[0] = mul(gMatInvProj, float4(ndcMin.x, ndcMin.y, ndcMin.z, 1.0f));
  57. corner[1] = mul(gMatInvProj, float4(ndcMax.x, ndcMin.y, ndcMin.z, 1.0f));
  58. corner[2] = mul(gMatInvProj, float4(ndcMax.x, ndcMax.y, ndcMin.z, 1.0f));
  59. corner[3] = mul(gMatInvProj, float4(ndcMin.x, ndcMax.y, ndcMin.z, 1.0f));
  60. // Far
  61. corner[4] = mul(gMatInvProj, float4(ndcMin.x, ndcMin.y, ndcMax.z, 1.0f));
  62. corner[5] = mul(gMatInvProj, float4(ndcMax.x, ndcMin.y, ndcMax.z, 1.0f));
  63. corner[6] = mul(gMatInvProj, float4(ndcMax.x, ndcMax.y, ndcMax.z, 1.0f));
  64. corner[7] = mul(gMatInvProj, float4(ndcMin.x, ndcMax.y, ndcMax.z, 1.0f));
  65. [unroll]
  66. for(uint i = 0; i < 8; ++i)
  67. corner[i].xy /= corner[i].w;
  68. float3 viewMin = float3(corner[0].xy, viewZMin);
  69. float3 viewMax = float3(corner[0].xy, viewZMax);
  70. [unroll]
  71. for(uint i = 1; i < 8; ++i)
  72. {
  73. viewMin.xy = min(viewMin.xy, corner[i].xy);
  74. viewMax.xy = max(viewMax.xy, corner[i].xy);
  75. }
  76. extent = (viewMax - viewMin) * 0.5f;
  77. center = viewMin + extent;
  78. }
  79. [numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
  80. void main(
  81. uint3 groupId : SV_GroupID,
  82. uint3 groupThreadId : SV_GroupThreadID,
  83. uint3 dispatchThreadId : SV_DispatchThreadID)
  84. {
  85. // Ignore pixels out of valid range
  86. if (any(dispatchThreadId.xy >= gGridSize.xy))
  87. return;
  88. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  89. uint cellIdx = (dispatchThreadId.z * gGridSize.y + dispatchThreadId.y) * gGridSize.x + dispatchThreadId.x;
  90. float3 cellCenter;
  91. float3 cellExtent;
  92. calcCellAABB(dispatchThreadId, cellCenter, cellExtent);
  93. for(uint type = 1; type < 3; ++type)
  94. {
  95. uint lightOffset = gLightOffsets[type - 1];
  96. uint lightEnd = gLightOffsets[type];
  97. for(uint i = lightOffset; i < lightEnd; ++i)
  98. {
  99. float4 lightPosition = mul(gMatView, float4(gLights[i].position, 1.0f));
  100. float lightRadius = gLights[i].attRadius;
  101. // Calculate distance from box to light
  102. float3 distances = max(abs(lightPosition - cellCenter) - cellExtent, 0);
  103. float distSqrd = dot(distances, distances);
  104. if(distSqrd <= (lightRadius * lightRadius))
  105. {
  106. uint nextLink;
  107. InterlockedAdd(gLightsCounter[0], 1U, nextLink);
  108. if(nextLink < maxNumLinks)
  109. {
  110. uint prevLink;
  111. InterlockedExchange(gLightsLLHeads[cellIdx], nextLink, prevLink);
  112. gLightsLL[nextLink] = uint4(i, type, prevLink, 0);
  113. }
  114. }
  115. }
  116. }
  117. for(uint i = 0; i < gNumReflProbes; ++i)
  118. {
  119. float4 probePosition = mul(gMatView, float4(gReflectionProbes[i].position, 1.0f));
  120. float probeRadius = gReflectionProbes[i].radius;
  121. // Calculate distance from box to light
  122. float3 distances = max(abs(probePosition - cellCenter) - cellExtent, 0);
  123. float distSqrd = dot(distances, distances);
  124. if(distSqrd <= (probeRadius * probeRadius))
  125. {
  126. uint nextLink;
  127. InterlockedAdd(gProbesCounter[0], 1U, nextLink);
  128. if(nextLink < maxNumLinks)
  129. {
  130. uint prevLink;
  131. InterlockedExchange(gProbesLLHeads[cellIdx], nextLink, prevLink);
  132. gProbesLL[nextLink] = uint2(i, prevLink);
  133. }
  134. }
  135. }
  136. }
  137. };
  138. };
  139. };