Просмотр исходного кода

Added sky irradiance for indirect lighting

BearishSun 8 лет назад
Родитель
Сommit
4bd929ade3

+ 8 - 8
Data/Raw/Engine/Includes/ReflectionCubemapSampling.bslinc

@@ -20,8 +20,11 @@ Technique : base("ReflectionCubemapSampling") =
 				uint type; // 0 - Sphere, 1 - Box
 			};
 		
-			TextureCube gSkyCubemapTex;
-			SamplerState gSkyCubemapSamp;
+			TextureCube gSkyReflectionTex;
+			SamplerState gSkyReflectionSamp;
+			
+			TextureCube gSkyIrradianceTex;
+			SamplerState gSkyIrradianceSamp;
 			
 			TextureCubeArray gReflProbeCubemaps;
 			SamplerState gReflProbeSamp;
@@ -45,12 +48,9 @@ Technique : base("ReflectionCubemapSampling") =
 				uint gSkyCubemapNumMips;
 			}	
 			
-			float3 getSkyReflection(float3 dir, float roughness)
+			float3 getSkyIndirectDiffuse(float3 dir)
 			{
-				float mipLevel = mapRoughnessToMipLevel(roughness, gReflCubemapNumMips);
-				float3 reflection = gSkyCubemapTex.SampleLevel(gSkyCubemapSamp, dir, mipLevel);
-
-				return reflection;
+				return gSkyIrradianceTex.SampleLevel(gSkyIrradianceSamp, dir, 0).rgb;
 			}
 			
 			float3 getSphereReflectionContribution(float normalizedDistance)
@@ -182,7 +182,7 @@ Technique : base("ReflectionCubemapSampling") =
 				if(gSkyCubemapAvailable > 0)
 				{
 					float skyMipLevel = mapRoughnessToMipLevel(roughness, gSkyCubemapNumMips);
-					float4 sample = gSkyCubemapTex.SampleLevel(gSkyCubemapSamp, dir, skyMipLevel);
+					float4 sample = gSkyReflectionTex.SampleLevel(gSkyReflectionSamp, dir, skyMipLevel);
 					
 					output += sample.rgb * leftoverContribution; 
 				}

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

@@ -68,6 +68,17 @@ Technique : base("SHCommon") =
 				lhs.v6 *= rhs.v6;
 			}	
 			
+			void SHMultiply(inout SHVector5 lhs, float rhs)
+			{
+				lhs.v0 *= rhs;
+				lhs.v1 *= rhs;
+				lhs.v2 *= rhs;
+				lhs.v3 *= rhs;
+				lhs.v4 *= rhs;
+				lhs.v5 *= rhs;
+				lhs.v6 *= rhs;
+			}				
+			
 			SHVector5 SHBasis5(float3 dir)
 			{
 				float x = dir.x;
@@ -109,7 +120,7 @@ Technique : base("SHCommon") =
 				o.v4[1] = -1.770130f * y * z * (3.0f * x2 - y2);
 				o.v4[2] =  0.946175f * y * x * (-1.0f + 7.0f * z2);
 				o.v4[3] = -0.669046f * y * z * (-3.0f + 7.0f * z2);
-				o.v5[0] =  (105.0f * z4 - 90.0f * z2 + 9.0f) / 9.02703f;
+				o.v5[0] =  (105.0f * z4 - 90.0f * z2 + 9.0f) / 28.359261f;
 				o.v5[1] = -0.669046f * x * z * (-3.0f + 7.0f * z2);
 				o.v5[2] =  0.473087f * (x2 - y2) * (-1.0f + 7.0f * z2);
 				o.v5[3] = -1.770130f * x * z * (x2 - 3.0f * y2);

+ 12 - 12
Data/Raw/Engine/Shaders/IrradianceComputeSH.bsl

@@ -3,7 +3,7 @@
 
 Technique
  : inherits("ReflectionCubemapCommon")
- : inherits("SHCommon")
+ : inherits("SHCommon") =
 {
 	Language = "HLSL11";
 	
@@ -15,7 +15,7 @@ Technique
 			{
 				SHVector5RGB coeffs;
 				float weight;
-			}
+			};
 		
 			SamplerState gInputSamp;
 			TextureCube gInputTex;
@@ -59,7 +59,7 @@ Technique
 			[numthreads(TILE_WIDTH, TILE_HEIGHT, 1)]
 			void main(
 				uint groupIdx : SV_GroupIndex,
-				uint groupId : SV_GroupID,
+				uint3 groupId : SV_GroupID,
 				uint3 dispatchThreadId : SV_DispatchThreadID)
 			{
 				SHCoeffsAndWeight data;
@@ -82,13 +82,12 @@ Technique
 							break;
 							
 						// Map from [0, size-1] to [-1.0 + invSize, 1.0 - invSize].
-                        // Reference: u = 2.0 * (x + 0.5) / faceSize - 1.0;
-                        //      	  v = 2.0 * (y + 0.5) / faceSize - 1.0;
 						// (+0.5 in order to sample center of texel)
-                        float u = x * invFaceSize - 1.0f;
-                        float v = x * invFaceSize - 1.0f;
+                        float u = 2.0f * (x + 0.5f) * invFaceSize - 1.0f;
+                        float v = 2.0f * (y + 0.5f) * invFaceSize - 1.0f;
 						
 						float3 dir = getDirFromCubeFace(gCubeFace, float2(u, v));
+						dir = normalize(dir);
 						
 						// Need to calculate solid angle (weight) of the texel, as cube face corners have
 						// much smaller solid angle, meaning many of them occupy the same area when projected
@@ -96,7 +95,7 @@ Technique
 						float weight = texelSolidAngle(u, v, invFaceSize);
 						
 						SHVector5 shBasis = SHBasis5(dir);
-						float3 radiance = gInputTex.SampleLevel(gInputSamp, dir, 0);
+						float3 radiance = gInputTex.SampleLevel(gInputSamp, dir, 0).rgb;
 						
 						SHMultiplyAdd(data.coeffs.R, shBasis, radiance.r * weight);
 						SHMultiplyAdd(data.coeffs.G, shBasis, radiance.g * weight);
@@ -116,9 +115,9 @@ Technique
 				{
 					if(groupIdx < tc)
 					{
-						SHAdd(sCoeffs[groupIdx].R, sCoeffs[groupIdx + tc].R);
-						SHAdd(sCoeffs[groupIdx].G, sCoeffs[groupIdx + tc].G);
-						SHAdd(sCoeffs[groupIdx].B, sCoeffs[groupIdx + tc].B);
+						SHAdd(sCoeffs[groupIdx].coeffs.R, sCoeffs[groupIdx + tc].coeffs.R);
+						SHAdd(sCoeffs[groupIdx].coeffs.G, sCoeffs[groupIdx + tc].coeffs.G);
+						SHAdd(sCoeffs[groupIdx].coeffs.B, sCoeffs[groupIdx + tc].coeffs.B);
 
 						sCoeffs[groupIdx].weight += sCoeffs[groupIdx + tc].weight;
 					}
@@ -128,7 +127,8 @@ Technique
 				
 				if(groupIdx == 0)
 				{
-					uint outputIdx = groupId.y * gDispatchSize.x + groupId.x;
+					uint faceOffset = gDispatchSize.x * gDispatchSize.y * gCubeFace;
+					uint outputIdx = faceOffset + groupId.y * gDispatchSize.x + groupId.x;
 					gOutput[outputIdx] = sCoeffs[0];
 				}
 			}

+ 1 - 0
Data/Raw/Engine/Shaders/IrradianceProjectSH.bsl

@@ -60,6 +60,7 @@ Technique
 			{
 				float2 scaledUV = input.uv0 * 2.0f - 1.0f;
 				float3 dir = getDirFromCubeFace(gCubeFace, scaledUV);
+				dir = normalize(dir);
 				
 				SHVector5 shBasis = SHBasis5(dir);
 								

+ 2 - 2
Data/Raw/Engine/Shaders/IrradianceReduceSH.bsl

@@ -3,7 +3,7 @@
 
 Technique
  : inherits("ReflectionCubemapCommon")
- : inherits("SHCommon")
+ : inherits("SHCommon") =
 {
 	Language = "HLSL11";
 	
@@ -17,7 +17,7 @@ Technique
 			{
 				SHVector5RGB coeffs;
 				float weight;
-			}
+			};
 
 			StructuredBuffer<SHCoeffsAndWeight> gInput;
 			RWStructuredBuffer<SHVector5RGB> gOutput;

+ 2 - 0
Data/Raw/Engine/Shaders/TiledDeferredLighting.bsl

@@ -163,9 +163,11 @@ Technique
 				float3 V = normalize(gViewOrigin - worldPosition);
 				
 				float4 directLighting = getDirectLighting(worldPosition, surfaceData, lightOffsets);
+				float3 indirectDiffuse = getSkyIndirectDiffuse(surfaceData.worldNormal) * surfaceData.albedo;
 				float3 imageBasedSpecular = getImageBasedSpecular(worldPosition, V, surfaceData);
 
 				float4 totalLighting = directLighting;
+				totalLighting.rgb += indirectDiffuse;
 				totalLighting.rgb += imageBasedSpecular;
 				
 				return totalLighting;				

+ 1 - 1
Source/BansheeEngine/Include/BsReflectionProbes.h

@@ -131,7 +131,7 @@ namespace bs { namespace ct
 	 */
 	class IrradianceReduceSHMat : public RendererMaterial<IrradianceReduceSHMat>
 	{
-		RMAT_DEF("IrradianceComputeSH.bsl")
+		RMAT_DEF("IrradianceReduceSH.bsl")
 
 	public:
 		IrradianceReduceSHMat();

+ 12 - 5
Source/BansheeEngine/Source/BsReflectionProbes.cpp

@@ -79,7 +79,7 @@ namespace bs { namespace ct
 
 	IrradianceComputeSHParamDef gIrradianceComputeSHParamDef;
 
-	const static UINT32 TILE_WIDTH = 16;
+	const static UINT32 TILE_WIDTH = 8;
 	const static UINT32 TILE_HEIGHT = 8;
 	const static UINT32 PIXELS_PER_THREAD = 4;
 
@@ -138,13 +138,14 @@ namespace bs { namespace ct
 		dispatchSize.x = Math::divideAndRoundUp(faceSize, TILE_WIDTH * PIXELS_PER_THREAD);
 		dispatchSize.y = Math::divideAndRoundUp(faceSize, TILE_HEIGHT * PIXELS_PER_THREAD);
 
-		numCoeffSets = dispatchSize.x * dispatchSize.y;
+		numCoeffSets = dispatchSize.x * dispatchSize.y * 6;
 
 		GPU_BUFFER_DESC bufferDesc;
 		bufferDesc.type = GBT_STRUCTURED;
 		bufferDesc.elementCount = numCoeffSets;
 		bufferDesc.elementSize = sizeof(SHCoeffsAndWeight);
 		bufferDesc.format = BF_UNKNOWN;
+		bufferDesc.randomGpuWrite = true;
 
 		return GpuBuffer::create(bufferDesc);
 	}
@@ -189,6 +190,7 @@ namespace bs { namespace ct
 		bufferDesc.elementCount = 1;
 		bufferDesc.elementSize = sizeof(SHVector5RGB);
 		bufferDesc.format = BF_UNKNOWN;
+		bufferDesc.randomGpuWrite = true;
 
 		return GpuBuffer::create(bufferDesc);
 	}
@@ -285,6 +287,9 @@ namespace bs { namespace ct
 				importanceSampleMat.execute(scratchCubemap, face, mip, target);
 			}
 		}
+
+		RenderAPI& rapi = RenderAPI::instance();
+		rapi.setRenderTarget(nullptr);
 	}
 
 	void ReflectionProbes::filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<Texture>& output)
@@ -295,7 +300,12 @@ namespace bs { namespace ct
 
 		UINT32 numCoeffSets;
 		SPtr<GpuBuffer> coeffSetBuffer = IrradianceComputeSHMat::createOutputBuffer(cubemap, numCoeffSets);
+		for (UINT32 face = 0; face < 6; face++)
+			shCompute.execute(cubemap, face, coeffSetBuffer);
+
 		SPtr<GpuBuffer> coeffBuffer = IrradianceReduceSHMat::createOutputBuffer();
+		shReduce.execute(coeffSetBuffer, numCoeffSets, coeffBuffer);
+
 		for (UINT32 face = 0; face < 6; face++)
 		{
 			RENDER_TEXTURE_DESC cubeFaceRTDesc;
@@ -305,9 +315,6 @@ namespace bs { namespace ct
 			cubeFaceRTDesc.colorSurfaces[0].mipLevel = 0;
 
 			SPtr<RenderTarget> target = RenderTexture::create(cubeFaceRTDesc);
-
-			shCompute.execute(cubemap, face, coeffSetBuffer);
-			shReduce.execute(coeffSetBuffer, numCoeffSets, coeffBuffer);
 			shProject.execute(coeffBuffer, face, target);
 		}
 	}

+ 8 - 7
Source/RenderBeast/Include/BsLightRendering.h

@@ -92,8 +92,8 @@ namespace bs { namespace ct
 		/** Binds all the active reflection probes. */
 		void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps);
 
-		/** Binds the sky reflection. If no sky reflection set to null. */
-		void setSkyReflections(const SPtr<Texture>& skyReflections);
+		/** Binds the sky reflection & irradiance textures. Set textures to null if not available. */
+		void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance);
 
 		/** 
 		 * Generates a 2D 2-channel texture containing a pre-integrated G and F factors of the microfactet BRDF. This is an
@@ -116,7 +116,8 @@ namespace bs { namespace ct
 		GpuParamTexture mGBufferC;
 		GpuParamTexture mGBufferDepth;
 
-		GpuParamTexture mSkyCubemapTexParam;
+		GpuParamTexture mSkyReflectionsParam;
+		GpuParamTexture mSkyIrradianceParam;
 		GpuParamTexture mReflectionProbeCubemapsParam;
 		GpuParamTexture mPreintegratedEnvBRDFParam;
 		GpuParamBuffer mReflectionProbesParam;
@@ -148,8 +149,8 @@ namespace bs { namespace ct
 		/** @copydoc TiledDeferredLighting::setReflectionProbes() */
 		virtual void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps) = 0;
 
-		/** @copydoc TiledDeferredLighting::setSkyReflections() */
-		virtual void setSkyReflections(const SPtr<Texture>& skyReflections) = 0;
+		/** @copydoc TiledDeferredLighting::setSky() */
+		virtual void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance) = 0;
 	};
 
 	/** Shader that performs a lighting pass over data stored in the Gbuffer. */
@@ -171,8 +172,8 @@ namespace bs { namespace ct
 		/** @copydoc ITiledDeferredLightingMat::setReflectionProbes() */
 		void setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps) override;
 
-		/** @copydoc ITiledDeferredLightingMat::setSkyReflections() */
-		void setSkyReflections(const SPtr<Texture>& skyReflections) override;
+		/** @copydoc ITiledDeferredLightingMat::setSky() */
+		void setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance) override;
 	private:
 		TiledDeferredLighting mInternal;
 	};

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

@@ -254,6 +254,7 @@ namespace bs
 		Skybox* mSkybox;
 		SPtr<Texture> mSkyboxTexture;
 		SPtr<Texture> mSkyboxFilteredReflections;
+		SPtr<Texture> mSkyboxIrradiance;
 
 		SPtr<Texture> mPreintegratedEnvBRDF;
 		GPULightData* mGPULightData;

+ 14 - 8
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -115,8 +115,11 @@ namespace bs { namespace ct
 		mParamBuffer = gTiledLightingParamDef.createBuffer();
 		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, "gSkyCubemapTex", mSkyCubemapTexParam);
 		params->getTextureParam(GPT_COMPUTE_PROGRAM, "gReflProbeCubemaps", mReflectionProbeCubemapsParam);
 		params->getTextureParam(GPT_COMPUTE_PROGRAM, "gPreintegratedEnvBRDF", mPreintegratedEnvBRDFParam);
 
@@ -132,7 +135,7 @@ namespace bs { namespace ct
 
 		mReflectionSamplerState = SamplerState::create(reflSamplerDesc);
 
-		params->setSamplerState(GPT_COMPUTE_PROGRAM, "gSkyCubemapSamp", mReflectionSamplerState);
+		params->setSamplerState(GPT_COMPUTE_PROGRAM, "gSkyReflectionSamp", mReflectionSamplerState);
 		params->setSamplerState(GPT_COMPUTE_PROGRAM, "gReflProbeSamp", mReflectionSamplerState);
 	}
 
@@ -217,9 +220,10 @@ namespace bs { namespace ct
 		gReflProbeParamsParamDef.gReflCubemapNumMips.set(mReflectionsParamBuffer, numMips);
 	}
 
-	void TiledDeferredLighting::setSkyReflections(const SPtr<Texture>& skyReflections)
+	void TiledDeferredLighting::setSky(const SPtr<Texture>& skyReflections, const SPtr<Texture>& skyIrradiance)
 	{
-		mSkyCubemapTexParam.set(skyReflections);
+		mSkyReflectionsParam.set(skyReflections);
+		mSkyIrradianceParam.set(skyIrradiance);
 
 		UINT32 skyReflectionsAvailable = 0;
 		UINT32 numMips = 0;
@@ -388,7 +392,7 @@ namespace bs { namespace ct
 
 	template<int MSAA_COUNT, bool FixedReflColor>
 	void TTiledDeferredLightingMat<MSAA_COUNT, FixedReflColor>::execute(const SPtr<RenderTargets>& gbuffer,
-																		const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<Texture>& preintegratedGF, bool noLighting)
+		const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<Texture>& preintegratedGF, bool noLighting)
 	{
 		mInternal.execute(gbuffer, perCamera, preintegratedGF, noLighting);
 	}
@@ -400,15 +404,17 @@ namespace bs { namespace ct
 	}
 
 	template<int MSAA_COUNT, bool FixedReflColor>
-	void TTiledDeferredLightingMat<MSAA_COUNT, FixedReflColor>::setReflectionProbes(const GPUReflProbeData& probeData, const SPtr<Texture>& reflectionCubemaps)
+	void TTiledDeferredLightingMat<MSAA_COUNT, FixedReflColor>::setReflectionProbes(const GPUReflProbeData& probeData, 
+		const SPtr<Texture>& reflectionCubemaps)
 	{
 		mInternal.setReflectionProbes(probeData, reflectionCubemaps);
 	}
 
 	template<int MSAA_COUNT, bool FixedReflColor>
-	void TTiledDeferredLightingMat<MSAA_COUNT, FixedReflColor>::setSkyReflections(const SPtr<Texture>& skyReflections)
+	void TTiledDeferredLightingMat<MSAA_COUNT, FixedReflColor>::setSky(const SPtr<Texture>& skyReflections, 
+		const SPtr<Texture>& skyIrradiance)
 	{
-		mInternal.setSkyReflections(skyReflections);
+		mInternal.setSky(skyReflections, skyIrradiance);
 	}
 
 	TiledDeferredLightingMaterials::TiledDeferredLightingMaterials()

+ 27 - 4
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -122,6 +122,7 @@ namespace bs { namespace ct
 		mReflCubemapArrayTex = nullptr;
 		mSkyboxTexture = nullptr;
 		mSkyboxFilteredReflections = nullptr;
+		mSkyboxIrradiance = nullptr;
 
 		PostProcessing::shutDown();
 		GpuResourcePool::shutDown();
@@ -551,6 +552,7 @@ namespace bs { namespace ct
 			mSkyboxTexture = skyTex;
 
 		mSkyboxFilteredReflections = nullptr;
+		mSkyboxIrradiance = nullptr;
 	}
 
 	void RenderBeast::notifySkyboxTextureChanged(Skybox* skybox)
@@ -561,6 +563,7 @@ namespace bs { namespace ct
 		{
 			mSkyboxTexture = skybox->getTexture();
 			mSkyboxFilteredReflections = nullptr;
+			mSkyboxIrradiance = nullptr;
 		}
 	}
 
@@ -778,8 +781,6 @@ namespace bs { namespace ct
 		gCoreThread().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime(), gTime().getFrameDelta()));
 	}
 
-	static SPtr<Texture> dbgSkyTex;
-
 	void RenderBeast::renderAllCore(float time, float delta)
 	{
 		THROW_IF_NOT_CORE_THREAD;
@@ -1039,7 +1040,7 @@ namespace bs { namespace ct
 
 		lightingMat->setLights(*mGPULightData);
 		lightingMat->setReflectionProbes(*mGPUReflProbeData, mReflCubemapArrayTex);
-		lightingMat->setSkyReflections(mSkyboxFilteredReflections);
+		lightingMat->setSky(mSkyboxFilteredReflections, mSkyboxIrradiance);
 
 		lightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF, viewInfo->renderWithNoLighting());
 
@@ -1329,7 +1330,7 @@ namespace bs { namespace ct
 				// Note: Consider pruning the reflection cubemap array if empty slot count becomes too high
 			}
 
-			// Get reflections for skybox if needed/available
+			// Get skybox image-based lighting textures if needed/available
 			if (mSkybox != nullptr && mSkyboxTexture != nullptr)
 			{
 				// If haven't assigned them already, do it now
@@ -1346,9 +1347,31 @@ namespace bs { namespace ct
 						ReflectionCubemapCache::instance().setCachedTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
 					}
 				}
+
+				if(mSkyboxIrradiance == nullptr)
+				{
+					// TODO - Not uisng cache
+
+
+					TEXTURE_DESC irradianceCubemapDesc;
+					irradianceCubemapDesc.type = TEX_TYPE_CUBE_MAP;
+					irradianceCubemapDesc.format = PF_FLOAT_R11G11B10;
+					irradianceCubemapDesc.width = 32;
+					irradianceCubemapDesc.height = 32;
+					irradianceCubemapDesc.numMips = 0;
+					irradianceCubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
+
+					mSkyboxIrradiance = Texture::create(irradianceCubemapDesc);
+
+					ReflectionProbes::filterCubemapForIrradiance(mSkyboxFilteredReflections, mSkyboxIrradiance);
+					//ReflectionCubemapCache::instance().setCachedTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
+				}
 			}
 			else
+			{
 				mSkyboxFilteredReflections = nullptr;
+				mSkyboxIrradiance = nullptr;
+			}
 
 		}
 		bs_frame_clear();