Browse Source

Updated spherical harmonic shaders so they can output order-3 SH coefficients, and output to a larger buffer of coefficients
Hooked up light probe rendering with the SH shaders

BearishSun 8 years ago
parent
commit
5ede6f0788

+ 76 - 1
Data/Raw/Engine/Includes/SHCommon.bslinc

@@ -13,6 +13,13 @@ mixin SHCommon
 			float v6;
 		};
 		
+		struct SHVector3
+		{
+			float4 v0;
+			float4 v1;
+			float v2;
+		};			
+		
 		struct SHVector5RGB
 		{
 			SHVector5 R;
@@ -20,6 +27,13 @@ mixin SHCommon
 			SHVector5 B;
 		};
 		
+		struct SHVector3RGB
+		{
+			SHVector3 R;
+			SHVector3 G;
+			SHVector3 B;
+		};		
+		
 		void SHZero(inout SHVector5 v)
 		{
 			v.v0 = 0;
@@ -30,6 +44,13 @@ mixin SHCommon
 			v.v5 = 0;
 			v.v6 = 0;
 		}
+		
+		void SHZero(inout SHVector3 v)
+		{
+			v.v0 = 0;
+			v.v1 = 0;
+			v.v2 = 0;
+		}	
 
 		void SHMultiplyAdd(inout SHVector5 lhs, SHVector5 rhs, float c)
 		{
@@ -42,6 +63,13 @@ mixin SHCommon
 			lhs.v6 += rhs.v6 * c;
 		}
 		
+		void SHMultiplyAdd(inout SHVector3 lhs, SHVector3 rhs, float c)
+		{
+			lhs.v0 += rhs.v0 * c;
+			lhs.v1 += rhs.v1 * c;
+			lhs.v2 += rhs.v2 * c;
+		}		
+		
 		void SHAdd(inout SHVector5 lhs, SHVector5 rhs)
 		{
 			lhs.v0 += rhs.v0;
@@ -53,6 +81,13 @@ mixin SHCommon
 			lhs.v6 += rhs.v6;
 		}
 		
+		void SHAdd(inout SHVector3 lhs, SHVector3 rhs)
+		{
+			lhs.v0 += rhs.v0;
+			lhs.v1 += rhs.v1;
+			lhs.v2 += rhs.v2;
+		}		
+		
 		void SHMultiply(inout SHVector5 lhs, SHVector5 rhs)
 		{
 			lhs.v0 *= rhs.v0;
@@ -64,6 +99,13 @@ mixin SHCommon
 			lhs.v6 *= rhs.v6;
 		}	
 		
+		void SHMultiply(inout SHVector3 lhs, SHVector3 rhs)
+		{
+			lhs.v0 *= rhs.v0;
+			lhs.v1 *= rhs.v1;
+			lhs.v2 *= rhs.v2;
+		}		
+		
 		void SHMultiply(inout SHVector5 lhs, float rhs)
 		{
 			lhs.v0 *= rhs;
@@ -73,7 +115,14 @@ mixin SHCommon
 			lhs.v4 *= rhs;
 			lhs.v5 *= rhs;
 			lhs.v6 *= rhs;
-		}				
+		}
+
+		void SHMultiply(inout SHVector3 lhs, float rhs)
+		{
+			lhs.v0 *= rhs;
+			lhs.v1 *= rhs;
+			lhs.v2 *= rhs;
+		}		
 		
 		SHVector5 SHBasis5(float3 dir)
 		{
@@ -124,5 +173,31 @@ mixin SHCommon
 			
 			return o;
 		}
+		
+		SHVector3 SHBasis3(float3 dir)
+		{
+			float x = dir.x;
+			float y = dir.y;
+			float z = dir.z;
+
+			float x2 = x*x;
+			float y2 = y*y;
+			float z2 = z*z;
+
+			SHVector3 o;
+			o.v0[0] = 0.282095f;
+
+			o.v0[1] = -0.488603f * y;
+			o.v0[2] =  0.488603f * z;
+			o.v0[3] = -0.488603f * x;
+
+			o.v1[0] =  1.092548f * x * y;
+			o.v1[1] = -1.092548f * y * z;
+			o.v1[2] =  0.315392f * (3.0f * z2 - 1.0f);
+			o.v1[3] = -1.092548f * x * z;
+			o.v2 =  0.546274f * (x2 - y2);
+
+			return o;
+		}		
 	};
 };

+ 8 - 0
Data/Raw/Engine/Shaders/IrradianceComputeSH.bsl

@@ -10,7 +10,11 @@ technique IrradianceComputeSH
 	{
 		struct SHCoeffsAndWeight
 		{
+			#if ORDER == 3
+			SHVector3RGB coeffs;
+			#else // Assuming order 5
 			SHVector5RGB coeffs;
+			#endif
 			float weight;
 		};
 	
@@ -92,7 +96,11 @@ technique IrradianceComputeSH
 					// on a sphere. Without weighing that area would look too bright.
 					float weight = texelSolidAngle(u, v, invFaceSize);
 					
+					#if ORDER == 3
+					SHVector3 shBasis = SHBasis3(dir);
+					#else // Assuming order 5
 					SHVector5 shBasis = SHBasis5(dir);
+					#endif
 					float3 radiance = gInputTex.SampleLevel(gInputSamp, dir, 0).rgb;
 					
 					SHMultiplyAdd(data.coeffs.R, shBasis, radiance.r * weight);

+ 15 - 1
Data/Raw/Engine/Shaders/IrradianceReduceSH.bsl

@@ -12,17 +12,27 @@ technique IrradianceReduceSH
 	
 		struct SHCoeffsAndWeight
 		{
+			#if ORDER == 3
+			SHVector3RGB coeffs;
+			#else // Assuming order 5
 			SHVector5RGB coeffs;
+			#endif
 			float weight;
 		};
 
 		StructuredBuffer<SHCoeffsAndWeight> gInput;
+		
+		#if ORDER == 3
+		RWStructuredBuffer<SHVector3RGB> gOutput;
+		#else // Assuming order 5
 		RWStructuredBuffer<SHVector5RGB> gOutput;
+		#endif
 		
 		[internal]
 		cbuffer Params
 		{
 			uint gNumEntries;
+			uint gOutputIdx;
 		}			
 		
 		[numthreads(1, 1, 1)]
@@ -31,7 +41,11 @@ technique IrradianceReduceSH
 			uint groupId : SV_GroupID,
 			uint3 dispatchThreadId : SV_DispatchThreadID)
 		{
+			#if ORDER == 3
+			SHVector3RGB coeffs;
+			#else // Assuming order 5
 			SHVector5RGB coeffs;
+			#endif
 			float weight = 0;
 			
 			SHZero(coeffs.R);
@@ -56,7 +70,7 @@ technique IrradianceReduceSH
 			SHMultiply(coeffs.G, normFactor);
 			SHMultiply(coeffs.B, normFactor);
 				
-			gOutput[0] = coeffs;
+			gOutput[gOutputIdx] = coeffs;
 		}
 	};
 };

+ 0 - 12
Source/BansheeCore/Include/BsLightProbeVolume.h

@@ -148,18 +148,6 @@ namespace bs
 
 	namespace ct
 	{
-	/** Vector representing spherical harmonic coefficients for 3 bands. */
-	struct SHVector3
-	{
-		float coeffs[9];
-	};
-
-	/** Vector representing spherical coefficients for 3 bands, separate for red, green and blue components. */
-	struct SHVector3RGB
-	{
-		SHVector3 R, G, B;
-	};
-
 	/** Information about a single light probe in a light probe volume. */
 	struct LightProbeInfo
 	{

+ 53 - 14
Source/BansheeEngine/Include/BsIBLUtility.h

@@ -78,13 +78,32 @@ namespace bs { namespace ct
 		SHVector5 R, G, B;
 	};
 
+	/** Vector representing spherical harmonic coefficients for 3 bands. */
+	struct SHVector3
+	{
+		float coeffs[9];
+	};
+
+	/** Vector representing spherical coefficients for 3 bands, separate for red, green and blue components. */
+	struct SHVector3RGB
+	{
+		SHVector3 R, G, B;
+	};
+
 	/** Intermediate structure used for spherical coefficient calculation. Contains RGB coefficients and weight. */
-	struct SHCoeffsAndWeight
+	struct SHCoeffsAndWeight5
 	{
 		SHVector5RGB coeffs;
 		float weight;
 	};
 
+	/** Intermediate structure used for spherical coefficient calculation. Contains RGB coefficients and weight. */
+	struct SHCoeffsAndWeight3
+	{
+		SHVector3RGB coeffs;
+		float weight;
+	};
+
 	BS_PARAM_BLOCK_BEGIN(IrradianceComputeSHParamDef)
 		BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
 		BS_PARAM_BLOCK_ENTRY(int, gFaceSize)
@@ -93,8 +112,14 @@ namespace bs { namespace ct
 
 	extern IrradianceComputeSHParamDef gIrradianceComputeSHParamDef;
 
-	/** Computes spherical harmonic coefficients from a radiance cubemap. */
-	class IrradianceComputeSHMat : public RendererMaterial<IrradianceComputeSHMat>
+	/** 
+	 * Computes spherical harmonic coefficients from a radiance cubemap. 
+	 * 
+	 * @tparam ORDER	SH order, which defines the number of coefficients and quality. Only values of 3 and 5 are 
+	 *					supported.
+	 */
+	template<int ORDER = 5>
+	class IrradianceComputeSHMat : public RendererMaterial<IrradianceComputeSHMat<ORDER>>
 	{
 		RMAT_DEF("IrradianceComputeSH.bsl")
 
@@ -112,8 +137,6 @@ namespace bs { namespace ct
 		static SPtr<GpuBuffer> createOutputBuffer(const SPtr<Texture>& source, UINT32& numCoeffSets);
 
 	private:
-		static const UINT32 NUM_SAMPLES;
-
 		SPtr<GpuParamBlockBuffer> mParamBuffer;
 		GpuParamTexture mInputTexture;
 		GpuParamBuffer mOutputBuffer;
@@ -121,6 +144,7 @@ namespace bs { namespace ct
 
 	BS_PARAM_BLOCK_BEGIN(IrradianceReduceSHParamDef)
 		BS_PARAM_BLOCK_ENTRY(int, gNumEntries)
+		BS_PARAM_BLOCK_ENTRY(int, gOutputIdx)
 	BS_PARAM_BLOCK_END
 
 	extern IrradianceReduceSHParamDef gIrradianceReduceSHParamDef;
@@ -128,8 +152,12 @@ namespace bs { namespace ct
 	/** 
 	 * Sums spherical harmonic coefficients calculated by each thread group of IrradianceComputeSHMat and outputs a single
 	 * set of normalized coefficients. 
+	 *
+	 * @tparam ORDER	SH order, which defines the number of coefficients and quality. Only values of 3 and 5 are 
+	 *					supported.
 	 */
-	class IrradianceReduceSHMat : public RendererMaterial<IrradianceReduceSHMat>
+	template<int ORDER = 5>
+	class IrradianceReduceSHMat : public RendererMaterial<IrradianceReduceSHMat<ORDER>>
 	{
 		RMAT_DEF("IrradianceReduceSH.bsl")
 
@@ -138,16 +166,15 @@ namespace bs { namespace ct
 
 		/** 
 		 * Sums spherical harmonic coefficients calculated by each thread group of IrradianceComputeSHMat and outputs a
-		 * single set of normalized coefficients. Output buffer should be created by calling createOutputBuffer().
+		 * single set of normalized coefficients. Output buffer should be created by calling createOutputBuffer(). The
+		 * value will be recorded at the @p outputIdx position in the buffer.
 		 */
-		void execute(const SPtr<GpuBuffer>& source, UINT32 numCoeffSets, const SPtr<GpuBuffer>& output);
+		void execute(const SPtr<GpuBuffer>& source, UINT32 numCoeffSets, const SPtr<GpuBuffer>& output, UINT32 outputIdx);
 
 		/** Creates a buffer of adequate size to be used as output for this material. */
-		static SPtr<GpuBuffer> createOutputBuffer();
+		static SPtr<GpuBuffer> createOutputBuffer(UINT32 numEntries);
 
 	private:
-		static const UINT32 NUM_SAMPLES;
-
 		SPtr<GpuParamBlockBuffer> mParamBuffer;
 		GpuParamBuffer mInputBuffer;
 		GpuParamBuffer mOutputBuffer;
@@ -177,8 +204,6 @@ namespace bs { namespace ct
 		void execute(const SPtr<GpuBuffer>& shCoeffs, UINT32 face, const SPtr<RenderTarget>& target);
 
 	private:
-		static const UINT32 NUM_SAMPLES;
-
 		SPtr<GpuParamBlockBuffer> mParamBuffer;
 		GpuParamBuffer mInputBuffer;
 	};
@@ -206,13 +231,27 @@ namespace bs { namespace ct
 
 		/**
 		 * Performs filtering on the cubemap, populating the output cubemap with values that can be used for evaluating
-		 * irradiance for use in diffuse lighting.
+		 * irradiance for use in diffuse lighting. Uses order-5 SH (25 coefficients) and outputs the values in the form of
+		 * a cubemap.
 		 * 
 		 * @param[in]		cubemap		Cubemap to filter. Its mip level 0 will be used as source.
 		 * @param[in]		output		Output cubemap to store the irradiance data in.
 		 */
 		static void filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<Texture>& output);
 
+		/**
+		 * Performs filtering on the cubemap, populating the output cubemap with values that can be used for evaluating
+		 * irradiance for use in diffuse lighting. Uses order-5 SH (9 coefficients) and outputs the values in the form of
+		 * a cubemap.
+		 * 
+		 * @param[in]		cubemap		Cubemap to filter. Its mip level 0 will be used as source.
+		 * @param[in]		output		Output buffer in which to place the results. Must be allocated using 
+		 *								IrradianceReduceMat<ORDER>::createOutputBuffer();
+		 * @param[in]		outputIdx	Index in the output buffer at which to write the output coefficients to.
+		 */
+		static void filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<GpuBuffer>& output, 
+			UINT32 outputIdx);
+
 		/**
 		 * Scales a cubemap and outputs it in the destination texture, using hardware acceleration. If both textures are the
 		 * same size, performs a copy instead.

+ 59 - 21
Source/BansheeEngine/Source/BsIBLUtility.cpp

@@ -13,9 +13,11 @@ namespace bs { namespace ct
 		ReflectionCubeDownsampleMat downsampleMat;
 		ReflectionCubeImportanceSampleMat importanceSampleMat;
 
-		IrradianceComputeSHMat shCompute;
-		IrradianceReduceSHMat shReduce;
-		IrradianceProjectSHMat shProject;
+		IrradianceComputeSHMat<3> shCompute3;
+		IrradianceComputeSHMat<5> shCompute5;
+		IrradianceReduceSHMat<3> shReduce3;
+		IrradianceReduceSHMat<5> shReduce5;
+		IrradianceProjectSHMat shProject5;
 	};
 
 	IBLUtility::Members* IBLUtility::m = nullptr;
@@ -105,7 +107,8 @@ namespace bs { namespace ct
 	const static UINT32 TILE_HEIGHT = 8;
 	const static UINT32 PIXELS_PER_THREAD = 4;
 
-	IrradianceComputeSHMat::IrradianceComputeSHMat()
+	template<int ORDER>
+	IrradianceComputeSHMat<ORDER>::IrradianceComputeSHMat()
 	{
 		mParamBuffer = gIrradianceComputeSHParamDef.createBuffer();
 
@@ -116,7 +119,8 @@ namespace bs { namespace ct
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputBuffer);
 	}
 
-	void IrradianceComputeSHMat::_initDefines(ShaderDefines& defines)
+	template<int ORDER>
+	void IrradianceComputeSHMat<ORDER>::_initDefines(ShaderDefines& defines)
 	{
 		// TILE_WIDTH * TILE_HEIGHT must be pow2 because of parallel reduction algorithm
 		defines.set("TILE_WIDTH", TILE_WIDTH);
@@ -124,9 +128,12 @@ namespace bs { namespace ct
 
 		// For very small textures this should be reduced so number of launched threads can properly utilize GPU cores
 		defines.set("PIXELS_PER_THREAD", PIXELS_PER_THREAD);
+
+		defines.set("ORDER", ORDER);
 	}
 
-	void IrradianceComputeSHMat::execute(const SPtr<Texture>& source, UINT32 face, const SPtr<GpuBuffer>& output)
+	template<int ORDER>
+	void IrradianceComputeSHMat<ORDER>::execute(const SPtr<Texture>& source, UINT32 face, const SPtr<GpuBuffer>& output)
 	{
 		auto& props = source->getProperties();
 		UINT32 faceSize = props.getWidth();
@@ -150,7 +157,8 @@ namespace bs { namespace ct
 		rapi.dispatchCompute(dispatchSize.x, dispatchSize.y);
 	}
 
-	SPtr<GpuBuffer> IrradianceComputeSHMat::createOutputBuffer(const SPtr<Texture>& source, UINT32& numCoeffSets)
+	template<int ORDER>
+	SPtr<GpuBuffer> IrradianceComputeSHMat<ORDER>::createOutputBuffer(const SPtr<Texture>& source, UINT32& numCoeffSets)
 	{
 		auto& props = source->getProperties();
 		UINT32 faceSize = props.getWidth();
@@ -165,16 +173,24 @@ namespace bs { namespace ct
 		GPU_BUFFER_DESC bufferDesc;
 		bufferDesc.type = GBT_STRUCTURED;
 		bufferDesc.elementCount = numCoeffSets;
-		bufferDesc.elementSize = sizeof(SHCoeffsAndWeight);
 		bufferDesc.format = BF_UNKNOWN;
 		bufferDesc.randomGpuWrite = true;
 
+		if(ORDER == 3)
+			bufferDesc.elementSize = sizeof(SHCoeffsAndWeight3);
+		else
+			bufferDesc.elementSize = sizeof(SHCoeffsAndWeight5);
+
 		return GpuBuffer::create(bufferDesc);
 	}
 
+	template class IrradianceComputeSHMat<3>;
+	template class IrradianceComputeSHMat<5>;
+
 	IrradianceReduceSHParamDef gIrradianceReduceSHParamDef;
 
-	IrradianceReduceSHMat::IrradianceReduceSHMat()
+	template<int ORDER>
+	IrradianceReduceSHMat<ORDER>::IrradianceReduceSHMat()
 	{
 		mParamBuffer = gIrradianceReduceSHParamDef.createBuffer();
 
@@ -185,15 +201,18 @@ namespace bs { namespace ct
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gOutput", mOutputBuffer);
 	}
 
-	void IrradianceReduceSHMat::_initDefines(ShaderDefines& defines)
+	template<int ORDER>
+	void IrradianceReduceSHMat<ORDER>::_initDefines(ShaderDefines& defines)
 	{
-		// Do nothing
+		defines.set("ORDER", ORDER);
 	}
 
-	void IrradianceReduceSHMat::execute(const SPtr<GpuBuffer>& source, UINT32 numCoeffSets, 
-		const SPtr<GpuBuffer>& output)
+	template<int ORDER>
+	void IrradianceReduceSHMat<ORDER>::execute(const SPtr<GpuBuffer>& source, UINT32 numCoeffSets, 
+		const SPtr<GpuBuffer>& output, UINT32 outputIdx)
 	{
 		gIrradianceReduceSHParamDef.gNumEntries.set(mParamBuffer, numCoeffSets);
+		gIrradianceReduceSHParamDef.gOutputIdx.set(mParamBuffer, outputIdx);
 
 		mInputBuffer.set(source);
 		mOutputBuffer.set(output);
@@ -205,18 +224,26 @@ namespace bs { namespace ct
 		rapi.dispatchCompute(1);
 	}
 
-	SPtr<GpuBuffer> IrradianceReduceSHMat::createOutputBuffer()
+	template<int ORDER>
+	SPtr<GpuBuffer> IrradianceReduceSHMat<ORDER>::createOutputBuffer(UINT32 numEntries)
 	{
 		GPU_BUFFER_DESC bufferDesc;
 		bufferDesc.type = GBT_STRUCTURED;
-		bufferDesc.elementCount = 1;
-		bufferDesc.elementSize = sizeof(SHVector5RGB);
+		bufferDesc.elementCount = numEntries;
 		bufferDesc.format = BF_UNKNOWN;
 		bufferDesc.randomGpuWrite = true;
 
+		if(ORDER == 3)
+			bufferDesc.elementSize = sizeof(SHVector3RGB);
+		else
+			bufferDesc.elementSize = sizeof(SHVector5RGB);
+
 		return GpuBuffer::create(bufferDesc);
 	}
 
+	template class IrradianceReduceSHMat<3>;
+	template class IrradianceReduceSHMat<5>;
+
 	IrradianceProjectSHParamDef gIrradianceProjectSHParamDef;
 
 	IrradianceProjectSHMat::IrradianceProjectSHMat()
@@ -315,12 +342,12 @@ namespace bs { namespace ct
 	void IBLUtility::filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<Texture>& output)
 	{
 		UINT32 numCoeffSets;
-		SPtr<GpuBuffer> coeffSetBuffer = IrradianceComputeSHMat::createOutputBuffer(cubemap, numCoeffSets);
+		SPtr<GpuBuffer> coeffSetBuffer = IrradianceComputeSHMat<5>::createOutputBuffer(cubemap, numCoeffSets);
 		for (UINT32 face = 0; face < 6; face++)
-			m->shCompute.execute(cubemap, face, coeffSetBuffer);
+			m->shCompute5.execute(cubemap, face, coeffSetBuffer);
 
-		SPtr<GpuBuffer> coeffBuffer = IrradianceReduceSHMat::createOutputBuffer();
-		m->shReduce.execute(coeffSetBuffer, numCoeffSets, coeffBuffer);
+		SPtr<GpuBuffer> coeffBuffer = IrradianceReduceSHMat<5>::createOutputBuffer(1);
+		m->shReduce5.execute(coeffSetBuffer, numCoeffSets, coeffBuffer, 0);
 
 		for (UINT32 face = 0; face < 6; face++)
 		{
@@ -331,10 +358,21 @@ namespace bs { namespace ct
 			cubeFaceRTDesc.colorSurfaces[0].mipLevel = 0;
 
 			SPtr<RenderTarget> target = RenderTexture::create(cubeFaceRTDesc);
-			m->shProject.execute(coeffBuffer, face, target);
+			m->shProject5.execute(coeffBuffer, face, target);
 		}
 	}
 
+	void IBLUtility::filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<GpuBuffer>& output, 
+		UINT32 outputIdx)
+	{
+		UINT32 numCoeffSets;
+		SPtr<GpuBuffer> coeffSetBuffer = IrradianceComputeSHMat<3>::createOutputBuffer(cubemap, numCoeffSets);
+		for (UINT32 face = 0; face < 6; face++)
+			m->shCompute3.execute(cubemap, face, coeffSetBuffer);
+
+		m->shReduce3.execute(coeffSetBuffer, numCoeffSets, output, outputIdx);
+	}
+
 	void IBLUtility::scaleCubemap(const SPtr<Texture>& src, UINT32 srcMip, const SPtr<Texture>& dst, UINT32 dstMip)
 	{
 		auto& srcProps = src->getProperties();

+ 3 - 1
Source/RenderBeast/Include/BsLightProbes.h

@@ -9,6 +9,7 @@
 
 namespace bs { namespace ct
 {
+	struct FrameInfo;
 	class LightProbeVolume;
 	struct VisibleLightProbeData;
 
@@ -56,6 +57,7 @@ namespace bs { namespace ct
 		 * Updates any dirty light probes by rendering the scene from their perspective and generating their SH 
 		 * coefficients.
 		 *
+		 * @param[in]	frameInfo		Information about the current frame.
 		 * @param[in]	maxProbes		Places a limit of how many probes can be updated in a single call to this method.
 		 *								Any probes that weren't updated will be updated when the method is called next 
 		 *								(up to the @p maxProbes limit), as so on.
@@ -66,7 +68,7 @@ namespace bs { namespace ct
 		 *								
 		 *								Provide a limit of 0 to force all probes to be updated.
 		 */
-		void updateProbes(UINT32 maxProbes = 3);
+		void updateProbes(const FrameInfo& frameInfo, UINT32 maxProbes = 3);
 
 		/** Generates GPU buffers that contain a list of probe tetrahedrons visible from the provided view. */
 		void updateVisibleProbes(const RendererView& view, VisibleLightProbeData& output);

+ 10 - 10
Source/RenderBeast/Include/BsRenderBeast.h

@@ -74,6 +74,16 @@ namespace bs
 		/** @copydoc Renderer::createPostProcessSettings */
 		SPtr<PostProcessSettings> createPostProcessSettings() const override;
 
+		/** 
+		 * Captures the scene at the specified location into a cubemap. 
+		 * 
+		 * @param[in]	cubemap		Cubemap to store the results in.
+		 * @param[in]	position	Position to capture the scene at.
+		 * @param[in]	hdr			If true scene will be captured in a format that supports high dynamic range.
+		 * @param[in]	frameInfo	Global information about the the frame currently being rendered.
+		 */
+		void captureSceneCubeMap(const SPtr<Texture>& cubemap, const Vector3& position, bool hdr, const FrameInfo& frameInfo);
+
 	private:
 		/** @copydoc Renderer::notifyCameraAdded */
 		void notifyCameraAdded(Camera* camera) override;
@@ -178,16 +188,6 @@ namespace bs
 		 */
 		void renderElement(const BeastRenderableElement& element, UINT32 passIdx, bool bindPass, const Matrix4& viewProj);
 
-		/** 
-		 * Captures the scene at the specified location into a cubemap. 
-		 * 
-		 * @param[in]	cubemap		Cubemap to store the results in.
-		 * @param[in]	position	Position to capture the scene at.
-		 * @param[in]	hdr			If true scene will be captured in a format that supports high dynamic range.
-		 * @param[in]	frameInfo	Global information about the the frame currently being rendered.
-		 */
-		void captureSceneCubeMap(const SPtr<Texture>& cubemap, const Vector3& position, bool hdr, const FrameInfo& frameInfo);
-
 		/**	Creates data used by the renderer on the core thread. */
 		void initializeCore();
 

+ 26 - 5
Source/RenderBeast/Source/BsLightProbes.cpp

@@ -4,6 +4,9 @@
 #include "BsLightProbeVolume.h"
 #include "BsGpuBuffer.h"
 #include "BsRendererView.h"
+#include "BsIBLUtility.h"
+#include "BsRendererManager.h"
+#include "BsRenderBeast.h"
 
 namespace bs { namespace ct 
 {
@@ -61,7 +64,7 @@ namespace bs { namespace ct
 		mTetrahedronVolumeDirty = true;
 	}
 
-	void LightProbes::updateProbes(UINT32 maxProbes)
+	void LightProbes::updateProbes(const FrameInfo& frameInfo, UINT32 maxProbes)
 	{
 		if(mTetrahedronVolumeDirty)
 		{
@@ -110,6 +113,7 @@ namespace bs { namespace ct
 				continue;
 
 			Vector<LightProbeInfo>& probes = entry.volume->getLightProbeInfos();
+			const Vector<Vector3>& probePositions = entry.volume->getLightProbePositions();
 			for (; entry.lastUpdatedProbe < (UINT32)probes.size(); ++entry.lastUpdatedProbe)
 			{
 				LightProbeInfo& probeInfo = probes[entry.lastUpdatedProbe];
@@ -133,7 +137,19 @@ namespace bs { namespace ct
 
 				if(probeInfo.flags == LightProbeFlags::Dirty)
 				{
-					// TODO - Render probe
+					TEXTURE_DESC cubemapDesc;
+					cubemapDesc.type = TEX_TYPE_CUBE_MAP;
+					cubemapDesc.format = PF_FLOAT16_RGB;
+					cubemapDesc.width = IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
+					cubemapDesc.height = IBLUtility::REFLECTION_CUBEMAP_SIZE;
+					cubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
+
+					SPtr<Texture> cubemap = Texture::create(cubemapDesc);
+
+					RenderBeast& renderer = static_cast<RenderBeast&>(*RendererManager::instance().getActive());
+					renderer.captureSceneCubeMap(cubemap, probePositions[entry.lastUpdatedProbe], true, frameInfo);
+
+					IBLUtility::filterCubemapForIrradiance(cubemap, mProbeCoefficientsGPU, probeInfo.bufferIdx);
 
 					probeInfo.flags = LightProbeFlags::Clean;
 					numProbeUpdates++;
@@ -146,9 +162,6 @@ namespace bs { namespace ct
 			if (entry.lastUpdatedProbe == (UINT32)probes.size())
 				entry.isDirty = false;
 		}
-
-		// TODO - In another function, need to find visible tetrahedrons and update their buffers per-view
-		// - Allow culling with an optimal maximum range
 	}
 
 	void LightProbes::resizeTetrahedronBuffers(VisibleLightProbeData& data, UINT32 count)
@@ -205,11 +218,19 @@ namespace bs { namespace ct
 
 	void LightProbes::updateVisibleProbes(const RendererView& view, VisibleLightProbeData& output)
 	{
+		// Ignore all probes past this point
+		static const float MAX_PROBE_DISTANCE = 100.0f;
+
 		const RendererViewProperties& viewProps = view.getProperties();
 		const ConvexVolume& worldFrustum = viewProps.cullFrustum;
 
+		const float maxProbeDistance2 = MAX_PROBE_DISTANCE * MAX_PROBE_DISTANCE;
 		for (UINT32 i = 0; i < (UINT32)mTetrahedronBounds.size(); i++)
 		{
+			float distance2 = viewProps.viewOrigin.squaredDistance(mTetrahedronBounds[i].getCenter());
+			if (distance2 > maxProbeDistance2)
+				continue;
+
 			if (worldFrustum.intersects(mTetrahedronBounds[i]))
 				mTempTetrahedronVisibility.push_back(i);
 		}