| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- Technique : base("LightGridCommon") =
- {
- Language = "HLSL11";
-
- Pass =
- {
- Common =
- {
- cbuffer GridParams : register(b4)
- {
- // Offsets at which specific light types begin in gLights buffer
- // Assumed directional lights start at 0
- // x - offset to point lights, y - offset to spot lights, z - total number of lights
- uint3 gLightOffsets;
- uint gNumReflProbes;
- uint gNumCells;
- uint3 gGridSize;
- uint gMaxNumLightsPerCell;
- uint2 gGridPixelSize;
- }
-
- float calcViewZFromCellZ(uint cellZ)
- {
- // We don't want to subdivide depth uniformly because XY sizes will be much
- // smaller closer to the near plane, and larger towards far plane. We want
- // our cells to be as close to cube shape as possible, so that width/height/depth
- // are all similar. Ideally we would use either width or height as calculated for
- // purposes of the projection matrix, for the depth. But since we'll be splitting
- // the depth range into multiple slices, in practice this ends up with many tiny
- // cells close to the near plane. Instead we use a square function, which is
- // somewhere between the two extremes:
- // view = slice^2
-
- // We need it in range [near, far] so we normalize and scale
- // view = slice^2 / maxSlices^2 * (far - near) + near
-
- // Note: Some of these calculations could be moved to CPU
- float viewZ = (pow(cellZ, 2) / pow(gGridSize.z, 2)) * (gNearFar.y - gNearFar.x) + gNearFar.x;
- return -viewZ;
- }
-
- uint calcCellZFromViewZ(float viewZ)
- {
- // Inverse of calculation in calcViewZFromCellZ
- uint cellZ = min((uint)floor(sqrt(((-viewZ - gNearFar.x)*pow(gGridSize.z, 2))/(gNearFar.y - gNearFar.x))), gGridSize.z);
-
- return cellZ;
- }
-
- uint calcCellIdx(uint2 pixelPos, float deviceZ)
- {
- // Note: Use bitshift to divide since gGridPixelSize will be a power of 2
- uint2 cellXY = pixelPos / gGridPixelSize;
- uint cellZ = calcCellZFromViewZ(convertFromDeviceZ(deviceZ));
-
- uint cellIdx = (cellZ * gGridSize.y + cellXY.y) * gGridSize.x + cellXY.x;
- return cellIdx;
- }
- };
- };
- };
- Technique : base("LightGridCommon") =
- {
- Language = "GLSL";
-
- Pass =
- {
- Common =
- {
- layout(binding = 4, std140) uniform GridParams
- {
- // Offsets at which specific light types begin in gLights buffer
- // Assumed directional lights start at 0
- // x - offset to point lights, y - offset to spot lights, z - total number of lights
- uvec3 gLightOffsets;
- uint gNumCells;
- uvec3 gGridSize;
- uint gMaxNumLightsPerCell;
- uvec2 gGridPixelSize;
- };
-
- float convertToNDCZ(float viewZ)
- {
- return -gNDCZToWorldZ.y + (gNDCZToWorldZ.x / viewZ);
- }
-
- float calcViewZFromCellZ(uint cellZ)
- {
- // See HLSL version for reasons behind this formulation
-
- // Note: Some of these calculations could be moved to CPU
- float viewZ = (pow(cellZ, 2) / pow(gGridSize.z, 2)) * (gNearFar.y - gNearFar.x) + gNearFar.x;
- return -viewZ;
- }
-
- uint calcCellZFromViewZ(float viewZ)
- {
- // Inverse of calculation in calcViewZFromCellZ
- uint cellZ = min(uint(floor(sqrt(((-viewZ - gNearFar.x)*pow(gGridSize.z, 2))/(gNearFar.y - gNearFar.x)))), gGridSize.z);
-
- return cellZ;
- }
-
- int calcCellIdx(uvec2 pixelPos, float deviceZ)
- {
- // OpenGL uses lower left for window space origin, we use upper-left
- #ifdef OPENGL
- pixelPos.y = gViewportRectangle.w - pixelPos.y;
- #endif
-
- // Note: Use bitshift to divide since gGridPixelSize will be a power of 2
- uvec2 cellXY = pixelPos / gGridPixelSize;
- uint cellZ = calcCellZFromViewZ(convertFromDeviceZ(deviceZ));
-
- int cellIdx = int((cellZ * gGridSize.y + cellXY.y) * gGridSize.x + cellXY.x);
- return cellIdx;
- }
- };
- };
- };
|