Pārlūkot izejas kodu

Added SSAO bias to control false occlusion
Added SSAO settings

BearishSun 8 gadi atpakaļ
vecāks
revīzija
8a3241c722

+ 4 - 2
Data/Raw/Engine/Shaders/PPSSAO.bsl

@@ -16,6 +16,7 @@ technique PPSSAO
 			float2 gTanHalfFOV; // x - horz FOV, y - vert FOV
 			float2 gRandomTileScale;
 			float gCotHalfFOV;
+			float gBias;
 		}		
 
 		SamplerState gInputSamp;
@@ -72,14 +73,15 @@ technique PPSSAO
 			float3 viewNormal = normalize(mul((float3x3)gMatView, worldNormal));
 			float3 viewPos = getViewSpacePos(input.screenPos, sceneDepth);
 			
+			// Apply bias to avoid false occlusion due to depth quantization or other precision issues
+			viewPos += viewNormal * gBias * -sceneDepth;
+			
 			// Project sample radius to screen space (approximately), using the formula:
 			// screenRadius = worldRadius * 1/tan(fov/2) / z
 			// The formula approximates sphere projection and is more accurate the closer to the screen center
 			// the sphere origin is.
 			float sampleRadius = gSampleRadius * lerp(-sceneDepth, 1, gWorldSpaceRadiusMask) * gCotHalfFOV / -sceneDepth;
 			
-			// TODO - Apply bias to viewposition (and reconstruct screen pos from it)
-
 			// Get random rotation
 			float2 rotateDir = gRandomTex.Sample(gRandomSamp, input.uv0 * gRandomTileScale) * 2 - 1;
 			

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

@@ -232,6 +232,7 @@ namespace bs
 		TID_TonemappingSettings = 30017,
 		TID_WhiteBalanceSettings = 30018,
 		TID_ColorGradingSettings = 30019,
-		TID_DepthOfFieldSettings = 30020
+		TID_DepthOfFieldSettings = 30020,
+		TID_AmbientOcclusionSettings = 30021
 	};
 }

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

@@ -199,6 +199,38 @@ namespace bs
 		RTTITypeBase* getRTTI() const override;
 	};
 
+	/** Settings that control screen space ambient occlusion. */
+	struct BS_EXPORT AmbientOcclusionSettings : public IReflectable
+	{
+		AmbientOcclusionSettings();
+
+		/** Enables or disabled the screen space ambient occlusion effect. */
+		bool enabled;
+
+		/** 
+		 * Radius (in world space, in meters) over which occluders are searched for. Smaller radius ensures better sampling
+		 * precision but can miss occluders. Larger radius ensures far away occluders are considered but can yield lower
+		 * quality or noise because of low sampling precision. Usually best to keep at around a few centimeters, valid range
+		 * is roughly [0.005, 0.5].
+		 */
+		float radius;
+
+		/**
+		 * Bias used to reduce false occlusion artifacts. Higher values reduce the amount of artifacts but will cause
+		 * details to be lost in areas where occlusion isn't high. Value is in millimeters. Usually best to keep at a few
+		 * dozen millimeters, valid range is roughly [0, 200].
+		 */
+		float bias;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class AmbientOcclusionSettingsRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+	};
+
 	/** Settings that control the depth-of-field effect. */
 	struct BS_EXPORT DepthOfFieldSettings : public IReflectable
 	{
@@ -304,6 +336,9 @@ namespace bs
 		/** Parameters used for customizing the depth of field effect. */
 		DepthOfFieldSettings depthOfField;
 
+		/** Parameters used for customizing screen space ambient occlusion. */
+		AmbientOcclusionSettings ambientOcclusion;
+
 		/** Enables the fast approximate anti-aliasing effect. */
 		bool enableFXAA;
 

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

@@ -181,6 +181,37 @@ namespace bs
 		}
 	};
 
+	class BS_EXPORT AmbientOcclusionSettingsRTTI : public RTTIType <AmbientOcclusionSettings, IReflectable, AmbientOcclusionSettingsRTTI>
+	{
+	private:
+		BS_BEGIN_RTTI_MEMBERS
+			BS_RTTI_MEMBER_PLAIN(enabled, 0)
+			BS_RTTI_MEMBER_PLAIN(radius, 1)
+			BS_RTTI_MEMBER_PLAIN(bias, 2)
+		BS_END_RTTI_MEMBERS
+
+	public:
+		AmbientOcclusionSettingsRTTI()
+			:mInitMembers(this)
+		{ }
+
+		const String& getRTTIName() override
+		{
+			static String name = "AmbientOcclusionSettings";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_AmbientOcclusionSettings;
+		}
+
+		SPtr<IReflectable> newRTTIObject() override
+		{
+			return bs_shared_ptr_new<AmbientOcclusionSettings>();
+		}
+	};
+
 	class BS_EXPORT StandardPostProcessSettingsRTTI : public RTTIType <StandardPostProcessSettings, PostProcessSettings, StandardPostProcessSettingsRTTI>
 	{
 	private:
@@ -195,6 +226,7 @@ namespace bs
 			BS_RTTI_MEMBER_PLAIN(gamma, 7)
 			BS_RTTI_MEMBER_REFL(depthOfField, 8)
 			BS_RTTI_MEMBER_PLAIN(enableFXAA, 9)
+			BS_RTTI_MEMBER_REFL(ambientOcclusion, 10)
 		BS_END_RTTI_MEMBERS
 			
 	public:

+ 26 - 0
Source/BansheeEngine/Source/BsStandardPostProcessSettings.cpp

@@ -65,6 +65,20 @@ namespace bs
 		return ColorGradingSettings::getRTTIStatic();
 	}
 
+	AmbientOcclusionSettings::AmbientOcclusionSettings()
+		: enabled(true), radius(0.03f), bias(1.0f)
+	{ }
+
+	RTTITypeBase* AmbientOcclusionSettings::getRTTIStatic()
+	{
+		return AmbientOcclusionSettingsRTTI::instance();
+	}
+
+	RTTITypeBase* AmbientOcclusionSettings::getRTTI() const
+	{
+		return AmbientOcclusionSettings::getRTTIStatic();
+	}
+
 	DepthOfFieldSettings::DepthOfFieldSettings()
 		: enabled(false), focalDistance(0.75f), focalRange(0.75f), nearTransitionRange(0.25f), farTransitionRange(0.25f)
 		, nearBlurAmount(0.15f), farBlurAmount(0.15f)
@@ -136,6 +150,10 @@ namespace bs
 		bufferSize += rttiGetElemSize(depthOfField.nearBlurAmount);
 		bufferSize += rttiGetElemSize(depthOfField.farBlurAmount);
 
+		bufferSize += rttiGetElemSize(ambientOcclusion.enabled);
+		bufferSize += rttiGetElemSize(ambientOcclusion.radius);
+		bufferSize += rttiGetElemSize(ambientOcclusion.bias);
+
 		if (buffer == nullptr)
 		{
 			size = bufferSize;
@@ -187,6 +205,10 @@ namespace bs
 		writeDst = rttiWriteElem(depthOfField.farTransitionRange, writeDst);
 		writeDst = rttiWriteElem(depthOfField.nearBlurAmount, writeDst);
 		writeDst = rttiWriteElem(depthOfField.farBlurAmount, writeDst);
+
+		writeDst = rttiWriteElem(ambientOcclusion.enabled, writeDst);
+		writeDst = rttiWriteElem(ambientOcclusion.radius, writeDst);
+		writeDst = rttiWriteElem(ambientOcclusion.bias, writeDst);
 	}
 
 	void StandardPostProcessSettings::_setSyncData(UINT8* buffer, UINT32 size)
@@ -231,5 +253,9 @@ namespace bs
 		readSource = rttiReadElem(depthOfField.farTransitionRange, readSource);
 		readSource = rttiReadElem(depthOfField.nearBlurAmount, readSource);
 		readSource = rttiReadElem(depthOfField.farBlurAmount, readSource);
+
+		readSource = rttiReadElem(ambientOcclusion.enabled, readSource);
+		readSource = rttiReadElem(ambientOcclusion.radius, readSource);
+		readSource = rttiReadElem(ambientOcclusion.bias, readSource);
 	}
 }

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

@@ -589,6 +589,7 @@ namespace bs { namespace ct
 		BS_PARAM_BLOCK_ENTRY(Vector2, gTanHalfFOV)
 		BS_PARAM_BLOCK_ENTRY(Vector2, gRandomTileScale)
 		BS_PARAM_BLOCK_ENTRY(float, gCotHalfFOV)
+		BS_PARAM_BLOCK_ENTRY(float, gBias)
 	BS_PARAM_BLOCK_END
 
 	extern SSAOParamDef gSSAOParamDef;
@@ -609,9 +610,11 @@ namespace bs { namespace ct
 		 * @param[in]	sceneNormals	Input texture containing scene world space normals.
 		 * @param[in]	randomRotations	Tileable texture containing random rotations that will be applied to AO samples.
 		 * @param[in]	destination		Output texture to which to write the ambient occlusion data to.
+		 * @param[in]	settings		Settings used to control the ambient occlusion effect.
 		 */
 		void execute(const RendererView& view, const SPtr<Texture>& sceneDepth, const SPtr<Texture>& sceneNormals, 
-			const SPtr<Texture>& randomRotations, const SPtr<RenderTexture>& destination);
+			const SPtr<Texture>& randomRotations, const SPtr<RenderTexture>& destination, 
+			const AmbientOcclusionSettings& settings);
 
 		/**
 		 * Generates a texture that is used for randomizing sample locations during SSAO calculation. The texture contains

+ 5 - 5
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -1163,7 +1163,7 @@ namespace bs { namespace ct
 		randomSampDesc.addressMode.v = TAM_WRAP;
 		randomSampDesc.addressMode.w = TAM_WRAP;
 
-		SPtr<SamplerState> randomSampState = SamplerState::create(inputSampDesc);
+		SPtr<SamplerState> randomSampState = SamplerState::create(randomSampDesc);
 		gpuParams->setSamplerState(GPT_FRAGMENT_PROGRAM, "gRandomSamp", randomSampState);
 	}
 
@@ -1173,21 +1173,21 @@ namespace bs { namespace ct
 	}
 
 	void SSAOMat::execute(const RendererView& view, const SPtr<Texture>& depth, const SPtr<Texture>& normals, 
-		const SPtr<Texture>& random, const SPtr<RenderTexture>& destination)
+		const SPtr<Texture>& random, const SPtr<RenderTexture>& destination, const AmbientOcclusionSettings& settings)
 	{
 		const RendererViewProperties& viewProps = view.getProperties();
 
-		// TODO - Retrieve these from settings
 		Vector2 tanHalfFOV;
 		tanHalfFOV.x = 1.0f / viewProps.projTransform[0][0];
 		tanHalfFOV.y = 1.0f / viewProps.projTransform[1][1];
 
 		float cotHalfFOV = viewProps.projTransform[0][0];
 
-		gSSAOParamDef.gSampleRadius.set(mParamBuffer, 0.03f);
+		gSSAOParamDef.gSampleRadius.set(mParamBuffer, settings.radius);
 		gSSAOParamDef.gCotHalfFOV.set(mParamBuffer, cotHalfFOV);
 		gSSAOParamDef.gTanHalfFOV.set(mParamBuffer, tanHalfFOV);
 		gSSAOParamDef.gWorldSpaceRadiusMask.set(mParamBuffer, 1.0f);
+		gSSAOParamDef.gBias.set(mParamBuffer, settings.bias / 1000.0f);
 
 		// Generate a scale which we need to use in order to achieve tiling
 		const TextureProperties& rndProps = random->getProperties();
@@ -1267,7 +1267,7 @@ namespace bs { namespace ct
 		//	TU_RENDERTARGET));
 
 		//mSSAO.execute(*viewInfo, renderTargets->getSceneDepth(), renderTargets->getGBufferB(), mSSAORandomizationTex, 
-		//	temp->renderTexture);
+		//	temp->renderTexture, settings.ambientOcclusion);
 		// END DEBUG ONLY
 
 		if(hdr && settings.enableAutoExposure)