Explorar el Código

Added upsampling to SSAO (untested)
Streamlined RenderTargets interface

BearishSun hace 8 años
padre
commit
824849ff57

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

@@ -309,6 +309,10 @@
         {
         {
             "Path": "PPSSAO.bsl",
             "Path": "PPSSAO.bsl",
             "UUID": "7a65b0f1-9a37-452e-ba3f-2a1fb58362cb"
             "UUID": "7a65b0f1-9a37-452e-ba3f-2a1fb58362cb"
+        },
+        {
+            "Path": "PPSSAODownsample.bsl",
+            "UUID": "c06a649a-646e-48cf-89fc-f97e46f75264"
         }
         }
     ],
     ],
     "Skin": [
     "Skin": [

+ 61 - 3
Data/Raw/Engine/Shaders/PPSSAO.bsl

@@ -17,11 +17,14 @@ technique PPSSAO
 			float2 gRandomTileScale;
 			float2 gRandomTileScale;
 			float gCotHalfFOV;
 			float gCotHalfFOV;
 			float gBias;
 			float gBias;
+			float2 gDownsampledPixelSize;
 		}		
 		}		
 
 
 		SamplerState gInputSamp;
 		SamplerState gInputSamp;
 		Texture2D gDepthTex;
 		Texture2D gDepthTex;
 		Texture2D gNormalsTex;
 		Texture2D gNormalsTex;
+		Texture2D gDownsampledAO;
+		Texture2D gSetupAO;
 		
 		
 		SamplerState gRandomSamp;
 		SamplerState gRandomSamp;
 		Texture2D gRandomTex;
 		Texture2D gRandomTex;
@@ -63,18 +66,64 @@ technique PPSSAO
 			return float3(clipSpace * gTanHalfFOV, depth);
 			return float3(clipSpace * gTanHalfFOV, depth);
 		}
 		}
 		
 		
+		float getUpsampledAO(float2 uv, float depth, float3 normal)
+		{
+			float2 uvs[9];
+			uvs[0] = uv + float2(-1, -1) * gDownsampledPixelSize;
+			uvs[1] = uv + float2( 0, -1) * gDownsampledPixelSize;
+			uvs[2] = uv + float2( 1, -1) * gDownsampledPixelSize;
+			uvs[3] = uv + float2(-1,  0) * gDownsampledPixelSize;
+			uvs[4] = uv + float2( 0,  0) * gDownsampledPixelSize;
+			uvs[5] = uv + float2( 1,  0) * gDownsampledPixelSize;
+			uvs[6] = uv + float2(-1,  1) * gDownsampledPixelSize;
+			uvs[7] = uv + float2( 0,  1) * gDownsampledPixelSize;
+			uvs[8] = uv + float2( 1,  1) * gDownsampledPixelSize;
+			
+			float weightedSum = 0.0f;
+			float weightSum = 0.00001f;
+			
+			[unroll]
+			for(int i = 0; i < 9; ++i)
+			{
+				// Get AO from previous step (half-resolution buffer)
+				float sampleAO = gDownsampledAO.Sample(gInputSamp, uvs[i]).r;
+				
+				// Get filtered normal/depth
+				float4 sampleNormalAndDepth = gSetupAO.Sample(gInputSamp, uvs[i]);
+				float3 sampleNormal = sampleNormalAndDepth.xyz * 2.0f - 1.0f;
+				float sampleDepth = sampleNormalAndDepth.w;
+				
+				// Compute sample contribution depending on how close it is to current
+				// depth and normal
+				float weight = saturate(1.0f - abs(sampleDepth - depth) * 0.3f);
+				weight *= saturate(dot(sampleNormal, normal));
+				
+				weightedSum += sampleAO * weight;
+				weightSum += weight;
+			}
+			
+			return weightedSum / weightSum;
+		}
+		
 		float4 fsmain(VStoFS input) : SV_Target0
 		float4 fsmain(VStoFS input) : SV_Target0
 		{
 		{
 			// TODO - Support MSAA (most likely don't require all samples)
 			// TODO - Support MSAA (most likely don't require all samples)
 		
 		
-			// TODO - Read depth and normal from intermediates if they are available
+			#if FINAL_AO // Final uses gbuffer input
 			float sceneDepth = convertFromDeviceZ(gDepthTex.Sample(gInputSamp, input.uv0).r);
 			float sceneDepth = convertFromDeviceZ(gDepthTex.Sample(gInputSamp, input.uv0).r);
 			float3 worldNormal = gNormalsTex.Sample(gInputSamp, input.uv0).xyz * 2.0f - 1.0f;
 			float3 worldNormal = gNormalsTex.Sample(gInputSamp, input.uv0).xyz * 2.0f - 1.0f;
+			#else // Input from AO setup pass
+			float4 aoSetup = gSetupAO.Sample(gInputSamp, input.uv0);
+			float sceneDepth = aoSetup.w;
+			float3 worldNormal = aoSetup.xyz * 2.0f - 1.0f;
+			#endif
+			
 			float3 viewNormal = normalize(mul((float3x3)gMatView, worldNormal));
 			float3 viewNormal = normalize(mul((float3x3)gMatView, worldNormal));
 			float3 viewPos = getViewSpacePos(input.screenPos, sceneDepth);
 			float3 viewPos = getViewSpacePos(input.screenPos, sceneDepth);
 			
 			
 			// Apply bias to avoid false occlusion due to depth quantization or other precision issues
 			// Apply bias to avoid false occlusion due to depth quantization or other precision issues
 			viewPos += viewNormal * gBias * -sceneDepth;
 			viewPos += viewNormal * gBias * -sceneDepth;
+			// Note: Do I want to recalculate screen position from this new view position?
 			
 			
 			// Project sample radius to screen space (approximately), using the formula:
 			// Project sample radius to screen space (approximately), using the formula:
 			// screenRadius = worldRadius * 1/tan(fov/2) / z
 			// screenRadius = worldRadius * 1/tan(fov/2) / z
@@ -158,10 +207,19 @@ technique PPSSAO
 			// Divide by total weight to get the weighted average
 			// Divide by total weight to get the weighted average
 			output.r = accumulator.x / accumulator.y;
 			output.r = accumulator.x / accumulator.y;
 			
 			
-			// TODO - Mix with upsampled AO data
+			#if MIX_WITH_UPSAMPLED
+			float upsampledAO = getUpsampledAO(input.uv0, sceneDepth, worldNormal);
+			
+			// Note: 0.6f just an arbitrary constant that looks good. Make this adjustable externally?
+			output.r = lerp(output.r, upsampledAO, 0.6f);
+			#endif
+			
+			#if FINAL_AO
 			// TODO - Fade out far away AO
 			// TODO - Fade out far away AO
 			// TODO - Adjust power/intensity
 			// TODO - Adjust power/intensity
-			// TODO - Perform filtering over 2x2 pixels using derivatives
+			#endif
+			
+			// TODO - Perform filtering over 2x2 pixels using derivatives (on quality levels with no upsampling)
 			return output;
 			return output;
 		}	
 		}	
 	};
 	};

+ 54 - 0
Data/Raw/Engine/Shaders/PPSSAODownsample.bsl

@@ -0,0 +1,54 @@
+#include "$ENGINE$\PPBase.bslinc"
+#include "$ENGINE$\PerCameraData.bslinc"
+
+technique PPSSAODownsample
+{
+	mixin PPBase;
+	mixin PerCameraData;
+
+	code
+	{
+		[internal]
+		cbuffer Input
+		{
+			float2 gPixelSize;
+			float gInvDepthThreshold;
+		}		
+
+		SamplerState gInputSamp;
+		Texture2D gDepthTex;
+		Texture2D gNormalsTex;
+		
+		float4 fsmain(VStoFS input) : SV_Target0
+		{
+			float2 uvs[4];
+			uvs[0] = input.uv0 + float2(-0.5f, -0.5f) * gPixelSize;
+			uvs[1] = input.uv0 + float2(-0.5f,  0.5f) * gPixelSize;
+			uvs[2] = input.uv0 + float2( 0.5f, -0.5f) * gPixelSize;
+			uvs[3] = input.uv0 + float2( 0.5f,  0.5f) * gPixelSize;
+			
+			float4 samples[4];
+			[unroll]
+			for(int i = 0; i < 4; i++)
+			{
+				samples[i].xyz = gNormalsTex.Sample(gInputSamp, uvs[i]).xyz;
+				samples[i].w = convertFromDeviceZ(gDepthTex.Sample(gInputSamp, uvs[i]).r);
+			}
+		
+			float maxZ = max(max(samples[0].w, samples[1].w), max(samples[2].w, samples[3].w));
+			
+			float3 weightedSum = 0.0f;
+			float weightSum = 0.00001f; // Avoid division by 0
+			[unroll]
+			for(int i = 0; i < 4; i++)
+			{
+				float weight = saturate(1.0f - abs(samples[i].w - maxZ) * gInvDepthThreshold);
+			
+				weightedSum += samples[i].xyz * weight;
+				weightSum += weight;
+			}
+			
+			return float4(weightedSum / weightSum, maxZ);
+		}	
+	};
+};

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

@@ -66,7 +66,7 @@ namespace bs
 	}
 	}
 
 
 	AmbientOcclusionSettings::AmbientOcclusionSettings()
 	AmbientOcclusionSettings::AmbientOcclusionSettings()
-		: enabled(true), radius(0.03f), bias(1.0f)
+		: enabled(false), radius(0.03f), bias(1.0f)
 	{ }
 	{ }
 
 
 	RTTITypeBase* AmbientOcclusionSettings::getRTTIStatic()
 	RTTITypeBase* AmbientOcclusionSettings::getRTTIStatic()

+ 123 - 16
Source/RenderBeast/Include/BsPostProcessing.h

@@ -588,12 +588,42 @@ namespace bs { namespace ct
 		BS_PARAM_BLOCK_ENTRY(Vector2, gRandomTileScale)
 		BS_PARAM_BLOCK_ENTRY(Vector2, gRandomTileScale)
 		BS_PARAM_BLOCK_ENTRY(float, gCotHalfFOV)
 		BS_PARAM_BLOCK_ENTRY(float, gCotHalfFOV)
 		BS_PARAM_BLOCK_ENTRY(float, gBias)
 		BS_PARAM_BLOCK_ENTRY(float, gBias)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gDownsampledPixelSize)
 	BS_PARAM_BLOCK_END
 	BS_PARAM_BLOCK_END
 
 
 	extern SSAOParamDef gSSAOParamDef;
 	extern SSAOParamDef gSSAOParamDef;
 
 
-	/** Shader that computes ambient occlusion using screen based methods. */
-	class SSAOMat : public RendererMaterial<SSAOMat>
+	/** Textures used as input when calculating SSAO. */
+	struct SSAOTextureInputs
+	{
+		/** Full resolution scene depth. Only used by final SSAO pass. */
+		SPtr<Texture> sceneDepth;
+
+		/** Full resolution buffer containing scene normals. Only used by final SSAO pass. */
+		SPtr<Texture> sceneNormals;
+
+		/** Precalculated texture containing downsampled normals/depth, to be used for AO input. */
+		SPtr<Texture> aoSetup;
+
+		/** Texture containing AO from the previous pass. Only used if upsampling is enabled. */
+		SPtr<Texture> aoDownsampled;
+
+		/** Tileable texture containing random rotations that will be applied to AO samples. */
+		SPtr<Texture> randomRotations;
+	};
+
+	/** 
+	 * Shader that computes ambient occlusion using screen based methods.
+	 *
+	 * @tparam	UPSAMPLE	If true the shader will blend the calculated AO with AO data from the previous pass.
+	 * @tparam	FINAL_PASS	If true the shader will use the full screen normal/depth information and perform
+	 *						intensity scaling, as well as distance fade. Otherwise the shader will use the
+	 *						downsampled AO setup information, with no scaling/fade.
+	 * @tparam	QUALITY		Integer in range [0, 4] that controls the quality of SSAO sampling. Higher numbers yield
+	 *						better quality at the cost of performance. 
+	 */
+	template<bool UPSAMPLE, bool FINAL_PASS, int QUALITY>
+	class SSAOMat : public RendererMaterial<SSAOMat<UPSAMPLE, FINAL_PASS, QUALITY>>
 	{
 	{
 		RMAT_DEF("PPSSAO.bsl");
 		RMAT_DEF("PPSSAO.bsl");
 
 
@@ -604,14 +634,73 @@ namespace bs { namespace ct
 		 * Renders the post-process effect with the provided parameters. 
 		 * Renders the post-process 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]	sceneDepth		Input texture containing scene depth.
-		 * @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]	textures		Set of textures to be used as input. Which textures are used depends on the
+		 *								template parameters of this class.
 		 * @param[in]	destination		Output texture to which to write the ambient occlusion data to.
 		 * @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.
 		 * @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, 
+		void execute(const RendererView& view, const SSAOTextureInputs& textures, const SPtr<RenderTexture>& destination, 
+			const AmbientOcclusionSettings& settings);
+
+	private:
+		SPtr<GpuParamBlockBuffer> mParamBuffer;
+		GpuParamTexture mDepthTexture;
+		GpuParamTexture mNormalsTexture;
+		GpuParamTexture mDownsampledAOTexture;
+		GpuParamTexture mSetupAOTexture;
+		GpuParamTexture mRandomTexture;
+	};
+
+	BS_PARAM_BLOCK_BEGIN(SSAODownsampleParamDef)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gPixelSize)
+		BS_PARAM_BLOCK_ENTRY(float, gInvDepthThreshold)
+	BS_PARAM_BLOCK_END
+
+	extern SSAOParamDef gSSAOParamDef;
+
+	/** 
+	 * Shader that downsamples the depth & normal buffer and stores their results in a common texture, to be consumed
+	 * by SSAOMat. 
+	 */
+	class SSAODownsampleMat : public RendererMaterial<SSAODownsampleMat>
+	{
+		RMAT_DEF("PPSSAODownsample.bsl");
+
+	public:
+		SSAODownsampleMat();
+
+		/** 
+		 * Renders the post-process effect with the provided parameters. 
+		 * 
+		 * @param[in]	view			Information about the view we're rendering from.
+		 * @param[in]	sceneDepth		Input texture containing scene depth.
+		 * @param[in]	sceneNormals	Input texture containing scene world space normals.
+		 * @param[in]	destination		Output texture to which to write the downsampled data to.
+		 * @param[in]	depthRange		Valid depth range (in view space) within which nearby samples will be averaged.
+		 */
+		void execute(const RendererView& view, const SPtr<Texture>& sceneDepth, const SPtr<Texture>& sceneNormals,
+			const SPtr<RenderTexture>& destination, float depthRange);
+
+	private:
+		SPtr<GpuParamBlockBuffer> mParamBuffer;
+		GpuParamTexture mDepthTexture;
+		GpuParamTexture mNormalsTexture;
+	};
+
+	/** Helper class that is used for calculating the SSAO information. */
+	class SSAO
+	{
+	public:
+		SSAO();
+
+		/** 
+		 * Calculates SSAO for the specified view. 
+		 * 
+		 * @param[in]	view			Information about the view we're rendering from.
+		 * @param[in]	destination		Output texture to which to write the SSAO data to.
+		 * @param[in]	settings		Settings that control how is SSAO calculated.
+		 */
+		void execute(const RendererView& view, const SPtr<RenderTexture>& destination, 
 			const AmbientOcclusionSettings& settings);
 			const AmbientOcclusionSettings& settings);
 
 
 		/**
 		/**
@@ -621,10 +710,27 @@ namespace bs { namespace ct
 		SPtr<Texture> generate4x4RandomizationTexture() const;
 		SPtr<Texture> generate4x4RandomizationTexture() const;
 
 
 	private:
 	private:
-		SPtr<GpuParamBlockBuffer> mParamBuffer;
-		GpuParamTexture mDepthTexture;
-		GpuParamTexture mNormalsTexture;
-		GpuParamTexture mRandomTexture;
+		/** @copydoc SSAOMat::execute() */
+		void executeSSAOMat(bool upsample, bool final, int quality, const RendererView& view, 
+			const SSAOTextureInputs& textures, const SPtr<RenderTexture>& destination, 
+			const AmbientOcclusionSettings& settings);
+
+		SSAODownsampleMat mDownsample;
+		SPtr<Texture> mSSAORandomizationTex;
+
+#define DEFINE_MATERIAL(QUALITY)							\
+		SSAOMat<false, false, QUALITY> mSSAO_FF_##QUALITY;	\
+		SSAOMat<true, false, QUALITY> mSSAO_TF_##QUALITY;	\
+		SSAOMat<false, true, QUALITY> mSSAO_FT_##QUALITY;	\
+		SSAOMat<true, true, QUALITY> mSSAO_TT_##QUALITY;	\
+
+		DEFINE_MATERIAL(0)
+		DEFINE_MATERIAL(1)
+		DEFINE_MATERIAL(2)
+		DEFINE_MATERIAL(3)
+		DEFINE_MATERIAL(4)
+
+#undef DEFINE_MATERIAL
 	};
 	};
 
 
 	/**
 	/**
@@ -635,8 +741,6 @@ namespace bs { namespace ct
 	class PostProcessing : public Module<PostProcessing>
 	class PostProcessing : public Module<PostProcessing>
 	{
 	{
 	public:
 	public:
-		PostProcessing();
-
 		/** 
 		/** 
 		 * Renders post-processing effects for the provided render target. Resolves provided scene color texture into the
 		 * Renders post-processing effects for the provided render target. Resolves provided scene color texture into the
 		 * view's final output render target. Once the method exits, final render target is guaranteed to be currently
 		 * view's final output render target. Once the method exits, final render target is guaranteed to be currently
@@ -644,6 +748,11 @@ namespace bs { namespace ct
 		 */
 		 */
 		void postProcess(RendererView* viewInfo, const SPtr<RenderTargets>& renderTargets, float frameDelta);
 		void postProcess(RendererView* viewInfo, const SPtr<RenderTargets>& renderTargets, float frameDelta);
 		
 		
+		/**
+		 * Populates the ambient occlusion texture of the specified view with screen-space ambient occlusion information.
+		 * Ambient occlusion texture must be allocated on the view's render targets before calling this method.
+		 */
+		void buildSSAO(const RendererView& view);
 	private:
 	private:
 		DownsampleMaterials mDownsample;
 		DownsampleMaterials mDownsample;
 		EyeAdaptHistogramMat mEyeAdaptHistogram;
 		EyeAdaptHistogramMat mEyeAdaptHistogram;
@@ -654,9 +763,7 @@ namespace bs { namespace ct
 		TonemappingMaterials mTonemapping;
 		TonemappingMaterials mTonemapping;
 		GaussianDOF mGaussianDOF;
 		GaussianDOF mGaussianDOF;
 		FXAAMat mFXAA;
 		FXAAMat mFXAA;
-		SSAOMat mSSAO;
-
-		SPtr<Texture> mSSAORandomizationTex;
+		SSAO mSSAO;
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 21 - 70
Source/RenderBeast/Include/BsRenderTargets.h

@@ -37,7 +37,7 @@ namespace bs { namespace ct
 		 */
 		 */
 		RTT_ResolvedSceneColorSecondary,
 		RTT_ResolvedSceneColorSecondary,
 		/**
 		/**
-		 * Buffer containing a hierarchical Z buffer. If passed to RenderTargets::generate() it will allocate and build
+		 * Buffer containing a hierarchical Z buffer. If passed to RenderTargets::generate() it will build
 		 * the hierarchical Z buffer from the current contents of the scene depth buffer. Generated buffer can be
 		 * the hierarchical Z buffer from the current contents of the scene depth buffer. Generated buffer can be
 		 * accessed from getHiZ(). If using MSAA render targets, make sure to first generate the RTT_ResolvedDepth
 		 * accessed from getHiZ(). If using MSAA render targets, make sure to first generate the RTT_ResolvedDepth
 		 * target as HiZ can't be built from multisampled depth buffer.
 		 * target as HiZ can't be built from multisampled depth buffer.
@@ -45,11 +45,13 @@ namespace bs { namespace ct
 		RTT_HiZ,
 		RTT_HiZ,
 		/**
 		/**
 		 * Buffer containing the resolved (non-multisampled) depth buffer. If multisampling isn't used then this will be
 		 * Buffer containing the resolved (non-multisampled) depth buffer. If multisampling isn't used then this will be
-		 * the same buffer as the scene depth buffer. If passed to RenderTargets::generate() it will allocate and resolve
+		 * the same buffer as the scene depth buffer. If passed to RenderTargets::generate() it will resolve
 		 * the scene depth buffer into the newly allocated buffer. Scene depth must be previously allocated and populated
 		 * the scene depth buffer into the newly allocated buffer. Scene depth must be previously allocated and populated
 		 * with scene data.
 		 * with scene data.
 		 */
 		 */
-		RTT_ResolvedDepth
+		RTT_ResolvedDepth,
+		/** Buffer containing ambient occlusion. */
+		RTT_AmbientOcclusion
 	};
 	};
 
 
 	/**
 	/**
@@ -88,6 +90,11 @@ namespace bs { namespace ct
 		 */
 		 */
 		void release(RenderTargetType type);
 		void release(RenderTargetType type);
 
 
+		/**
+		 * Binds the specified render target for rendering, and performs any clear operations as necessary.
+		 */
+		void bind(RenderTargetType type, bool readOnlyDepthStencil = false);
+
 		/**
 		/**
 		 * Generates contents for the specified render target type. Target must first be allocated by calling allocate().
 		 * Generates contents for the specified render target type. Target must first be allocated by calling allocate().
 		 * Note that not all target types can have their contents automatically generated, most are meant to be populated
 		 * Note that not all target types can have their contents automatically generated, most are meant to be populated
@@ -96,81 +103,21 @@ namespace bs { namespace ct
 		 */
 		 */
 		void generate(RenderTargetType type);
 		void generate(RenderTargetType type);
 
 
-		/**	Binds the GBuffer render target for rendering. */
-		void bindGBuffer();
-
-		/**	
-		 * Binds the scene color render target for rendering. If using MSAA this texture will be allocated as a texture 
-		 * with multiple samples.
-		 */
-		void bindSceneColor(bool readOnlyDepthStencil);
-
-		/** Binds the light accumulation render target for rendering. */
-		void bindLightAccumulation();
-
-		/** 
-		 * Binds the light occlusion render target for rendering. Light occlusion texture and GBuffer must be allocated,
-		 * and depth must have been previously rendered to the depth buffer. Target is cleared before the method returns.
-		 */
-		void bindLightOcclusion();
-
-		/**	Returns the first color texture of the gbuffer as a bindable texture. */
-		SPtr<Texture> getGBufferA() const;
-
-		/**	Returns the second color texture of the gbuffer as a bindable texture. */
-		SPtr<Texture> getGBufferB() const;
-
-		/**	Returns the third color texture of the gbuffer as a bindable texture. */
-		SPtr<Texture> getGBufferC() const;
-
-		/**	Returns the depth buffer as a bindable texture. */
-		SPtr<Texture> getSceneDepth() const;
-
-		/** Returns the hierarchical Z buffer texture generated by calling generateHiZ(). */
-		SPtr<Texture> getHiZ() const;
+		/** Returns a bindable texture for a render target previously allocated using allocate().*/
+		SPtr<Texture> get(RenderTargetType type, RenderSurfaceMaskBits surface = RT_COLOR0) const;
 
 
-		/** Returns the texture containing (potentially multisampled) scene color. */
-		SPtr<Texture> getSceneColor() const;
+		/** Returns a render target previously allocated using allocate(). */
+		SPtr<RenderTexture> getRT(RenderTargetType type) const;
 
 
 		/** 
 		/** 
-		 * Flattened, buffer version of the texture returned by getSceneColor(). Only available when MSAA is used, since
+		 * Flattened, buffer version of the texture returned by get(RTT_SceneColor). Only available when MSAA is used, since
 		 * random writes to multisampled textures aren't supported on all render backends.
 		 * random writes to multisampled textures aren't supported on all render backends.
 		 */
 		 */
 		SPtr<GpuBuffer> getSceneColorBuffer() const;
 		SPtr<GpuBuffer> getSceneColorBuffer() const;
 
 
 		/**
 		/**
-		 * Returns a non-MSAA version of the scene color texture. If MSAA is not used this is equivalent to calling
-		 * getSceneColor() (as long as @p secondary is set to false).
-		 * 
-		 * @param[in]	secondary	If true, a seconday scene color texture will be returned. This texture can be used
-		 *							for ping-pong operations between it and the primary scene color.
-		 */
-		SPtr<Texture> getResolvedSceneColor(bool secondary = false) const;
-
-		/**
-		 * Returns a non-MSAA version of the scene color render target. If MSAA is not used this will return the default
-		 * scene color render target (as long as @p secondary is set to false).
-		 * 
-		 * @param[in]	secondary	If true, a seconday scene color target will be returned. This target can be used
-		 *							for ping-pong operations between it and the primary scene color.
-		 */
-		SPtr<RenderTarget> getResolvedSceneColorRT(bool secondary = false) const;
-
-		/**
-		 * Returns the non-MSAA version of the scene depth texture. If MSAA is not used this is equivalent to calling
-		 * getSceneDepth().
-		 */
-		SPtr<Texture> getResolvedDepth() const;
-
-		/** Returns the texture for storing of the intermediate lighting information. */
-		SPtr<Texture> getLightAccumulation() const;
-
-		/** Returns the texture for storing shadow/attenuation data for single light, from viewers perspective. */
-		SPtr<Texture> getLightOcclusion() const;
-
-		/**
-		 * Flattened, buffer version of the texture returned by getLightAccumulation(). Required when MSAA is used, since
-		 * random writes to multisampled textures aren't supported on all render backends.
+		 * Flattened, buffer version of the texture returned by get(RTT_LightAccumulation). Required when MSAA is used, 
+		 * since random writes to multisampled textures aren't supported on all render backends.
 		 */
 		 */
 		SPtr<GpuBuffer> getLightAccumulationBuffer() const;
 		SPtr<GpuBuffer> getLightAccumulationBuffer() const;
 
 
@@ -199,6 +146,9 @@ namespace bs { namespace ct
 	private:
 	private:
 		RenderTargets(const RENDERER_VIEW_TARGET_DESC& view, bool hdr);
 		RenderTargets(const RENDERER_VIEW_TARGET_DESC& view, bool hdr);
 
 
+		/** Returns a pooled texture previously allocated with a call to allocate(). */
+		SPtr<PooledRenderTexture> getPooledTexture(RenderTargetType type, RenderSurfaceMaskBits surface = RT_COLOR0) const;
+
 		RENDERER_VIEW_TARGET_DESC mViewTarget;
 		RENDERER_VIEW_TARGET_DESC mViewTarget;
 
 
 		SPtr<PooledRenderTexture> mAlbedoTex;
 		SPtr<PooledRenderTexture> mAlbedoTex;
@@ -217,6 +167,7 @@ namespace bs { namespace ct
 
 
 		SPtr<PooledRenderTexture> mHiZ;
 		SPtr<PooledRenderTexture> mHiZ;
 		SPtr<PooledRenderTexture> mResolvedDepthTex;
 		SPtr<PooledRenderTexture> mResolvedDepthTex;
+		SPtr<PooledRenderTexture> mAmbientOcclusionTex;
 
 
 		SPtr<RenderTexture> mGBufferRT;
 		SPtr<RenderTexture> mGBufferRT;
 		SPtr<RenderTexture> mSceneColorRT;
 		SPtr<RenderTexture> mSceneColorRT;

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

@@ -273,6 +273,9 @@ namespace bs { namespace ct
 		 */
 		 */
 		PostProcessInfo& getPPInfo() { return mPostProcessInfo; }
 		PostProcessInfo& getPPInfo() { return mPostProcessInfo; }
 
 
+		/** @copydoc getPPInfo() */
+		const PostProcessInfo& getPPInfo() const { return mPostProcessInfo; }
+
 		/** Updates the GPU buffer containing per-view information, with the latest internal data. */
 		/** Updates the GPU buffer containing per-view information, with the latest internal data. */
 		void updatePerViewBuffer();
 		void updatePerViewBuffer();
 
 

+ 6 - 6
Source/RenderBeast/Source/BsImageBasedLighting.cpp

@@ -201,20 +201,20 @@ namespace bs { namespace ct
 		mParamBuffer->flushToGPU();
 		mParamBuffer->flushToGPU();
 		mReflectionsParamBuffer->flushToGPU();
 		mReflectionsParamBuffer->flushToGPU();
 
 
-		mGBufferA.set(renderTargets->getGBufferA());
-		mGBufferB.set(renderTargets->getGBufferB());
-		mGBufferC.set(renderTargets->getGBufferC());
-		mGBufferDepth.set(renderTargets->getSceneDepth());
+		mGBufferA.set(renderTargets->get(RTT_GBuffer, RT_COLOR0));
+		mGBufferB.set(renderTargets->get(RTT_GBuffer, RT_COLOR1));
+		mGBufferC.set(renderTargets->get(RTT_GBuffer, RT_COLOR2));
+		mGBufferDepth.set(renderTargets->get(RTT_GBuffer, RT_DEPTH));
 
 
 		mImageBasedParams.preintegratedEnvBRDFParam.set(preintegratedGF);
 		mImageBasedParams.preintegratedEnvBRDFParam.set(preintegratedGF);
 
 
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 
 
-		mInColorTextureParam.set(renderTargets->getLightAccumulation());
+		mInColorTextureParam.set(renderTargets->get(RTT_LightAccumulation));
 		if (mSampleCount > 1)
 		if (mSampleCount > 1)
 			mOutputBufferParam.set(renderTargets->getSceneColorBuffer());
 			mOutputBufferParam.set(renderTargets->getSceneColorBuffer());
 		else
 		else
-			mOutputTextureParam.set(renderTargets->getSceneColor());
+			mOutputTextureParam.set(renderTargets->get(RTT_SceneColor));
 
 
 		UINT32 width = renderTargets->getWidth();
 		UINT32 width = renderTargets->getWidth();
 		UINT32 height = renderTargets->getHeight();
 		UINT32 height = renderTargets->getHeight();

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

@@ -111,10 +111,10 @@ namespace bs { namespace ct
 
 
 	void GBufferParams::bind(const RenderTargets& renderTargets)
 	void GBufferParams::bind(const RenderTargets& renderTargets)
 	{
 	{
-		mGBufferA.set(renderTargets.getGBufferA());
-		mGBufferB.set(renderTargets.getGBufferB());
-		mGBufferC.set(renderTargets.getGBufferC());
-		mGBufferDepth.set(renderTargets.getSceneDepth());
+		mGBufferA.set(renderTargets.get(RTT_GBuffer, RT_COLOR0));
+		mGBufferB.set(renderTargets.get(RTT_GBuffer, RT_COLOR1));
+		mGBufferC.set(renderTargets.get(RTT_GBuffer, RT_COLOR2));
+		mGBufferDepth.set(renderTargets.get(RTT_GBuffer, RT_DEPTH));
 
 
 		mMaterial->updateParamsSet(mParamsSet);
 		mMaterial->updateParamsSet(mParamsSet);
 	}
 	}
@@ -287,7 +287,7 @@ namespace bs { namespace ct
 		}
 		}
 		else
 		else
 		{
 		{
-			SPtr<Texture> lightAccumulation = renderTargets->getLightAccumulation();
+			SPtr<Texture> lightAccumulation = renderTargets->get(RTT_LightAccumulation);
 			mOutputTextureParam.set(lightAccumulation);
 			mOutputTextureParam.set(lightAccumulation);
 		}
 		}
 
 

+ 262 - 36
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -1101,7 +1101,8 @@ namespace bs { namespace ct
 
 
 	SSAOParamDef gSSAOParamDef;
 	SSAOParamDef gSSAOParamDef;
 
 
-	SSAOMat::SSAOMat()
+	template<bool UPSAMPLE, bool FINAL_PASS, int QUALITY>
+	SSAOMat<UPSAMPLE, FINAL_PASS, QUALITY>::SSAOMat()
 	{
 	{
 		mParamBuffer = gSSAOParamDef.createBuffer();
 		mParamBuffer = gSSAOParamDef.createBuffer();
 
 
@@ -1110,6 +1111,8 @@ namespace bs { namespace ct
 		SPtr<GpuParams> gpuParams = mParamsSet->getGpuParams();
 		SPtr<GpuParams> gpuParams = mParamsSet->getGpuParams();
 		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gDepthTex", mDepthTexture);
 		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gDepthTex", mDepthTexture);
 		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gNormalsTex", mNormalsTexture);
 		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gNormalsTex", mNormalsTexture);
+		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gDownsampledAO", mDownsampledAOTexture);
+		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gSetupAO", mSetupAOTexture);
 		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gRandomTex", mRandomTexture);
 		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gRandomTex", mRandomTexture);
 
 
 		SAMPLER_STATE_DESC inputSampDesc;
 		SAMPLER_STATE_DESC inputSampDesc;
@@ -1135,13 +1138,17 @@ namespace bs { namespace ct
 		gpuParams->setSamplerState(GPT_FRAGMENT_PROGRAM, "gRandomSamp", randomSampState);
 		gpuParams->setSamplerState(GPT_FRAGMENT_PROGRAM, "gRandomSamp", randomSampState);
 	}
 	}
 
 
-	void SSAOMat::_initDefines(ShaderDefines& defines)
+	template<bool UPSAMPLE, bool FINAL_PASS, int QUALITY>
+	void SSAOMat<UPSAMPLE, FINAL_PASS, QUALITY>::_initDefines(ShaderDefines& defines)
 	{
 	{
-		// Do nothing
+		defines.set("MIX_WITH_UPSAMPLED", UPSAMPLE ? 1 : 0);
+		defines.set("FINAL_AO", FINAL_PASS ? 1 : 0);
+		defines.set("QUALITY", QUALITY);
 	}
 	}
 
 
-	void SSAOMat::execute(const RendererView& view, const SPtr<Texture>& depth, const SPtr<Texture>& normals, 
-		const SPtr<Texture>& random, const SPtr<RenderTexture>& destination, const AmbientOcclusionSettings& settings)
+	template <bool UPSAMPLE, bool FINAL_PASS, int QUALITY>
+	void SSAOMat<UPSAMPLE, FINAL_PASS, QUALITY>::execute(const RendererView& view, const SSAOTextureInputs& textures, 
+		const SPtr<RenderTexture>& destination, const AmbientOcclusionSettings& settings)
 	{
 	{
 		const RendererViewProperties& viewProps = view.getProperties();
 		const RendererViewProperties& viewProps = view.getProperties();
 
 
@@ -1156,9 +1163,20 @@ namespace bs { namespace ct
 		gSSAOParamDef.gTanHalfFOV.set(mParamBuffer, tanHalfFOV);
 		gSSAOParamDef.gTanHalfFOV.set(mParamBuffer, tanHalfFOV);
 		gSSAOParamDef.gWorldSpaceRadiusMask.set(mParamBuffer, 1.0f);
 		gSSAOParamDef.gWorldSpaceRadiusMask.set(mParamBuffer, 1.0f);
 		gSSAOParamDef.gBias.set(mParamBuffer, settings.bias / 1000.0f);
 		gSSAOParamDef.gBias.set(mParamBuffer, settings.bias / 1000.0f);
+		
+		if(UPSAMPLE)
+		{
+			const TextureProperties& props = textures.aoDownsampled->getProperties();
+
+			Vector2 downsampledPixelSize;
+			downsampledPixelSize.x = 1.0f / props.getWidth();
+			downsampledPixelSize.y = 1.0f / props.getHeight();
+
+			gSSAOParamDef.gDownsampledPixelSize.set(mParamBuffer, downsampledPixelSize);
+		}
 
 
 		// Generate a scale which we need to use in order to achieve tiling
 		// Generate a scale which we need to use in order to achieve tiling
-		const TextureProperties& rndProps = random->getProperties();
+		const TextureProperties& rndProps = textures.randomRotations->getProperties();
 		UINT32 rndWidth = rndProps.getWidth();
 		UINT32 rndWidth = rndProps.getWidth();
 		UINT32 rndHeight = rndProps.getHeight();
 		UINT32 rndHeight = rndProps.getHeight();
 
 
@@ -1169,9 +1187,75 @@ namespace bs { namespace ct
 		Vector2 randomTileScale((float)scaleWidth, (float)scaleHeight);
 		Vector2 randomTileScale((float)scaleWidth, (float)scaleHeight);
 		gSSAOParamDef.gRandomTileScale.set(mParamBuffer, randomTileScale);
 		gSSAOParamDef.gRandomTileScale.set(mParamBuffer, randomTileScale);
 
 
+		mSetupAOTexture.set(textures.aoSetup);
+
+		if (FINAL_PASS)
+		{
+			mDepthTexture.set(textures.sceneDepth);
+			mNormalsTexture.set(textures.sceneNormals);
+		}
+
+		if (UPSAMPLE)
+			mDownsampledAOTexture.set(textures.aoDownsampled);
+		
+		mRandomTexture.set(textures.randomRotations);
+
+		SPtr<GpuParamBlockBuffer> perView = view.getPerViewBuffer();
+		mParamsSet->setParamBlockBuffer("PerCamera", perView);
+
+		RenderAPI& rapi = RenderAPI::instance();
+		rapi.setRenderTarget(destination);
+
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
+		gRendererUtility().drawScreenQuad();
+	}
+
+	SSAODownsampleParamDef gSSAODownsampleParamDef;
+
+	SSAODownsampleMat::SSAODownsampleMat()
+	{
+		mParamBuffer = gSSAODownsampleParamDef.createBuffer();
+		mParamsSet->setParamBlockBuffer("Input", mParamBuffer);
+
+		SPtr<GpuParams> gpuParams = mParamsSet->getGpuParams();
+		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gDepthTex", mDepthTexture);
+		gpuParams->getTextureParam(GPT_FRAGMENT_PROGRAM, "gNormalsTex", mNormalsTexture);
+
+		SAMPLER_STATE_DESC inputSampDesc;
+		inputSampDesc.minFilter = FO_LINEAR;
+		inputSampDesc.magFilter = FO_LINEAR;
+		inputSampDesc.mipFilter = FO_LINEAR;
+		inputSampDesc.addressMode.u = TAM_CLAMP;
+		inputSampDesc.addressMode.v = TAM_CLAMP;
+		inputSampDesc.addressMode.w = TAM_CLAMP;
+
+		SPtr<SamplerState> inputSampState = SamplerState::create(inputSampDesc);
+		gpuParams->setSamplerState(GPT_FRAGMENT_PROGRAM, "gInputSamp", inputSampState);
+	}
+
+	void SSAODownsampleMat::_initDefines(ShaderDefines& defines)
+	{
+		// Do nothing
+	}
+
+	void SSAODownsampleMat::execute(const RendererView& view, const SPtr<Texture>& depth, const SPtr<Texture>& normals, 
+		const SPtr<RenderTexture>& destination, float depthRange)
+	{
+		const RendererViewProperties& viewProps = view.getProperties();
+		const RenderTargetProperties& rtProps = destination->getProperties();
+
+		Vector2 pixelSize;
+		pixelSize.x = 1.0f / rtProps.getWidth();
+		pixelSize.y = 1.0f / rtProps.getHeight();
+
+		float scale = viewProps.viewRect.width / (float)rtProps.getWidth();
+
+		gSSAODownsampleParamDef.gPixelSize.set(mParamBuffer, pixelSize);
+		gSSAODownsampleParamDef.gInvDepthThreshold.set(mParamBuffer, (1.0f / depthRange) / scale);
+
 		mDepthTexture.set(depth);
 		mDepthTexture.set(depth);
 		mNormalsTexture.set(normals);
 		mNormalsTexture.set(normals);
-		mRandomTexture.set(random);
 
 
 		SPtr<GpuParamBlockBuffer> perView = view.getPerViewBuffer();
 		SPtr<GpuParamBlockBuffer> perView = view.getPerViewBuffer();
 		mParamsSet->setParamBlockBuffer("PerCamera", perView);
 		mParamsSet->setParamBlockBuffer("PerCamera", perView);
@@ -1184,7 +1268,162 @@ namespace bs { namespace ct
 		gRendererUtility().drawScreenQuad();
 		gRendererUtility().drawScreenQuad();
 	}
 	}
 
 
-	SPtr<Texture> SSAOMat::generate4x4RandomizationTexture() const
+	SSAO::SSAO()
+	{
+		mSSAORandomizationTex = generate4x4RandomizationTexture();
+	}
+
+	void SSAO::execute(const RendererView& view, const SPtr<RenderTexture>& destination, 
+		const AmbientOcclusionSettings& settings)
+	{
+		/** Maximum valid depth range within samples in a sample set. In meters. */
+		static const float DEPTH_RANGE = 1.0f;
+
+		const RendererViewProperties& viewProps = view.getProperties();
+		SPtr<RenderTargets> renderTargets = view.getRenderTargets();
+
+		SPtr<Texture> sceneDepth = renderTargets->get(RTT_ResolvedDepth);
+		SPtr<Texture> sceneNormals = renderTargets->get(RTT_GBuffer, RT_COLOR1);
+
+		// TODO - Resolve normals if MSAA
+
+		UINT32 numDownsampleLevels = 1; // TODO - Make it a property, ranging [0, 2]
+		UINT32 quality = 1; // TODO - Make it a property
+
+		SPtr<PooledRenderTexture> setupTex0;
+		if(numDownsampleLevels > 0)
+		{
+			Vector2I downsampledSize(
+				std::max(1, Math::divideAndRoundUp(viewProps.viewRect.width, 2)),
+				std::max(1, Math::divideAndRoundUp(viewProps.viewRect.height, 2))
+			);
+
+			POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_FLOAT16_RGBA, downsampledSize.x, 
+				downsampledSize.y, TU_RENDERTARGET);
+			setupTex0 = GpuResourcePool::instance().get(desc);
+
+			mDownsample.execute(view, sceneDepth, sceneNormals, setupTex0->renderTexture, DEPTH_RANGE);
+		}
+
+		SPtr<PooledRenderTexture> setupTex1;
+		if(numDownsampleLevels > 1)
+		{
+			Vector2I downsampledSize(
+				std::max(1, Math::divideAndRoundUp(viewProps.viewRect.width, 4)),
+				std::max(1, Math::divideAndRoundUp(viewProps.viewRect.height, 4))
+			);
+
+			POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_FLOAT16_RGBA, downsampledSize.x, 
+				downsampledSize.y, TU_RENDERTARGET);
+			setupTex1 = GpuResourcePool::instance().get(desc);
+
+			mDownsample.execute(view, sceneDepth, sceneNormals, setupTex1->renderTexture, DEPTH_RANGE);
+		}
+
+		SSAOTextureInputs textures;
+		textures.sceneDepth = sceneDepth;
+		textures.sceneNormals = sceneNormals;
+		textures.randomRotations = mSSAORandomizationTex;
+
+		SPtr<PooledRenderTexture> downAOTex1;
+		if(numDownsampleLevels > 1)
+		{
+			textures.aoSetup = setupTex1->texture;
+
+			Vector2I downsampledSize(
+				std::max(1, Math::divideAndRoundUp(viewProps.viewRect.width, 4)),
+				std::max(1, Math::divideAndRoundUp(viewProps.viewRect.height, 4))
+			);
+
+			POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, downsampledSize.x, 
+				downsampledSize.y, TU_RENDERTARGET);
+			downAOTex1 = GpuResourcePool::instance().get(desc);
+
+			executeSSAOMat(false, false, quality, view, textures, downAOTex1->renderTexture, settings);
+
+			GpuResourcePool::instance().release(setupTex1);
+			setupTex1 = nullptr;
+		}
+
+		SPtr<PooledRenderTexture> downAOTex0;
+		if(numDownsampleLevels > 0)
+		{
+			textures.aoSetup = setupTex0->texture;
+			textures.aoDownsampled = downAOTex1->texture;
+
+			Vector2I downsampledSize(
+				std::max(1, Math::divideAndRoundUp(viewProps.viewRect.width, 2)),
+				std::max(1, Math::divideAndRoundUp(viewProps.viewRect.height, 2))
+			);
+
+			POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, downsampledSize.x, 
+				downsampledSize.y, TU_RENDERTARGET);
+			downAOTex0 = GpuResourcePool::instance().get(desc);
+
+			bool upsample = numDownsampleLevels > 1;
+			executeSSAOMat(upsample, false, quality, view, textures, downAOTex0->renderTexture, settings);
+
+			if(upsample)
+			{
+				GpuResourcePool::instance().release(downAOTex1);
+				downAOTex1 = nullptr;
+			}
+		}
+
+		{
+			textures.aoSetup = setupTex0->texture;
+			textures.aoDownsampled = downAOTex0->texture;
+
+			bool upsample = numDownsampleLevels > 0;
+			executeSSAOMat(upsample, true, quality, view, textures, destination, settings);
+		}
+
+		if(numDownsampleLevels > 0)
+		{
+			GpuResourcePool::instance().release(setupTex0);
+			GpuResourcePool::instance().release(downAOTex0);
+		}
+	}
+
+	void SSAO::executeSSAOMat(bool upsample, bool final, int quality, const RendererView& view, 
+		const SSAOTextureInputs& textures, const SPtr<RenderTexture>& destination, const AmbientOcclusionSettings& settings)
+	{
+#define PICK_MATERIAL(QUALITY)															\
+		if(upsample)																	\
+			if(final)																	\
+				mSSAO_TT_##QUALITY.execute(view, textures, destination, settings);		\
+			else																		\
+				mSSAO_TF_##QUALITY.execute(view, textures, destination, settings);		\
+		else																			\
+			if(final)																	\
+				mSSAO_FT_##QUALITY.execute(view, textures, destination, settings);		\
+			else																		\
+				mSSAO_FF_##QUALITY.execute(view, textures, destination, settings);		\
+
+		switch(quality)
+		{
+		case 0:
+			PICK_MATERIAL(0)
+			break;
+		case 1:
+			PICK_MATERIAL(1)
+			break;
+		case 2:
+			PICK_MATERIAL(2)
+			break;
+		case 3:
+			PICK_MATERIAL(3)
+			break;
+		default:
+		case 4:
+			PICK_MATERIAL(4)
+			break;
+		}
+
+#undef PICK_MATERIAL
+	}
+
+	SPtr<Texture> SSAO::generate4x4RandomizationTexture() const
 	{
 	{
 		UINT32 mapping[16] = { 13, 5, 1, 9, 14, 3, 7, 11, 15, 2, 6, 12, 4, 8, 0, 10 };
 		UINT32 mapping[16] = { 13, 5, 1, 9, 14, 3, 7, 11, 15, 2, 6, 12, 4, 8, 0, 10 };
 		Vector2 bases[16];
 		Vector2 bases[16];
@@ -1211,11 +1450,6 @@ namespace bs { namespace ct
 		return Texture::create(pixelData);
 		return Texture::create(pixelData);
 	}
 	}
 
 
-	PostProcessing::PostProcessing()
-	{
-		mSSAORandomizationTex = mSSAO.generate4x4RandomizationTexture();
-	}
-
 	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();
@@ -1223,21 +1457,12 @@ namespace bs { namespace ct
 		PostProcessInfo& ppInfo = viewInfo->getPPInfo();
 		PostProcessInfo& ppInfo = viewInfo->getPPInfo();
 		const StandardPostProcessSettings& settings = *ppInfo.settings;
 		const StandardPostProcessSettings& settings = *ppInfo.settings;
 
 
-		SPtr<Texture> sceneColor = renderTargets->getSceneColor();
+		SPtr<Texture> sceneColor = renderTargets->get(RTT_SceneColor);
 		Rect2 viewportRect = viewProps.nrmViewRect;
 		Rect2 viewportRect = viewProps.nrmViewRect;
 
 
 		bool hdr = viewProps.isHDR;
 		bool hdr = viewProps.isHDR;
 		bool msaa = viewProps.numSamples > 1;
 		bool msaa = viewProps.numSamples > 1;
 
 
-		// DEBUG ONLY
-		//SPtr<PooledRenderTexture> temp = GpuResourcePool::instance().get(
-		//	POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, viewProps.viewRect.width, viewProps.viewRect.height, 
-		//	TU_RENDERTARGET));
-
-		//mSSAO.execute(*viewInfo, renderTargets->getSceneDepth(), renderTargets->getGBufferB(), mSSAORandomizationTex, 
-		//	temp->renderTexture, settings.ambientOcclusion);
-		// END DEBUG ONLY
-
 		if(hdr && settings.enableAutoExposure)
 		if(hdr && settings.enableAutoExposure)
 		{
 		{
 			mDownsample.execute(1, msaa, sceneColor, ppInfo);
 			mDownsample.execute(1, msaa, sceneColor, ppInfo);
@@ -1281,7 +1506,7 @@ namespace bs { namespace ct
 		else
 		else
 		{
 		{
 			renderTargets->allocate(RTT_ResolvedSceneColorSecondary);
 			renderTargets->allocate(RTT_ResolvedSceneColorSecondary);
-			tonemapTarget = renderTargets->getResolvedSceneColorRT(true);
+			tonemapTarget = renderTargets->getRT(RTT_ResolvedSceneColorSecondary);
 		}
 		}
 
 
 		mTonemapping.execute(gammaOnly, autoExposure, msaa, sceneColor, tonemapTarget, viewportRect, ppInfo);
 		mTonemapping.execute(gammaOnly, autoExposure, msaa, sceneColor, tonemapTarget, viewportRect, ppInfo);
@@ -1294,14 +1519,14 @@ namespace bs { namespace ct
 			if (settings.enableFXAA)
 			if (settings.enableFXAA)
 			{
 			{
 				renderTargets->allocate(RTT_ResolvedSceneColor);
 				renderTargets->allocate(RTT_ResolvedSceneColor);
-				dofTarget = renderTargets->getResolvedSceneColorRT(false);
+				dofTarget = renderTargets->getRT(RTT_ResolvedSceneColor);
 			}
 			}
 			else
 			else
 				dofTarget = viewProps.target;
 				dofTarget = viewProps.target;
 
 
-			SPtr<Texture> sceneDepth = renderTargets->getResolvedDepth();
+			SPtr<Texture> sceneDepth = renderTargets->get(RTT_ResolvedDepth);
 
 
-			mGaussianDOF.execute(renderTargets->getResolvedSceneColor(true), sceneDepth, dofTarget, *viewInfo, 
+			mGaussianDOF.execute(renderTargets->get(RTT_ResolvedSceneColorSecondary), sceneDepth, dofTarget, *viewInfo, 
 				settings.depthOfField);
 				settings.depthOfField);
 
 
 			renderTargets->release(RTT_ResolvedSceneColorSecondary);
 			renderTargets->release(RTT_ResolvedSceneColorSecondary);
@@ -1311,9 +1536,9 @@ namespace bs { namespace ct
 		{
 		{
 			SPtr<Texture> fxaaSource;
 			SPtr<Texture> fxaaSource;
 			if (performDOF)
 			if (performDOF)
-				fxaaSource = renderTargets->getResolvedSceneColor(false);
+				fxaaSource = renderTargets->get(RTT_ResolvedSceneColor);
 			else
 			else
-				fxaaSource = renderTargets->getResolvedSceneColor(true);
+				fxaaSource = renderTargets->get(RTT_ResolvedSceneColorSecondary);
 
 
 			// Note: I could skip executing FXAA over DOF and motion blurred pixels
 			// Note: I could skip executing FXAA over DOF and motion blurred pixels
 			mFXAA.execute(fxaaSource, viewProps.target);
 			mFXAA.execute(fxaaSource, viewProps.target);
@@ -1324,14 +1549,15 @@ namespace bs { namespace ct
 				renderTargets->release(RTT_ResolvedSceneColorSecondary);
 				renderTargets->release(RTT_ResolvedSceneColorSecondary);
 		}
 		}
 
 
-		// BEGIN DEBUG ONLY
-		//RenderAPI::instance().setRenderTarget(viewProps.target);
-		//gRendererUtility().blit(temp->texture);
-
-		//GpuResourcePool::instance().release(temp);
-		// END DEBUG ONLY
-
 		if (ppInfo.settingDirty)
 		if (ppInfo.settingDirty)
 			ppInfo.settingDirty = false;
 			ppInfo.settingDirty = false;
 	}
 	}
+
+	void PostProcessing::buildSSAO(const RendererView& view)
+	{
+		const SPtr<RenderTargets> renderTargets = view.getRenderTargets();
+		const PostProcessInfo& ppInfo = view.getPPInfo();
+
+		mSSAO.execute(view, renderTargets->getRT(RTT_AmbientOcclusion), ppInfo.settings->ambientOcclusion);
+	}
 }}
 }}

+ 25 - 12
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -508,7 +508,7 @@ namespace bs { namespace ct
 
 
 		SPtr<RenderTargets> renderTargets = viewInfo->getRenderTargets();
 		SPtr<RenderTargets> renderTargets = viewInfo->getRenderTargets();
 		renderTargets->allocate(RTT_GBuffer);
 		renderTargets->allocate(RTT_GBuffer);
-		renderTargets->bindGBuffer();
+		renderTargets->bind(RTT_GBuffer);
 
 
 		// Trigger pre-base-pass callbacks
 		// Trigger pre-base-pass callbacks
 		auto iterRenderCallback = mCallbacks.begin();
 		auto iterRenderCallback = mCallbacks.begin();
@@ -545,9 +545,6 @@ namespace bs { namespace ct
 			renderTargets->generate(RTT_ResolvedDepth);
 			renderTargets->generate(RTT_ResolvedDepth);
 		}
 		}
 
 
-		renderTargets->allocate(RTT_HiZ);
-		renderTargets->generate(RTT_HiZ);
-
 		// Trigger post-base-pass callbacks
 		// Trigger post-base-pass callbacks
 		if (viewProps.triggerCallbacks)
 		if (viewProps.triggerCallbacks)
 		{
 		{
@@ -564,6 +561,19 @@ namespace bs { namespace ct
 			}
 			}
 		}
 		}
 
 
+		renderTargets->allocate(RTT_HiZ);
+		renderTargets->generate(RTT_HiZ);
+
+		// Build AO if required
+		bool useSSAO = viewInfo->getPPInfo().settings->ambientOcclusion.enabled;
+		if(useSSAO)
+		{
+			renderTargets->allocate(RTT_AmbientOcclusion);
+
+			// Note: This could be done as async compute (and started earlier, right after base pass)
+			PostProcessing::instance().buildSSAO(*viewInfo);
+		}
+
 		RenderAPI& rapi = RenderAPI::instance();
 		RenderAPI& rapi = RenderAPI::instance();
 		rapi.setRenderTarget(nullptr);
 		rapi.setRenderTarget(nullptr);
 
 
@@ -579,9 +589,9 @@ namespace bs { namespace ct
 		// continuing
 		// continuing
 		if(isMSAA)
 		if(isMSAA)
 		{
 		{
-			renderTargets->bindLightAccumulation();
+			renderTargets->bind(RTT_LightAccumulation);
 			mFlatFramebufferToTextureMat->execute(renderTargets->getLightAccumulationBuffer(), 
 			mFlatFramebufferToTextureMat->execute(renderTargets->getLightAccumulationBuffer(), 
-				renderTargets->getLightAccumulation());
+				renderTargets->get(RTT_LightAccumulation));
 		}
 		}
 
 
 		// Render shadowed lights into light accumulation texture, using standard deferred
 		// Render shadowed lights into light accumulation texture, using standard deferred
@@ -601,14 +611,14 @@ namespace bs { namespace ct
 
 
 				for (UINT32 j = 0; j < count; j++)
 				for (UINT32 j = 0; j < count; j++)
 				{
 				{
-					renderTargets->bindLightOcclusion();
+					renderTargets->bind(RTT_LightOcclusion);
 
 
 					UINT32 lightIdx = offset + j;
 					UINT32 lightIdx = offset + j;
 					const RendererLight& light = *lights[lightIdx];
 					const RendererLight& light = *lights[lightIdx];
 					ShadowRendering::instance().renderShadowOcclusion(*mScene, mCoreOptions->shadowFilteringQuality,
 					ShadowRendering::instance().renderShadowOcclusion(*mScene, mCoreOptions->shadowFilteringQuality,
 						light, viewIdx);
 						light, viewIdx);
 
 
-					renderTargets->bindLightAccumulation();
+					renderTargets->bind(RTT_LightAccumulation);
 					StandardDeferred::instance().renderLight(lightType, light, *viewInfo, *renderTargets);
 					StandardDeferred::instance().renderLight(lightType, light, *viewInfo, *renderTargets);
 				}
 				}
 			}
 			}
@@ -623,15 +633,18 @@ namespace bs { namespace ct
 		renderTargets->allocate(RTT_SceneColor);
 		renderTargets->allocate(RTT_SceneColor);
 		imageBasedLightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF);
 		imageBasedLightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF);
 
 
+		if (useSSAO)
+			renderTargets->release(RTT_AmbientOcclusion);
+
 		renderTargets->release(RTT_LightAccumulation);
 		renderTargets->release(RTT_LightAccumulation);
 		renderTargets->release(RTT_GBuffer);
 		renderTargets->release(RTT_GBuffer);
 
 
-		renderTargets->bindSceneColor(true);
+		renderTargets->bind(RTT_SceneColor, true);
 
 
 		// If we're using flattened framebuffer for MSAA we need to copy its contents to the MSAA scene texture before
 		// If we're using flattened framebuffer for MSAA we need to copy its contents to the MSAA scene texture before
 		// continuing
 		// continuing
 		if(isMSAA)
 		if(isMSAA)
-			mFlatFramebufferToTextureMat->execute(renderTargets->getSceneColorBuffer(), renderTargets->getSceneColor());
+			mFlatFramebufferToTextureMat->execute(renderTargets->getSceneColorBuffer(), renderTargets->get(RTT_SceneColor));
 
 
 		// Render skybox (if any)
 		// Render skybox (if any)
 		if (mSkyboxTexture != nullptr)
 		if (mSkyboxTexture != nullptr)
@@ -650,7 +663,7 @@ namespace bs { namespace ct
 		SPtr<Mesh> mesh = gRendererUtility().getSkyBoxMesh();
 		SPtr<Mesh> mesh = gRendererUtility().getSkyBoxMesh();
 		gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
 		gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
 
 
-		renderTargets->bindSceneColor(false);
+		renderTargets->bind(RTT_SceneColor, false);
 
 
 		// Render transparent objects
 		// Render transparent objects
 		// TODO: Transparent objects cannot receive shadows. In order to support this I'd have to render the light occlusion
 		// TODO: Transparent objects cannot receive shadows. In order to support this I'd have to render the light occlusion
@@ -695,7 +708,7 @@ namespace bs { namespace ct
 			rapi.setRenderTarget(target);
 			rapi.setRenderTarget(target);
 			rapi.setViewport(viewportArea);
 			rapi.setViewport(viewportArea);
 
 
-			SPtr<Texture> sceneColor = renderTargets->getSceneColor();
+			SPtr<Texture> sceneColor = renderTargets->get(RTT_SceneColor);
 			gRendererUtility().blit(sceneColor, Rect2I::EMPTY, viewProps.flipView);
 			gRendererUtility().blit(sceneColor, Rect2I::EMPTY, viewProps.flipView);
 		}
 		}
 
 

+ 144 - 103
Source/RenderBeast/Source/BsRenderTargets.cpp

@@ -242,6 +242,10 @@ namespace bs { namespace ct
 					1, false));
 					1, false));
 			}
 			}
 		}
 		}
+		else if(type == RTT_AmbientOcclusion)
+		{
+			mAmbientOcclusionTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, width, height, TU_RENDERTARGET));
+		}
 	}
 	}
 
 
 	void RenderTargets::release(RenderTargetType type)
 	void RenderTargets::release(RenderTargetType type)
@@ -295,56 +299,75 @@ namespace bs { namespace ct
 			if (mResolvedDepthTex != nullptr)
 			if (mResolvedDepthTex != nullptr)
 				texPool.release(mResolvedDepthTex);
 				texPool.release(mResolvedDepthTex);
 		}
 		}
+		else if(type == RTT_AmbientOcclusion)
+		{
+			if (mAmbientOcclusionTex != nullptr)
+				texPool.release(mAmbientOcclusionTex);
+		}
 	}
 	}
 
 
-	void RenderTargets::bindGBuffer()
+	void RenderTargets::bind(RenderTargetType type, bool readOnlyDepthStencil)
 	{
 	{
 		RenderAPI& rapi = RenderAPI::instance();
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mGBufferRT);
-
-		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
-		rapi.setViewport(area);
-
-		// Clear depth & stencil according to user defined values, don't clear color as all values will get written to
-		UINT32 clearFlags = mViewTarget.clearFlags & ~FBT_COLOR;
-		if (clearFlags != 0)
+		switch(type)
 		{
 		{
-			RenderAPI::instance().clearViewport(clearFlags, mViewTarget.clearColor,
-				mViewTarget.clearDepthValue, mViewTarget.clearStencilValue, 0x01);
-		}
+		case RTT_GBuffer:
+		{
+			rapi.setRenderTarget(mGBufferRT);
 
 
-		// Clear all non primary targets (Note: I could perhaps clear all but albedo, since it stores a per-pixel write mask)
-		RenderAPI::instance().clearViewport(FBT_COLOR, Color::ZERO, 1.0f, 0, 0xFF & ~0x01);
-	}
+			Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
+			rapi.setViewport(area);
 
 
-	void RenderTargets::bindSceneColor(bool readOnlyDepthStencil)
-	{
-		int readOnlyFlags = 0;
-		if (readOnlyDepthStencil)
-			readOnlyFlags = FBT_DEPTH | FBT_STENCIL;
+			// Clear depth & stencil according to user defined values, don't clear color as all values will get written to
+			UINT32 clearFlags = mViewTarget.clearFlags & ~FBT_COLOR;
+			if (clearFlags != 0)
+			{
+				RenderAPI::instance().clearViewport(clearFlags, mViewTarget.clearColor,
+					mViewTarget.clearDepthValue, mViewTarget.clearStencilValue, 0x01);
+			}
 
 
-		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mSceneColorRT, readOnlyFlags, RT_COLOR0 | RT_DEPTH_STENCIL);
+			// Clear all non primary targets (Note: I could perhaps clear all but albedo, since it stores a per-pixel write mask)
+			RenderAPI::instance().clearViewport(FBT_COLOR, Color::ZERO, 1.0f, 0, 0xFF & ~0x01);
+		}
+		break;
+		case RTT_SceneColor:
+		{
+			int readOnlyFlags = 0;
+			if (readOnlyDepthStencil)
+				readOnlyFlags = FBT_DEPTH | FBT_STENCIL;
 
 
-		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
-		rapi.setViewport(area);
-	}
+			rapi.setRenderTarget(mSceneColorRT, readOnlyFlags, RT_COLOR0 | RT_DEPTH_STENCIL);
 
 
-	void RenderTargets::bindLightAccumulation()
-	{
-		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mLightAccumulationRT, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH_STENCIL);
-	}
+			Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
+			rapi.setViewport(area);
+			
+		}
+		break;
+		case RTT_LightAccumulation:
+			rapi.setRenderTarget(mLightAccumulationRT, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH_STENCIL);
+		break;
+		case RTT_LightOcclusion:
+		{
+			rapi.setRenderTarget(mLightOcclusionRT, FBT_DEPTH, RT_DEPTH_STENCIL);
 
 
-	void RenderTargets::bindLightOcclusion()
-	{
-		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mLightOcclusionRT, FBT_DEPTH, RT_DEPTH_STENCIL);
+			Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
+			rapi.setViewport(area);
 
 
-		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
-		rapi.setViewport(area);
+			RenderAPI::instance().clearViewport(FBT_COLOR, Color::ZERO);
+		}
+		break;
+		default:
+		{
+			int readOnlyFlags = 0;
+			if (readOnlyDepthStencil)
+				readOnlyFlags = FBT_DEPTH | FBT_STENCIL;
 
 
-		RenderAPI::instance().clearViewport(FBT_COLOR, Color::ZERO);
+			SPtr<RenderTexture> rt = getRT(type);
+			if (rt)
+				rapi.setRenderTarget(rt, readOnlyFlags);
+		}
+		break;
+		}
 	}
 	}
 
 
 	void RenderTargets::generate(RenderTargetType type)
 	void RenderTargets::generate(RenderTargetType type)
@@ -352,12 +375,12 @@ namespace bs { namespace ct
 		switch(type)
 		switch(type)
 		{
 		{
 		case RTT_HiZ:
 		case RTT_HiZ:
-			mBuildHiZ.execute(mViewTarget, getResolvedDepth(), mHiZ->texture);
+			mBuildHiZ.execute(mViewTarget, get(RTT_ResolvedDepth), mHiZ->texture);
 		break;
 		break;
 		case RTT_ResolvedSceneColor:
 		case RTT_ResolvedSceneColor:
 			if (mViewTarget.numSamples > 1)
 			if (mViewTarget.numSamples > 1)
 			{
 			{
-				RenderAPI::instance().setRenderTarget(mResolvedDepthTex->renderTexture);
+				RenderAPI::instance().setRenderTarget(mResolvedSceneColorTex1->renderTexture);
 				gRendererUtility().blit(mDepthTex->texture);
 				gRendererUtility().blit(mDepthTex->texture);
 			}
 			}
 			break;
 			break;
@@ -366,45 +389,99 @@ namespace bs { namespace ct
 		}
 		}
 	}
 	}
 
 
-	SPtr<Texture> RenderTargets::getResolvedDepth() const
-	{
-		if (mViewTarget.numSamples > 1)
-			return mResolvedDepthTex->texture;
-
-		return mDepthTex->texture;
-	}
-
-	SPtr<Texture> RenderTargets::getHiZ() const
+	SPtr<Texture> RenderTargets::get(RenderTargetType type, RenderSurfaceMaskBits surface) const
 	{
 	{
-		if (mHiZ)
-			return mHiZ->texture;
+		switch(type)
+		{
+		case RTT_ResolvedDepth:
+			if (mViewTarget.numSamples > 1)
+				return mResolvedDepthTex->texture;
 
 
-		return nullptr;
-	}
+			return mDepthTex->texture;
+		case RTT_ResolvedSceneColor:
+			if (mViewTarget.numSamples > 1)
+				return mResolvedSceneColorTex1->texture;
+			else
+				return mSceneColorTex->texture;
+		default:
+		{
+			SPtr<PooledRenderTexture> pooledTex = getPooledTexture(type, surface);
+			if(pooledTex)
+				return pooledTex->texture;
 
 
-	SPtr<Texture> RenderTargets::getSceneColor() const
-	{
-		return mSceneColorTex->texture;
+			return nullptr;
+		}
+		}
 	}
 	}
 
 
-	SPtr<Texture> RenderTargets::getGBufferA() const
+	SPtr<RenderTexture> RenderTargets::getRT(RenderTargetType type) const
 	{
 	{
-		return mAlbedoTex->texture;
-	}
+		switch(type)
+		{
+		case RTT_GBuffer:
+			return mGBufferRT;
+		case RTT_SceneColor:
+			return mSceneColorRT;
+		case RTT_LightOcclusion:
+			return mLightOcclusionRT;
+		case RTT_LightAccumulation:
+			return mLightAccumulationRT;
+		case RTT_ResolvedSceneColor:
+			if (mViewTarget.numSamples > 1)
+				return mResolvedSceneColorTex1->renderTexture;
+			else
+				return mSceneColorRT;
+		default:
+		{
+			SPtr<PooledRenderTexture> pooledTex = getPooledTexture(type);
 
 
-	SPtr<Texture> RenderTargets::getGBufferB() const
-	{
-		return mNormalTex->texture;
-	}
+			if(pooledTex)
+				return pooledTex->renderTexture;
 
 
-	SPtr<Texture> RenderTargets::getGBufferC() const
-	{
-		return mRoughMetalTex->texture;
+			return nullptr;
+		}
+		}
 	}
 	}
 
 
-	SPtr<Texture> RenderTargets::getSceneDepth() const
+	SPtr<PooledRenderTexture> RenderTargets::getPooledTexture(RenderTargetType type, RenderSurfaceMaskBits surface) const
 	{
 	{
-		return mDepthTex->texture;
+		switch(type)
+		{
+		case RTT_GBuffer:
+		{
+			switch (surface)
+			{
+			default:
+			case RT_COLOR0:
+				return mAlbedoTex;
+			case RT_COLOR1:
+				return mNormalTex;
+			case RT_COLOR2:
+				return mRoughMetalTex;
+			case RT_DEPTH_STENCIL:
+			case RT_DEPTH:
+				return mDepthTex;
+			}
+		}
+		case RTT_SceneColor:
+			return mSceneColorTex;
+		case RTT_LightAccumulation:
+			return mLightAccumulationTex;
+		case RTT_LightOcclusion:
+			return mLightOcclusionTex;
+		case RTT_ResolvedSceneColor:
+			return mResolvedSceneColorTex1;
+		case RTT_ResolvedSceneColorSecondary:
+			return mResolvedSceneColorTex1;
+		case RTT_HiZ:
+			return mHiZ;
+		case RTT_ResolvedDepth:
+			return mResolvedDepthTex;
+		case RTT_AmbientOcclusion:
+			return mAmbientOcclusionTex;
+		default:
+			return nullptr;
+		}
 	}
 	}
 
 
 	SPtr<GpuBuffer> RenderTargets::getSceneColorBuffer() const
 	SPtr<GpuBuffer> RenderTargets::getSceneColorBuffer() const
@@ -412,44 +489,8 @@ namespace bs { namespace ct
 		return mFlattenedSceneColorBuffer->buffer;
 		return mFlattenedSceneColorBuffer->buffer;
 	}
 	}
 
 
-	SPtr<Texture> RenderTargets::getLightAccumulation() const
-	{
-		return mLightAccumulationTex->texture;
-	}
-
-	SPtr<Texture> RenderTargets::getLightOcclusion() const
-	{
-		return mLightOcclusionTex->texture;
-	}
-
 	SPtr<GpuBuffer> RenderTargets::getLightAccumulationBuffer() const
 	SPtr<GpuBuffer> RenderTargets::getLightAccumulationBuffer() const
 	{
 	{
 		return mFlattenedLightAccumulationBuffer->buffer;
 		return mFlattenedLightAccumulationBuffer->buffer;
 	}
 	}
-
-	SPtr<Texture> RenderTargets::getResolvedSceneColor(bool secondary) const
-	{
-		if (secondary)
-			return mResolvedSceneColorTex2->texture;
-		else
-		{
-			if (mViewTarget.numSamples > 1)
-				return mResolvedSceneColorTex1->texture;
-			else
-				return mSceneColorTex->texture;
-		}
-	}
-
-	SPtr<RenderTarget> RenderTargets::getResolvedSceneColorRT(bool secondary) const
-	{
-		if (secondary)
-			return mResolvedSceneColorTex2->renderTexture;
-		else
-		{
-			if (mViewTarget.numSamples > 1)
-				return mResolvedSceneColorTex1->renderTexture;
-			else
-				return mSceneColorRT;
-		}
-	}
 }}
 }}

+ 2 - 2
Source/RenderBeast/Source/BsStandardDeferredLighting.cpp

@@ -33,7 +33,7 @@ namespace bs { namespace ct {
 		RendererUtility::instance().setPass(mMaterial, 0);
 		RendererUtility::instance().setPass(mMaterial, 0);
 
 
 		mGBufferParams.bind(renderTargets);
 		mGBufferParams.bind(renderTargets);
-		mLightOcclusionTexParam.set(renderTargets.getLightOcclusion());
+		mLightOcclusionTexParam.set(renderTargets.get(RTT_LightOcclusion));
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 	}
 	}
 
 
@@ -75,7 +75,7 @@ namespace bs { namespace ct {
 		RendererUtility::instance().setPass(mMaterial, 0);
 		RendererUtility::instance().setPass(mMaterial, 0);
 
 
 		mGBufferParams.bind(renderTargets);
 		mGBufferParams.bind(renderTargets);
-		mLightOcclusionTexParam.set(renderTargets.getLightOcclusion());
+		mLightOcclusionTexParam.set(renderTargets.get(RTT_LightOcclusion));
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 	}
 	}