Prechádzať zdrojové kódy

Work on transparent rendering path - DirectX functional

BearishSun 9 rokov pred
rodič
commit
42c00ad036

+ 4 - 0
Data/Raw/Engine/DataList.json

@@ -111,6 +111,10 @@
         {
         {
             "Path": "BasePass.bslinc",
             "Path": "BasePass.bslinc",
             "UUID": "ec1d3d37-5509-4bcb-9be2-93208d6ae224"
             "UUID": "ec1d3d37-5509-4bcb-9be2-93208d6ae224"
+        },
+        {
+            "Path": "LightGridCommon.bslinc",
+            "UUID": "26caf86e-433c-4ade-9bc5-55c136d82912"
         }
         }
     ],
     ],
     "Shaders": [
     "Shaders": [

+ 115 - 0
Data/Raw/Engine/Includes/LightGridCommon.bslinc

@@ -0,0 +1,115 @@
+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 gNumCells;
+				uint3 gGridSize;
+				uint gMaxNumLightsPerCell;
+				uint2 gGridPixelSize;
+			}
+			
+			float convertToDeviceZ(float viewZ)
+			{
+				return -gDeviceZToWorldZ.y + (gDeviceZToWorldZ.x / viewZ);
+			}
+			
+			float calcViewZFromCellZ(uint cellZ)
+			{
+				// TODO - Need better Z distribution. Currently I uniformly distribute in view space, but this
+				// results in very elongated cells along Z
+				float viewZ = gNearFar.x + (gNearFar.y - gNearFar.x) * cellZ / (float)gGridSize.z;
+				
+				return -viewZ;
+			}
+			
+			uint calcCellZFromViewZ(float viewZ)
+			{
+				// TODO - Need better Z distribution. Currently I uniformly distribute in view space, but this
+				// results in very elongated cells along Z
+				uint cellZ = min((gGridSize.z * (-viewZ - gNearFar.x))/(gNearFar.y - gNearFar.x), gGridSize.z);
+				
+				return cellZ;
+			}
+			
+			uint calcCellIdx(uint2 pixelPos, float deviceZ)
+			{
+				// MARK: API_SPECIFIC
+				// Grid origin is bottom left but DirectX pixel position origin is top left
+				pixelPos.y = gViewportRectangle.w - pixelPos.y;
+			
+				// 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 convertToDeviceZ(float viewZ)
+			{
+				return -gDeviceZToWorldZ.y + (gDeviceZToWorldZ.x / viewZ);
+			}
+			
+			float calcViewZFromCellZ(uint cellZ)
+			{
+				// TODO - Need better Z distribution. Currently I uniformly distribute in view space, but this
+				// results in very elongated cells along Z
+				float viewZ = gNearFar.x + (gNearFar.y - gNearFar.x) * cellZ / float(gGridSize.z);
+				
+				return -viewZ;
+			}
+						
+			uint calcCellZFromViewZ(float viewZ)
+			{
+				// TODO - Need better Z distribution. Currently I uniformly distribute in view space, but this
+				// results in very elongated cells along Z
+				uint cellZ = min(uint((gGridSize.z * (-viewZ - gNearFar.x))/(gNearFar.y - gNearFar.x)), gGridSize.z);
+				
+				return cellZ;
+			}
+			
+			int calcCellIdx(uvec2 pixelPos, float deviceZ)
+			{
+				// 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;
+			}
+		};
+	};
+};

+ 2 - 12
Data/Raw/Engine/Includes/LightingCommon.bslinc

@@ -20,12 +20,7 @@ Technique
 				float radiusSqrdInv;
 				float radiusSqrdInv;
 				float3 color;
 				float3 color;
 			};
 			};
-			
-			float convertFromDeviceZ(float deviceZ)
-			{
-				return (1.0f / (deviceZ + gDeviceZToWorldZ.y)) * gDeviceZToWorldZ.x;
-			}
-			
+						
 			float getSpotAttenuation(float3 worldPosToLight, float3 direction, float3 angles)
 			float getSpotAttenuation(float3 worldPosToLight, float3 direction, float3 angles)
 			{
 			{
 				float output = saturate((dot(-worldPosToLight, direction) - angles.y) * angles.z);
 				float output = saturate((dot(-worldPosToLight, direction) - angles.y) * angles.z);
@@ -101,12 +96,7 @@ Technique
 				float radiusSqrdInv;
 				float radiusSqrdInv;
 				vec3 color;
 				vec3 color;
 			};
 			};
-			
-			float convertFromDeviceZ(float deviceZ)
-			{
-				return (1.0f / (deviceZ + gDeviceZToWorldZ.y)) * gDeviceZToWorldZ.x;	
-			}
-						
+									
 			float getSpotAttenuation(vec3 worldPosToLight, vec3 direction, vec3 angles)
 			float getSpotAttenuation(vec3 worldPosToLight, vec3 direction, vec3 angles)
 			{
 			{
 				float atten = clamp((dot(-worldPosToLight, direction) - angles.y) * angles.z, 0.0, 1.0);
 				float atten = clamp((dot(-worldPosToLight, direction) - angles.y) * angles.z, 0.0, 1.0);

+ 10 - 0
Data/Raw/Engine/Includes/PerCameraData.bslinc

@@ -56,6 +56,11 @@ Technique : base("PerCameraData") =
 				int4 	 gViewportRectangle;
 				int4 	 gViewportRectangle;
 				float4 	 gClipToUVScaleOffset;				
 				float4 	 gClipToUVScaleOffset;				
 			}
 			}
+			
+			float convertFromDeviceZ(float deviceZ)
+			{
+				return (1.0f / (deviceZ + gDeviceZToWorldZ.y)) * gDeviceZToWorldZ.x;
+			}
 		};
 		};
 	};
 	};
 };
 };
@@ -83,6 +88,11 @@ Technique : base("PerCameraData") =
 				ivec4 gViewportRectangle;
 				ivec4 gViewportRectangle;
 				vec4 gClipToUVScaleOffset;				
 				vec4 gClipToUVScaleOffset;				
 			};
 			};
+			
+			float convertFromDeviceZ(float deviceZ)
+			{
+				return (1.0f / (deviceZ + gDeviceZToWorldZ.y)) * gDeviceZToWorldZ.x;	
+			}
 		};
 		};
 	};
 	};
 };
 };

+ 67 - 70
Data/Raw/Engine/Shaders/LightGridLLCreation.bsl

@@ -1,16 +1,19 @@
 #include "$ENGINE$\GBuffer.bslinc"
 #include "$ENGINE$\GBuffer.bslinc"
 #include "$ENGINE$\PerCameraData.bslinc"
 #include "$ENGINE$\PerCameraData.bslinc"
 #include "$ENGINE$\LightingCommon.bslinc"
 #include "$ENGINE$\LightingCommon.bslinc"
+#include "$ENGINE$\LightGridCommon.bslinc"
 
 
 Blocks =
 Blocks =
 {
 {
 	Block PerCamera : auto("PerCamera");
 	Block PerCamera : auto("PerCamera");
+	Block GridParams : auto("GridParams");
 };
 };
 
 
 Technique
 Technique
  : inherits("GBuffer")
  : inherits("GBuffer")
  : inherits("PerCameraData")
  : inherits("PerCameraData")
- : inherits("LightingCommon") =
+ : inherits("LightingCommon")
+ : inherits("LightGridCommon") =
 {
 {
 	Language = "HLSL11";
 	Language = "HLSL11";
 	
 	
@@ -18,36 +21,14 @@ Technique
 	{
 	{
 		Compute = 
 		Compute = 
 		{
 		{
-			cbuffer Params : register(b0)
-			{
-				// 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 gNumCells;
-				uint3 gGridSize;
-				uint gMaxNumLightsPerCell;
-			}
-			
 			StructuredBuffer<LightData> gLights : register(t0);
 			StructuredBuffer<LightData> gLights : register(t0);
 			RWBuffer<uint> gLinkedListCounter : register(u0);
 			RWBuffer<uint> gLinkedListCounter : register(u0);
 			RWBuffer<uint> gLinkedListHeads : register(u1);
 			RWBuffer<uint> gLinkedListHeads : register(u1);
-			RWBuffer<uint2> gLinkedList : register(u2);
-			
-			float convertToDeviceZ(float viewZ)
-			{
-				return (gDeviceZToWorldZ.x - viewZ * gDeviceZToWorldZ.y) / viewZ;
-			}
-			
-			float calcViewZFromCellZ(uint cellZ)
-			{
-				// TODO - Need better Z distribution. Currently I uniformly distribute in view space, but this
-				// results in very elongated cells along Z
-				float viewZ = gNearFar.x + (gNearFar.y - gNearFar.x) * cellZ / (float)gGridSize.z;
-				
-				return viewZ;
-			}
-		
+			RWBuffer<uint4> gLinkedList : register(u2);
+					
+			// Generates a an axis aligned bounding box in NDC and transforms it to view space.
+			// Note: This will overlap other cells, so it might be better to use frustum planes
+			// instead of AABB, although frustum testing procedure could result in more false positive
 			void calcCellAABB(uint3 cellIdx, out float3 center, out float3 extent)
 			void calcCellAABB(uint3 cellIdx, out float3 center, out float3 extent)
 			{
 			{
 				// Convert grid XY coordinates to clip coordinates
 				// Convert grid XY coordinates to clip coordinates
@@ -63,19 +44,40 @@ Technique
 				float flipY = sign(gMatProj[1][1]);
 				float flipY = sign(gMatProj[1][1]);
 				ndcMin.y *= flipY;
 				ndcMin.y *= flipY;
 				ndcMax.y *= flipY;
 				ndcMax.y *= flipY;
-				
+			
 				// Because we're viewing along negative Z, farther end is the minimum
 				// Because we're viewing along negative Z, farther end is the minimum
 				float viewZMin = calcViewZFromCellZ(cellIdx.z + 1);
 				float viewZMin = calcViewZFromCellZ(cellIdx.z + 1);
 				float viewZMax = calcViewZFromCellZ(cellIdx.z);
 				float viewZMax = calcViewZFromCellZ(cellIdx.z);
 			
 			
-				ndcMin.z = convertToDeviceZ(viewZMin);
-				ndcMax.z = convertToDeviceZ(viewZMax);
+				ndcMin.z = convertToDeviceZ(viewZMax);
+				ndcMax.z = convertToDeviceZ(viewZMin);
+			
+				float4 corner[8];
+				// Near
+				corner[0] = mul(gMatInvProj, float4(ndcMin.x, ndcMin.y, ndcMin.z, 1.0f));
+				corner[1] = mul(gMatInvProj, float4(ndcMax.x, ndcMin.y, ndcMin.z, 1.0f));
+				corner[2] = mul(gMatInvProj, float4(ndcMax.x, ndcMax.y, ndcMin.z, 1.0f));
+				corner[3] = mul(gMatInvProj, float4(ndcMin.x, ndcMax.y, ndcMin.z, 1.0f));
+			
+				// Far
+				corner[4] = mul(gMatInvProj, float4(ndcMin.x, ndcMin.y, ndcMax.z, 1.0f));
+				corner[5] = mul(gMatInvProj, float4(ndcMax.x, ndcMin.y, ndcMax.z, 1.0f));
+				corner[6] = mul(gMatInvProj, float4(ndcMax.x, ndcMax.y, ndcMax.z, 1.0f));
+				corner[7] = mul(gMatInvProj, float4(ndcMin.x, ndcMax.y, ndcMax.z, 1.0f));
+			
+				[unroll]
+				for(uint i = 0; i < 8; ++i)
+					corner[i].xy /= corner[i].w;
 			
 			
-				float4 clipMin = mul(gMatInvProj, float4(ndcMin, 1.0f));
-				float4 clipMax = mul(gMatInvProj, float4(ndcMax, 1.0f));
+				float3 viewMin = float3(corner[0].xy, viewZMin);
+				float3 viewMax = float3(corner[0].xy, viewZMax);
 				
 				
-				float3 viewMin = float3(clipMin.xy / clipMin.w, viewZMin);
-				float3 viewMax = float3(clipMax.xy / clipMax.w, viewZMax);				
+				[unroll]
+				for(uint i = 1; i < 8; ++i)
+				{
+					viewMin.xy = min(viewMin.xy, corner[i].xy);
+					viewMax.xy = max(viewMax.xy, corner[i].xy);
+				}
 				
 				
 				extent = (viewMax - viewMin) * 0.5f;
 				extent = (viewMax - viewMin) * 0.5f;
 				center = viewMin + extent;
 				center = viewMin + extent;
@@ -123,7 +125,7 @@ Technique
 								uint prevLink;
 								uint prevLink;
 								InterlockedExchange(gLinkedListHeads[cellIdx], nextLink, prevLink);
 								InterlockedExchange(gLinkedListHeads[cellIdx], nextLink, prevLink);
 								
 								
-								gLinkedList[nextLink] = uint2(i, prevLink);
+								gLinkedList[nextLink] = uint4(i, type, prevLink, 0);
 							}
 							}
 						}
 						}
 					}
 					}
@@ -136,7 +138,8 @@ Technique
 Technique
 Technique
  : inherits("GBuffer")
  : inherits("GBuffer")
  : inherits("PerCameraData")
  : inherits("PerCameraData")
- : inherits("LightingCommon") =
+ : inherits("LightingCommon")
+ : inherits("LightGridCommon") =
 {
 {
 	Language = "GLSL";
 	Language = "GLSL";
 	
 	
@@ -146,40 +149,15 @@ Technique
 		{
 		{
 			layout (local_size_x = THREADGROUP_SIZE, local_size_y = THREADGROUP_SIZE, local_size_z = THREADGROUP_SIZE) in;
 			layout (local_size_x = THREADGROUP_SIZE, local_size_y = THREADGROUP_SIZE, local_size_z = THREADGROUP_SIZE) in;
 		
 		
-			layout(binding = 0, std140) uniform Params
-			{
-				// 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;
-			};
-			
-			layout(std430, binding = 1) buffer gLights
+			layout(std430, binding = 1) readonly buffer gLights
 			{
 			{
 				LightData[] gLightsData;
 				LightData[] gLightsData;
 			};
 			};
 			
 			
 			layout(binding = 2, r32ui) uniform uimageBuffer gLinkedListCounter;
 			layout(binding = 2, r32ui) uniform uimageBuffer gLinkedListCounter;
 			layout(binding = 3, r32ui) uniform uimageBuffer gLinkedListHeads;
 			layout(binding = 3, r32ui) uniform uimageBuffer gLinkedListHeads;
-			layout(binding = 4, rg32ui) uniform uimageBuffer gLinkedList;
+			layout(binding = 5, rgba32ui) uniform uimageBuffer gLinkedList;
 			
 			
-			float convertToDeviceZ(float viewZ)
-			{
-				return (gDeviceZToWorldZ.x - viewZ * gDeviceZToWorldZ.y) / viewZ;
-			}
-			
-			float calcViewZFromCellZ(uint cellZ)
-			{
-				// TODO - Need better Z distribution. Currently I uniformly distribute in view space, but this
-				// results in very elongated cells along Z
-				float viewZ = gNearFar.x + (gNearFar.y - gNearFar.x) * cellZ / float(gGridSize.z);
-				
-				return viewZ;
-			}
-		
 			void calcCellAABB(uvec3 cellIdx, out vec3 center, out vec3 extent)
 			void calcCellAABB(uvec3 cellIdx, out vec3 center, out vec3 extent)
 			{
 			{
 				// Convert grid XY coordinates to clip coordinates
 				// Convert grid XY coordinates to clip coordinates
@@ -195,19 +173,38 @@ Technique
 				float flipY = sign(gMatProj[1][1]);
 				float flipY = sign(gMatProj[1][1]);
 				ndcMin.y *= flipY;
 				ndcMin.y *= flipY;
 				ndcMax.y *= flipY;
 				ndcMax.y *= flipY;
-				
+			
 				// Because we're viewing along negative Z, farther end is the minimum
 				// Because we're viewing along negative Z, farther end is the minimum
 				float viewZMin = calcViewZFromCellZ(cellIdx.z + 1);
 				float viewZMin = calcViewZFromCellZ(cellIdx.z + 1);
 				float viewZMax = calcViewZFromCellZ(cellIdx.z);
 				float viewZMax = calcViewZFromCellZ(cellIdx.z);
 			
 			
 				ndcMin.z = convertToDeviceZ(viewZMin);
 				ndcMin.z = convertToDeviceZ(viewZMin);
 				ndcMax.z = convertToDeviceZ(viewZMax);
 				ndcMax.z = convertToDeviceZ(viewZMax);
+							
+				vec4 corner[8];
+				// Near
+				corner[0] = gMatInvProj * vec4(ndcMin.x, ndcMin.y, ndcMin.z, 1.0f);
+				corner[1] = gMatInvProj * vec4(ndcMax.x, ndcMin.y, ndcMin.z, 1.0f);
+				corner[2] = gMatInvProj * vec4(ndcMax.x, ndcMax.y, ndcMin.z, 1.0f);
+				corner[3] = gMatInvProj * vec4(ndcMin.x, ndcMax.y, ndcMin.z, 1.0f);
+			
+				// Far
+				corner[4] = gMatInvProj * vec4(ndcMin.x, ndcMin.y, ndcMax.z, 1.0f);
+				corner[5] = gMatInvProj * vec4(ndcMax.x, ndcMin.y, ndcMax.z, 1.0f);
+				corner[6] = gMatInvProj * vec4(ndcMax.x, ndcMax.y, ndcMax.z, 1.0f);
+				corner[7] = gMatInvProj * vec4(ndcMin.x, ndcMax.y, ndcMax.z, 1.0f);
 			
 			
-				vec4 clipMin = gMatInvProj * vec4(ndcMin, 1.0f);
-				vec4 clipMax = gMatInvProj * vec4(ndcMax, 1.0f);
+				for(uint i = 0; i < 8; ++i)
+					corner[i].xy /= corner[i].w;
+			
+				vec3 viewMin = vec3(corner[0].xy, viewZMin);
+				vec3 viewMax = vec3(corner[0].xy, viewZMax);
 				
 				
-				vec3 viewMin = vec3(clipMin.xy / clipMin.w, viewZMin);
-				vec3 viewMax = vec3(clipMax.xy / clipMax.w, viewZMax);				
+				for(uint i = 1; i < 8; ++i)
+				{
+					viewMin.xy = min(viewMin.xy, corner[i].xy);
+					viewMax.xy = max(viewMax.xy, corner[i].xy);
+				}		
 				
 				
 				extent = (viewMax - viewMin) * 0.5f;
 				extent = (viewMax - viewMin) * 0.5f;
 				center = viewMin + extent;
 				center = viewMin + extent;
@@ -248,7 +245,7 @@ Technique
 							{
 							{
 								uint prevLink = imageAtomicExchange(gLinkedListHeads, int(cellIdx), nextLink);
 								uint prevLink = imageAtomicExchange(gLinkedListHeads, int(cellIdx), nextLink);
 								
 								
-								imageStore(gLinkedList, int(nextLink), uvec4(i, prevLink, 0, 0));
+								imageStore(gLinkedList, int(nextLink), uvec4(i, type, prevLink, 0));
 							}
 							}
 						}
 						}
 					}
 					}

+ 43 - 46
Data/Raw/Engine/Shaders/LightGridLLReduction.bsl

@@ -1,6 +1,9 @@
 #include "$ENGINE$\PerCameraData.bslinc"
 #include "$ENGINE$\PerCameraData.bslinc"
+#include "$ENGINE$\LightGridCommon.bslinc"
 
 
-Technique : inherits("PerCameraData") = 
+Technique 
+ : inherits("PerCameraData")
+ : inherits("LightGridCommon") = 
 {
 {
 	Language = "HLSL11";
 	Language = "HLSL11";
 	
 	
@@ -8,22 +11,11 @@ Technique : inherits("PerCameraData") =
 	{
 	{
 		Compute = 
 		Compute = 
 		{
 		{
-			cbuffer Params : register(b0)
-			{
-				// 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 gNumCells;
-				uint3 gGridSize;
-				uint gMaxNumLightsPerCell;
-			}
-			
 			Buffer<uint> gLinkedListHeads : register(t0);
 			Buffer<uint> gLinkedListHeads : register(t0);
-			Buffer<uint2> gLinkedList : register(t1);
+			Buffer<uint4> gLinkedList : register(t1);
 			
 			
 			RWBuffer<uint> gGridDataCounter : register(u0);
 			RWBuffer<uint> gGridDataCounter : register(u0);
-			RWBuffer<uint2> gGridLightOffsetAndSize : register(u1);
+			RWBuffer<uint4> gGridLightOffsetAndSize : register(u1);
 			RWBuffer<uint> gGridLightIndices : register(u2);
 			RWBuffer<uint> gGridLightIndices : register(u2);
 			
 			
 			[numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
 			[numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
@@ -43,29 +35,36 @@ Technique : inherits("PerCameraData") =
 				
 				
 				// First count total number of lights affecting the tile
 				// First count total number of lights affecting the tile
 				uint currentIdx = gLinkedListHeads[cellIdx];
 				uint currentIdx = gLinkedListHeads[cellIdx];
-				uint numLights = 0;
+				uint numRadialLights = 0;
+				uint numSpotLights = 0;
 				while(currentIdx != 0xFFFFFFFF)
 				while(currentIdx != 0xFFFFFFFF)
 				{
 				{
-					numLights++;
-					currentIdx = gLinkedList[currentIdx].y;
+					uint4 entry = gLinkedList[currentIdx];
+				
+					if(entry.y == 1) // Radial
+						numRadialLights++;
+					else // Spot
+						numSpotLights++;
+
+					currentIdx = entry.z;
 				}
 				}
 				
 				
 				// Allocate enough room and remember the offset to indices
 				// Allocate enough room and remember the offset to indices
+				uint numLights = numRadialLights + numSpotLights;
 				uint indicesStart;
 				uint indicesStart;
 				InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
 				InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
-				gGridLightOffsetAndSize[cellIdx] = uint2(indicesStart, numLights);
+				gGridLightOffsetAndSize[cellIdx] = uint4(indicesStart, numRadialLights, numSpotLights, 0);
 				
 				
-				// Actually write light indices
-				// Note: Values are written in the reverse order than they were found in
+				// Actually write light indices (reverse order, so that radial lights come first, as is the convention)
 				currentIdx = gLinkedListHeads[cellIdx];
 				currentIdx = gLinkedListHeads[cellIdx];
 				uint lightIdx = 0;
 				uint lightIdx = 0;
 				while(currentIdx != 0xFFFFFFFF)
 				while(currentIdx != 0xFFFFFFFF)
 				{
 				{
-					uint2 entry = gLinkedList[currentIdx];
+					uint4 entry = gLinkedList[currentIdx];
 				
 				
-					gGridLightIndices[indicesStart + lightIdx] = entry.x;
+					gGridLightIndices[indicesStart + numLights - 1 - lightIdx] = entry.x;
 					
 					
-					currentIdx = entry.y;
+					currentIdx = entry.z;
 					lightIdx++;
 					lightIdx++;
 				}
 				}
 			}
 			}
@@ -73,7 +72,9 @@ Technique : inherits("PerCameraData") =
 	};
 	};
 };
 };
 
 
-Technique : inherits("PerCameraData") = 
+Technique 
+ : inherits("PerCameraData")
+ : inherits("LightGridCommon") = 
 {
 {
 	Language = "GLSL";
 	Language = "GLSL";
 	
 	
@@ -83,23 +84,12 @@ Technique : inherits("PerCameraData") =
 		{
 		{
 			layout (local_size_x = THREADGROUP_SIZE, local_size_y = THREADGROUP_SIZE, local_size_z = THREADGROUP_SIZE) in;
 			layout (local_size_x = THREADGROUP_SIZE, local_size_y = THREADGROUP_SIZE, local_size_z = THREADGROUP_SIZE) in;
 		
 		
-			layout(binding = 0, std140) uniform Params
-			{
-				// 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;
-			};
-			
 			layout(binding = 1) uniform usamplerBuffer gLinkedListHeads;
 			layout(binding = 1) uniform usamplerBuffer gLinkedListHeads;
 			layout(binding = 2) uniform usamplerBuffer gLinkedList;
 			layout(binding = 2) uniform usamplerBuffer gLinkedList;
 			
 			
 			layout(binding = 3, r32ui) uniform uimageBuffer gGridDataCounter;
 			layout(binding = 3, r32ui) uniform uimageBuffer gGridDataCounter;
-			layout(binding = 4, rg32ui) uniform uimageBuffer gGridLightOffsetAndSize;
-			layout(binding = 5, r32ui) uniform uimageBuffer gGridLightIndices;
+			layout(binding = 5, rgba32ui) uniform uimageBuffer gGridLightOffsetAndSize;
+			layout(binding = 6, r32ui) uniform uimageBuffer gGridLightIndices;
 			
 			
 			void main()
 			void main()
 			{
 			{
@@ -114,28 +104,35 @@ Technique : inherits("PerCameraData") =
 				
 				
 				// First count total number of lights affecting the tile
 				// First count total number of lights affecting the tile
 				int currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
 				int currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
-				uint numLights = 0;
+				uint numRadialLights = 0;
+				uint numSpotLights = 0;
 				while(currentIdx != 0xFFFFFFFF)
 				while(currentIdx != 0xFFFFFFFF)
 				{
 				{
-					numLights++;
-					currentIdx = int(texelFetch(gLinkedList, currentIdx).y);
+					uvec3 entry = texelFetch(gLinkedList, currentIdx).xyz;
+				
+					if(entry.y == 1) // Radial
+						numRadialLights++;
+					else // Spot
+						numSpotLights++;
+
+					currentIdx = int(entry.z);
 				}
 				}
 				
 				
 				// Allocate enough room and remember the offset to indices
 				// Allocate enough room and remember the offset to indices
+				uint numLights = numRadialLights + numSpotLights;
 				uint indicesStart = imageAtomicAdd(gGridDataCounter, 0, numLights);
 				uint indicesStart = imageAtomicAdd(gGridDataCounter, 0, numLights);
-				imageStore(gGridLightOffsetAndSize, cellIdx, uvec4(indicesStart, numLights, 0, 0));
+				imageStore(gGridLightOffsetAndSize, cellIdx, uvec4(indicesStart, numRadialLights, numSpotLights, 0));
 
 
-				// Actually write light indices
-				// Note: Values are written in the reverse order than they were found in
+				// Actually write light indices (reverse order, so that radial lights come first, as is the convention)
 				currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
 				currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
 				uint lightIdx = 0;
 				uint lightIdx = 0;
 				while(currentIdx != 0xFFFFFFFF)
 				while(currentIdx != 0xFFFFFFFF)
 				{
 				{
-					uvec2 entry = texelFetch(gLinkedList, currentIdx).xy;
+					uvec3 entry = texelFetch(gLinkedList, currentIdx).xyz;
 				
 				
-					imageStore(gGridLightIndices, int(indicesStart + lightIdx), uvec4(entry.x, 0, 0, 0));
+					imageStore(gGridLightIndices, int(indicesStart + numLights - 1 - lightIdx), uvec4(entry.x, 0, 0, 0));
 					
 					
-					currentIdx = int(entry.y);
+					currentIdx = int(entry.z);
 					lightIdx++;
 					lightIdx++;
 				}
 				}
 			}
 			}

+ 1 - 1
Data/Raw/Engine/Shaders/TiledDeferredLighting.bsl

@@ -329,7 +329,7 @@ Technique
 				return decodeGBuffer(GBufferAData, GBufferBData, deviceZ);
 				return decodeGBuffer(GBufferAData, GBufferBData, deviceZ);
 			}	
 			}	
 			
 			
-			layout(std430, binding = 4) buffer gLights
+			layout(std430, binding = 4) readonly buffer gLights
 			{
 			{
 				LightData[] gLightsData;
 				LightData[] gLightsData;
 			};
 			};

+ 61 - 35
Data/Raw/Engine/Shaders/Transparent.bsl

@@ -1,5 +1,6 @@
 #include "$ENGINE$\BasePass.bslinc"
 #include "$ENGINE$\BasePass.bslinc"
 #include "$ENGINE$\LightingCommon.bslinc"
 #include "$ENGINE$\LightingCommon.bslinc"
+#include "$ENGINE$\LightGridCommon.bslinc"
 
 
 Parameters =
 Parameters =
 {
 {
@@ -21,6 +22,7 @@ Transparent = true;
 
 
 Technique 
 Technique 
  : inherits("LightingCommon")
  : inherits("LightingCommon")
+ : inherits("LightGridCommon")
  : base("Surface") =
  : base("Surface") =
 {
 {
 	Language = "HLSL11";
 	Language = "HLSL11";
@@ -43,16 +45,10 @@ Technique
 			Texture2D gAlbedoTex : register(t0);
 			Texture2D gAlbedoTex : register(t0);
 			Texture2D gNormalTex : register(t1);
 			Texture2D gNormalTex : register(t1);
 			
 			
-			StructuredBuffer<LightData> gLights : register(t2);
-		
-			cbuffer LightParams : 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;
-			}
-			
+			Buffer<uint3> gGridOffsetsAndSize : register(t2);
+			Buffer<uint> gGridLightIndices : register(t3);
+			StructuredBuffer<LightData> gLights : register(t4);
+
 			cbuffer MaterialParams : register(b5)
 			cbuffer MaterialParams : register(b5)
 			{
 			{
 				float gOpacity;
 				float gOpacity;
@@ -60,7 +56,7 @@ Technique
 			
 			
 			float4 main(in VStoFS input) : SV_Target0
 			float4 main(in VStoFS input) : SV_Target0
 			{
 			{
-				float3 normal = normalize(gNormalTex.Sample(gNormalSamp, input.uv0) * 2.0f - float3(1, 1, 1));
+				float3 normal = normalize(gNormalTex.Sample(gNormalSamp, input.uv0).xyz * 2.0f - float3(1, 1, 1));
 				float3 worldNormal = calcWorldNormal(input, normal);
 				float3 worldNormal = calcWorldNormal(input, normal);
 			
 			
 				SurfaceData surfaceData;
 				SurfaceData surfaceData;
@@ -68,14 +64,35 @@ Technique
 				surfaceData.worldNormal.xyz = worldNormal;
 				surfaceData.worldNormal.xyz = worldNormal;
 				
 				
 				float3 lightAccumulator = 0;
 				float3 lightAccumulator = 0;
-				for(uint i = 0; i < gLightOffsets[0]; ++i)
-					lightAccumulator += getDirLightContibution(surfaceData, gLights[i]);
 				
 				
-				for (uint i = gLightOffsets[0]; i < gLightOffsets[1]; ++i)
-					lightAccumulator += getPointLightContribution(input.worldPosition, surfaceData, gLights[i]);
-
-				for(uint i = gLightOffsets[1]; i < gLightOffsets[2]; ++i)
-					lightAccumulator += getSpotLightContribution(input.worldPosition, surfaceData, gLights[i]);
+				// Directional lights
+				for(uint lightIdx = 0; lightIdx < gLightOffsets[0]; ++lightIdx)
+					lightAccumulator += getDirLightContibution(surfaceData, gLights[lightIdx]);
+				
+				uint2 pixelPos = (uint2)input.position.xy;
+				uint cellIdx = calcCellIdx(pixelPos, input.position.z);
+				uint3 offsetAndSize = gGridOffsetsAndSize[cellIdx];
+				
+				// Radial lights
+				uint i = offsetAndSize.x;
+				uint end = offsetAndSize.x + offsetAndSize.y;
+				for(; i < end; i++)
+				{
+					uint lightIndex = gGridLightIndices[i];
+					LightData lightData = gLights[lightIndex];
+					
+					lightAccumulator += getPointLightContribution(input.worldPosition, surfaceData, lightData);
+				}
+				
+				// Spot lights
+				end += offsetAndSize.z;
+				for(; i < end; i++)
+				{
+					uint lightIndex = gGridLightIndices[i];
+					LightData lightData = gLights[lightIndex];
+					
+					lightAccumulator += getSpotLightContribution(input.worldPosition, surfaceData, lightData);
+				}
 				
 				
 				float3 diffuse = surfaceData.albedo.xyz / PI;
 				float3 diffuse = surfaceData.albedo.xyz / PI;
 				return float4(diffuse * lightAccumulator, gOpacity); // TODO - Add better lighting model later
 				return float4(diffuse * lightAccumulator, gOpacity); // TODO - Add better lighting model later
@@ -86,6 +103,7 @@ Technique
 
 
 Technique 
 Technique 
  : inherits("LightingCommon")
  : inherits("LightingCommon")
+ : inherits("LightGridCommon")
  : base("Surface") =
  : base("Surface") =
 {
 {
 	Language = "GLSL";
 	Language = "GLSL";
@@ -107,23 +125,17 @@ Technique
 			layout(location = 2) in vec3 tangentToWorldZ;
 			layout(location = 2) in vec3 tangentToWorldZ;
 			layout(location = 3) in vec4 tangentToWorldX;			
 			layout(location = 3) in vec4 tangentToWorldX;			
 		
 		
-			layout(binding = 4) uniform sampler2D gAlbedoTex;
-			layout(binding = 5) uniform sampler2D gNormalTex;
+			layout(binding = 5) uniform sampler2D gAlbedoTex;
+			layout(binding = 6) uniform sampler2D gNormalTex;
 
 
-			layout(std430, binding = 6) buffer gLights
+			layout(binding = 7) uniform usamplerBuffer gGridOffsetsAndSize;
+			layout(binding = 8) uniform usamplerBuffer gGridLightIndices;
+			layout(std430, binding = 9) readonly buffer gLights
 			{
 			{
 				LightData[] gLightsData;
 				LightData[] gLightsData;
 			};
 			};
 						
 						
-			layout(binding = 7, std140) uniform LightParams
-			{
-				// 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;
-			};
-			
-			layout(binding = 8, std140) uniform MaterialParams
+			layout(binding = 10, std140) uniform MaterialParams
 			{
 			{
 				float gOpacity;
 				float gOpacity;
 			};
 			};
@@ -139,6 +151,7 @@ Technique
 				surfaceData.albedo = texture(gAlbedoTex, uv0);
 				surfaceData.albedo = texture(gAlbedoTex, uv0);
 				surfaceData.worldNormal.xyz = worldNormal;
 				surfaceData.worldNormal.xyz = worldNormal;
 				
 				
+				// Directional lights
 				vec3 lightAccumulator = vec3(0, 0, 0);
 				vec3 lightAccumulator = vec3(0, 0, 0);
 				for(uint i = 0; i < gLightOffsets[0]; ++i)
 				for(uint i = 0; i < gLightOffsets[0]; ++i)
 				{
 				{
@@ -146,15 +159,28 @@ Technique
 					lightAccumulator += getDirLightContibution(surfaceData, lightData);
 					lightAccumulator += getDirLightContibution(surfaceData, lightData);
 				}
 				}
 				
 				
-				for (uint i = gLightOffsets[0]; i < gLightOffsets[1]; ++i)
+				uvec2 pixelPos = uvec2(gl_FragCoord.xy);
+				int cellIdx = calcCellIdx(pixelPos, gl_FragCoord.z);
+				uvec3 offsetAndSize = texelFetch(gGridOffsetsAndSize, cellIdx).xyz;
+				
+				// Radial lights
+				int i = int(offsetAndSize.x);
+				uint end = offsetAndSize.x + offsetAndSize.y;
+				for(; i < end; i++)
 				{
 				{
-					LightData lightData = gLightsData[i];
+					uint lightIndex = texelFetch(gGridLightIndices, i).x;
+					LightData lightData = gLightsData[lightIndex];
+					
 					lightAccumulator += getPointLightContribution(worldPosition, surfaceData, lightData);
 					lightAccumulator += getPointLightContribution(worldPosition, surfaceData, lightData);
 				}
 				}
-
-				for(uint i = gLightOffsets[1]; i < gLightOffsets[2]; ++i)
+				
+				// Spot lights
+				end += offsetAndSize.z;
+				for(; i < end; i++)
 				{
 				{
-					LightData lightData = gLightsData[i];
+					uint lightIndex = texelFetch(gGridLightIndices, i).x;
+					LightData lightData = gLightsData[lightIndex];
+					
 					lightAccumulator += getSpotLightContribution(worldPosition, surfaceData, lightData);
 					lightAccumulator += getSpotLightContribution(worldPosition, surfaceData, lightData);
 				}
 				}
 				
 				

+ 22 - 3
Source/BansheeD3D11RenderAPI/Source/BsD3D11GpuBufferView.cpp

@@ -6,6 +6,7 @@
 #include "BsD3D11Device.h"
 #include "BsD3D11Device.h"
 #include "BsRenderStats.h"
 #include "BsRenderStats.h"
 #include "BsException.h"
 #include "BsException.h"
+#include "BsD3D11Mappings.h"
 
 
 namespace bs { namespace ct
 namespace bs { namespace ct
 {
 {
@@ -74,7 +75,14 @@ namespace bs { namespace ct
 		D3D11_SHADER_RESOURCE_VIEW_DESC desc;
 		D3D11_SHADER_RESOURCE_VIEW_DESC desc;
 		ZeroMemory(&desc, sizeof(desc));
 		ZeroMemory(&desc, sizeof(desc));
 
 
-		if (props.getType() == GBT_STRUCTURED || props.getType() == GBT_STANDARD)
+		if (props.getType() == GBT_STANDARD)
+		{
+			desc.Format = D3D11Mappings::getBF(props.getFormat());
+			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+			desc.Buffer.FirstElement = firstElement;
+			desc.Buffer.NumElements = numElements;
+		}
+		else if (props.getType() == GBT_STRUCTURED)
 		{
 		{
 			desc.Format = DXGI_FORMAT_UNKNOWN;
 			desc.Format = DXGI_FORMAT_UNKNOWN;
 			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
 			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
@@ -121,7 +129,18 @@ namespace bs { namespace ct
 
 
 		desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
 		desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
 
 
-		if (props.getType() == GBT_STRUCTURED || props.getType() == GBT_STANDARD)
+		if (props.getType() == GBT_STANDARD)
+		{
+			desc.Format = D3D11Mappings::getBF(props.getFormat());
+			desc.Buffer.FirstElement = firstElement;
+			desc.Buffer.NumElements = numElements;
+
+			if (useCounter)
+				desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER;
+			else
+				desc.Buffer.Flags = 0;
+		} 
+		else if (props.getType() == GBT_STRUCTURED)
 		{
 		{
 			desc.Format = DXGI_FORMAT_UNKNOWN;
 			desc.Format = DXGI_FORMAT_UNKNOWN;
 			desc.Buffer.FirstElement = firstElement;
 			desc.Buffer.FirstElement = firstElement;
@@ -167,4 +186,4 @@ namespace bs { namespace ct
 
 
 		return uav;
 		return uav;
 	}
 	}
-}}
+}}

+ 8 - 4
Source/RenderBeast/Include/BsLightGrid.h

@@ -9,6 +9,8 @@
 
 
 namespace bs { namespace ct
 namespace bs { namespace ct
 {
 {
+	class GPULightData;
+
 	/** @addtogroup RenderBeast
 	/** @addtogroup RenderBeast
 	 *  @{
 	 *  @{
 	 */
 	 */
@@ -18,6 +20,7 @@ namespace bs { namespace ct
 		BS_PARAM_BLOCK_ENTRY(INT32, gNumCells)
 		BS_PARAM_BLOCK_ENTRY(INT32, gNumCells)
 		BS_PARAM_BLOCK_ENTRY(Vector3I, gGridSize)
 		BS_PARAM_BLOCK_ENTRY(Vector3I, gGridSize)
 		BS_PARAM_BLOCK_ENTRY(INT32, gMaxNumLightsPerCell)
 		BS_PARAM_BLOCK_ENTRY(INT32, gMaxNumLightsPerCell)
+		BS_PARAM_BLOCK_ENTRY(Vector2I, gGridPixelSize)
 	BS_PARAM_BLOCK_END
 	BS_PARAM_BLOCK_END
 
 
 	extern LightGridParamDef gLightGridParamDefDef;
 	extern LightGridParamDef gLightGridParamDefDef;
@@ -96,19 +99,20 @@ namespace bs { namespace ct
 		LightGrid();
 		LightGrid();
 
 
 		/** Updates the light grid from the provided view. */
 		/** Updates the light grid from the provided view. */
-		void updateGrid(const RendererCamera& view, const SPtr<GpuBuffer>& lightsBuffer, UINT32 numDirLights, 
-						UINT32 numRadialLights, UINT32 numSpotLights);
+		void updateGrid(const RendererCamera& view, const GPULightData& lightData);
 
 
 		/** 
 		/** 
-		 * Returns the buffers containing light indices per grid cell. 
+		 * Returns the buffers containing light indices per grid cell and global grid parameters. 
 		 *
 		 *
 		 * @param[out]	gridOffsetsAndSize	Flattened array of grid cells, where each entry contains the number of lights
 		 * @param[out]	gridOffsetsAndSize	Flattened array of grid cells, where each entry contains the number of lights
 		 *									affecting that cell, and a index into the @p gridLightIndices buffer.
 		 *									affecting that cell, and a index into the @p gridLightIndices buffer.
 		 * @param[out]	gridLightIndices	A list of light indices. Each cell's indices start at specific position and
 		 * @param[out]	gridLightIndices	A list of light indices. Each cell's indices start at specific position and
 		 *									are placed sequentially one after another. Lookup into this array is done
 		 *									are placed sequentially one after another. Lookup into this array is done
 		 *									through offset & size provided by @p gridOffsetsAndSize. 
 		 *									through offset & size provided by @p gridOffsetsAndSize. 
+		 * @param[out]	gridParams			Global grid parameter block.
 		 */
 		 */
-		void getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices) const;
+		void getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices, 
+						SPtr<GpuParamBlockBuffer>& gridParams) const;
 
 
 	private:
 	private:
 		LightGridLLCreationMat mLLCreationMat;
 		LightGridLLCreationMat mLLCreationMat;

+ 11 - 0
Source/RenderBeast/Include/BsLightRendering.h

@@ -56,9 +56,20 @@ namespace bs { namespace ct
 		/** Returns a GPU bindable param buffer containing meta-data about light in the ligth buffer. */
 		/** Returns a GPU bindable param buffer containing meta-data about light in the ligth buffer. */
 		SPtr<GpuParamBlockBuffer> getParamBuffer() const { return mParamBuffer; }
 		SPtr<GpuParamBlockBuffer> getParamBuffer() const { return mParamBuffer; }
 
 
+		/** Returns the number of directional lights in the lights buffer. */
+		UINT32 getNumDirLights() const { return mNumLights[0]; }
+
+		/** Returns the number of radial point lights in the lights buffer. */
+		UINT32 getNumRadialLights() const { return mNumLights[1]; }
+
+		/** Returns the number of spot point lights in the lights buffer. */
+		UINT32 getNumSpotLights() const { return mNumLights[2]; }
+
 	private:
 	private:
 		SPtr<GpuParamBlockBuffer> mParamBuffer;
 		SPtr<GpuParamBlockBuffer> mParamBuffer;
 		SPtr<GpuBuffer> mLightBuffer;
 		SPtr<GpuBuffer> mLightBuffer;
+
+		UINT32 mNumLights[3];
 	};
 	};
 
 
 	BS_PARAM_BLOCK_BEGIN(TiledLightingParamDef)
 	BS_PARAM_BLOCK_BEGIN(TiledLightingParamDef)

+ 3 - 0
Source/RenderBeast/Include/BsRenderBeast.h

@@ -19,6 +19,8 @@ namespace bs
 
 
 	namespace ct
 	namespace ct
 	{
 	{
+	class LightGrid;
+
 	/** @addtogroup RenderBeast
 	/** @addtogroup RenderBeast
 	 *  @{
 	 *  @{
 	 */
 	 */
@@ -220,6 +222,7 @@ namespace bs
 		SkyboxMat* mSkyboxMat;
 		SkyboxMat* mSkyboxMat;
 
 
 		GPULightData* mGPULightData;
 		GPULightData* mGPULightData;
+		LightGrid* mLightGrid;
 
 
 		ObjectRenderer* mObjectRenderer;
 		ObjectRenderer* mObjectRenderer;
 
 

+ 10 - 1
Source/RenderBeast/Include/BsRendererObject.h

@@ -65,7 +65,16 @@ namespace bs { namespace ct
 		UINT32 perCameraBindingIdx;
 		UINT32 perCameraBindingIdx;
 
 
 		/** Index to which should the lights param block buffer be bound to. */
 		/** Index to which should the lights param block buffer be bound to. */
-		UINT32 lightParamsBindingIdx;
+		UINT32 gridParamsBindingIdx;
+
+		/** 
+		 * Parameter to which to bind a buffer containing light grid offsets and size, per grid cell. Used for forward
+		 * rendering. 
+		 */
+		GpuParamBuffer gridOffsetsAndSizeParam;
+
+		/** Parameter to which to bind a buffer containing all light indices, as mapped by grid offsets & size. */
+		GpuParamBuffer gridLightIndicesParam;
 
 
 		/** Parameter to which to bind light buffer used for forward rendering. */
 		/** Parameter to which to bind light buffer used for forward rendering. */
 		GpuParamBuffer lightsBufferParam;
 		GpuParamBuffer lightsBufferParam;

+ 19 - 12
Source/RenderBeast/Source/BsLightGrid.cpp

@@ -6,6 +6,7 @@
 #include "BsRendererUtility.h"
 #include "BsRendererUtility.h"
 #include "BsRendererCamera.h"
 #include "BsRendererCamera.h"
 #include "BsRenderTargets.h"
 #include "BsRenderTargets.h"
+#include "BsLightRendering.h"
 
 
 namespace bs { namespace ct
 namespace bs { namespace ct
 {
 {
@@ -31,6 +32,7 @@ namespace bs { namespace ct
 		desc.format = BF_32X1U;
 		desc.format = BF_32X1U;
 		desc.randomGpuWrite = true;
 		desc.randomGpuWrite = true;
 		desc.type = GBT_STANDARD;
 		desc.type = GBT_STANDARD;
+		desc.elementSize = 0;
 
 
 		mLinkedListCounter = GpuBuffer::create(desc);
 		mLinkedListCounter = GpuBuffer::create(desc);
 		mLinkedListCounterParam.set(mLinkedListCounter);
 		mLinkedListCounterParam.set(mLinkedListCounter);
@@ -54,11 +56,12 @@ namespace bs { namespace ct
 			desc.format = BF_32X1U;
 			desc.format = BF_32X1U;
 			desc.randomGpuWrite = true;
 			desc.randomGpuWrite = true;
 			desc.type = GBT_STANDARD;
 			desc.type = GBT_STANDARD;
+			desc.elementSize = 0;
 
 
 			mLinkedListHeads = GpuBuffer::create(desc);
 			mLinkedListHeads = GpuBuffer::create(desc);
 			mLinkedListHeadsParam.set(mLinkedListHeads);
 			mLinkedListHeadsParam.set(mLinkedListHeads);
 
 
-			desc.format = BF_32X2U;
+			desc.format = BF_32X4U;
 			desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
 			desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
 
 
 			mLinkedList = GpuBuffer::create(desc);
 			mLinkedList = GpuBuffer::create(desc);
@@ -78,7 +81,7 @@ namespace bs { namespace ct
 
 
 		bs_stack_free(headsClearData);
 		bs_stack_free(headsClearData);
 
 
-		mParamsSet->setParamBlockBuffer("Params", gridParams, true);
+		mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
 		mLightBufferParam.set(lightsBuffer);
 		mLightBufferParam.set(lightsBuffer);
 	}
 	}
 
 
@@ -122,6 +125,7 @@ namespace bs { namespace ct
 		desc.format = BF_32X1U;
 		desc.format = BF_32X1U;
 		desc.randomGpuWrite = true;
 		desc.randomGpuWrite = true;
 		desc.type = GBT_STANDARD;
 		desc.type = GBT_STANDARD;
+		desc.elementSize = 0;
 
 
 		mGridDataCounter = GpuBuffer::create(desc);
 		mGridDataCounter = GpuBuffer::create(desc);
 		mGridDataCounterParam.set(mGridDataCounter);
 		mGridDataCounterParam.set(mGridDataCounter);
@@ -142,14 +146,15 @@ namespace bs { namespace ct
 		{
 		{
 			GPU_BUFFER_DESC desc;
 			GPU_BUFFER_DESC desc;
 			desc.elementCount = numCells;
 			desc.elementCount = numCells;
-			desc.format = BF_32X1U;
+			desc.format = BF_32X4U;
 			desc.randomGpuWrite = true;
 			desc.randomGpuWrite = true;
 			desc.type = GBT_STANDARD;
 			desc.type = GBT_STANDARD;
+			desc.elementSize = 0;
 
 
 			mGridLightOffsetAndSize = GpuBuffer::create(desc);
 			mGridLightOffsetAndSize = GpuBuffer::create(desc);
 			mGridLightOffsetAndSizeParam.set(mGridLightOffsetAndSize);
 			mGridLightOffsetAndSizeParam.set(mGridLightOffsetAndSize);
 
 
-			desc.format = BF_32X2U;
+			desc.format = BF_32X1U;
 			desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
 			desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
 			mGridLightIndices = GpuBuffer::create(desc);
 			mGridLightIndices = GpuBuffer::create(desc);
 			mGridLightIndicesParam.set(mGridLightIndices);
 			mGridLightIndicesParam.set(mGridLightIndices);
@@ -161,7 +166,7 @@ namespace bs { namespace ct
 		UINT32 zero = 0;
 		UINT32 zero = 0;
 		mGridDataCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
 		mGridDataCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
 
 
-		mParamsSet->setParamBlockBuffer("Params", gridParams, true);
+		mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
 		mLinkedListHeadsParam.set(linkedListHeads);
 		mLinkedListHeadsParam.set(linkedListHeads);
 		mLinkedListParam.set(linkedList);
 		mLinkedListParam.set(linkedList);
 	}
 	}
@@ -191,8 +196,7 @@ namespace bs { namespace ct
 		mGridParamBuffer = gLightGridParamDefDef.createBuffer();
 		mGridParamBuffer = gLightGridParamDefDef.createBuffer();
 	}
 	}
 
 
-	void LightGrid::updateGrid(const RendererCamera& view, const SPtr<GpuBuffer>& lightsBuffer, UINT32 numDirLights,
-					UINT32 numRadialLights, UINT32 numSpotLights)
+	void LightGrid::updateGrid(const RendererCamera& view, const GPULightData& lightData)
 	{
 	{
 		UINT32 width = view.getRenderTargets()->getWidth();
 		UINT32 width = view.getRenderTargets()->getWidth();
 		UINT32 height = view.getRenderTargets()->getHeight();
 		UINT32 height = view.getRenderTargets()->getHeight();
@@ -203,9 +207,9 @@ namespace bs { namespace ct
 		gridSize[2] = NUM_Z_SUBDIVIDES;
 		gridSize[2] = NUM_Z_SUBDIVIDES;
 
 
 		Vector3I lightOffsets;
 		Vector3I lightOffsets;
-		lightOffsets[0] = numDirLights;
-		lightOffsets[1] = lightOffsets[0] + numRadialLights;
-		lightOffsets[2] = lightOffsets[1] + numSpotLights;
+		lightOffsets[0] = lightData.getNumDirLights();
+		lightOffsets[1] = lightOffsets[0] + lightData.getNumRadialLights();
+		lightOffsets[2] = lightOffsets[1] + lightData.getNumSpotLights();
 
 
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
 
 
@@ -213,8 +217,9 @@ namespace bs { namespace ct
 		gLightGridParamDefDef.gNumCells.set(mGridParamBuffer, numCells);
 		gLightGridParamDefDef.gNumCells.set(mGridParamBuffer, numCells);
 		gLightGridParamDefDef.gGridSize.set(mGridParamBuffer, gridSize);
 		gLightGridParamDefDef.gGridSize.set(mGridParamBuffer, gridSize);
 		gLightGridParamDefDef.gMaxNumLightsPerCell.set(mGridParamBuffer, MAX_LIGHTS_PER_CELL);
 		gLightGridParamDefDef.gMaxNumLightsPerCell.set(mGridParamBuffer, MAX_LIGHTS_PER_CELL);
+		gLightGridParamDefDef.gGridPixelSize.set(mGridParamBuffer, Vector2I(CELL_XY_SIZE, CELL_XY_SIZE));
 
 
-		mLLCreationMat.setParams(gridSize, mGridParamBuffer, lightsBuffer);
+		mLLCreationMat.setParams(gridSize, mGridParamBuffer, lightData.getLightBuffer());
 		mLLCreationMat.execute(view);
 		mLLCreationMat.execute(view);
 
 
 		SPtr<GpuBuffer> linkedListHeads;
 		SPtr<GpuBuffer> linkedListHeads;
@@ -225,8 +230,10 @@ namespace bs { namespace ct
 		mLLReductionMat.execute(view);
 		mLLReductionMat.execute(view);
 	}
 	}
 
 
-	void LightGrid::getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices) const
+	void LightGrid::getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices, 
+							   SPtr<GpuParamBlockBuffer>& gridParams) const
 	{
 	{
 		mLLReductionMat.getOutputs(gridOffsetsAndSize, gridLightIndices);
 		mLLReductionMat.getOutputs(gridOffsetsAndSize, gridLightIndices);
+		gridParams = mGridParamBuffer;
 	}
 	}
 }}
 }}

+ 5 - 0
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -39,6 +39,7 @@ namespace bs { namespace ct
 	}
 	}
 
 
 	GPULightData::GPULightData()
 	GPULightData::GPULightData()
+		:mNumLights {}
 	{
 	{
 		mParamBuffer = gTiledLightingParamDef.createBuffer();
 		mParamBuffer = gTiledLightingParamDef.createBuffer();
 	}
 	}
@@ -46,6 +47,10 @@ namespace bs { namespace ct
 	void GPULightData::setLights(const Vector<LightData>& lightData, UINT32 numDirLights, UINT32 numRadialLights,
 	void GPULightData::setLights(const Vector<LightData>& lightData, UINT32 numDirLights, UINT32 numRadialLights,
 				   UINT32 numSpotLights)
 				   UINT32 numSpotLights)
 	{
 	{
+		mNumLights[0] = numDirLights;
+		mNumLights[1] = numRadialLights;
+		mNumLights[2] = numSpotLights;
+
 		Vector3I lightOffsets;
 		Vector3I lightOffsets;
 		lightOffsets[0] = numDirLights;
 		lightOffsets[0] = numDirLights;
 		lightOffsets[1] = lightOffsets[0] + numRadialLights;
 		lightOffsets[1] = lightOffsets[0] + numRadialLights;

+ 9 - 3
Source/RenderBeast/Source/BsObjectRendering.cpp

@@ -27,7 +27,7 @@ namespace bs { namespace ct
 		if (shader == nullptr)
 		if (shader == nullptr)
 		{
 		{
 			element.perCameraBindingIdx = -1;
 			element.perCameraBindingIdx = -1;
-			element.lightParamsBindingIdx = -1;
+			element.gridParamsBindingIdx = -1;
 
 
 			LOGWRN("Missing shader on material.");
 			LOGWRN("Missing shader on material.");
 			return;
 			return;
@@ -57,12 +57,18 @@ namespace bs { namespace ct
 			}
 			}
 		}
 		}
 
 
-		element.lightParamsBindingIdx = element.params->getParamBlockBufferIndex("LightParams");
+		element.gridParamsBindingIdx = element.params->getParamBlockBufferIndex("GridParams");
 
 
 		SPtr<GpuParams> gpuParams = element.params->getGpuParams();
 		SPtr<GpuParams> gpuParams = element.params->getGpuParams();
-		if(gpuParams->hasBuffer(GPT_FRAGMENT_PROGRAM, "gLights"))
+		if (gpuParams->hasBuffer(GPT_FRAGMENT_PROGRAM, "gLights"))
 			gpuParams->getBufferParam(GPT_FRAGMENT_PROGRAM, "gLights", element.lightsBufferParam);
 			gpuParams->getBufferParam(GPT_FRAGMENT_PROGRAM, "gLights", element.lightsBufferParam);
 
 
+		if(gpuParams->hasBuffer(GPT_FRAGMENT_PROGRAM, "gGridOffsetsAndSize"))
+			gpuParams->getBufferParam(GPT_FRAGMENT_PROGRAM, "gGridOffsetsAndSize", element.gridOffsetsAndSizeParam);
+
+		if (gpuParams->hasBuffer(GPT_FRAGMENT_PROGRAM, "gGridLightIndices"))
+			gpuParams->getBufferParam(GPT_FRAGMENT_PROGRAM, "gGridLightIndices", element.gridLightIndicesParam);
+
 		const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferDescs = shader->getBufferParams();
 		const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferDescs = shader->getBufferParams();
 		String boneMatricesParamName;
 		String boneMatricesParamName;
 
 

+ 18 - 13
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -33,6 +33,7 @@
 #include "BsRendererExtension.h"
 #include "BsRendererExtension.h"
 #include "BsReflectionCubemap.h"
 #include "BsReflectionCubemap.h"
 #include "BsMeshData.h"
 #include "BsMeshData.h"
+#include "BsLightGrid.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -40,7 +41,8 @@ namespace bs { namespace ct
 {
 {
 	RenderBeast::RenderBeast()
 	RenderBeast::RenderBeast()
 		: mDefaultMaterial(nullptr), mTiledDeferredLightingMat(nullptr), mSkyboxMat(nullptr), mGPULightData(nullptr)
 		: mDefaultMaterial(nullptr), mTiledDeferredLightingMat(nullptr), mSkyboxMat(nullptr), mGPULightData(nullptr)
-		, mObjectRenderer(nullptr), mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true)
+		, mLightGrid(nullptr), mObjectRenderer(nullptr), mOptions(bs_shared_ptr_new<RenderBeastOptions>())
+		, mOptionsDirty(true)
 	{ }
 	{ }
 
 
 	const StringID& RenderBeast::getName() const
 	const StringID& RenderBeast::getName() const
@@ -76,6 +78,7 @@ namespace bs { namespace ct
 		mSkyboxMat = bs_new<SkyboxMat>();
 		mSkyboxMat = bs_new<SkyboxMat>();
 
 
 		mGPULightData = bs_new<GPULightData>();
 		mGPULightData = bs_new<GPULightData>();
+		mLightGrid = bs_new<LightGrid>();
 
 
 		RenderTexturePool::startUp();
 		RenderTexturePool::startUp();
 		PostProcessing::startUp();
 		PostProcessing::startUp();
@@ -104,6 +107,7 @@ namespace bs { namespace ct
 		bs_delete(mTiledDeferredLightingMat);
 		bs_delete(mTiledDeferredLightingMat);
 		bs_delete(mSkyboxMat);
 		bs_delete(mSkyboxMat);
 		bs_delete(mGPULightData);
 		bs_delete(mGPULightData);
+		bs_delete(mLightGrid);
 
 
 		RendererUtility::shutDown();
 		RendererUtility::shutDown();
 
 
@@ -756,15 +760,7 @@ namespace bs { namespace ct
 			// Note: Could this step be moved in notifyRenderableUpdated, so it only triggers when material actually gets
 			// Note: Could this step be moved in notifyRenderableUpdated, so it only triggers when material actually gets
 			// changed? Although it shouldn't matter much because if the internal versions keeping track of dirty params.
 			// changed? Although it shouldn't matter much because if the internal versions keeping track of dirty params.
 			for (auto& element : mRenderables[i]->elements)
 			for (auto& element : mRenderables[i]->elements)
-			{
-				bool isTransparent = (element.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
-				if(isTransparent)
-				{
-					
-				}
-
 				element.material->updateParamsSet(element.params);
 				element.material->updateParamsSet(element.params);
-			}
 
 
 			mRenderables[i]->perObjectParamBuffer->flushToGPU();
 			mRenderables[i]->perObjectParamBuffer->flushToGPU();
 		}
 		}
@@ -789,6 +785,15 @@ namespace bs { namespace ct
 
 
 		Matrix4 viewProj = viewInfo->getViewProjMatrix();
 		Matrix4 viewProj = viewInfo->getViewProjMatrix();
 
 
+		viewInfo->beginRendering(true);
+
+		// Prepare light grid required for transparent object rendering
+		mLightGrid->updateGrid(*viewInfo, *mGPULightData);
+
+		SPtr<GpuParamBlockBuffer> gridParams;
+		SPtr<GpuBuffer> gridOffsetsAndSize, gridLightIndices;
+		mLightGrid->getOutputs(gridOffsetsAndSize, gridLightIndices, gridParams);
+
 		// Assign camera and per-call data to all relevant renderables
 		// Assign camera and per-call data to all relevant renderables
 		const VisibilityInfo& visibility = viewInfo->getVisibilityMasks();
 		const VisibilityInfo& visibility = viewInfo->getVisibilityMasks();
 		UINT32 numRenderables = (UINT32)mRenderables.size();
 		UINT32 numRenderables = (UINT32)mRenderables.size();
@@ -805,15 +810,15 @@ namespace bs { namespace ct
 				if (element.perCameraBindingIdx != -1)
 				if (element.perCameraBindingIdx != -1)
 					element.params->setParamBlockBuffer(element.perCameraBindingIdx, perCameraBuffer, true);
 					element.params->setParamBlockBuffer(element.perCameraBindingIdx, perCameraBuffer, true);
 
 
-				if (element.lightParamsBindingIdx != -1)
-					element.params->setParamBlockBuffer(element.lightParamsBindingIdx, mGPULightData->getParamBuffer(), true);
+				if (element.gridParamsBindingIdx != -1)
+					element.params->setParamBlockBuffer(element.gridParamsBindingIdx, gridParams, true);
 
 
+				element.gridOffsetsAndSizeParam.set(gridOffsetsAndSize);
+				element.gridLightIndicesParam.set(gridLightIndices);
 				element.lightsBufferParam.set(mGPULightData->getLightBuffer());
 				element.lightsBufferParam.set(mGPULightData->getLightBuffer());
 			}
 			}
 		}
 		}
 
 
-		viewInfo->beginRendering(true);
-
 		SPtr<RenderTargets> renderTargets = viewInfo->getRenderTargets();
 		SPtr<RenderTargets> renderTargets = viewInfo->getRenderTargets();
 		renderTargets->bindGBuffer();
 		renderTargets->bindGBuffer();