mixin LightGridCommon { code { cbuffer GridParams : register(b4) { // Number of lights per type in the lights buffer // x - directional lights, y - radial lights, z - spot lights, w - total number of lights uint4 gLightCounts; // Strides between different light types in the light buffer // x - stride to radial lights, y - stride to spot lights. Directional lights are assumed to start at 0. uint2 gLightStrides; 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) { // OpenGL uses lower left for window space origin #ifdef OPENGL pixelPos.y = gViewportRectangle.w - pixelPos.y; #endif // 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; } }; };