Kaynağa Gözat

More work on the standard deferred rendering path

BearishSun 8 yıl önce
ebeveyn
işleme
5bded03f19

+ 2 - 2
Data/Raw/Engine/DataList.json

@@ -283,8 +283,8 @@
             "UUID": "17d573f8-1142-4257-9e32-90038d3786f3"
         },
         {
-            "Path": "DeferredPointLight.bslinc",
-            "UUID": "863e3d6c-7342-4715-900c-b38e03011798"
+            "Path": "DeferredPointLight.bsl",
+            "UUID": "428d9fde-9838-4367-9857-57bd80c8f599"
         }
     ],
     "Skin": [

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

@@ -38,7 +38,7 @@ Technique : inherits("DeferredLightCommon") =
 		
 		Fragment = 
 		{
-			float4 main(VStoFS input) : SV_Target0
+			float4 main(VStoFS input, uint sampleIdx : SV_SampleIndex) : SV_Target0
 			{
 				uint2 pixelPos = (uint2)(input.uv0 * (float2)gViewportRectangle.zw - ((float2)gViewportRectangle.xy + 0.5f));
 				

+ 0 - 0
Data/Raw/Engine/Shaders/DeferredPointLight.bslinc → Data/Raw/Engine/Shaders/DeferredPointLight.bsl


+ 72 - 5
Source/RenderBeast/Include/BsLightRendering.h

@@ -22,11 +22,23 @@ namespace bs { namespace ct
 		Vector3 spotAngles;
 		float attRadiusSqrdInv;
 		Vector3 color;
-        float srcRadius;
+		float srcRadius;
 		Vector3 shiftedLightPosition;
 		float padding;
 	};
 
+	BS_PARAM_BLOCK_BEGIN(PerLightParamDef)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gLightPositionAndSrcRadius)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gLightColorAndLuminance)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gLightSpotAnglesAndSqrdInvAttRadius)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gLightDirectionAndAttRadius)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gShiftedLightPositionAndType)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gLightGeometry)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatConeTransform)
+	BS_PARAM_BLOCK_END
+
+	extern PerLightParamDef gPerLightParamDef;
+
 	/**	Renderer information specific to a single light. */
 	class RendererLight
 	{
@@ -35,10 +47,68 @@ namespace bs { namespace ct
 
 		/** Populates the structure with light parameters. */
 		void getParameters(LightData& output) const;
+
+		/** 
+		 * Populates the provided parameter block buffer with information about the light. Provided buffer's structure
+		 * must match PerLightParamDef.
+		 */
+		void getParameters(SPtr<GpuParamBlockBuffer>& buffer) const;
 		
 		Light* internal;
 	};
 
+	/** Allows you to easily bind GBuffer textures to some material. */
+	class GBufferParams
+	{
+	public:
+		GBufferParams(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet);
+
+		/** Binds the GBuffer textures to the pipeline. */
+		void bind(const SPtr<RenderTargets>& renderTargets);
+
+	private:
+		GpuParamTexture mGBufferA;
+		GpuParamTexture mGBufferB;
+		GpuParamTexture mGBufferC;
+		GpuParamTexture mGBufferDepth;
+	};
+
+	/** Shader that renders directional light sources during deferred rendering light pass. */
+	template<bool MSAA>
+	class DirectionalLightMat : public RendererMaterial<DirectionalLightMat<MSAA>>
+	{
+		RMAT_DEF("DeferredDirectionalLight.bsl");
+
+	public:
+		DirectionalLightMat();
+
+		/** Binds the material for rendering and sets up any global parameters. */
+		void bind(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera);
+
+		/** Updates the per-light buffers used by the material. */
+		void setPerLightParams(const SPtr<GpuParamBlockBuffer>& perLight);
+	private:
+		GBufferParams mGBufferParams;
+	};
+
+	/** Shader that renders point (radial & spot) light sources during deferred rendering light pass. */
+	template<bool MSAA, bool InsideGeometry>
+	class PointLightMat : public RendererMaterial<PointLightMat<MSAA, InsideGeometry>>
+	{
+		RMAT_DEF("DeferredPointLight.bsl");
+
+	public:
+		PointLightMat();
+
+		/** Binds the material for rendering and sets up any global parameters. */
+		void bind(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera);
+
+		/** Updates the per-light buffers used by the material. */
+		void setPerLightParams(const SPtr<GpuParamBlockBuffer>& perLight);
+	private:
+		GBufferParams mGBufferParams;
+	};
+
 	/** Contains GPU buffers used by the renderer to manipulate lights. */
 	class GPULightData
 	{
@@ -92,10 +162,7 @@ namespace bs { namespace ct
 		SPtr<Material> mMaterial;
 		SPtr<GpuParamsSet> mParamsSet;
 
-		GpuParamTexture mGBufferA;
-		GpuParamTexture mGBufferB;
-		GpuParamTexture mGBufferC;
-		GpuParamTexture mGBufferDepth;
+		GBufferParams mGBufferParams;
 
 		Vector3I mLightOffsets;
 		GpuParamBuffer mLightBufferParam;

+ 142 - 19
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -16,6 +16,7 @@ namespace bs { namespace ct
 	static const UINT32 BUFFER_INCREMENT = 16 * sizeof(LightData);
 
 	TiledLightingParamDef gTiledLightingParamDef;
+	PerLightParamDef gPerLightParamDef;
 
 	RendererLight::RendererLight(Light* light)
 		:internal(light)
@@ -49,6 +50,144 @@ namespace bs { namespace ct
 			output.shiftedLightPosition = output.position;
 	}
 
+	void RendererLight::getParameters(SPtr<GpuParamBlockBuffer>& buffer) const
+	{
+		LightData lightData;
+		getParameters(lightData);
+
+		float type = 0.0f;
+		switch (internal->getType())
+		{
+		case LightType::Directional:
+			type = 0;
+			break;
+		case LightType::Radial:
+			type = 0.3f;
+			break;
+		case LightType::Spot:
+			type = 0.8f;
+			break;
+		}
+
+		gPerLightParamDef.gLightPositionAndSrcRadius.set(buffer, Vector4(lightData.position, lightData.srcRadius));
+		gPerLightParamDef.gLightColorAndLuminance.set(buffer, Vector4(lightData.color, lightData.luminance));
+		gPerLightParamDef.gLightSpotAnglesAndSqrdInvAttRadius.set(buffer, Vector4(lightData.spotAngles, lightData.attRadiusSqrdInv));
+		gPerLightParamDef.gLightDirectionAndAttRadius.set(buffer, Vector4(lightData.direction, lightData.attRadius));
+		gPerLightParamDef.gShiftedLightPositionAndType.set(buffer, Vector4(lightData.shiftedLightPosition, type));
+
+		Vector4 lightGeometry;
+		lightGeometry.x = internal->getType() == LightType::Spot ? (float)Light::LIGHT_CONE_NUM_SIDES : 0;
+		lightGeometry.y = (float)Light::LIGHT_CONE_NUM_SLICES;
+		lightGeometry.z = internal->getBounds().getRadius();
+
+		float coneRadius = Math::sin(lightData.spotAngles.x) * internal->getAttenuationRadius();
+		lightGeometry.w = coneRadius;
+
+		gPerLightParamDef.gLightGeometry.set(buffer, lightGeometry);
+
+		Matrix4 transform = Matrix4::TRS(internal->getPosition(), internal->getRotation(), Vector3::ONE);
+		gPerLightParamDef.gMatConeTransform.set(buffer, transform);
+	}
+
+	GBufferParams::GBufferParams(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet)
+	{
+		SPtr<GpuParams> params = paramsSet->getGpuParams();
+
+		auto& texParams = material->getShader()->getTextureParams();
+		for (auto& entry : texParams)
+		{
+			if (entry.second.rendererSemantic == RPS_GBufferA)
+				params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferA);
+			else if (entry.second.rendererSemantic == RPS_GBufferB)
+				params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferB);
+			else if (entry.second.rendererSemantic == RPS_GBufferC)
+				params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferC);
+			else if (entry.second.rendererSemantic == RPS_GBufferDepth)
+				params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferDepth);
+		}
+	}
+
+	void GBufferParams::bind(const SPtr<RenderTargets>& renderTargets)
+	{
+		mGBufferA.set(renderTargets->getGBufferA());
+		mGBufferB.set(renderTargets->getGBufferB());
+		mGBufferC.set(renderTargets->getGBufferC());
+		mGBufferDepth.set(renderTargets->getSceneDepth());
+	}
+
+	template<bool MSAA>
+	DirectionalLightMat<MSAA>::DirectionalLightMat()
+		:mGBufferParams(mMaterial, mParamsSet)
+	{
+
+	}
+
+	template<bool MSAA>
+	void DirectionalLightMat<MSAA>::_initDefines(ShaderDefines& defines)
+	{
+		if (MSAA)
+			defines.set("MSAA_COUNT", 2); // Actual count doesn't matter, as long as it's greater than one
+		else
+			defines.set("MSAA_COUNT", 1);
+	}
+
+	template<bool MSAA>
+	void DirectionalLightMat<MSAA>::bind(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera)
+	{
+		RendererUtility::instance().setPass(mMaterial, 0);
+
+		mGBufferParams.bind(gbuffer);
+		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
+	}
+
+	template<bool MSAA>
+	void DirectionalLightMat<MSAA>::setPerLightParams(const SPtr<GpuParamBlockBuffer>& perLight)
+	{
+		mParamsSet->setParamBlockBuffer("PerLight", perLight, true);
+	}
+
+	template class DirectionalLightMat<true>;
+	template class DirectionalLightMat<false>;
+
+	template<bool MSAA, bool InsideGeometry>
+	PointLightMat<MSAA, InsideGeometry>::PointLightMat()
+		:mGBufferParams(mMaterial, mParamsSet)
+	{
+	}
+
+	template<bool MSAA, bool InsideGeometry>
+	void PointLightMat<MSAA, InsideGeometry>::_initDefines(ShaderDefines& defines)
+	{
+		if (MSAA)
+			defines.set("MSAA_COUNT", 2); // Actual count doesn't matter, as long as it's greater than one
+		else
+			defines.set("MSAA_COUNT", 1);
+
+		if (InsideGeometry)
+			defines.set("INSIDE_GEOMETRY", 1);
+	}
+
+	template<bool MSAA, bool InsideGeometry>
+	void PointLightMat<MSAA, InsideGeometry>::bind(const SPtr<RenderTargets>& gbuffer, 
+		const SPtr<GpuParamBlockBuffer>& perCamera)
+	{
+		RendererUtility::instance().setPass(mMaterial, 0);
+
+		mGBufferParams.bind(gbuffer);
+		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
+	}
+
+	template<bool MSAA, bool InsideGeometry>
+	void PointLightMat<MSAA, InsideGeometry>::setPerLightParams(const SPtr<GpuParamBlockBuffer>& perLight)
+	{
+		mParamsSet->setParamBlockBuffer("PerLight", perLight, true);
+	}
+
+	template class PointLightMat<false, false>;
+	template class PointLightMat<false, true>;
+	template class PointLightMat<true, false>;
+	template class PointLightMat<true, true>;
+
 	GPULightData::GPULightData()
 		:mNumLights{}
 	{ }
@@ -97,23 +236,11 @@ namespace bs { namespace ct
 
 	TiledDeferredLighting::TiledDeferredLighting(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet,
 													UINT32 sampleCount)
-		:mSampleCount(sampleCount), mMaterial(material), mParamsSet(paramsSet), mLightOffsets()
+		: mSampleCount(sampleCount), mMaterial(material), mParamsSet(paramsSet), mGBufferParams(material, paramsSet)
+		, mLightOffsets()
 	{
 		SPtr<GpuParams> params = mParamsSet->getGpuParams();
 
-		auto& texParams = mMaterial->getShader()->getTextureParams();
-		for (auto& entry : texParams)
-		{
-			if (entry.second.rendererSemantic == RPS_GBufferA)
-				params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferA);
-			else if (entry.second.rendererSemantic == RPS_GBufferB)
-				params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferB);
-			else if (entry.second.rendererSemantic == RPS_GBufferC)
-				params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferC);
-			else if (entry.second.rendererSemantic == RPS_GBufferDepth)
-				params->getTextureParam(GPT_COMPUTE_PROGRAM, entry.second.name, mGBufferDepth);
-		}
-
 		params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLights", mLightBufferParam);
 
 		if (params->hasLoadStoreTexture(GPT_COMPUTE_PROGRAM, "gOutput"))
@@ -149,11 +276,7 @@ namespace bs { namespace ct
 		}
 		mParamBuffer->flushToGPU();
 
-		mGBufferA.set(renderTargets->getGBufferA());
-		mGBufferB.set(renderTargets->getGBufferB());
-		mGBufferC.set(renderTargets->getGBufferC());
-		mGBufferDepth.set(renderTargets->getSceneDepth());
-
+		mGBufferParams.bind(renderTargets);
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 
 		if (mSampleCount > 1)