Kaynağa Gözat

More work on screen space reflections

BearishSun 8 yıl önce
ebeveyn
işleme
fb505fd6fd

+ 4 - 0
Data/Raw/Engine/DataList.json

@@ -325,6 +325,10 @@
         {
         {
             "Path": "PPSSRTrace.bsl",
             "Path": "PPSSRTrace.bsl",
             "UUID": "daadcf73-1ae5-4f8f-90e5-a6e538832304"
             "UUID": "daadcf73-1ae5-4f8f-90e5-a6e538832304"
+        },
+        {
+            "Path": "PPSSRStencil.bsl",
+            "UUID": "a9eb5ddf-1196-48d8-9403-a80a9595cde0"
         }
         }
     ],
     ],
     "Skin": [
     "Skin": [

+ 41 - 0
Data/Raw/Engine/Shaders/PPSSRStencil.bsl

@@ -0,0 +1,41 @@
+#include "$ENGINE$\PPBase.bslinc"
+#include "$ENGINE$\GBufferInput.bslinc"
+#include "$ENGINE$\PerCameraData.bslinc"
+
+technique PPSSRStencil
+{
+	mixin PPBase;
+	mixin PerCameraData;
+	mixin GBufferInput;
+
+	stencil
+	{
+		enabled = true;
+		reference = 1;
+		front = { replace, replace, replace, always };
+	};		
+	
+	code
+	{
+		[internal]
+		cbuffer Input
+		{
+			float2 gRoughnessScaleBias;
+		}
+		
+		float fsmain(VStoFS input) : SV_Target0
+		{
+			// TODO - Support MSAA?
+		
+			SurfaceData surfData = getGBufferData(input.uv0);
+			
+			// Surfaces that are too rough fall back to refl. probes
+			float fadeValue = 1.0f - saturate(surfData.roughness * gRoughnessScaleBias.x + gRoughnessScaleBias.y);
+			
+			if(fadeValue > 0.0f)
+				discard;
+			
+			return 0.0f;
+		}	
+	};
+};

+ 7 - 0
Data/Raw/Engine/Shaders/PPSSRTrace.bsl

@@ -10,6 +10,13 @@ technique PPSSRTrace
 	mixin GBufferInput;
 	mixin GBufferInput;
 	mixin RayMarch;
 	mixin RayMarch;
 
 
+	stencil
+	{
+		enabled = true;
+		reference = 0;
+		front = { keep, keep, keep, eq };
+	};	
+	
 	code
 	code
 	{
 	{
 		[internal]
 		[internal]

+ 2 - 1
Source/BansheeEngine/Include/BsPrerequisites.h

@@ -233,6 +233,7 @@ namespace bs
 		TID_WhiteBalanceSettings = 30018,
 		TID_WhiteBalanceSettings = 30018,
 		TID_ColorGradingSettings = 30019,
 		TID_ColorGradingSettings = 30019,
 		TID_DepthOfFieldSettings = 30020,
 		TID_DepthOfFieldSettings = 30020,
-		TID_AmbientOcclusionSettings = 30021
+		TID_AmbientOcclusionSettings = 30021,
+		TID_ScreenSpaceReflectionsSettings = 30022
 	};
 	};
 }
 }

+ 43 - 0
Source/BansheeEngine/Include/BsStandardPostProcessSettings.h

@@ -314,6 +314,46 @@ namespace bs
 		RTTITypeBase* getRTTI() const override;
 		RTTITypeBase* getRTTI() const override;
 	};
 	};
 
 
+	/** 
+	 * Settings that control the screen space reflections effect. Screen space reflections provide high quality mirror-like
+	 * reflections at low performance cost. They should be used together with reflection probes as the effects complement
+	 * each other. As the name implies, the reflections are only limited to geometry drawn on the screen and the system will
+	 * fall back to refl. probes when screen space data is unavailable. Similarly the system will fall back to refl. probes
+	 * for rougher (more glossy rather than mirror-like) surfaces. Those surfaces require a higher number of samples to
+	 * achieve the glossy look, so we instead fall back to refl. probes which are pre-filtered and can be quickly sampled.
+	 */
+	struct BS_EXPORT ScreenSpaceReflectionsSettings : public IReflectable
+	{
+		ScreenSpaceReflectionsSettings();
+
+		/** Enables or disables the SSR effect. */
+		bool enabled;
+
+		/** 
+		 * Quality of the SSR effect. Higher values cast more sample rays, and march those rays are lower increments for
+		 * better precision. This results in higher quality, as well as a higher performance requirement. Valid range is
+		 * [0, 4], default is 2.
+		 */
+		UINT32 quality;
+
+		/** Intensity of the screen space reflections. Valid range is [0, 1]. Default is 1 (100%). */
+		float intensity;
+
+		/** 
+		 * Roughness at which screen space reflections start fading out and become replaced with refl. probes. Valid range
+		 * is [0, 1]. Default is 0.8.
+		 */
+		float maxRoughness;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ScreenSpaceReflectionsRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+	};
+
 	/** Settings that control the post-process operations. */
 	/** Settings that control the post-process operations. */
 	struct BS_EXPORT StandardPostProcessSettings : public PostProcessSettings
 	struct BS_EXPORT StandardPostProcessSettings : public PostProcessSettings
 	{
 	{
@@ -370,6 +410,9 @@ namespace bs
 		/** Parameters used for customizing screen space ambient occlusion. */
 		/** Parameters used for customizing screen space ambient occlusion. */
 		AmbientOcclusionSettings ambientOcclusion;
 		AmbientOcclusionSettings ambientOcclusion;
 
 
+		/** Parameters used for customizing screen space reflections. */
+		ScreenSpaceReflectionsSettings screenSpaceReflections;
+
 		/** Enables the fast approximate anti-aliasing effect. */
 		/** Enables the fast approximate anti-aliasing effect. */
 		bool enableFXAA;
 		bool enableFXAA;
 
 

+ 33 - 0
Source/BansheeEngine/Include/BsStandardPostProcessSettingsRTTI.h

@@ -217,6 +217,38 @@ namespace bs
 		}
 		}
 	};
 	};
 
 
+	class BS_EXPORT ScreenSpaceReflectionsSettingsRTTI : public RTTIType <ScreenSpaceReflectionsSettings, IReflectable, ScreenSpaceReflectionsSettingsRTTI>
+	{
+	private:
+		BS_BEGIN_RTTI_MEMBERS
+			BS_RTTI_MEMBER_PLAIN(enabled, 0)
+			BS_RTTI_MEMBER_PLAIN(intensity, 1)
+			BS_RTTI_MEMBER_PLAIN(maxRoughness, 2)
+			BS_RTTI_MEMBER_PLAIN(quality, 3)
+		BS_END_RTTI_MEMBERS
+
+	public:
+		ScreenSpaceReflectionsSettingsRTTI()
+			:mInitMembers(this)
+		{ }
+
+		const String& getRTTIName() override
+		{
+			static String name = "ScreenSpaceReflectionsSettings";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_ScreenSpaceReflectionsSettings;
+		}
+
+		SPtr<IReflectable> newRTTIObject() override
+		{
+			return bs_shared_ptr_new<ScreenSpaceReflectionsSettings>();
+		}
+	};
+
 	class BS_EXPORT StandardPostProcessSettingsRTTI : public RTTIType <StandardPostProcessSettings, PostProcessSettings, StandardPostProcessSettingsRTTI>
 	class BS_EXPORT StandardPostProcessSettingsRTTI : public RTTIType <StandardPostProcessSettings, PostProcessSettings, StandardPostProcessSettingsRTTI>
 	{
 	{
 	private:
 	private:
@@ -232,6 +264,7 @@ namespace bs
 			BS_RTTI_MEMBER_REFL(depthOfField, 8)
 			BS_RTTI_MEMBER_REFL(depthOfField, 8)
 			BS_RTTI_MEMBER_PLAIN(enableFXAA, 9)
 			BS_RTTI_MEMBER_PLAIN(enableFXAA, 9)
 			BS_RTTI_MEMBER_REFL(ambientOcclusion, 10)
 			BS_RTTI_MEMBER_REFL(ambientOcclusion, 10)
+			BS_RTTI_MEMBER_REFL(screenSpaceReflections, 11)
 		BS_END_RTTI_MEMBERS
 		BS_END_RTTI_MEMBERS
 			
 			
 	public:
 	public:

+ 30 - 1
Source/BansheeEngine/Source/BsStandardPostProcessSettings.cpp

@@ -95,6 +95,20 @@ namespace bs
 		return DepthOfFieldSettings::getRTTIStatic();
 		return DepthOfFieldSettings::getRTTIStatic();
 	}
 	}
 
 
+	ScreenSpaceReflectionsSettings::ScreenSpaceReflectionsSettings()
+		: enabled(true), intensity(1.0f), maxRoughness(0.8f), quality(2)
+	{ }
+
+	RTTITypeBase* ScreenSpaceReflectionsSettings::getRTTIStatic()
+	{
+		return ScreenSpaceReflectionsSettingsRTTI::instance();
+	}
+
+	RTTITypeBase* ScreenSpaceReflectionsSettings::getRTTI() const
+	{
+		return ScreenSpaceReflectionsSettings::getRTTIStatic();
+	}
+
 	StandardPostProcessSettings::StandardPostProcessSettings()
 	StandardPostProcessSettings::StandardPostProcessSettings()
 		: enableAutoExposure(true), enableTonemapping(true), enableFXAA(false), exposureScale(0.0f), gamma(2.2f)
 		: enableAutoExposure(true), enableTonemapping(true), enableFXAA(false), exposureScale(0.0f), gamma(2.2f)
 	{ }
 	{ }
@@ -160,6 +174,11 @@ namespace bs
 		bufferSize += rttiGetElemSize(ambientOcclusion.power);
 		bufferSize += rttiGetElemSize(ambientOcclusion.power);
 		bufferSize += rttiGetElemSize(ambientOcclusion.quality);
 		bufferSize += rttiGetElemSize(ambientOcclusion.quality);
 
 
+		bufferSize += rttiGetElemSize(screenSpaceReflections.enabled);
+		bufferSize += rttiGetElemSize(screenSpaceReflections.intensity);
+		bufferSize += rttiGetElemSize(screenSpaceReflections.maxRoughness);
+		bufferSize += rttiGetElemSize(screenSpaceReflections.quality);
+
 		if (buffer == nullptr)
 		if (buffer == nullptr)
 		{
 		{
 			size = bufferSize;
 			size = bufferSize;
@@ -220,6 +239,11 @@ namespace bs
 		writeDst = rttiWriteElem(ambientOcclusion.intensity, writeDst);
 		writeDst = rttiWriteElem(ambientOcclusion.intensity, writeDst);
 		writeDst = rttiWriteElem(ambientOcclusion.power, writeDst);
 		writeDst = rttiWriteElem(ambientOcclusion.power, writeDst);
 		writeDst = rttiWriteElem(ambientOcclusion.quality, writeDst);
 		writeDst = rttiWriteElem(ambientOcclusion.quality, writeDst);
+
+		writeDst = rttiWriteElem(screenSpaceReflections.enabled, writeDst);
+		writeDst = rttiWriteElem(screenSpaceReflections.intensity, writeDst);
+		writeDst = rttiWriteElem(screenSpaceReflections.maxRoughness, writeDst);
+		writeDst = rttiWriteElem(screenSpaceReflections.quality, writeDst);
 	}
 	}
 
 
 	void StandardPostProcessSettings::_setSyncData(UINT8* buffer, UINT32 size)
 	void StandardPostProcessSettings::_setSyncData(UINT8* buffer, UINT32 size)
@@ -273,5 +297,10 @@ namespace bs
 		readSource = rttiReadElem(ambientOcclusion.intensity, readSource);
 		readSource = rttiReadElem(ambientOcclusion.intensity, readSource);
 		readSource = rttiReadElem(ambientOcclusion.power, readSource);
 		readSource = rttiReadElem(ambientOcclusion.power, readSource);
 		readSource = rttiReadElem(ambientOcclusion.quality, readSource);
 		readSource = rttiReadElem(ambientOcclusion.quality, readSource);
+
+		readSource = rttiReadElem(screenSpaceReflections.enabled, readSource);
+		readSource = rttiReadElem(screenSpaceReflections.intensity, readSource);
+		readSource = rttiReadElem(screenSpaceReflections.maxRoughness, readSource);
+		readSource = rttiReadElem(screenSpaceReflections.quality, readSource);
 	}
 	}
-}
+}

+ 35 - 1
Source/RenderBeast/Include/BsPostProcessing.h

@@ -776,6 +776,32 @@ namespace bs { namespace ct
 #undef DEFINE_MATERIAL
 #undef DEFINE_MATERIAL
 	};
 	};
 
 
+	BS_PARAM_BLOCK_BEGIN(SSRStencilParamDef)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gRoughnessScaleBias)
+	BS_PARAM_BLOCK_END
+
+	extern SSRStencilParamDef gSSRStencilParamDef;
+
+	/** Shader used for marking which parts of the screen require screen space reflections. */
+	class SSRStencilMat : public RendererMaterial<SSRStencilMat>
+	{
+		RMAT_DEF("PPSSRStencil.bsl");
+
+	public:
+		SSRStencilMat();
+
+		/** 
+		 * Renders the effect with the provided parameters, using the currently bound render target. 
+		 * 
+		 * @param[in]	view			Information about the view we're rendering from.
+		 * @param[in]	settings		Parameters used for controling the SSR effect.
+		 */
+		void execute(const RendererView& view, const ScreenSpaceReflectionsSettings& settings);
+	private:
+		SPtr<GpuParamBlockBuffer> mParamBuffer;
+		GBufferParams mGBufferParams;
+	};
+
 	BS_PARAM_BLOCK_BEGIN(SSRTraceParamDef)
 	BS_PARAM_BLOCK_BEGIN(SSRTraceParamDef)
 		BS_PARAM_BLOCK_ENTRY(Vector4, gHiZUVMapping)
 		BS_PARAM_BLOCK_ENTRY(Vector4, gHiZUVMapping)
 		BS_PARAM_BLOCK_ENTRY(Vector2I, gHiZSize)
 		BS_PARAM_BLOCK_ENTRY(Vector2I, gHiZSize)
@@ -796,10 +822,18 @@ namespace bs { namespace ct
 		 * Renders the effect with the provided parameters. 
 		 * Renders the effect with the provided parameters. 
 		 * 
 		 * 
 		 * @param[in]	view			Information about the view we're rendering from.
 		 * @param[in]	view			Information about the view we're rendering from.
+		 * @param[in]	settings		Parameters used for controling the SSR effect.
 		 * @param[in]	destination		Output texture to which to write the results to.
 		 * @param[in]	destination		Output texture to which to write the results to.
 		 */
 		 */
-		void execute(const RendererView& view, const SPtr<RenderTexture>& destination);
+		void execute(const RendererView& view, const ScreenSpaceReflectionsSettings& settings, 
+			const SPtr<RenderTexture>& destination);
 
 
+		/**
+		 * Calculates a scale & bias that is used for transforming roughness into a fade out value. Anything that is below
+		 * @p maxRoughness will have the fade value of 1. Values above @p maxRoughness is slowly fade out over a range that
+		 * is 1/2 the length of @p maxRoughness.
+		 */
+		static Vector2 calcRoughnessFadeScaleBias(float maxRoughness);
 	private:
 	private:
 		SPtr<GpuParamBlockBuffer> mParamBuffer;
 		SPtr<GpuParamBlockBuffer> mParamBuffer;
 		GBufferParams mGBufferParams;
 		GBufferParams mGBufferParams;

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

@@ -107,6 +107,14 @@ namespace bs { namespace ct
 		mGBufferB = material->getParamTexture("gGBufferBTex");
 		mGBufferB = material->getParamTexture("gGBufferBTex");
 		mGBufferC = material->getParamTexture("gGBufferCTex");
 		mGBufferC = material->getParamTexture("gGBufferCTex");
 		mGBufferDepth = material->getParamTexture("gDepthBufferTex");
 		mGBufferDepth = material->getParamTexture("gDepthBufferTex");
+
+		SAMPLER_STATE_DESC desc;
+		desc.minFilter = FO_POINT;
+		desc.magFilter = FO_POINT;
+		desc.mipFilter = FO_POINT;
+
+		SPtr<SamplerState> ss = SamplerState::create(desc);
+		material->setSamplerState("gDepthBufferSamp", ss);
 	}
 	}
 
 
 	void GBufferParams::bind(const RenderTargets& renderTargets)
 	void GBufferParams::bind(const RenderTargets& renderTargets)

+ 46 - 2
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -1058,7 +1058,7 @@ namespace bs { namespace ct
 	POOLED_RENDER_TEXTURE_DESC BuildHiZ::getHiZTextureDesc(UINT32 viewWidth, UINT32 viewHeight)
 	POOLED_RENDER_TEXTURE_DESC BuildHiZ::getHiZTextureDesc(UINT32 viewWidth, UINT32 viewHeight)
 	{
 	{
 		UINT32 size = Bitwise::nextPow2(std::max(viewWidth, viewHeight));
 		UINT32 size = Bitwise::nextPow2(std::max(viewWidth, viewHeight));
-		UINT32 numMips = std::max(1U, PixelUtil::getMaxMipmaps(size, size, 1, PF_FLOAT32_R) - 1);
+		UINT32 numMips = PixelUtil::getMaxMipmaps(size, size, 1, PF_FLOAT32_R);
 		size = 1 << numMips;
 		size = 1 << numMips;
 
 
 		// Note: Use the 32-bit buffer here as 16-bit causes too much banding (most of the scene gets assigned 4-5 different
 		// Note: Use the 32-bit buffer here as 16-bit causes too much banding (most of the scene gets assigned 4-5 different
@@ -1593,6 +1593,38 @@ namespace bs { namespace ct
 		return Texture::create(pixelData);
 		return Texture::create(pixelData);
 	}
 	}
 
 
+	SSRStencilParamDef gSSRStencilParamDef;
+
+	SSRStencilMat::SSRStencilMat()
+		:mGBufferParams(mMaterial, mParamsSet)
+	{
+		mParamBuffer = gSSRStencilParamDef.createBuffer();
+		mParamsSet->setParamBlockBuffer("Input", mParamBuffer);
+	}
+
+	void SSRStencilMat::_initDefines(ShaderDefines& defines)
+	{
+		// Do nothing
+	}
+
+	void SSRStencilMat::execute(const RendererView& view, const ScreenSpaceReflectionsSettings& settings)
+	{
+		const RendererViewProperties& viewProps = view.getProperties();
+		RenderTargets& renderTargets = *view.getRenderTargets();
+
+		mGBufferParams.bind(renderTargets);
+
+		Vector2 roughnessScaleBias = SSRTraceMat::calcRoughnessFadeScaleBias(settings.maxRoughness);
+		gSSRStencilParamDef.gRoughnessScaleBias.set(mParamBuffer, roughnessScaleBias);
+
+		SPtr<GpuParamBlockBuffer> perView = view.getPerViewBuffer();
+		mParamsSet->setParamBlockBuffer("PerCamera", perView);
+
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
+		gRendererUtility().drawScreenQuad();
+	}
+
 	SSRTraceParamDef gSSRTraceParamDef;
 	SSRTraceParamDef gSSRTraceParamDef;
 
 
 	SSRTraceMat::SSRTraceMat()
 	SSRTraceMat::SSRTraceMat()
@@ -1610,7 +1642,8 @@ namespace bs { namespace ct
 		// Do nothing
 		// Do nothing
 	}
 	}
 
 
-	void SSRTraceMat::execute(const RendererView& view, const SPtr<RenderTexture>& destination)
+	void SSRTraceMat::execute(const RendererView& view, const ScreenSpaceReflectionsSettings& settings, 
+		const SPtr<RenderTexture>& destination)
 	{
 	{
 		const RendererViewProperties& viewProps = view.getProperties();
 		const RendererViewProperties& viewProps = view.getProperties();
 		RenderTargets& renderTargets = *view.getRenderTargets();
 		RenderTargets& renderTargets = *view.getRenderTargets();
@@ -1655,6 +1688,17 @@ namespace bs { namespace ct
 		gRendererUtility().drawScreenQuad();
 		gRendererUtility().drawScreenQuad();
 	}
 	}
 
 
+	Vector2 SSRTraceMat::calcRoughnessFadeScaleBias(float maxRoughness)
+	{
+		const static float RANGE_SCALE = 2.0f;
+
+		Vector2 scaleBias;
+		scaleBias.x = -RANGE_SCALE / (-1.0f + maxRoughness);
+		scaleBias.y = (RANGE_SCALE * maxRoughness) / (-1.0f + maxRoughness);
+
+		return scaleBias;
+	}
+
 	void PostProcessing::postProcess(RendererView* viewInfo, const SPtr<RenderTargets>& renderTargets, float frameDelta)
 	void PostProcessing::postProcess(RendererView* viewInfo, const SPtr<RenderTargets>& renderTargets, float frameDelta)
 	{
 	{
 		auto& viewProps = viewInfo->getProperties();
 		auto& viewProps = viewInfo->getProperties();