Bläddra i källkod

Shadow mapping functional for radial lights

BearishSun 8 år sedan
förälder
incheckning
fa62ac09d3

+ 4 - 4
Data/Raw/Engine/Includes/GBufferInput.bslinc

@@ -13,10 +13,10 @@ mixin GBufferInput
 		SamplerState gDepthBufferSamp;
 		SamplerState gDepthBufferSamp;
 
 
 		#if MSAA_COUNT > 1
 		#if MSAA_COUNT > 1
-		Texture2DMS<float4, MSAA_COUNT> gGBufferATex;
-		Texture2DMS<float4, MSAA_COUNT>	gGBufferBTex;
-		Texture2DMS<float2, MSAA_COUNT>	gGBufferCTex;
-		Texture2DMS<float4, MSAA_COUNT> gDepthBufferTex;
+		Texture2DMS<float4> gGBufferATex;
+		Texture2DMS<float4>	gGBufferBTex;
+		Texture2DMS<float2>	gGBufferCTex;
+		Texture2DMS<float4> gDepthBufferTex;
 		#else
 		#else
 		Texture2D gGBufferATex;
 		Texture2D gGBufferATex;
 		Texture2D gGBufferBTex;
 		Texture2D gGBufferBTex;

+ 0 - 1
Data/Raw/Engine/Includes/ShadowDepthBase.bslinc

@@ -24,7 +24,6 @@ mixin ShadowDepthBase
 			#endif
 			#endif
 		};
 		};
 		
 		
-		[internal]
 		cbuffer ShadowParams
 		cbuffer ShadowParams
 		{
 		{
 			float4x4 gMatViewProj;
 			float4x4 gMatViewProj;

+ 4 - 1
Data/Raw/Engine/Includes/ShadowProjectionCommon.bslinc

@@ -9,6 +9,7 @@ mixin ShadowProjectionCommon
 		struct VStoFS
 		struct VStoFS
 		{
 		{
 			float4 position : SV_POSITION;
 			float4 position : SV_POSITION;
+			float4 clipSpacePos : TEXCOORD0;
 		};
 		};
 
 
 		struct VertexInput
 		struct VertexInput
@@ -30,8 +31,10 @@ mixin ShadowProjectionCommon
 			
 			
 			#if NEEDS_TRANSFORM
 			#if NEEDS_TRANSFORM
 				float3 worldPos = input.position.xyz * gPositionAndScale.w + gPositionAndScale.xyz;
 				float3 worldPos = input.position.xyz * gPositionAndScale.w + gPositionAndScale.xyz;
-				output.position = mul(gMatViewProj, float4(worldPos, 1));
+				output.clipSpacePos = mul(gMatViewProj, float4(worldPos, 1));
+				output.position = output.clipSpacePos;
 			#else
 			#else
+				output.clipSpacePos = float4(input.position, 1);
 				output.position = float4(input.position, 1);
 				output.position = float4(input.position, 1);
 			#endif
 			#endif
 		
 		

+ 7 - 2
Data/Raw/Engine/Shaders/DeferredDirectionalLight.bsl

@@ -60,11 +60,16 @@ technique DeferredDirectionalLight
 				LightData lightData = getLightData();
 				LightData lightData = getLightData();
 				
 				
 				#if MSAA_COUNT > 1
 				#if MSAA_COUNT > 1
-				float occlusion = 1.0f - gLightOcclusionTex.Load(pixelPos, 0).r;
+				float occlusion = gLightOcclusionTex.Load(pixelPos, sampleIdx).r;
 				#else
 				#else
-				float occlusion = 1.0f - gLightOcclusionTex.Load(int3(pixelPos, 0)).r;
+				float occlusion = gLightOcclusionTex.Load(int3(pixelPos, 0)).r;
 				#endif
 				#endif
 				
 				
+				// Reverse the sqrt we did when storing it
+				occlusion *= occlusion;
+				
+				occlusion = 1.0f - occlusion;
+				
 				return float4(getLuminanceDirectional(lightData, worldPosition, V, R, surfaceData) * occlusion, 1.0f);
 				return float4(getLuminanceDirectional(lightData, worldPosition, V, R, surfaceData) * occlusion, 1.0f);
 			}
 			}
 			else
 			else

+ 7 - 2
Data/Raw/Engine/Shaders/DeferredPointLight.bsl

@@ -109,11 +109,16 @@ technique DeferredPointLight
 				LightData lightData = getLightData();
 				LightData lightData = getLightData();
 				
 				
 				#if MSAA_COUNT > 1
 				#if MSAA_COUNT > 1
-				float occlusion = 1.0f - gLightOcclusionTex.Load(pixelPos, 0).r;
+				float occlusion = gLightOcclusionTex.Load(pixelPos, sampleIdx).r;
 				#else
 				#else
-				float occlusion = 1.0f - gLightOcclusionTex.Load(int3(pixelPos, 0)).r;
+				float occlusion = gLightOcclusionTex.Load(int3(pixelPos, 0)).r;
 				#endif
 				#endif
 				
 				
+				// Reverse the sqrt we did when storing it
+				occlusion *= occlusion;
+				
+				occlusion = 1.0f - occlusion;
+				
 				bool isSpot = gShiftedLightPositionAndType.w > 0.5f;
 				bool isSpot = gShiftedLightPositionAndType.w > 0.5f;
 				if(isSpot)
 				if(isSpot)
 					return float4(getLuminanceSpot(lightData, worldPosition, V, R, roughness2, surfaceData) * occlusion, 1.0f);
 					return float4(getLuminanceSpot(lightData, worldPosition, V, R, roughness2, surfaceData) * occlusion, 1.0f);

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

@@ -72,7 +72,7 @@ technique PPCreateTonemapLUT
 			return color;
 			return color;
 		}		
 		}		
 		
 		
-		RWTexture3D<float4> gOutputTex;
+		RWTexture3D<unorm float4> gOutputTex;
 		
 		
 		[numthreads(8, 8, 1)]
 		[numthreads(8, 8, 1)]
 		void csmain(
 		void csmain(

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

@@ -11,13 +11,11 @@ mixin ShadowDepth
 			uint targetIdx : SV_RenderTargetArrayIndex;
 			uint targetIdx : SV_RenderTargetArrayIndex;
 		};
 		};
 
 
-		[internal]
 		cbuffer ShadowCubeMatrices
 		cbuffer ShadowCubeMatrices
 		{
 		{
 			float4x4 gFaceVPMatrices[6];
 			float4x4 gFaceVPMatrices[6];
 		};
 		};
 		
 		
-		[internal]
 		cbuffer ShadowCubeMasks
 		cbuffer ShadowCubeMasks
 		{
 		{
 			uint gFaceMasks[6];
 			uint gFaceMasks[6];

+ 7 - 6
Data/Raw/Engine/Shaders/ShadowProject.bsl

@@ -215,17 +215,18 @@ technique ShadowProject
 
 
 		float4 fsmain(VStoFS input, uint sampleIdx : SV_SampleIndex) : SV_Target0
 		float4 fsmain(VStoFS input, uint sampleIdx : SV_SampleIndex) : SV_Target0
 		{
 		{
+			float2 ndcPos = input.clipSpacePos.xy / input.clipSpacePos.w;
+			uint2 pixelPos = NDCToScreen(ndcPos);
+		
 			// Get depth & calculate world position
 			// Get depth & calculate world position
 			#if MSAA_COUNT > 1
 			#if MSAA_COUNT > 1
-			uint2 screenPos = NDCToScreen(input.position.xy);
-			float deviceZ = gDepthBufferTex.Load(screenPos, sampleIdx).r;
-			#else
-			float2 screenUV = NDCToUV(input.position.xy);				
-			float deviceZ = gDepthBufferTex.Sample(gDepthBufferSamp, screenUV).r;
+			float deviceZ = gDepthBufferTex.Load(pixelPos, sampleIdx).r;
+			#else			
+			float deviceZ = gDepthBufferTex.Load(int3(pixelPos, 0)).r;
 			#endif
 			#endif
 			
 			
 			float depth = convertFromDeviceZ(deviceZ);
 			float depth = convertFromDeviceZ(deviceZ);
-			float4 mixedSpacePos = float4(input.position.xy * -depth, depth, 1);
+			float4 mixedSpacePos = float4(ndcPos * -depth, depth, 1);
 			
 			
 			float4 shadowPosition = mul(gMixedToShadowSpace, mixedSpacePos); 
 			float4 shadowPosition = mul(gMixedToShadowSpace, mixedSpacePos); 
 			shadowPosition.xy /= shadowPosition.w;
 			shadowPosition.xy /= shadowPosition.w;

+ 22 - 22
Data/Raw/Engine/Shaders/ShadowProjectOmni.bsl

@@ -106,7 +106,6 @@ technique ShadowProjectOmni
 		TextureCube gShadowCubeTex;
 		TextureCube gShadowCubeTex;
 		SamplerComparisonState gShadowCubeSampler;
 		SamplerComparisonState gShadowCubeSampler;
 		
 		
-		[internal]
 		cbuffer Params
 		cbuffer Params
 		{
 		{
 			float4x4 gFaceVPMatrices[6];
 			float4x4 gFaceVPMatrices[6];
@@ -119,14 +118,14 @@ technique ShadowProjectOmni
 		// Returns occlusion where 1 = fully shadowed, 0 = not shadowed
 		// Returns occlusion where 1 = fully shadowed, 0 = not shadowed
 		float cubemapPCF(float3 worldPos, float3 lightPos, float lightRadius)
 		float cubemapPCF(float3 worldPos, float3 lightPos, float lightRadius)
 		{
 		{
-			float3 toLight = lightPos - worldPos;
-			float distToLight = length(toLight);
+			float3 fromLight = worldPos - lightPos;
+			float distToLight = length(fromLight);
 			
 			
 			// No occlusion if outside radius
 			// No occlusion if outside radius
 			if(distToLight > lightRadius)
 			if(distToLight > lightRadius)
 				return 0.0f;
 				return 0.0f;
 				
 				
-			float3 lightDir = toLight / distToLight;
+			float3 lightDir = fromLight / distToLight;
 			
 			
 			float3 up = abs(lightDir.z) < 0.999f ? float3(0, 0, 1) : float3(1, 0, 0);
 			float3 up = abs(lightDir.z) < 0.999f ? float3(0, 0, 1) : float3(1, 0, 0);
 			float3 side = normalize(cross(up, lightDir));
 			float3 side = normalize(cross(up, lightDir));
@@ -136,22 +135,22 @@ technique ShadowProjectOmni
 			side *= gInvResolution;
 			side *= gInvResolution;
 			
 			
 			// Determine cube face to sample from
 			// Determine cube face to sample from
-			float3 absToLight = abs(toLight);
-			float maxComponent = max(absToLight.x, max(absToLight.y, absToLight.z));
+			float3 absFromLight = abs(fromLight);
+			float maxComponent = max(absFromLight.x, max(absFromLight.y, absFromLight.z));
 			
 			
 			int faceIdx = 0;
 			int faceIdx = 0;
-			if(maxComponent == absToLight.x)
-				faceIdx = toLight.x > 0.0f ? 0 : 1;
-			else if(maxComponent == absToLight.z)
-				faceIdx = toLight.z > 0.0f ? 4 : 5;
+			if(maxComponent == absFromLight.x)
+				faceIdx = fromLight.x > 0.0f ? 0 : 1;
+			else if(maxComponent == absFromLight.z)
+				faceIdx = fromLight.z > 0.0f ? 4 : 5;
 			else
 			else
-				faceIdx = toLight.y > 0.0f ? 2 : 3;
+				faceIdx = fromLight.y > 0.0f ? 2 : 3;
 			
 			
 			// Get position of the receiver in shadow space
 			// Get position of the receiver in shadow space
-			float4 shadowPos = mul(gFaceVPMatrices[faceIdx], worldPos);
+			float4 shadowPos = mul(gFaceVPMatrices[faceIdx], float4(worldPos, 1));
 			
 			
 			float receiverDepth = NDCZToDeviceZ(shadowPos.z / shadowPos.w);
 			float receiverDepth = NDCZToDeviceZ(shadowPos.z / shadowPos.w);
-			float shadowBias = gDepthBias / -shadowPos.w;
+			float shadowBias = gDepthBias / shadowPos.w;
 			
 			
 			float occlusion = 0.0f;
 			float occlusion = 0.0f;
 			#if SHADOW_QUALITY <= 1
 			#if SHADOW_QUALITY <= 1
@@ -160,7 +159,7 @@ technique ShadowProjectOmni
 				[unroll]
 				[unroll]
 				for(int i = 0; i < 4; ++i)
 				for(int i = 0; i < 4; ++i)
 				{
 				{
-					float sampleDir = lightDir + side * discSamples4[i].x + up * discSamples4[i].y;
+					float3 sampleDir = lightDir + side * discSamples4[i].x + up * discSamples4[i].y;
 					occlusion += gShadowCubeTex.SampleCmpLevelZero(gShadowCubeSampler, sampleDir, receiverDepth - shadowBias);
 					occlusion += gShadowCubeTex.SampleCmpLevelZero(gShadowCubeSampler, sampleDir, receiverDepth - shadowBias);
 				}
 				}
 				
 				
@@ -169,7 +168,7 @@ technique ShadowProjectOmni
 				[unroll]
 				[unroll]
 				for(int i = 0; i < 12; ++i)
 				for(int i = 0; i < 12; ++i)
 				{
 				{
-					float sampleDir = lightDir + side * discSamples12[i].x + up * discSamples12[i].y;
+					float3 sampleDir = lightDir + side * discSamples12[i].x + up * discSamples12[i].y;
 					occlusion += gShadowCubeTex.SampleCmpLevelZero(gShadowCubeSampler, sampleDir, receiverDepth - shadowBias);
 					occlusion += gShadowCubeTex.SampleCmpLevelZero(gShadowCubeSampler, sampleDir, receiverDepth - shadowBias);
 				}
 				}
 				
 				
@@ -178,7 +177,7 @@ technique ShadowProjectOmni
 				[unroll]
 				[unroll]
 				for(int i = 0; i < 32; ++i)
 				for(int i = 0; i < 32; ++i)
 				{
 				{
-					float sampleDir = lightDir + side * discSamples32[i].x + up * discSamples32[i].y;
+					float3 sampleDir = lightDir + side * discSamples32[i].x + up * discSamples32[i].y;
 					occlusion += gShadowCubeTex.SampleCmpLevelZero(gShadowCubeSampler, sampleDir, receiverDepth - shadowBias);
 					occlusion += gShadowCubeTex.SampleCmpLevelZero(gShadowCubeSampler, sampleDir, receiverDepth - shadowBias);
 				}
 				}
 				
 				
@@ -190,17 +189,18 @@ technique ShadowProjectOmni
 		
 		
 		float4 fsmain(VStoFS input, uint sampleIdx : SV_SampleIndex) : SV_Target0
 		float4 fsmain(VStoFS input, uint sampleIdx : SV_SampleIndex) : SV_Target0
 		{
 		{
+			float2 ndcPos = input.clipSpacePos.xy / input.clipSpacePos.w;
+			uint2 pixelPos = NDCToScreen(ndcPos);
+		
 			// Get depth & calculate world position
 			// Get depth & calculate world position
 			#if MSAA_COUNT > 1
 			#if MSAA_COUNT > 1
-			uint2 screenPos = NDCToScreen(input.position.xy);
-			float deviceZ = gDepthBufferTex.Load(screenPos, sampleIdx).r;
-			#else
-			float2 screenUV = NDCToUV(input.position.xy);				
-			float deviceZ = gDepthBufferTex.Sample(gDepthBufferSamp, screenUV).r;
+			float deviceZ = gDepthBufferTex.Load(pixelPos, sampleIdx).r;
+			#else		
+			float deviceZ = gDepthBufferTex.Load(int3(pixelPos, 0)).r;
 			#endif
 			#endif
 			
 			
 			float depth = convertFromDeviceZ(deviceZ);
 			float depth = convertFromDeviceZ(deviceZ);
-			float3 worldPos = NDCToWorld(input.position.xy, depth);
+			float3 worldPos = NDCToWorld(ndcPos, depth);
 		
 		
 			float occlusion = cubemapPCF(worldPos, gLightPosAndRadius.xyz, gLightPosAndRadius.w);
 			float occlusion = cubemapPCF(worldPos, gLightPosAndRadius.xyz, gLightPosAndRadius.w);
 			occlusion *= gFadePercent;
 			occlusion *= gFadePercent;

+ 0 - 1
Source/BansheeCore/Include/BsLight.h

@@ -324,7 +324,6 @@ namespace bs
 		void syncToCore(const CoreSyncData& data) override;
 		void syncToCore(const CoreSyncData& data) override;
 
 
 		UINT32 mRendererId;
 		UINT32 mRendererId;
-		SPtr<Mesh> mMesh;
 	};
 	};
 	}
 	}
 
 

+ 0 - 7
Source/BansheeCore/Source/BsGpuParamsSet.cpp

@@ -418,13 +418,6 @@ namespace bs
 				continue;
 				continue;
 			}
 			}
 
 
-			if (findIter->second->arraySize != iter->second.arraySize)
-			{
-				LOGWRN("Ignoring shader parameter \"" + iter->first + "\". Array size doesn't match the one defined in the gpu program."
-					+ "Shader defined array size: " + toString(iter->second.arraySize) + " - Gpu program defined array size: " + toString(findIter->second->arraySize));
-				continue;
-			}
-
 			auto findBlockIter = paramToParamBlockMap.find(iter->second.gpuVariableName);
 			auto findBlockIter = paramToParamBlockMap.find(iter->second.gpuVariableName);
 
 
 			if (findBlockIter == paramToParamBlockMap.end())
 			if (findBlockIter == paramToParamBlockMap.end())

+ 1 - 2
Source/BansheeCore/Source/BsGpuPipelineParamInfo.cpp

@@ -160,11 +160,10 @@ namespace bs
 			// Samplers need to be handled specially because certain slots could be texture/buffer + sampler combinations
 			// Samplers need to be handled specially because certain slots could be texture/buffer + sampler combinations
 			{
 			{
 				int typeIdx = (int)ParamType::SamplerState;
 				int typeIdx = (int)ParamType::SamplerState;
-				UINT32 sequentialIdx = mNumElementsPerType[typeIdx];
-
 				for (auto& entry : paramDesc->samplers)
 				for (auto& entry : paramDesc->samplers)
 				{
 				{
 					const GpuParamObjectDesc& samplerDesc = entry.second;
 					const GpuParamObjectDesc& samplerDesc = entry.second;
+					UINT32 sequentialIdx = mNumElementsPerType[typeIdx];
 
 
 					SetInfo& setInfo = mSetInfos[samplerDesc.set];
 					SetInfo& setInfo = mSetInfos[samplerDesc.set];
 					if (setInfo.slotIndices[samplerDesc.slot] == -1) // Slot is sampler only
 					if (setInfo.slotIndices[samplerDesc.slot] == -1) // Slot is sampler only

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

@@ -59,6 +59,9 @@ namespace bs { namespace ct
 		void bind(const RenderTargets& renderTargets);
 		void bind(const RenderTargets& renderTargets);
 
 
 	private:
 	private:
+		SPtr<Material> mMaterial;
+		SPtr<GpuParamsSet> mParamsSet;
+
 		MaterialParamTexture mGBufferA;
 		MaterialParamTexture mGBufferA;
 		MaterialParamTexture mGBufferB;
 		MaterialParamTexture mGBufferB;
 		MaterialParamTexture mGBufferC;
 		MaterialParamTexture mGBufferC;

+ 2 - 1
Source/RenderBeast/Include/BsShadowRendering.h

@@ -481,12 +481,13 @@ namespace bs { namespace ct
 		 * 
 		 * 
 		 * @param[in]	light			Light for which to calculate the shadow map properties. Cannot be a directional light.
 		 * @param[in]	light			Light for which to calculate the shadow map properties. Cannot be a directional light.
 		 * @param[in]	scene			Scene information containing all the views the light can be seen through.
 		 * @param[in]	scene			Scene information containing all the views the light can be seen through.
+		 * @param[in]	border			Border to reduce the shadow map size by, in pixels.
 		 * @param[out]	size			Optimal size of the shadow map, in pixels.
 		 * @param[out]	size			Optimal size of the shadow map, in pixels.
 		 * @param[out]	fadePercents	Value in range [0, 1] determining how much should the shadow map be faded out. Each
 		 * @param[out]	fadePercents	Value in range [0, 1] determining how much should the shadow map be faded out. Each
 		 *								entry corresponds to a single view.
 		 *								entry corresponds to a single view.
 		 * @param[out]	maxFadePercent	Maximum value in the @p fadePercents array.
 		 * @param[out]	maxFadePercent	Maximum value in the @p fadePercents array.
 		 */
 		 */
-		void calcShadowMapProperties(const RendererLight& light, RendererScene& scene, UINT32& size, 
+		void calcShadowMapProperties(const RendererLight& light, RendererScene& scene, UINT32 border, UINT32& size, 
 			SmallVector<float, 4>& fadePercents, float& maxFadePercent) const;
 			SmallVector<float, 4>& fadePercents, float& maxFadePercent) const;
 
 
 		/**
 		/**

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

@@ -90,6 +90,7 @@ namespace bs { namespace ct
 	}
 	}
 
 
 	GBufferParams::GBufferParams(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet)
 	GBufferParams::GBufferParams(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet)
+		: mMaterial(material), mParamsSet(paramsSet)
 	{
 	{
 		mGBufferA = material->getParamTexture("gGBufferATex");
 		mGBufferA = material->getParamTexture("gGBufferATex");
 		mGBufferB = material->getParamTexture("gGBufferBTex");
 		mGBufferB = material->getParamTexture("gGBufferBTex");
@@ -103,6 +104,8 @@ namespace bs { namespace ct
 		mGBufferB.set(renderTargets.getGBufferB());
 		mGBufferB.set(renderTargets.getGBufferB());
 		mGBufferC.set(renderTargets.getGBufferC());
 		mGBufferC.set(renderTargets.getGBufferC());
 		mGBufferDepth.set(renderTargets.getSceneDepth());
 		mGBufferDepth.set(renderTargets.getSceneDepth());
+
+		mMaterial->updateParamsSet(mParamsSet);
 	}
 	}
 
 
 	VisibleLightData::VisibleLightData()
 	VisibleLightData::VisibleLightData()

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

@@ -354,7 +354,7 @@ namespace bs { namespace ct
 		mMainViewGroup.determineVisibility(sceneInfo);
 		mMainViewGroup.determineVisibility(sceneInfo);
 
 
 		// Render shadow maps
 		// Render shadow maps
-		//ShadowRendering::instance().renderShadowMaps(*mScene, mMainViewGroup, frameInfo);
+		ShadowRendering::instance().renderShadowMaps(*mScene, mMainViewGroup, frameInfo);
 
 
 		// Update reflection probes
 		// Update reflection probes
 		updateLightProbes(frameInfo);
 		updateLightProbes(frameInfo);
@@ -568,12 +568,12 @@ namespace bs { namespace ct
 		bool isMSAA = numSamples > 1;
 		bool isMSAA = numSamples > 1;
 		if(isMSAA)
 		if(isMSAA)
 		{
 		{
+			renderTargets->bindLightAccumulation();
 			mFlatFramebufferToTextureMat->execute(renderTargets->getLightAccumulationBuffer(), 
 			mFlatFramebufferToTextureMat->execute(renderTargets->getLightAccumulationBuffer(), 
 				renderTargets->getLightAccumulation());
 				renderTargets->getLightAccumulation());
 		}
 		}
 
 
 		// Render shadowed lights into light accumulation texture, using standard deferred
 		// Render shadowed lights into light accumulation texture, using standard deferred
-		allowShadows = false; // DEBUG ONLY
 		if (allowShadows)
 		if (allowShadows)
 		{
 		{
 			renderTargets->allocate(RTT_LightOcclusion);
 			renderTargets->allocate(RTT_LightOcclusion);
@@ -605,6 +605,9 @@ namespace bs { namespace ct
 			renderTargets->release(RTT_LightOcclusion);
 			renderTargets->release(RTT_LightOcclusion);
 		}
 		}
 
 
+		// Make sure light accumulation buffer isn't bound and can be read from
+		rapi.setRenderTarget(nullptr);
+
 		// Render image based lighting, add it to light accumulation and output scene color
 		// Render image based lighting, add it to light accumulation and output scene color
 		renderTargets->allocate(RTT_SceneColor);
 		renderTargets->allocate(RTT_SceneColor);
 		imageBasedLightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF);
 		imageBasedLightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF);
@@ -1012,7 +1015,7 @@ namespace bs { namespace ct
 				up = -Vector3::UNIT_Z;
 				up = -Vector3::UNIT_Z;
 				break;
 				break;
 			case CF_NegativeY:
 			case CF_NegativeY:
-				forward = Vector3::UNIT_X;
+				forward = Vector3::UNIT_X; // TODO: Why X here?
 				up = Vector3::UNIT_Z;
 				up = Vector3::UNIT_Z;
 				break;
 				break;
 			case CF_PositiveZ:
 			case CF_PositiveZ:
@@ -1024,7 +1027,7 @@ namespace bs { namespace ct
 			}
 			}
 
 
 			Vector3 right = Vector3::cross(up, forward);
 			Vector3 right = Vector3::cross(up, forward);
-			viewRotationMat = Matrix3(right, up, forward);
+			viewRotationMat = Matrix3(right, up, forward); // TODO - Use -forward here? (Works for shadows)
 
 
 			viewDesc.viewDirection = forward;
 			viewDesc.viewDirection = forward;
 			viewDesc.viewTransform = Matrix4(viewRotationMat) * viewOffsetMat;
 			viewDesc.viewTransform = Matrix4(viewRotationMat) * viewOffsetMat;

+ 15 - 3
Source/RenderBeast/Source/BsRenderTargets.cpp

@@ -6,6 +6,7 @@
 #include "BsRenderAPI.h"
 #include "BsRenderAPI.h"
 #include "BsTextureManager.h"
 #include "BsTextureManager.h"
 #include "BsRendererUtility.h"
 #include "BsRendererUtility.h"
+#include "BsGpuBuffer.h"
 
 
 namespace bs { namespace ct
 namespace bs { namespace ct
 {
 {
@@ -151,6 +152,17 @@ namespace bs { namespace ct
 				UINT32 bufferNumElements = width * height * mViewTarget.numSamples;
 				UINT32 bufferNumElements = width * height * mViewTarget.numSamples;
 				mFlattenedLightAccumulationBuffer =
 				mFlattenedLightAccumulationBuffer =
 					texPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
 					texPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
+
+				SPtr<GpuBuffer> buffer = mFlattenedLightAccumulationBuffer->buffer;
+
+				auto& bufferProps = buffer->getProperties();
+
+				UINT32 bufferSize = bufferProps.getElementSize() * bufferProps.getElementCount();
+				UINT16* data = (UINT16*)buffer->lock(0, bufferSize, GBL_WRITE_ONLY_DISCARD);
+				{
+					memset(data, 0, bufferSize);
+				}
+				buffer->unlock();
 			}
 			}
 
 
 			mLightAccumulationTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width,
 			mLightAccumulationTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width,
@@ -272,13 +284,13 @@ namespace bs { namespace ct
 	void RenderTargets::bindLightAccumulation()
 	void RenderTargets::bindLightAccumulation()
 	{
 	{
 		RenderAPI& rapi = RenderAPI::instance();
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mLightAccumulationRT);
+		rapi.setRenderTarget(mLightAccumulationRT, true, RT_COLOR0 | RT_DEPTH);
 	}
 	}
 
 
 	void RenderTargets::bindLightOcclusion()
 	void RenderTargets::bindLightOcclusion()
 	{
 	{
 		RenderAPI& rapi = RenderAPI::instance();
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mLightOcclusionRT);
+		rapi.setRenderTarget(mLightOcclusionRT, true, RT_DEPTH);
 
 
 		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
 		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
 		rapi.setViewport(area);
 		rapi.setViewport(area);
@@ -346,4 +358,4 @@ namespace bs { namespace ct
 	{
 	{
 		return mFlattenedLightAccumulationBuffer->buffer;
 		return mFlattenedLightAccumulationBuffer->buffer;
 	}
 	}
-}}
+}}

+ 45 - 35
Source/RenderBeast/Source/BsShadowRendering.cpp

@@ -238,11 +238,11 @@ namespace bs { namespace ct
 		TextureSurface surface;
 		TextureSurface surface;
 		surface.arraySlice = params.shadowMapFace;
 		surface.arraySlice = params.shadowMapFace;
 
 
+		mGBufferParams.bind(params.renderTargets);
+
 		mShadowMapParam.set(params.shadowMap, surface);
 		mShadowMapParam.set(params.shadowMap, surface);
 		mShadowSamplerParam.set(mSamplerState);
 		mShadowSamplerParam.set(mSamplerState);
 
 
-		mGBufferParams.bind(params.renderTargets);
-
 		mParamsSet->setParamBlockBuffer("Params", params.shadowParams);
 		mParamsSet->setParamBlockBuffer("Params", params.shadowParams);
 		mParamsSet->setParamBlockBuffer("PerCamera", params.perCamera);
 		mParamsSet->setParamBlockBuffer("PerCamera", params.perCamera);
 
 
@@ -338,11 +338,11 @@ namespace bs { namespace ct
 		Vector4 lightPosAndScale(params.light.getPosition(), params.light.getAttenuationRadius());
 		Vector4 lightPosAndScale(params.light.getPosition(), params.light.getAttenuationRadius());
 		gShadowProjectVertParamsDef.gPositionAndScale.set(mVertParams, lightPosAndScale);
 		gShadowProjectVertParamsDef.gPositionAndScale.set(mVertParams, lightPosAndScale);
 
 
+		mGBufferParams.bind(params.renderTargets);
+
 		mShadowMapParam.set(params.shadowMap);
 		mShadowMapParam.set(params.shadowMap);
 		mShadowSamplerParam.set(mSamplerState);
 		mShadowSamplerParam.set(mSamplerState);
 
 
-		mGBufferParams.bind(params.renderTargets);
-
 		mParamsSet->setParamBlockBuffer("Params", params.shadowParams);
 		mParamsSet->setParamBlockBuffer("Params", params.shadowParams);
 		mParamsSet->setParamBlockBuffer("PerCamera", params.perCamera);
 		mParamsSet->setParamBlockBuffer("PerCamera", params.perCamera);
 
 
@@ -350,11 +350,11 @@ namespace bs { namespace ct
 		gRendererUtility().setPassParams(mParamsSet);
 		gRendererUtility().setPassParams(mParamsSet);
 	}
 	}
 
 
-	void ShadowProjectOmniMaterials::bind(UINT32 quality, bool directional, bool MSAA, const ShadowProjectParams& params)
+	void ShadowProjectOmniMaterials::bind(UINT32 quality, bool insideVolume, bool MSAA, const ShadowProjectParams& params)
 	{
 	{
 #define BIND_MAT(QUALITY)						\
 #define BIND_MAT(QUALITY)						\
 	{											\
 	{											\
-		if(directional)							\
+		if(insideVolume)						\
 			if (MSAA)							\
 			if (MSAA)							\
 				mMat##QUALITY##TT.bind(params);	\
 				mMat##QUALITY##TT.bind(params);	\
 			else								\
 			else								\
@@ -449,10 +449,6 @@ namespace bs { namespace ct
 	{
 	{
 		mShadowMap = GpuResourcePool::instance().get(
 		mShadowMap = GpuResourcePool::instance().get(
 			POOLED_RENDER_TEXTURE_DESC::createCube(SHADOW_MAP_FORMAT, size, size, TU_DEPTHSTENCIL));
 			POOLED_RENDER_TEXTURE_DESC::createCube(SHADOW_MAP_FORMAT, size, size, TU_DEPTHSTENCIL));
-
-		RENDER_TEXTURE_DESC rtDesc;
-		rtDesc.depthStencilSurface.texture = mShadowMap->texture;
-		rtDesc.depthStencilSurface.numFaces = 6;
 	}
 	}
 
 
 	ShadowCubemap::~ShadowCubemap()
 	ShadowCubemap::~ShadowCubemap()
@@ -613,7 +609,7 @@ namespace bs { namespace ct
 			options.lightIdx = i;
 			options.lightIdx = i;
 
 
 			float maxFadePercent;
 			float maxFadePercent;
-			calcShadowMapProperties(light, scene, options.mapSize, options.fadePercents, maxFadePercent);
+			calcShadowMapProperties(light, scene, SHADOW_MAP_BORDER, options.mapSize, options.fadePercents, maxFadePercent);
 
 
 			// Don't render shadow maps that will end up nearly completely faded out
 			// Don't render shadow maps that will end up nearly completely faded out
 			if (maxFadePercent < 0.005f)
 			if (maxFadePercent < 0.005f)
@@ -639,7 +635,7 @@ namespace bs { namespace ct
 			options.lightIdx = i;
 			options.lightIdx = i;
 
 
 			float maxFadePercent;
 			float maxFadePercent;
-			calcShadowMapProperties(light, scene, options.mapSize, options.fadePercents, maxFadePercent);
+			calcShadowMapProperties(light, scene, 0, options.mapSize, options.fadePercents, maxFadePercent);
 
 
 			// Don't render shadow maps that will end up nearly completely faded out
 			// Don't render shadow maps that will end up nearly completely faded out
 			if (maxFadePercent < 0.005f)
 			if (maxFadePercent < 0.005f)
@@ -804,7 +800,7 @@ namespace bs { namespace ct
 				SPtr<Texture> shadowMap = mShadowCubemaps[shadowInfo.textureIdx].getTexture();
 				SPtr<Texture> shadowMap = mShadowCubemaps[shadowInfo.textureIdx].getTexture();
 				SPtr<RenderTargets> renderTargets = view->getRenderTargets();
 				SPtr<RenderTargets> renderTargets = view->getRenderTargets();
 
 
-				ShadowProjectParams shadowParams(*light, shadowMap, 0, shadowParamBuffer, perViewBuffer, *renderTargets);
+				ShadowProjectParams shadowParams(*light, shadowMap, 0, shadowOmniParamBuffer, perViewBuffer, *renderTargets);
 				mProjectOmniMaterials.bind(effectiveShadowQuality, viewerInsideVolume, viewProps.numSamples > 1, shadowParams);
 				mProjectOmniMaterials.bind(effectiveShadowQuality, viewerInsideVolume, viewProps.numSamples > 1, shadowParams);
 
 
 				gRendererUtility().draw(gRendererUtility().getRadialLightStencil());
 				gRendererUtility().draw(gRendererUtility().getRadialLightStencil());
@@ -933,6 +929,8 @@ namespace bs { namespace ct
 		shadowInfo.textureIdx = -1;
 		shadowInfo.textureIdx = -1;
 
 
 		UINT32 mapSize = std::min(mShadowMapSize, MAX_ATLAS_SIZE);
 		UINT32 mapSize = std::min(mShadowMapSize, MAX_ATLAS_SIZE);
+		shadowInfo.area = Rect2I(0, 0, mapSize, mapSize);
+		shadowInfo.updateNormArea(mapSize);
 
 
 		for (UINT32 i = 0; i < (UINT32)mCascadedShadowMaps.size(); i++)
 		for (UINT32 i = 0; i < (UINT32)mCascadedShadowMaps.size(); i++)
 		{
 		{
@@ -1145,6 +1143,8 @@ namespace bs { namespace ct
 		mapInfo.textureIdx = -1;
 		mapInfo.textureIdx = -1;
 		mapInfo.fadePerView = options.fadePercents;
 		mapInfo.fadePerView = options.fadePercents;
 		mapInfo.cascadeIdx = -1;
 		mapInfo.cascadeIdx = -1;
+		mapInfo.area = Rect2I(0, 0, options.mapSize, options.mapSize);
+		mapInfo.updateNormArea(options.mapSize);
 
 
 		for (UINT32 i = 0; i < (UINT32)mShadowCubemaps.size(); i++)
 		for (UINT32 i = 0; i < (UINT32)mShadowCubemaps.size(); i++)
 		{
 		{
@@ -1178,10 +1178,10 @@ namespace bs { namespace ct
 		mapInfo.depthBias = getDepthBias(*light, mapInfo.depthRange, options.mapSize);
 		mapInfo.depthBias = getDepthBias(*light, mapInfo.depthRange, options.mapSize);
 
 
 		Matrix4 proj = Matrix4::projectionPerspective(Degree(90.0f), 1.0f, 0.05f, light->getAttenuationRadius());
 		Matrix4 proj = Matrix4::projectionPerspective(Degree(90.0f), 1.0f, 0.05f, light->getAttenuationRadius());
-		RenderAPI::instance().convertProjectionMatrix(proj, proj);
-
 		ConvexVolume localFrustum(proj);
 		ConvexVolume localFrustum(proj);
 
 
+		RenderAPI::instance().convertProjectionMatrix(proj, proj);
+
 		gShadowParamsDef.gDepthBias.set(shadowParamsBuffer, mapInfo.depthBias);
 		gShadowParamsDef.gDepthBias.set(shadowParamsBuffer, mapInfo.depthBias);
 		gShadowParamsDef.gInvDepthRange.set(shadowParamsBuffer, 1.0f / mapInfo.depthRange);
 		gShadowParamsDef.gInvDepthRange.set(shadowParamsBuffer, 1.0f / mapInfo.depthRange);
 		gShadowParamsDef.gMatViewProj.set(shadowParamsBuffer, Matrix4::IDENTITY);
 		gShadowParamsDef.gMatViewProj.set(shadowParamsBuffer, Matrix4::IDENTITY);
@@ -1210,7 +1210,7 @@ namespace bs { namespace ct
 				up = -Vector3::UNIT_Z;
 				up = -Vector3::UNIT_Z;
 				break;
 				break;
 			case CF_NegativeY:
 			case CF_NegativeY:
-				forward = Vector3::UNIT_X;
+				forward = -Vector3::UNIT_Y;
 				up = Vector3::UNIT_Z;
 				up = Vector3::UNIT_Z;
 				break;
 				break;
 			case CF_PositiveZ:
 			case CF_PositiveZ:
@@ -1222,7 +1222,7 @@ namespace bs { namespace ct
 			}
 			}
 
 
 			Vector3 right = Vector3::cross(up, forward);
 			Vector3 right = Vector3::cross(up, forward);
-			Matrix3 viewRotationMat = Matrix3(right, up, forward);
+			Matrix3 viewRotationMat = Matrix3(right, up, -forward);
 
 
 			Matrix4 view = Matrix4(viewRotationMat) * viewOffsetMat;
 			Matrix4 view = Matrix4(viewRotationMat) * viewOffsetMat;
 			mapInfo.shadowVPTransforms[i] = proj * view;
 			mapInfo.shadowVPTransforms[i] = proj * view;
@@ -1265,7 +1265,7 @@ namespace bs { namespace ct
 
 
 			for(UINT32 j = 0; j < 6; j++)
 			for(UINT32 j = 0; j < 6; j++)
 			{
 			{
-				int mask = frustums->intersects(bounds) ? 1 : 0;
+				int mask = frustums[j].intersects(bounds) ? 1 : 0;
 				gShadowCubeMasksDef.gFaceMasks.set(shadowCubeMasksBuffer, mask, j);
 				gShadowCubeMasksDef.gFaceMasks.set(shadowCubeMasksBuffer, mask, j);
 			}
 			}
 
 
@@ -1288,32 +1288,43 @@ namespace bs { namespace ct
 		lightShadows.numShadows++;
 		lightShadows.numShadows++;
 	}
 	}
 
 
-	void ShadowRendering::calcShadowMapProperties(const RendererLight& light, RendererScene& scene, UINT32& size, 
-		SmallVector<float, 4>& fadePercents, float& maxFadePercent) const
+	void ShadowRendering::calcShadowMapProperties(const RendererLight& light, RendererScene& scene, UINT32 border,
+		UINT32& size, SmallVector<float, 4>& fadePercents, float& maxFadePercent) const
 	{
 	{
+		const static float SHADOW_TEXELS_PER_PIXEL = 1.0f;
+
 		const SceneInfo& sceneInfo = scene.getSceneInfo();
 		const SceneInfo& sceneInfo = scene.getSceneInfo();
 
 
 		// Find a view in which the light has the largest radius
 		// Find a view in which the light has the largest radius
-		float maxRadiusPercent = 0.0f;
+		float maxMapSize = 0.0f;
 		maxFadePercent = 0.0f;
 		maxFadePercent = 0.0f;
 		for (int i = 0; i < (int)sceneInfo.views.size(); ++i)
 		for (int i = 0; i < (int)sceneInfo.views.size(); ++i)
 		{
 		{
 			const RendererViewProperties& viewProps = sceneInfo.views[i]->getProperties();
 			const RendererViewProperties& viewProps = sceneInfo.views[i]->getProperties();
 
 
-			float viewScaleX = viewProps.projTransform[0][0] * 0.5f;
-			float viewScaleY = viewProps.projTransform[1][1] * 0.5f;
-			float viewScale = std::max(viewScaleX, viewScaleY);
-
+			// Approximation for screen space sphere radius: screenSize * 0.5 * cot(fov) * radius / Z, where FOV is the 
+			// largest one
+			//// First get sphere depth
 			const Matrix4& viewVP = viewProps.viewProjTransform;
 			const Matrix4& viewVP = viewProps.viewProjTransform;
+			float depth = viewVP.multiply(Vector4(light.internal->getPosition(), 1.0f)).w;
+
+			// This is just 1/tan(fov), for both horz. and vert. FOV
+			float viewScaleX = viewProps.projTransform[0][0];
+			float viewScaleY = viewProps.projTransform[1][1];
+
+			float screenScaleX = viewScaleX * viewProps.viewRect.width * 0.5f;
+			float screenScaleY = viewScaleY * viewProps.viewRect.height * 0.5f;
+
+			float screenScale = std::max(screenScaleX, screenScaleY);
 
 
-			Vector4 lightClipPos = viewVP.multiply(Vector4(light.internal->getPosition(), 1.0f));
-			float radiusNDC = light.internal->getBounds().getRadius() / std::max(lightClipPos.w, 1.0f);
+			//// Calc radius (clamp if too close to avoid massive numbers)
+			float radiusNDC = light.internal->getBounds().getRadius() / std::max(depth, 1.0f);
 
 
-			// Radius of light bounds in percent of the view surface
-			float radiusPercent = radiusNDC * viewScale;
-			maxRadiusPercent = std::max(maxRadiusPercent, radiusPercent);
+			//// Radius of light bounds in percent of the view surface, multiplied by screen size in pixels
+			float radiusScreen = radiusNDC * screenScale;
 
 
-			float optimalMapSize = mShadowMapSize * radiusPercent;
+			float optimalMapSize = SHADOW_TEXELS_PER_PIXEL * radiusScreen;
+			maxMapSize = std::max(maxMapSize, optimalMapSize);
 			
 			
 			// Determine if the shadow should fade out
 			// Determine if the shadow should fade out
 			float fadePercent = Math::lerp01(optimalMapSize, (float)MIN_SHADOW_MAP_SIZE, (float)SHADOW_MAP_FADE_SIZE);
 			float fadePercent = Math::lerp01(optimalMapSize, (float)MIN_SHADOW_MAP_SIZE, (float)SHADOW_MAP_FADE_SIZE);
@@ -1323,12 +1334,11 @@ namespace bs { namespace ct
 
 
 		// If light fully (or nearly fully) covers the screen, use full shadow map resolution, otherwise
 		// If light fully (or nearly fully) covers the screen, use full shadow map resolution, otherwise
 		// scale it down to smaller power of two, while clamping to minimal allowed resolution
 		// scale it down to smaller power of two, while clamping to minimal allowed resolution
-		float maxOptimalMapSize = mShadowMapSize * maxRadiusPercent;
-		UINT32 effectiveMapSize = Bitwise::nextPow2((UINT32)maxOptimalMapSize);
+		UINT32 effectiveMapSize = Bitwise::nextPow2((UINT32)maxMapSize);
 		effectiveMapSize = Math::clamp(effectiveMapSize, MIN_SHADOW_MAP_SIZE, mShadowMapSize);
 		effectiveMapSize = Math::clamp(effectiveMapSize, MIN_SHADOW_MAP_SIZE, mShadowMapSize);
 
 
 		// Leave room for border
 		// Leave room for border
-		size = std::max(effectiveMapSize - 2 * SHADOW_MAP_BORDER, 1u);
+		size = std::max(effectiveMapSize - 2 * border, 1u);
 	}
 	}
 
 
 	void ShadowRendering::drawNearFarPlanes(float near, float far, bool drawNear)
 	void ShadowRendering::drawNearFarPlanes(float near, float far, bool drawNear)
@@ -1604,7 +1614,7 @@ namespace bs { namespace ct
 			break;
 			break;
 		}
 		}
 		
 		
-		return defaultBias * light.getShadowBias() *resolutionScale * rangeScale;
+		return defaultBias * light.getShadowBias() * resolutionScale * rangeScale;
 	}
 	}
 
 
 	float ShadowRendering::getFadeTransition(const Light& light, float depthRange, UINT32 mapSize)
 	float ShadowRendering::getFadeTransition(const Light& light, float depthRange, UINT32 mapSize)