فهرست منبع

Reflection probe support added to forward path shaders

BearishSun 8 سال پیش
والد
کامیت
9bc64c077b

+ 9 - 7
Data/Raw/Engine/Includes/ImageBasedLighting.bslinc

@@ -1,4 +1,8 @@
-Technique : base("ImageBasedLighting") =
+#include "$ENGINE$\ReflectionCubemapCommon.bslinc"
+
+Technique 
+ : base("ImageBasedLighting")
+ : inherits("ReflectionCubemapCommon") =
 {
 {
 	Language = "HLSL11";
 	Language = "HLSL11";
 
 
@@ -46,6 +50,7 @@ Technique : base("ImageBasedLighting") =
 				uint gReflCubemapNumMips;
 				uint gReflCubemapNumMips;
 				uint gNumProbes;
 				uint gNumProbes;
 				uint gSkyCubemapAvailable;
 				uint gSkyCubemapAvailable;
+				uint gUseReflectionMaps;
 				uint gSkyCubemapNumMips;
 				uint gSkyCubemapNumMips;
 				float gSkyBrightness;
 				float gSkyBrightness;
 			}	
 			}	
@@ -139,10 +144,9 @@ Technique : base("ImageBasedLighting") =
 			
 			
 			float3 gatherReflectionRadiance(float3 worldPos, float3 dir, float roughness, float3 specularColor, uint probeOffset, uint numProbes)
 			float3 gatherReflectionRadiance(float3 worldPos, float3 dir, float roughness, float3 specularColor, uint probeOffset, uint numProbes)
 			{
 			{
-				#if CAPTURING_REFLECTIONS
+				if(gUseReflectionMaps == 0)
 					return specularColor;
 					return specularColor;
-				#else
-				
+										
 				float mipLevel = mapRoughnessToMipLevel(roughness, gReflCubemapNumMips);
 				float mipLevel = mapRoughnessToMipLevel(roughness, gReflCubemapNumMips);
 				
 				
 				float3 output = 0;
 				float3 output = 0;
@@ -180,7 +184,7 @@ Technique : base("ImageBasedLighting") =
 						leftoverContribution *= (1.0f - contribution);
 						leftoverContribution *= (1.0f - contribution);
 					}
 					}
 				}
 				}
-				
+					
 				if(gSkyCubemapAvailable > 0)
 				if(gSkyCubemapAvailable > 0)
 				{
 				{
 					float skyMipLevel = mapRoughnessToMipLevel(roughness, gSkyCubemapNumMips);
 					float skyMipLevel = mapRoughnessToMipLevel(roughness, gSkyCubemapNumMips);
@@ -190,8 +194,6 @@ Technique : base("ImageBasedLighting") =
 				}
 				}
 						
 						
 				return output;
 				return output;
-						
-				#endif
 			}
 			}
 			
 			
 			float3 getImageBasedSpecular(float3 worldPos, float3 V, float3 R, SurfaceData surfaceData, uint probeOffset, uint numProbes)
 			float3 getImageBasedSpecular(float3 worldPos, float3 V, float3 R, SurfaceData surfaceData, uint probeOffset, uint numProbes)

+ 2 - 1
Data/Raw/Engine/Includes/LightGridCommon.bslinc

@@ -11,7 +11,8 @@ Technique : base("LightGridCommon") =
 				// Offsets at which specific light types begin in gLights buffer
 				// Offsets at which specific light types begin in gLights buffer
 				// Assumed directional lights start at 0
 				// Assumed directional lights start at 0
 				// x - offset to point lights, y - offset to spot lights, z - total number of lights
 				// x - offset to point lights, y - offset to spot lights, z - total number of lights
-				uint3 gLightOffsets;			
+				uint3 gLightOffsets;
+				uint gNumReflProbes;
 				uint gNumCells;
 				uint gNumCells;
 				uint3 gGridSize;
 				uint3 gGridSize;
 				uint gMaxNumLightsPerCell;
 				uint gMaxNumLightsPerCell;

+ 41 - 8
Data/Raw/Engine/Shaders/LightGridLLCreation.bsl

@@ -1,6 +1,7 @@
 #include "$ENGINE$\PerCameraData.bslinc"
 #include "$ENGINE$\PerCameraData.bslinc"
 #define USE_LIGHT_GRID_INDICES
 #define USE_LIGHT_GRID_INDICES
 #include "$ENGINE$\LightingCommon.bslinc"
 #include "$ENGINE$\LightingCommon.bslinc"
+#include "$ENGINE$\ImageBasedLighting.bslinc"
 #include "$ENGINE$\LightGridCommon.bslinc"
 #include "$ENGINE$\LightGridCommon.bslinc"
 
 
 Blocks =
 Blocks =
@@ -12,7 +13,8 @@ Blocks =
 Technique
 Technique
  : inherits("PerCameraData")
  : inherits("PerCameraData")
  : inherits("LightingCommon")
  : inherits("LightingCommon")
- : inherits("LightGridCommon") =
+ : inherits("LightGridCommon")
+ : inherits("ImageBasedLighting") =
 {
 {
 	Language = "HLSL11";
 	Language = "HLSL11";
 	
 	
@@ -20,15 +22,22 @@ Technique
 	{
 	{
 		Compute = 
 		Compute = 
 		{
 		{
-			RWBuffer<uint> gLinkedListCounter : register(u0);
-			RWBuffer<uint> gLinkedListHeads : register(u1);
-			RWBuffer<uint4> gLinkedList : register(u2);
-					
+			RWBuffer<uint> gLightsCounter;
+			RWBuffer<uint> gLightsLLHeads;
+			RWBuffer<uint4> gLightsLL;
+				
+			RWBuffer<uint> gProbesCounter;
+			RWBuffer<uint> gProbesLLHeads;
+			RWBuffer<uint2> gProbesLL;
+				
 			// Generates a an axis aligned bounding box in NDC and transforms it to view space.
 			// 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
 			// 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
 			// 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)
 			{
 			{
+				// Note:: AABB calculation in tiled deferred image based lighting shader uses less instructions than this,
+				// see if it can be applied here.
+			
 				// Convert grid XY coordinates to clip coordinates
 				// Convert grid XY coordinates to clip coordinates
 				float2 a = 2.0f / gGridSize.xy;
 				float2 a = 2.0f / gGridSize.xy;
 			
 			
@@ -115,18 +124,42 @@ Technique
 						if(distSqrd <= (lightRadius * lightRadius))
 						if(distSqrd <= (lightRadius * lightRadius))
 						{
 						{
 							uint nextLink;
 							uint nextLink;
-							InterlockedAdd(gLinkedListCounter[0], 1U, nextLink);
+							InterlockedAdd(gLightsCounter[0], 1U, nextLink);
 							
 							
 							if(nextLink < maxNumLinks)
 							if(nextLink < maxNumLinks)
 							{
 							{
 								uint prevLink;
 								uint prevLink;
-								InterlockedExchange(gLinkedListHeads[cellIdx], nextLink, prevLink);
+								InterlockedExchange(gLightsLLHeads[cellIdx], nextLink, prevLink);
 								
 								
-								gLinkedList[nextLink] = uint4(i, type, prevLink, 0);
+								gLightsLL[nextLink] = uint4(i, type, prevLink, 0);
 							}
 							}
 						}
 						}
 					}
 					}
 				}
 				}
+				
+				for(uint i = 0; i < gNumReflProbes; ++i)
+				{
+					float4 probePosition = mul(gMatView, float4(gReflectionProbes[i].position, 1.0f));
+					float probeRadius = gReflectionProbes[i].radius;
+					
+					// Calculate distance from box to light
+					float3 distances = max(abs(probePosition - cellCenter) - cellExtent, 0);
+					float distSqrd = dot(distances, distances);
+					
+					if(distSqrd <= (probeRadius * probeRadius))
+					{
+						uint nextLink;
+						InterlockedAdd(gProbesCounter[0], 1U, nextLink);
+						
+						if(nextLink < maxNumLinks)
+						{
+							uint prevLink;
+							InterlockedExchange(gProbesLLHeads[cellIdx], nextLink, prevLink);
+							
+							gProbesLL[nextLink] = uint2(i, prevLink);
+						}
+					}
+				}
 			}
 			}
 		};
 		};
 	};
 	};

+ 49 - 12
Data/Raw/Engine/Shaders/LightGridLLReduction.bsl

@@ -11,12 +11,19 @@ Technique
 	{
 	{
 		Compute = 
 		Compute = 
 		{
 		{
-			Buffer<uint> gLinkedListHeads : register(t0);
-			Buffer<uint4> gLinkedList : register(t1);
+			Buffer<uint> gLightsLLHeads;
+			Buffer<uint4> gLightsLL;
+						
+			Buffer<uint> gProbesLLHeads;
+			Buffer<uint2> gProbesLL;
 			
 			
-			RWBuffer<uint> gGridDataCounter : register(u0);
-			RWBuffer<uint4> gGridLightOffsetAndSize : register(u1);
-			RWBuffer<uint> gGridLightIndices : register(u2);
+			RWBuffer<uint> gGridDataCounter;
+			
+			RWBuffer<uint4> gGridLightOffsetAndSize;
+			RWBuffer<uint> gGridLightIndices;
+
+			RWBuffer<uint2> gGridProbeOffsetAndSize;
+			RWBuffer<uint> gGridProbeIndices;
 			
 			
 			[numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
 			[numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
 			void main(
 			void main(
@@ -31,13 +38,14 @@ Technique
 				uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;	
 				uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;	
 				uint cellIdx = (dispatchThreadId.z * gGridSize.y + dispatchThreadId.y) * gGridSize.x + dispatchThreadId.x;
 				uint cellIdx = (dispatchThreadId.z * gGridSize.y + dispatchThreadId.y) * gGridSize.x + dispatchThreadId.x;
 				
 				
-				// First count total number of lights affecting the tile
-				uint currentIdx = gLinkedListHeads[cellIdx];
+				// Reduce lights
+				//// First count total number of lights affecting the tile
+				uint currentIdx = gLightsLLHeads[cellIdx];
 				uint numRadialLights = 0;
 				uint numRadialLights = 0;
 				uint numSpotLights = 0;
 				uint numSpotLights = 0;
 				while(currentIdx != 0xFFFFFFFF)
 				while(currentIdx != 0xFFFFFFFF)
 				{
 				{
-					uint4 entry = gLinkedList[currentIdx];
+					uint4 entry = gLightsLL[currentIdx];
 				
 				
 					if(entry.y == 1) // Radial
 					if(entry.y == 1) // Radial
 						numRadialLights++;
 						numRadialLights++;
@@ -47,24 +55,53 @@ Technique
 					currentIdx = entry.z;
 					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 numLights = numRadialLights + numSpotLights;
 				uint indicesStart;
 				uint indicesStart;
 				InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
 				InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
 				gGridLightOffsetAndSize[cellIdx] = uint4(indicesStart, numRadialLights, numSpotLights, 0);
 				gGridLightOffsetAndSize[cellIdx] = uint4(indicesStart, numRadialLights, numSpotLights, 0);
 				
 				
-				// Actually write light indices (reverse order, so that radial lights come first, as is the convention)
-				currentIdx = gLinkedListHeads[cellIdx];
+				//// Actually write light indices (reverse order, so that radial lights come first, as is the convention)
+				currentIdx = gLightsLLHeads[cellIdx];
 				uint lightIdx = 0;
 				uint lightIdx = 0;
 				while(currentIdx != 0xFFFFFFFF)
 				while(currentIdx != 0xFFFFFFFF)
 				{
 				{
-					uint4 entry = gLinkedList[currentIdx];
+					uint4 entry = gLightsLL[currentIdx];
 				
 				
 					gGridLightIndices[indicesStart + numLights - 1 - lightIdx] = entry.x;
 					gGridLightIndices[indicesStart + numLights - 1 - lightIdx] = entry.x;
 					
 					
 					currentIdx = entry.z;
 					currentIdx = entry.z;
 					lightIdx++;
 					lightIdx++;
 				}
 				}
+				
+				// Reduce probes
+				//// First count total number of probes affecting the tile
+				currentIdx = gProbesLLHeads[cellIdx];
+				uint numProbes = 0;
+				while(currentIdx != 0xFFFFFFFF)
+				{
+					uint2 entry = gProbesLL[currentIdx];
+				
+					numProbes++;
+					currentIdx = entry.y;
+				}
+				
+				//// Allocate enough room and remember the offset to indices
+				InterlockedAdd(gGridDataCounter[1], numProbes, indicesStart);
+				gGridProbeOffsetAndSize[cellIdx] = uint2(indicesStart, numProbes);
+				
+				//// Actually write probe indices (reverse order, in order to restore original order since LL was formed in reverse)
+				currentIdx = gProbesLLHeads[cellIdx];
+				uint probeIdx = 0;
+				while(currentIdx != 0xFFFFFFFF)
+				{
+					uint2 entry = gProbesLL[currentIdx];
+				
+					gGridProbeIndices[indicesStart + numProbes - 1 - probeIdx] = entry.x;
+					
+					currentIdx = entry.y;
+					probeIdx++;
+				}
 			}
 			}
 		};
 		};
 	};
 	};

+ 10 - 6
Data/Raw/Engine/Shaders/Transparent.bsl

@@ -59,7 +59,8 @@ Technique
 			Texture2D gRoughnessTex : register(t2);
 			Texture2D gRoughnessTex : register(t2);
 			Texture2D gMetalnessTex : register(t3);
 			Texture2D gMetalnessTex : register(t3);
 			
 			
-			Buffer<uint3> gGridOffsetsAndSize : register(t4);
+			Buffer<uint4> gGridLightOffsetsAndSize;
+			Buffer<uint2> gGridProbeOffsetsAndSize;
 
 
 			cbuffer MaterialParams : register(b5)
 			cbuffer MaterialParams : register(b5)
 			{
 			{
@@ -80,13 +81,15 @@ Technique
 				
 				
 				uint2 pixelPos = (uint2)input.position.xy;
 				uint2 pixelPos = (uint2)input.position.xy;
 				uint cellIdx = calcCellIdx(pixelPos, input.position.z);
 				uint cellIdx = calcCellIdx(pixelPos, input.position.z);
-				uint3 offsetAndSize = gGridOffsetsAndSize[cellIdx];
+				uint3 lightOffsetAndSize = gGridLightOffsetsAndSize[cellIdx].rgb;
 				
 				
 				uint4 lightOffsets;
 				uint4 lightOffsets;
 				lightOffsets.x = gLightOffsets[0];
 				lightOffsets.x = gLightOffsets[0];
-				lightOffsets.y = offsetAndSize.x;
-				lightOffsets.z = lightOffsets.y + offsetAndSize.y;
-				lightOffsets.w = lightOffsets.z + offsetAndSize.z;
+				lightOffsets.y = lightOffsetAndSize.x;
+				lightOffsets.z = lightOffsets.y + lightOffsetAndSize.y;
+				lightOffsets.w = lightOffsets.z + lightOffsetAndSize.z;
+				
+				uint2 reflProbeOffsetAndSize = gGridProbeOffsetsAndSize[cellIdx];
 				
 				
 				float3 V = normalize(gViewOrigin - input.worldPosition);
 				float3 V = normalize(gViewOrigin - input.worldPosition);
 				float3 N = surfaceData.worldNormal.xyz;
 				float3 N = surfaceData.worldNormal.xyz;
@@ -95,7 +98,8 @@ Technique
 				
 				
 				float4 directLighting = getDirectLighting(input.worldPosition, V, specR, surfaceData, lightOffsets);
 				float4 directLighting = getDirectLighting(input.worldPosition, V, specR, surfaceData, lightOffsets);
 				float3 indirectDiffuse = getSkyIndirectDiffuse(surfaceData.worldNormal) * surfaceData.albedo;
 				float3 indirectDiffuse = getSkyIndirectDiffuse(surfaceData.worldNormal) * surfaceData.albedo;
-				float3 imageBasedSpecular = getImageBasedSpecular(input.worldPosition, V, specR, surfaceData, 0, 0);
+				float3 imageBasedSpecular = getImageBasedSpecular(input.worldPosition, V, specR, surfaceData, 
+					reflProbeOffsetAndSize.x, reflProbeOffsetAndSize.y);
 
 
 				float3 totalLighting = directLighting.rgb;
 				float3 totalLighting = directLighting.rgb;
 				totalLighting.rgb += indirectDiffuse;
 				totalLighting.rgb += indirectDiffuse;

+ 65 - 22
Source/RenderBeast/Include/BsImageBasedLighting.h

@@ -49,6 +49,7 @@ namespace bs { namespace ct
 		BS_PARAM_BLOCK_ENTRY(INT32, gReflCubemapNumMips)
 		BS_PARAM_BLOCK_ENTRY(INT32, gReflCubemapNumMips)
 		BS_PARAM_BLOCK_ENTRY(INT32, gNumProbes)
 		BS_PARAM_BLOCK_ENTRY(INT32, gNumProbes)
 		BS_PARAM_BLOCK_ENTRY(INT32, gSkyCubemapAvailable)
 		BS_PARAM_BLOCK_ENTRY(INT32, gSkyCubemapAvailable)
+		BS_PARAM_BLOCK_ENTRY(INT32, gUseReflectionMaps)
 		BS_PARAM_BLOCK_ENTRY(INT32, gSkyCubemapNumMips)
 		BS_PARAM_BLOCK_ENTRY(INT32, gSkyCubemapNumMips)
 		BS_PARAM_BLOCK_ENTRY(float, gSkyBrightness)
 		BS_PARAM_BLOCK_ENTRY(float, gSkyBrightness)
 	BS_PARAM_BLOCK_END
 	BS_PARAM_BLOCK_END
@@ -79,6 +80,34 @@ namespace bs { namespace ct
 
 
 	extern TiledImageBasedLightingParamDef gTiledImageBasedLightingParamDef;
 	extern TiledImageBasedLightingParamDef gTiledImageBasedLightingParamDef;
 
 
+	/** Helper struct containing all parameters for binding image lighting related data to the GPU programs using them .*/
+	struct ImageBasedLightingParams
+	{
+		/** 
+		 * Initializes the parameters from the provided @p params object. 
+		 *
+		 * @param[in]	paramsSet	GPU parameters object to look for the parameters in.
+		 * @param[in]	programType	Type of the GPU program to look up the parameters for.
+		 * @param[in]	optional	If true no warnings will be thrown if some or all of the parameters will be found.
+		 * @param[in]	gridIndices	Set to true if grid indices (used by light grid) parameter is required.
+		 */
+		void populate(const SPtr<GpuParamsSet>& paramsSet, GpuProgramType programType, bool optional, bool gridIndices);
+
+		GpuParamTexture skyReflectionsTexParam;
+		GpuParamSampState skyReflectionsSampParam;
+
+		GpuParamTexture skyIrradianceTexParam;
+
+		GpuParamTexture reflectionProbeCubemapsTexParam;
+		GpuParamSampState reflectionProbeCubemapsSampParam;
+
+		GpuParamTexture preintegratedEnvBRDFParam;
+		GpuParamBuffer reflectionProbesParam;
+
+		GpuParamBuffer reflectionProbeIndicesParam;
+		UINT32 reflProbeParamsBindingIdx;
+	};
+
 	/** Functionality common to all versions of TiledDeferredImageBasedLightingMat<T>. */
 	/** Functionality common to all versions of TiledDeferredImageBasedLightingMat<T>. */
 	class TiledDeferredImageBasedLighting
 	class TiledDeferredImageBasedLighting
 	{
 	{
@@ -91,11 +120,18 @@ namespace bs { namespace ct
 					 const SPtr<Texture>& preintegratedGF);
 					 const SPtr<Texture>& preintegratedGF);
 
 
 		/** Binds all the active reflection probes. */
 		/** Binds all the active reflection probes. */
-		void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps);
+		void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps, 
+			bool capturingReflections);
 
 
 		/** Binds the sky reflection & irradiance textures. Set textures to null if not available. */
 		/** Binds the sky reflection & irradiance textures. Set textures to null if not available. */
 		void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance, float brightness);
 		void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance, float brightness);
 
 
+		/** Returns a param buffer containing information required to evaluate reflection probe data. */
+		SPtr<GpuParamBlockBuffer> getReflectionsParamBuffer() const { return mReflectionsParamBuffer; }
+
+		/** Returns a sampler state object that should be used for evaluating reflection maps. */
+		SPtr<SamplerState> getReflectionsSamplerState() const { return mReflectionSamplerState; }
+
 		/**
 		/**
 		 * Generates a 2D 2-channel texture containing a pre-integrated G and F factors of the microfactet BRDF. This is an
 		 * Generates a 2D 2-channel texture containing a pre-integrated G and F factors of the microfactet BRDF. This is an
 		 * approximation used for image based lighting, so we can avoid sampling environment maps for each light. Works in
 		 * approximation used for image based lighting, so we can avoid sampling environment maps for each light. Works in
@@ -120,11 +156,7 @@ namespace bs { namespace ct
 		GpuParamTexture mInColorTextureParam;
 		GpuParamTexture mInColorTextureParam;
 		GpuParamBuffer mInColorBufferParam;
 		GpuParamBuffer mInColorBufferParam;
 
 
-		GpuParamTexture mSkyReflectionsParam;
-		GpuParamTexture mSkyIrradianceParam;
-		GpuParamTexture mReflectionProbeCubemapsParam;
-		GpuParamTexture mPreintegratedEnvBRDFParam;
-		GpuParamBuffer mReflectionProbesParam;
+		ImageBasedLightingParams mImageBasedParams;
 
 
 		GpuParamLoadStoreTexture mOutputTextureParam;
 		GpuParamLoadStoreTexture mOutputTextureParam;
 		GpuParamBuffer mOutputBufferParam;
 		GpuParamBuffer mOutputBufferParam;
@@ -140,21 +172,28 @@ namespace bs { namespace ct
 	public:
 	public:
 		virtual ~ITiledDeferredImageBasedLightingMat() {}
 		virtual ~ITiledDeferredImageBasedLightingMat() {}
 
 
-		/** @copydoc ITiledDeferredImageBasedLightingMat::execute() */
+		/** @copydoc TiledDeferredImageBasedLighting::execute() */
 		virtual void execute(const SPtr<RenderTargets>& renderTargets, const SPtr<GpuParamBlockBuffer>& perCamera,
 		virtual void execute(const SPtr<RenderTargets>& renderTargets, const SPtr<GpuParamBlockBuffer>& perCamera,
 			const SPtr<Texture>& preintegratedGF) = 0;
 			const SPtr<Texture>& preintegratedGF) = 0;
 
 
-		/** @copydoc ITiledDeferredImageBasedLightingMat::setReflectionProbes() */
-		virtual void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps) = 0;
+		/** @copydoc TiledDeferredImageBasedLighting::setReflectionProbes() */
+		virtual void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps,
+			bool capturingReflections) = 0;
 
 
-		/** @copydoc ITiledDeferredImageBasedLightingMat::setSky() */
+		/** @copydoc TiledDeferredImageBasedLighting::setSky() */
 		virtual void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance, float brightness) = 0;
 		virtual void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance, float brightness) = 0;
+
+		/** @copydoc TiledDeferredImageBasedLighting::getReflectionsParamBuffer() */
+		virtual SPtr<GpuParamBlockBuffer> getReflectionsParamBuffer() const = 0;
+
+		/** @copydoc TiledDeferredImageBasedLighting::getReflectionsSamplerState() */
+		virtual SPtr<SamplerState> getReflectionsSamplerState() const = 0;
 	};
 	};
 
 
 	/** Shader that performs a lighting pass over data stored in the Gbuffer. */
 	/** Shader that performs a lighting pass over data stored in the Gbuffer. */
-	template<int MSAA_COUNT, bool CapturingReflections>
+	template<int MSAA_COUNT>
 	class TTiledDeferredImageBasedLightingMat : public ITiledDeferredImageBasedLightingMat, 
 	class TTiledDeferredImageBasedLightingMat : public ITiledDeferredImageBasedLightingMat, 
-		public RendererMaterial<TTiledDeferredImageBasedLightingMat<MSAA_COUNT, CapturingReflections>>
+		public RendererMaterial<TTiledDeferredImageBasedLightingMat<MSAA_COUNT>>
 	{
 	{
 		RMAT_DEF("TiledDeferredImageBasedLighting.bsl");
 		RMAT_DEF("TiledDeferredImageBasedLighting.bsl");
 
 
@@ -166,10 +205,17 @@ namespace bs { namespace ct
 			const SPtr<Texture>& preintegratedGF) override;
 			const SPtr<Texture>& preintegratedGF) override;
 
 
 		/** @copydoc ITiledDeferredImageBasedLightingMat::setReflectionProbes() */
 		/** @copydoc ITiledDeferredImageBasedLightingMat::setReflectionProbes() */
-		void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps) override;
+		void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps, 
+			bool capturingReflections) override;
 
 
 		/** @copydoc ITiledDeferredImageBasedLightingMat::setSky() */
 		/** @copydoc ITiledDeferredImageBasedLightingMat::setSky() */
 		void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance, float brightness) override;
 		void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance, float brightness) override;
+
+		/** @copydoc ITiledDeferredImageBasedLightingMat::getReflectionsParamBuffer() */
+		SPtr<GpuParamBlockBuffer> getReflectionsParamBuffer() const override;
+
+		/** @copydoc ITiledDeferredImageBasedLightingMat::getReflectionsSamplerState() */
+		SPtr<SamplerState> getReflectionsSamplerState() const override;
 	private:
 	private:
 		TiledDeferredImageBasedLighting mInternal;
 		TiledDeferredImageBasedLighting mInternal;
 	};
 	};
@@ -182,17 +228,14 @@ namespace bs { namespace ct
 		~TiledDeferredImageBasedLightingMaterials();
 		~TiledDeferredImageBasedLightingMaterials();
 
 
 		/**
 		/**
-		* Returns a version of the tile-deferred image based lighting material that matches the parameters.
-		*
-		* @param[in]   msaa						Number of samples per pixel.
-		* @param[in]   capturingReflections		If true reflection probes will not be evaluated and instead the material's
-		*										specular color will be returned instead. Useful when rendering reflection
-		*										probes.
-		*/
-		ITiledDeferredImageBasedLightingMat* get(UINT32 msaa, bool capturingReflections);
+		 * Returns a version of the tile-deferred image based lighting material that matches the parameters.
+		 *
+		 * @param[in]   msaa						Number of samples per pixel.
+		 */
+		ITiledDeferredImageBasedLightingMat* get(UINT32 msaa);
 
 
 	private:
 	private:
-		ITiledDeferredImageBasedLightingMat* mInstances[8];
+		ITiledDeferredImageBasedLightingMat* mInstances[4];
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 58 - 22
Source/RenderBeast/Include/BsLightGrid.h

@@ -9,6 +9,7 @@
 
 
 namespace bs { namespace ct
 namespace bs { namespace ct
 {
 {
+	class GPUReflProbeData;
 	class GPULightData;
 	class GPULightData;
 
 
 	/** @addtogroup RenderBeast
 	/** @addtogroup RenderBeast
@@ -17,6 +18,7 @@ namespace bs { namespace ct
 
 
 	BS_PARAM_BLOCK_BEGIN(LightGridParamDef)
 	BS_PARAM_BLOCK_BEGIN(LightGridParamDef)
 		BS_PARAM_BLOCK_ENTRY(Vector3I, gLightOffsets)
 		BS_PARAM_BLOCK_ENTRY(Vector3I, gLightOffsets)
+		BS_PARAM_BLOCK_ENTRY(INT32, gNumReflProbes)
 		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)
@@ -25,7 +27,10 @@ namespace bs { namespace ct
 
 
 	extern LightGridParamDef gLightGridParamDefDef;
 	extern LightGridParamDef gLightGridParamDefDef;
 
 
-	/** Shader that creates a linked list for each light grid cell, containing which light affects each cell. */
+	/** 
+	 * Shader that creates a linked list for each light grid cell, containing which lights and reflection probes affects
+	 * each cell. 
+	 */
 	class LightGridLLCreationMat : public RendererMaterial<LightGridLLCreationMat>
 	class LightGridLLCreationMat : public RendererMaterial<LightGridLLCreationMat>
 	{
 	{
 		RMAT_DEF("LightGridLLCreation.bsl");
 		RMAT_DEF("LightGridLLCreation.bsl");
@@ -35,22 +40,32 @@ namespace bs { namespace ct
 
 
 		/** Binds parameter buffers and prepares any internal buffers. Must be called before execute(). */
 		/** Binds parameter buffers and prepares any internal buffers. Must be called before execute(). */
 		void setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams, 
 		void setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams, 
-					   const SPtr<GpuBuffer>& lightsBuffer);
+					   const SPtr<GpuBuffer>& lightsBuffer, const SPtr<GpuBuffer>& probesBuffer);
 
 
 		/** Binds the material for rendering, sets up per-camera parameters and executes it. */
 		/** Binds the material for rendering, sets up per-camera parameters and executes it. */
 		void execute(const RendererCamera& view);
 		void execute(const RendererCamera& view);
 
 
 		/** Returns the buffers generated by execute(). */
 		/** Returns the buffers generated by execute(). */
-		void getOutputs(SPtr<GpuBuffer>& linkedListHeads, SPtr<GpuBuffer>& linkedList) const;
+		void getOutputs(SPtr<GpuBuffer>& lightsLLHeads, SPtr<GpuBuffer>& lightsLL, SPtr<GpuBuffer>& probesLLHeads, 
+			SPtr<GpuBuffer>& probesLL) const;
 	private:
 	private:
 		GpuParamBuffer mLightBufferParam;
 		GpuParamBuffer mLightBufferParam;
-		GpuParamBuffer mLinkedListCounterParam;
-		GpuParamBuffer mLinkedListHeadsParam;
-		GpuParamBuffer mLinkedListParam;
+		GpuParamBuffer mLightsCounterParam;
+		GpuParamBuffer mLightsLLHeadsParam;
+		GpuParamBuffer mLightsLLParam;
+
+		GpuParamBuffer mProbesBufferParam;
+		GpuParamBuffer mProbesCounterParam;
+		GpuParamBuffer mProbesLLHeadsParam;
+		GpuParamBuffer mProbesLLParam;
 
 
-		SPtr<GpuBuffer> mLinkedListCounter;
-		SPtr<GpuBuffer> mLinkedListHeads;
-		SPtr<GpuBuffer> mLinkedList;
+		SPtr<GpuBuffer> mLightsCounter;
+		SPtr<GpuBuffer> mLightsLLHeads;
+		SPtr<GpuBuffer> mLightsLL;
+
+		SPtr<GpuBuffer> mProbesCounter;
+		SPtr<GpuBuffer> mProbesLLHeads;
+		SPtr<GpuBuffer> mProbesLL;
 
 
 		UINT32 mBufferNumCells;
 		UINT32 mBufferNumCells;
 		Vector3I mGridSize;
 		Vector3I mGridSize;
@@ -66,25 +81,38 @@ namespace bs { namespace ct
 
 
 		/** Binds parameter buffers and prepares any internal buffers. Must be called before execute(). */
 		/** Binds parameter buffers and prepares any internal buffers. Must be called before execute(). */
 		void setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams, 
 		void setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams, 
-					   const SPtr<GpuBuffer>& linkedListHeads, const SPtr<GpuBuffer>& linkedList);
+			const SPtr<GpuBuffer>& lightLLHeads, const SPtr<GpuBuffer>& lightLL,
+			const SPtr<GpuBuffer>& probeLLHeads, const SPtr<GpuBuffer>& probeLL);
 
 
 		/** Binds the material for renderingand executes it. */
 		/** Binds the material for renderingand executes it. */
 		void execute(const RendererCamera& view);
 		void execute(const RendererCamera& view);
 
 
 		/** Returns the buffers generated by execute(). */
 		/** Returns the buffers generated by execute(). */
-		void getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices) const;
+		void getOutputs(SPtr<GpuBuffer>& gridLightOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices,
+			SPtr<GpuBuffer>& gridProbeOffsetsAndSize, SPtr<GpuBuffer>& gridProbeIndices) const;
 	private:
 	private:
-		GpuParamBuffer mLinkedListHeadsParam;
-		GpuParamBuffer mLinkedListParam;
+		GpuParamBuffer mLightsLLHeadsParam;
+		GpuParamBuffer mLightsLLParam;
+
+		GpuParamBuffer mProbesLLHeadsParam;
+		GpuParamBuffer mProbesLLParam;
 
 
 		GpuParamBuffer mGridDataCounterParam;
 		GpuParamBuffer mGridDataCounterParam;
+
 		GpuParamBuffer mGridLightOffsetAndSizeParam;
 		GpuParamBuffer mGridLightOffsetAndSizeParam;
 		GpuParamBuffer mGridLightIndicesParam;
 		GpuParamBuffer mGridLightIndicesParam;
 
 
+		GpuParamBuffer mGridProbeOffsetAndSizeParam;
+		GpuParamBuffer mGridProbeIndicesParam;
+
 		SPtr<GpuBuffer> mGridDataCounter;
 		SPtr<GpuBuffer> mGridDataCounter;
+
 		SPtr<GpuBuffer> mGridLightOffsetAndSize;
 		SPtr<GpuBuffer> mGridLightOffsetAndSize;
 		SPtr<GpuBuffer> mGridLightIndices;
 		SPtr<GpuBuffer> mGridLightIndices;
 
 
+		SPtr<GpuBuffer> mGridProbeOffsetAndSize;
+		SPtr<GpuBuffer> mGridProbeIndices;
+
 		UINT32 mBufferNumCells;
 		UINT32 mBufferNumCells;
 		Vector3I mGridSize;
 		Vector3I mGridSize;
 	};
 	};
@@ -99,20 +127,28 @@ 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 GPULightData& lightData, bool noLighting);
+		void updateGrid(const RendererCamera& view, const GPULightData& lightData, const GPUReflProbeData& probeData, 
+			bool noLighting);
 
 
 		/** 
 		/** 
 		 * Returns the buffers containing light indices per grid cell and global grid parameters. 
 		 * 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
-		 *									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
-		 *									are placed sequentially one after another. Lookup into this array is done
-		 *									through offset & size provided by @p gridOffsetsAndSize. 
-		 * @param[out]	gridParams			Global grid parameter block.
+		 * @param[out]	gridLightOffsetsAndSize	Flattened array of grid cells, where each entry contains the number of 
+		 *										lights 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
+		 *										are placed sequentially one after another. Lookup into this array is done
+		 *										through offset & size provided by @p gridLightOffsetsAndSize. 
+		 * @param[out]	gridProbeOffsetsAndSize	Flattened array of grid cells, where each entry contains the number of
+		 *										reflection probes affecting that cell, and a index into the 
+		 *										@p gridProbeIndices buffer.
+		 * @param[out]	gridProbeIndices		A list of reflection probe indices. Each cell's indices start at specific
+		 *										position and are placed sequentially one after another. Lookup into this
+		 *										array is done through offset & size provided by @p gridProbeOffsetsAndSize.
+		 * @param[out]	gridParams				Global grid parameter block.
 		 */
 		 */
-		void getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices, 
-						SPtr<GpuParamBlockBuffer>& gridParams) const;
+		void getOutputs(SPtr<GpuBuffer>& gridLightOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices, 
+			SPtr<GpuBuffer>& gridProbeOffsetsAndSize, SPtr<GpuBuffer>& gridProbeIndices, 
+			SPtr<GpuParamBlockBuffer>& gridParams) const;
 
 
 	private:
 	private:
 		LightGridLLCreationMat mLLCreationMat;
 		LightGridLLCreationMat mLLCreationMat;

+ 12 - 2
Source/RenderBeast/Include/BsRendererObject.h

@@ -7,6 +7,7 @@
 #include "BsRenderable.h"
 #include "BsRenderable.h"
 #include "BsParamBlocks.h"
 #include "BsParamBlocks.h"
 #include "BsMaterialParam.h"
 #include "BsMaterialParam.h"
+#include "BsImageBasedLighting.h"
 
 
 namespace bs { namespace ct
 namespace bs { namespace ct
 {
 {
@@ -71,7 +72,7 @@ namespace bs { namespace ct
 		 * Parameter to which to bind a buffer containing light grid offsets and size, per grid cell. Used for forward
 		 * Parameter to which to bind a buffer containing light grid offsets and size, per grid cell. Used for forward
 		 * rendering. 
 		 * rendering. 
 		 */
 		 */
-		GpuParamBuffer gridOffsetsAndSizeParam;
+		GpuParamBuffer gridLightOffsetsAndSizeParam;
 
 
 		/** Parameter to which to bind a buffer containing all light indices, as mapped by grid offsets & size. */
 		/** Parameter to which to bind a buffer containing all light indices, as mapped by grid offsets & size. */
 		GpuParamBuffer gridLightIndicesParam;
 		GpuParamBuffer gridLightIndicesParam;
@@ -79,6 +80,15 @@ namespace bs { namespace ct
 		/** 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;
 
 
+		/** 
+		 * Parameter to which to bind a buffer containing reflection probe grid offsets and size, per grid cell. Used for
+		 * forward rendering. 
+		 */
+		GpuParamBuffer gridProbeOffsetsAndSizeParam;
+
+		/** Collection of parameters used for image based lighting. */
+		ImageBasedLightingParams imageBasedParams;
+
 		/** GPU buffer containing element's bone matrices, if it requires any. */
 		/** GPU buffer containing element's bone matrices, if it requires any. */
 		SPtr<GpuBuffer> boneMatrixBuffer;
 		SPtr<GpuBuffer> boneMatrixBuffer;
 
 
@@ -116,4 +126,4 @@ namespace bs { namespace ct
 	};
 	};
 
 
 	/** @} */
 	/** @} */
-}}
+}}

+ 85 - 65
Source/RenderBeast/Source/BsImageBasedLighting.cpp

@@ -4,6 +4,7 @@
 #include "BsMaterial.h"
 #include "BsMaterial.h"
 #include "BsShader.h"
 #include "BsShader.h"
 #include "BsGpuBuffer.h"
 #include "BsGpuBuffer.h"
+#include "BsGpuParamsSet.h"
 #include "BsReflectionProbe.h"
 #include "BsReflectionProbe.h"
 #include "BsLightProbeCache.h"
 #include "BsLightProbeCache.h"
 #include "BsGpuParamsSet.h"
 #include "BsGpuParamsSet.h"
@@ -81,6 +82,40 @@ namespace bs { namespace ct
 		output.invBoxTransform.setInverseTRS(output.position, probe->getRotation(), output.boxExtents);
 		output.invBoxTransform.setInverseTRS(output.position, probe->getRotation(), output.boxExtents);
 	}
 	}
 
 
+	void ImageBasedLightingParams::populate(const SPtr<GpuParamsSet>& paramsSet, GpuProgramType programType, bool optional, 
+		bool gridIndices)
+	{
+		SPtr<GpuParams> params = paramsSet->getGpuParams();
+
+		// Sky
+		if (!optional || params->hasTexture(programType, "gSkyReflectionTex"))
+		{
+			params->getTextureParam(programType, "gSkyReflectionTex", skyReflectionsTexParam);
+			params->getSamplerStateParam(programType, "gSkyReflectionSamp", skyReflectionsSampParam);
+
+			params->getTextureParam(programType, "gSkyIrradianceTex", skyIrradianceTexParam);
+		}
+
+		// Reflections
+		if (!optional || params->hasTexture(programType, "gReflProbeCubemaps"))
+		{
+			params->getTextureParam(programType, "gReflProbeCubemaps", reflectionProbeCubemapsTexParam);
+			params->getSamplerStateParam(programType, "gReflProbeSamp", reflectionProbeCubemapsSampParam);
+
+			params->getBufferParam(programType, "gReflectionProbes", reflectionProbesParam);
+
+			params->getTextureParam(programType, "gPreintegratedEnvBRDF", preintegratedEnvBRDFParam);
+		}
+
+		if(gridIndices)
+		{
+			if (!optional || params->hasBuffer(programType, "gReflectionProbeIndices"))
+				params->getBufferParam(programType, "gReflectionProbeIndices", reflectionProbeIndicesParam);
+		}
+
+		reflProbeParamsBindingIdx = paramsSet->getParamBlockBufferIndex("ReflProbeParams");
+	}
+
 	// Note: Using larger tiles than in tiled deferred lighting since we use AABB for intersections, which is more
 	// Note: Using larger tiles than in tiled deferred lighting since we use AABB for intersections, which is more
 	// expensive to compute than frustums. This way we amortize the cost even though other parts of the shader might suffer
 	// expensive to compute than frustums. This way we amortize the cost even though other parts of the shader might suffer
 	// due to increased thread group load.
 	// due to increased thread group load.
@@ -119,15 +154,7 @@ namespace bs { namespace ct
 		mParamBuffer = gTiledImageBasedLightingParamDef.createBuffer();
 		mParamBuffer = gTiledImageBasedLightingParamDef.createBuffer();
 		mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
 		mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
 
 
-		// Sky
-		params->getTextureParam(GPT_COMPUTE_PROGRAM, "gSkyReflectionTex", mSkyReflectionsParam);
-		params->getTextureParam(GPT_COMPUTE_PROGRAM, "gSkyIrradianceTex", mSkyIrradianceParam);
-
-		// Reflections
-		params->getTextureParam(GPT_COMPUTE_PROGRAM, "gReflProbeCubemaps", mReflectionProbeCubemapsParam);
-		params->getTextureParam(GPT_COMPUTE_PROGRAM, "gPreintegratedEnvBRDF", mPreintegratedEnvBRDFParam);
-
-		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gReflectionProbes", mReflectionProbesParam);
+		mImageBasedParams.populate(mParamsSet, GPT_COMPUTE_PROGRAM, false, false);
 
 
 		mReflectionsParamBuffer = gReflProbeParamsParamDef.createBuffer();
 		mReflectionsParamBuffer = gReflProbeParamsParamDef.createBuffer();
 		mParamsSet->setParamBlockBuffer("ReflProbeParams", mReflectionsParamBuffer);
 		mParamsSet->setParamBlockBuffer("ReflProbeParams", mReflectionsParamBuffer);
@@ -139,8 +166,8 @@ namespace bs { namespace ct
 
 
 		mReflectionSamplerState = SamplerState::create(reflSamplerDesc);
 		mReflectionSamplerState = SamplerState::create(reflSamplerDesc);
 
 
-		params->setSamplerState(GPT_COMPUTE_PROGRAM, "gSkyReflectionSamp", mReflectionSamplerState);
-		params->setSamplerState(GPT_COMPUTE_PROGRAM, "gReflProbeSamp", mReflectionSamplerState);
+		mImageBasedParams.skyReflectionsSampParam.set(mReflectionSamplerState);
+		mImageBasedParams.reflectionProbeCubemapsSampParam.set(mReflectionSamplerState);
 	}
 	}
 
 
 	void TiledDeferredImageBasedLighting::execute(const SPtr<RenderTargets>& renderTargets,
 	void TiledDeferredImageBasedLighting::execute(const SPtr<RenderTargets>& renderTargets,
@@ -159,7 +186,7 @@ namespace bs { namespace ct
 		mGBufferC.set(renderTargets->getGBufferC());
 		mGBufferC.set(renderTargets->getGBufferC());
 		mGBufferDepth.set(renderTargets->getSceneDepth());
 		mGBufferDepth.set(renderTargets->getSceneDepth());
 
 
-		mPreintegratedEnvBRDFParam.set(preintegratedGF);
+		mImageBasedParams.preintegratedEnvBRDFParam.set(preintegratedGF);
 
 
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 
 
@@ -187,10 +214,10 @@ namespace bs { namespace ct
 	}
 	}
 
 
 	void TiledDeferredImageBasedLighting::setReflectionProbes(const GPUReflProbeData& probeData,
 	void TiledDeferredImageBasedLighting::setReflectionProbes(const GPUReflProbeData& probeData,
-		const SPtr<Texture>& reflectionCubemaps)
+		const SPtr<Texture>& reflectionCubemaps, bool capturingReflections)
 	{
 	{
-		mReflectionProbesParam.set(probeData.getProbeBuffer());
-		mReflectionProbeCubemapsParam.set(reflectionCubemaps);
+		mImageBasedParams.reflectionProbesParam.set(probeData.getProbeBuffer());
+		mImageBasedParams.reflectionProbeCubemapsTexParam.set(reflectionCubemaps);
 
 
 		gReflProbeParamsParamDef.gNumProbes.set(mReflectionsParamBuffer, probeData.getNumProbes());
 		gReflProbeParamsParamDef.gNumProbes.set(mReflectionsParamBuffer, probeData.getNumProbes());
 
 
@@ -199,13 +226,14 @@ namespace bs { namespace ct
 			numMips = reflectionCubemaps->getProperties().getNumMipmaps() + 1;
 			numMips = reflectionCubemaps->getProperties().getNumMipmaps() + 1;
 
 
 		gReflProbeParamsParamDef.gReflCubemapNumMips.set(mReflectionsParamBuffer, numMips);
 		gReflProbeParamsParamDef.gReflCubemapNumMips.set(mReflectionsParamBuffer, numMips);
+		gReflProbeParamsParamDef.gUseReflectionMaps.set(mReflectionsParamBuffer, capturingReflections ? 0 : 1);
 	}
 	}
 
 
 	void TiledDeferredImageBasedLighting::setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance,
 	void TiledDeferredImageBasedLighting::setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance,
 		float brightness)
 		float brightness)
 	{
 	{
-		mSkyReflectionsParam.set(skyReflections);
-		mSkyIrradianceParam.set(skyIrradiance);
+		mImageBasedParams.skyReflectionsTexParam.set(skyReflections);
+		mImageBasedParams.skyIrradianceTexParam.set(skyIrradiance);
 
 
 		UINT32 skyReflectionsAvailable = 0;
 		UINT32 skyReflectionsAvailable = 0;
 		UINT32 numMips = 0;
 		UINT32 numMips = 0;
@@ -317,10 +345,10 @@ namespace bs { namespace ct
 					float NoL = std::max(L.z, 0.0f); // N assumed (0, 0, 1)
 					float NoL = std::max(L.z, 0.0f); // N assumed (0, 0, 1)
 					float NoH = std::max(H.z, 0.0f); // N assumed (0, 0, 1)
 					float NoH = std::max(H.z, 0.0f); // N assumed (0, 0, 1)
 
 
-													 // Set second part of the split sum integral is split into two parts:
-													 //   F0*I[G * (1 - (1 - v.h)^5) * cos(theta)] + I[G * (1 - v.h)^5 * cos(theta)] (F0 * scale + bias)
+					// Set second part of the split sum integral is split into two parts:
+					//   F0*I[G * (1 - (1 - v.h)^5) * cos(theta)] + I[G * (1 - v.h)^5 * cos(theta)] (F0 * scale + bias)
 
 
-													 // We calculate the fresnel scale (1 - (1 - v.h)^5) and bias ((1 - v.h)^5) parts
+					// We calculate the fresnel scale (1 - (1 - v.h)^5) and bias ((1 - v.h)^5) parts
 					float fc = pow(1.0f - VoH, 5.0f);
 					float fc = pow(1.0f - VoH, 5.0f);
 					float fresnelScale = 1.0f - fc;
 					float fresnelScale = 1.0f - fc;
 					float fresnelOffset = fc;
 					float fresnelOffset = fc;
@@ -356,84 +384,76 @@ namespace bs { namespace ct
 		return texture;
 		return texture;
 	}
 	}
 
 
-	template<int MSAA_COUNT, bool CapturingReflections>
-	TTiledDeferredImageBasedLightingMat<MSAA_COUNT, CapturingReflections>::TTiledDeferredImageBasedLightingMat()
+	template<int MSAA_COUNT>
+	TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::TTiledDeferredImageBasedLightingMat()
 		:mInternal(mMaterial, mParamsSet, MSAA_COUNT)
 		:mInternal(mMaterial, mParamsSet, MSAA_COUNT)
 	{
 	{
 
 
 	}
 	}
 
 
-	template<int MSAA_COUNT, bool CapturingReflections>
-	void TTiledDeferredImageBasedLightingMat<MSAA_COUNT, CapturingReflections>::_initDefines(ShaderDefines& defines)
+	template<int MSAA_COUNT>
+	void TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::_initDefines(ShaderDefines& defines)
 	{
 	{
 		defines.set("TILE_SIZE", TiledDeferredImageBasedLighting::TILE_SIZE);
 		defines.set("TILE_SIZE", TiledDeferredImageBasedLighting::TILE_SIZE);
 		defines.set("MSAA_COUNT", MSAA_COUNT);
 		defines.set("MSAA_COUNT", MSAA_COUNT);
-		defines.set("CAPTURING_REFLECTIONS", CapturingReflections);
 	}
 	}
 
 
-	template<int MSAA_COUNT, bool CapturingReflections>
-	void TTiledDeferredImageBasedLightingMat<MSAA_COUNT, CapturingReflections>::execute(const SPtr<RenderTargets>& gbuffer,
+	template<int MSAA_COUNT>
+	void TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::execute(const SPtr<RenderTargets>& gbuffer,
 		const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<Texture>& preintegratedGF)
 		const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<Texture>& preintegratedGF)
 	{
 	{
 		mInternal.execute(gbuffer, perCamera, preintegratedGF);
 		mInternal.execute(gbuffer, perCamera, preintegratedGF);
 	}
 	}
 
 
-	template<int MSAA_COUNT, bool CapturingReflections>
-	void TTiledDeferredImageBasedLightingMat<MSAA_COUNT, CapturingReflections>::setReflectionProbes(
-		const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps)
+	template<int MSAA_COUNT>
+	void TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::setReflectionProbes(const GPUReflProbeData& probeData, 
+		const SPtr<Texture>& reflectionCubemaps, bool capturingReflections)
 	{
 	{
-		mInternal.setReflectionProbes(probeData, reflectionCubemaps);
+		mInternal.setReflectionProbes(probeData, reflectionCubemaps, capturingReflections);
 	}
 	}
 
 
-	template<int MSAA_COUNT, bool CapturingReflections>
-	void TTiledDeferredImageBasedLightingMat<MSAA_COUNT, CapturingReflections>::setSky(const SPtr<Texture>& skyReflections,
+	template<int MSAA_COUNT>
+	void TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::setSky(const SPtr<Texture>& skyReflections,
 		const SPtr<Texture>& skyIrradiance, float brightness)
 		const SPtr<Texture>& skyIrradiance, float brightness)
 	{
 	{
 		mInternal.setSky(skyReflections, skyIrradiance, brightness);
 		mInternal.setSky(skyReflections, skyIrradiance, brightness);
 	}
 	}
 
 
+	template<int MSAA_COUNT>
+	SPtr<GpuParamBlockBuffer> TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::getReflectionsParamBuffer() const
+	{
+		return mInternal.getReflectionsParamBuffer();
+	}
+
+	template<int MSAA_COUNT>
+	SPtr<SamplerState> TTiledDeferredImageBasedLightingMat<MSAA_COUNT>::getReflectionsSamplerState() const
+	{
+		return mInternal.getReflectionsSamplerState();
+	}
+
 	TiledDeferredImageBasedLightingMaterials::TiledDeferredImageBasedLightingMaterials()
 	TiledDeferredImageBasedLightingMaterials::TiledDeferredImageBasedLightingMaterials()
 	{
 	{
-		mInstances[0] = bs_new<TTiledDeferredImageBasedLightingMat<1, false>>();
-		mInstances[1] = bs_new<TTiledDeferredImageBasedLightingMat<2, false>>();
-		mInstances[2] = bs_new<TTiledDeferredImageBasedLightingMat<4, false>>();
-		mInstances[3] = bs_new<TTiledDeferredImageBasedLightingMat<8, false>>();
-
-		mInstances[4] = bs_new<TTiledDeferredImageBasedLightingMat<1, true>>();
-		mInstances[5] = bs_new<TTiledDeferredImageBasedLightingMat<2, true>>();
-		mInstances[6] = bs_new<TTiledDeferredImageBasedLightingMat<4, true>>();
-		mInstances[7] = bs_new<TTiledDeferredImageBasedLightingMat<8, true>>();
+		mInstances[0] = bs_new<TTiledDeferredImageBasedLightingMat<1>>();
+		mInstances[1] = bs_new<TTiledDeferredImageBasedLightingMat<2>>();
+		mInstances[2] = bs_new<TTiledDeferredImageBasedLightingMat<4>>();
+		mInstances[3] = bs_new<TTiledDeferredImageBasedLightingMat<8>>();
 	}
 	}
 
 
 	TiledDeferredImageBasedLightingMaterials::~TiledDeferredImageBasedLightingMaterials()
 	TiledDeferredImageBasedLightingMaterials::~TiledDeferredImageBasedLightingMaterials()
 	{
 	{
-		for (UINT32 i = 0; i < 8; i++)
+		for (UINT32 i = 0; i < 4; i++)
 			bs_delete(mInstances[i]);
 			bs_delete(mInstances[i]);
 	}
 	}
 
 
-	ITiledDeferredImageBasedLightingMat* TiledDeferredImageBasedLightingMaterials::get(UINT32 msaa, bool capturingReflections)
+	ITiledDeferredImageBasedLightingMat* TiledDeferredImageBasedLightingMaterials::get(UINT32 msaa)
 	{
 	{
-		if (!capturingReflections)
-		{
-			if (msaa == 1)
-				return mInstances[0];
-			else if (msaa == 2)
-				return mInstances[1];
-			else if (msaa == 4)
-				return mInstances[2];
-			else
-				return mInstances[3];
-		}
+		if (msaa == 1)
+			return mInstances[0];
+		else if (msaa == 2)
+			return mInstances[1];
+		else if (msaa == 4)
+			return mInstances[2];
 		else
 		else
-		{
-			if (msaa == 1)
-				return mInstances[4];
-			else if (msaa == 2)
-				return mInstances[5];
-			else if (msaa == 4)
-				return mInstances[6];
-			else
-				return mInstances[7];
-		}
+			return mInstances[3];
 	}
 	}
 }}
 }}

+ 91 - 37
Source/RenderBeast/Source/BsLightGrid.cpp

@@ -7,6 +7,7 @@
 #include "BsRendererCamera.h"
 #include "BsRendererCamera.h"
 #include "BsRenderTargets.h"
 #include "BsRenderTargets.h"
 #include "BsLightRendering.h"
 #include "BsLightRendering.h"
+#include "BsImageBasedLighting.h"
 
 
 namespace bs { namespace ct
 namespace bs { namespace ct
 {
 {
@@ -23,9 +24,14 @@ namespace bs { namespace ct
 		SPtr<GpuParams> params = mParamsSet->getGpuParams();
 		SPtr<GpuParams> params = mParamsSet->getGpuParams();
 
 
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLights", mLightBufferParam);
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLights", mLightBufferParam);
-		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedListCounter", mLinkedListCounterParam);
-		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedListHeads", mLinkedListHeadsParam);
-		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedList", mLinkedListParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsCounter", mLightsCounterParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLLHeads", mLightsLLHeadsParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLL", mLightsLLParam);
+
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gReflectionProbes", mProbesBufferParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesCounter", mProbesCounterParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLLHeads", mProbesLLHeadsParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLL", mProbesLLParam);
 
 
 		GPU_BUFFER_DESC desc;
 		GPU_BUFFER_DESC desc;
 		desc.elementCount = 1;
 		desc.elementCount = 1;
@@ -34,8 +40,11 @@ namespace bs { namespace ct
 		desc.type = GBT_STANDARD;
 		desc.type = GBT_STANDARD;
 		desc.elementSize = 0;
 		desc.elementSize = 0;
 
 
-		mLinkedListCounter = GpuBuffer::create(desc);
-		mLinkedListCounterParam.set(mLinkedListCounter);
+		mLightsCounter = GpuBuffer::create(desc);
+		mLightsCounterParam.set(mLightsCounter);
+
+		mProbesCounter = GpuBuffer::create(desc);
+		mProbesCounterParam.set(mProbesCounter);
 	}
 	}
 
 
 	void LightGridLLCreationMat::_initDefines(ShaderDefines& defines)
 	void LightGridLLCreationMat::_initDefines(ShaderDefines& defines)
@@ -44,7 +53,7 @@ namespace bs { namespace ct
 	}
 	}
 
 
 	void LightGridLLCreationMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
 	void LightGridLLCreationMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
-											   const SPtr<GpuBuffer>& lightsBuffer)
+		const SPtr<GpuBuffer>& lightsBuffer, const SPtr<GpuBuffer>& probesBuffer)
 	{
 	{
 		mGridSize = gridSize;
 		mGridSize = gridSize;
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
@@ -58,31 +67,45 @@ namespace bs { namespace ct
 			desc.type = GBT_STANDARD;
 			desc.type = GBT_STANDARD;
 			desc.elementSize = 0;
 			desc.elementSize = 0;
 
 
-			mLinkedListHeads = GpuBuffer::create(desc);
-			mLinkedListHeadsParam.set(mLinkedListHeads);
+			mLightsLLHeads = GpuBuffer::create(desc);
+			mLightsLLHeadsParam.set(mLightsLLHeads);
+
+			mProbesLLHeads = GpuBuffer::create(desc);
+			mProbesLLHeadsParam.set(mProbesLLHeads);
 
 
 			desc.format = BF_32X4U;
 			desc.format = BF_32X4U;
 			desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
 			desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
 
 
-			mLinkedList = GpuBuffer::create(desc);
-			mLinkedListParam.set(mLinkedList);
+			mLightsLL = GpuBuffer::create(desc);
+			mLightsLLParam.set(mLightsLL);
+
+			desc.format = BF_32X2U;
+			mProbesLL = GpuBuffer::create(desc);
+			mProbesLLParam.set(mProbesLL);
 
 
 			mBufferNumCells = numCells;
 			mBufferNumCells = numCells;
 		}
 		}
 
 
 		UINT32 zero = 0;
 		UINT32 zero = 0;
-		mLinkedListCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
+		mLightsCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
+		mProbesCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
 
 
 		// Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
 		// Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
-		UINT32* headsClearData = (UINT32*)bs_stack_alloc(mLinkedListHeads->getSize());
-		memset(headsClearData, 0xFFFFFFFF, mLinkedListHeads->getSize());
+		UINT32* headsClearData = (UINT32*)bs_stack_alloc(mLightsLLHeads->getSize());
+		memset(headsClearData, 0xFFFFFFFF, mLightsLLHeads->getSize());
 
 
-		mLinkedListHeads->writeData(0, mLinkedListHeads->getSize(), headsClearData, BWT_DISCARD);
+		mLightsLLHeads->writeData(0, mLightsLLHeads->getSize(), headsClearData, BWT_DISCARD);
+		bs_stack_free(headsClearData);
+
+		headsClearData = (UINT32*)bs_stack_alloc(mProbesLLHeads->getSize());
+		memset(headsClearData, 0xFFFFFFFF, mProbesLLHeads->getSize());
 
 
+		mProbesLLHeads->writeData(0, mProbesLLHeads->getSize(), headsClearData, BWT_DISCARD);
 		bs_stack_free(headsClearData);
 		bs_stack_free(headsClearData);
 
 
 		mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
 		mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
 		mLightBufferParam.set(lightsBuffer);
 		mLightBufferParam.set(lightsBuffer);
+		mProbesBufferParam.set(probesBuffer);
 	}
 	}
 
 
 	void LightGridLLCreationMat::execute(const RendererCamera& view)
 	void LightGridLLCreationMat::execute(const RendererCamera& view)
@@ -99,10 +122,13 @@ namespace bs { namespace ct
 		RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
 		RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
 	}
 	}
 
 
-	void LightGridLLCreationMat::getOutputs(SPtr<GpuBuffer>& linkedListHeads, SPtr<GpuBuffer>& linkedList) const
+	void LightGridLLCreationMat::getOutputs(SPtr<GpuBuffer>& lightsLLHeads, SPtr<GpuBuffer>& lightsLL, 
+		SPtr<GpuBuffer>& probesLLHeads, SPtr<GpuBuffer>& probesLL) const
 	{
 	{
-		linkedListHeads = mLinkedListHeads;
-		linkedList = mLinkedList;
+		lightsLLHeads = mLightsLLHeads;
+		lightsLL = mLightsLL;
+		probesLLHeads = mProbesLLHeads;
+		probesLL = mProbesLL;
 	}
 	}
 
 
 	LightGridLLReductionMat::LightGridLLReductionMat()
 	LightGridLLReductionMat::LightGridLLReductionMat()
@@ -110,15 +136,22 @@ namespace bs { namespace ct
 	{
 	{
 		SPtr<GpuParams> params = mParamsSet->getGpuParams();
 		SPtr<GpuParams> params = mParamsSet->getGpuParams();
 
 
-		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedListHeads", mLinkedListHeadsParam);
-		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedList", mLinkedListParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLLHeads", mLightsLLHeadsParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLL", mLightsLLParam);
+
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLLHeads", mProbesLLHeadsParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLL", mProbesLLParam);
 
 
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridDataCounter", mGridDataCounterParam);
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridDataCounter", mGridDataCounterParam);
+
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightOffsetAndSize", mGridLightOffsetAndSizeParam);
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightOffsetAndSize", mGridLightOffsetAndSizeParam);
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightIndices", mGridLightIndicesParam);
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightIndices", mGridLightIndicesParam);
 
 
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridProbeOffsetAndSize", mGridProbeOffsetAndSizeParam);
+		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridProbeIndices", mGridProbeIndicesParam);
+
 		GPU_BUFFER_DESC desc;
 		GPU_BUFFER_DESC desc;
-		desc.elementCount = 1;
+		desc.elementCount = 2;
 		desc.format = BF_32X1U;
 		desc.format = BF_32X1U;
 		desc.randomGpuWrite = true;
 		desc.randomGpuWrite = true;
 		desc.type = GBT_STANDARD;
 		desc.type = GBT_STANDARD;
@@ -134,7 +167,8 @@ namespace bs { namespace ct
 	}
 	}
 
 
 	void LightGridLLReductionMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
 	void LightGridLLReductionMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
-											const SPtr<GpuBuffer>& linkedListHeads, const SPtr<GpuBuffer>& linkedList)
+		const SPtr<GpuBuffer>& lightsLLHeads, const SPtr<GpuBuffer>& lightsLL,
+		const SPtr<GpuBuffer>& probeLLHeads, const SPtr<GpuBuffer>& probeLL)
 	{
 	{
 		mGridSize = gridSize;
 		mGridSize = gridSize;
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
@@ -151,21 +185,33 @@ namespace bs { namespace ct
 			mGridLightOffsetAndSize = GpuBuffer::create(desc);
 			mGridLightOffsetAndSize = GpuBuffer::create(desc);
 			mGridLightOffsetAndSizeParam.set(mGridLightOffsetAndSize);
 			mGridLightOffsetAndSizeParam.set(mGridLightOffsetAndSize);
 
 
+			desc.format = BF_32X2U;
+
+			mGridProbeOffsetAndSize = GpuBuffer::create(desc);
+			mGridProbeOffsetAndSizeParam.set(mGridProbeOffsetAndSize);
+
 			desc.format = BF_32X1U;
 			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);
 
 
+			mGridProbeIndices = GpuBuffer::create(desc);
+			mGridProbeIndicesParam.set(mGridProbeIndices);
+
 			mBufferNumCells = numCells;
 			mBufferNumCells = numCells;
 		}
 		}
 
 
 		// Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
 		// Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
-		UINT32 zero = 0;
-		mGridDataCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
+		UINT32 zeros[] = { 0, 0 };
+		mGridDataCounter->writeData(0, sizeof(UINT32) * 2, zeros, BWT_DISCARD);
 
 
 		mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
 		mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
-		mLinkedListHeadsParam.set(linkedListHeads);
-		mLinkedListParam.set(linkedList);
+
+		mLightsLLHeadsParam.set(lightsLLHeads);
+		mLightsLLParam.set(lightsLL);
+
+		mProbesLLHeadsParam.set(probeLLHeads);
+		mProbesLLParam.set(probeLL);
 	}
 	}
 
 
 	void LightGridLLReductionMat::execute(const RendererCamera& view)
 	void LightGridLLReductionMat::execute(const RendererCamera& view)
@@ -182,10 +228,13 @@ namespace bs { namespace ct
 		RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
 		RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
 	}
 	}
 
 
-	void LightGridLLReductionMat::getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices) const
+	void LightGridLLReductionMat::getOutputs(SPtr<GpuBuffer>& gridLightOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices,
+		SPtr<GpuBuffer>& gridProbeOffsetsAndSize, SPtr<GpuBuffer>& gridProbeIndices) const
 	{
 	{
-		gridOffsetsAndSize = mGridLightOffsetAndSize;
+		gridLightOffsetsAndSize = mGridLightOffsetAndSize;
 		gridLightIndices = mGridLightIndices;
 		gridLightIndices = mGridLightIndices;
+		gridProbeOffsetsAndSize = mGridProbeOffsetAndSize;
+		gridProbeIndices = mGridProbeIndices;
 	}
 	}
 
 
 	LightGrid::LightGrid()
 	LightGrid::LightGrid()
@@ -193,7 +242,8 @@ namespace bs { namespace ct
 		mGridParamBuffer = gLightGridParamDefDef.createBuffer();
 		mGridParamBuffer = gLightGridParamDefDef.createBuffer();
 	}
 	}
 
 
-	void LightGrid::updateGrid(const RendererCamera& view, const GPULightData& lightData, bool noLighting)
+	void LightGrid::updateGrid(const RendererCamera& view, const GPULightData& lightData, const GPUReflProbeData& probeData,
+		bool noLighting)
 	{
 	{
 		UINT32 width = view.getRenderTargets()->getWidth();
 		UINT32 width = view.getRenderTargets()->getWidth();
 		UINT32 height = view.getRenderTargets()->getHeight();
 		UINT32 height = view.getRenderTargets()->getHeight();
@@ -220,26 +270,30 @@ namespace bs { namespace ct
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
 
 
 		gLightGridParamDefDef.gLightOffsets.set(mGridParamBuffer, lightOffsets);
 		gLightGridParamDefDef.gLightOffsets.set(mGridParamBuffer, lightOffsets);
+		gLightGridParamDefDef.gNumReflProbes.set(mGridParamBuffer, probeData.getNumProbes());
 		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));
 		gLightGridParamDefDef.gGridPixelSize.set(mGridParamBuffer, Vector2I(CELL_XY_SIZE, CELL_XY_SIZE));
 
 
-		mLLCreationMat.setParams(gridSize, mGridParamBuffer, lightData.getLightBuffer());
+		mLLCreationMat.setParams(gridSize, mGridParamBuffer, lightData.getLightBuffer(), probeData.getProbeBuffer());
 		mLLCreationMat.execute(view);
 		mLLCreationMat.execute(view);
 
 
-		SPtr<GpuBuffer> linkedListHeads;
-		SPtr<GpuBuffer> linkedList;
-		mLLCreationMat.getOutputs(linkedListHeads, linkedList);
+		SPtr<GpuBuffer> lightLLHeads;
+		SPtr<GpuBuffer> lightLL;
+		SPtr<GpuBuffer> probeLLHeads;
+		SPtr<GpuBuffer> probeLL;
+		mLLCreationMat.getOutputs(lightLLHeads, lightLL, probeLLHeads, probeLL);
 
 
-		mLLReductionMat.setParams(gridSize, mGridParamBuffer, linkedListHeads, linkedList);
+		mLLReductionMat.setParams(gridSize, mGridParamBuffer, lightLLHeads, lightLL, probeLLHeads, probeLL);
 		mLLReductionMat.execute(view);
 		mLLReductionMat.execute(view);
 	}
 	}
 
 
-	void LightGrid::getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices, 
-							   SPtr<GpuParamBlockBuffer>& gridParams) const
+	void LightGrid::getOutputs(SPtr<GpuBuffer>& gridLightOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices,
+		SPtr<GpuBuffer>& gridProbeOffsetsAndSize, SPtr<GpuBuffer>& gridProbeIndices, 
+		SPtr<GpuParamBlockBuffer>& gridParams) const
 	{
 	{
-		mLLReductionMat.getOutputs(gridOffsetsAndSize, gridLightIndices);
+		mLLReductionMat.getOutputs(gridLightOffsetsAndSize, gridLightIndices, gridProbeOffsetsAndSize, gridProbeIndices);
 		gridParams = mGridParamBuffer;
 		gridParams = mGridParamBuffer;
 	}
 	}
-}}
+}}

+ 7 - 2
Source/RenderBeast/Source/BsObjectRendering.cpp

@@ -63,12 +63,17 @@ namespace bs { namespace ct
 		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, "gGridLightOffsetsAndSize"))
+			gpuParams->getBufferParam(GPT_FRAGMENT_PROGRAM, "gGridLightOffsetsAndSize", element.gridLightOffsetsAndSizeParam);
 
 
 		if (gpuParams->hasBuffer(GPT_FRAGMENT_PROGRAM, "gGridLightIndices"))
 		if (gpuParams->hasBuffer(GPT_FRAGMENT_PROGRAM, "gGridLightIndices"))
 			gpuParams->getBufferParam(GPT_FRAGMENT_PROGRAM, "gGridLightIndices", element.gridLightIndicesParam);
 			gpuParams->getBufferParam(GPT_FRAGMENT_PROGRAM, "gGridLightIndices", element.gridLightIndicesParam);
 
 
+		if (gpuParams->hasBuffer(GPT_FRAGMENT_PROGRAM, "gGridProbeOffsetsAndSize"))
+			gpuParams->getBufferParam(GPT_FRAGMENT_PROGRAM, "gGridProbeOffsetsAndSize", element.gridProbeOffsetsAndSizeParam);
+
+		element.imageBasedParams.populate(element.params, GPT_FRAGMENT_PROGRAM, true, true);
+
 		const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferDescs = shader->getBufferParams();
 		const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferDescs = shader->getBufferParams();
 		String boneMatricesParamName;
 		String boneMatricesParamName;
 
 

+ 39 - 10
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -948,19 +948,31 @@ namespace bs { namespace ct
 		perCameraBuffer->flushToGPU();
 		perCameraBuffer->flushToGPU();
 
 
 		Matrix4 viewProj = viewInfo->getViewProjMatrix();
 		Matrix4 viewProj = viewInfo->getViewProjMatrix();
+		UINT32 numSamples = viewInfo->getNumSamples();
 
 
 		viewInfo->beginRendering(true);
 		viewInfo->beginRendering(true);
 
 
 		// Prepare light grid required for transparent object rendering
 		// Prepare light grid required for transparent object rendering
-		mLightGrid->updateGrid(*viewInfo, *mGPULightData, viewInfo->renderWithNoLighting());
+		mLightGrid->updateGrid(*viewInfo, *mGPULightData, *mGPUReflProbeData, viewInfo->renderWithNoLighting());
 
 
 		SPtr<GpuParamBlockBuffer> gridParams;
 		SPtr<GpuParamBlockBuffer> gridParams;
-		SPtr<GpuBuffer> gridOffsetsAndSize, gridLightIndices;
-		mLightGrid->getOutputs(gridOffsetsAndSize, gridLightIndices, gridParams);
+		SPtr<GpuBuffer> gridLightOffsetsAndSize, gridLightIndices;
+		SPtr<GpuBuffer> gridProbeOffsetsAndSize, gridProbeIndices;
+		mLightGrid->getOutputs(gridLightOffsetsAndSize, gridLightIndices, gridProbeOffsetsAndSize, gridProbeIndices, 
+			gridParams);
+
+		// Prepare image based material and its param buffer
+		ITiledDeferredImageBasedLightingMat* imageBasedLightingMat =
+			mTileDeferredImageBasedLightingMats->get(numSamples);
+
+		imageBasedLightingMat->setReflectionProbes(*mGPUReflProbeData, mReflCubemapArrayTex, viewInfo->isRenderingReflections());
+		imageBasedLightingMat->setSky(mSkyboxFilteredReflections, mSkyboxIrradiance, mSkybox->getBrightness());
 
 
 		// 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();
+		SPtr<GpuParamBlockBuffer> reflParamBuffer = imageBasedLightingMat->getReflectionsParamBuffer();
+		SPtr<SamplerState> reflSamplerState = imageBasedLightingMat->getReflectionsSamplerState();
 		for (UINT32 i = 0; i < numRenderables; i++)
 		for (UINT32 i = 0; i < numRenderables; i++)
 		{
 		{
 			if (!visibility.renderables[i])
 			if (!visibility.renderables[i])
@@ -974,12 +986,35 @@ 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);
 
 
+				// Everything below is required only for forward rendering (ATM only used for transparent objects)
+				// Note: It would be nice to be able to set this once and keep it, only updating if the buffers actually
+				// change (e.g. when growing). Although technically the internal systems should be smart enough to
+				// avoid updates unless objects actually changed.
 				if (element.gridParamsBindingIdx != -1)
 				if (element.gridParamsBindingIdx != -1)
 					element.params->setParamBlockBuffer(element.gridParamsBindingIdx, gridParams, true);
 					element.params->setParamBlockBuffer(element.gridParamsBindingIdx, gridParams, true);
 
 
-				element.gridOffsetsAndSizeParam.set(gridOffsetsAndSize);
+				element.gridLightOffsetsAndSizeParam.set(gridLightOffsetsAndSize);
 				element.gridLightIndicesParam.set(gridLightIndices);
 				element.gridLightIndicesParam.set(gridLightIndices);
 				element.lightsBufferParam.set(mGPULightData->getLightBuffer());
 				element.lightsBufferParam.set(mGPULightData->getLightBuffer());
+
+				// Image based lighting params
+				ImageBasedLightingParams& iblParams = element.imageBasedParams;
+				if (iblParams.reflProbeParamsBindingIdx != -1)
+					element.params->setParamBlockBuffer(iblParams.reflProbeParamsBindingIdx, reflParamBuffer);
+
+				element.gridProbeOffsetsAndSizeParam.set(gridProbeOffsetsAndSize);
+
+				iblParams.reflectionProbeIndicesParam.set(gridProbeIndices);
+				iblParams.reflectionProbesParam.set(mGPUReflProbeData->getProbeBuffer());
+
+				iblParams.skyReflectionsTexParam.set(mSkyboxFilteredReflections);
+				iblParams.skyIrradianceTexParam.set(mSkyboxIrradiance);
+
+				iblParams.reflectionProbeCubemapsTexParam.set(mReflCubemapArrayTex);
+				iblParams.preintegratedEnvBRDFParam.set(mPreintegratedEnvBRDF);
+
+				iblParams.reflectionProbeCubemapsSampParam.set(reflSamplerState);
+				iblParams.skyReflectionsSampParam.set(reflSamplerState);
 			}
 			}
 		}
 		}
 
 
@@ -1033,7 +1068,6 @@ namespace bs { namespace ct
 		rapi.setRenderTarget(nullptr);
 		rapi.setRenderTarget(nullptr);
 
 
 		// Render light pass into light accumulation buffer
 		// Render light pass into light accumulation buffer
-		UINT32 numSamples = viewInfo->getNumSamples();
 		ITiledDeferredLightingMat* lightingMat = mTiledDeferredLightingMats->get(numSamples);
 		ITiledDeferredLightingMat* lightingMat = mTiledDeferredLightingMats->get(numSamples);
 
 
 		renderTargets->allocate(RTT_LightAccumulation);
 		renderTargets->allocate(RTT_LightAccumulation);
@@ -1047,11 +1081,6 @@ namespace bs { namespace ct
 		// Note: Image based lighting is split from direct lighting in order to reduce load on GPU shared memory. The
 		// Note: Image based lighting is split from direct lighting in order to reduce load on GPU shared memory. The
 		// image based shader ends up re-doing a lot of calculations and it could be beneficial to profile and see if
 		// image based shader ends up re-doing a lot of calculations and it could be beneficial to profile and see if
 		// both methods can be squeezed into the same shader.
 		// both methods can be squeezed into the same shader.
-		ITiledDeferredImageBasedLightingMat* imageBasedLightingMat =
-			mTileDeferredImageBasedLightingMats->get(numSamples, viewInfo->isRenderingReflections());
-
-		imageBasedLightingMat->setReflectionProbes(*mGPUReflProbeData, mReflCubemapArrayTex);
-		imageBasedLightingMat->setSky(mSkyboxFilteredReflections, mSkyboxIrradiance, mSkybox->getBrightness());
 		imageBasedLightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF);
 		imageBasedLightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF);
 
 
 		renderTargets->release(RTT_LightAccumulation);
 		renderTargets->release(RTT_LightAccumulation);