Browse Source

Added a shader for rendering light probe tetrahedrons

BearishSun 8 years ago
parent
commit
4096b350c8

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

@@ -347,8 +347,8 @@
             "UUID": "86b9699c-162d-4729-9985-c94e0f45bacb"
         },
         {
-            "Path": "TetrahedronRender.bsl",
-            "UUID": "0ea10201-ae22-4a64-bd09-06f8b4a35d9a"
+            "Path": "TetrahedraRender.bsl",
+            "UUID": "5912b0ab-b2be-4c0e-a039-91fcc2d3e536"
         }
     ],
     "Skin": [

+ 72 - 0
Data/Raw/Engine/Shaders/TetrahedraRender.bsl

@@ -0,0 +1,72 @@
+technique TetrahedraRender
+{
+	raster
+	{
+		cull = cw;
+	};
+
+	code
+	{
+		struct VertexInput
+		{
+			float3 position : POSITION;
+			uint index : TEXCOORD0;			
+		};		
+	
+		struct VStoFS
+		{
+			float4 position : SV_Position;
+			uint index : TEXCOORD0;
+		};
+		
+		cbuffer Params
+		{
+			float4x4 gMatViewProj;
+			float4 gNDCToUV;
+			float2 gNDCToDeviceZ;
+		};
+		
+		VStoFS vsmain(VertexInput input)
+		{
+			VStoFS output;
+		
+			output.position = mul(gMatViewProj, float4(input.position, 1.0f));
+			output.index = input.index;
+			
+			return output;
+		}
+		
+		#ifndef MSAA
+			#define MSAA 0
+		#endif
+
+		#if MSAA
+		Texture2DMS<float> gDepthBufferTex;
+		#else
+		Texture2D gDepthBufferTex;
+		SamplerState gDepthBufferSamp;
+		#endif		
+		
+		uint fsmain(VStoFS input
+		#if MSAA
+			,uint sampleIdx : SV_SampleIndex
+		#endif
+		) : SV_Target0
+		{
+			float2 uv = input.position.xy * gNDCToUV.xy + gNDCToUV.zw;
+			
+			float sceneDepth;
+			#if MSAA
+				sceneDepth = gDepthBufferTex.Load(trunc(uv), sampleIdx);
+			#else
+				sceneDepth = gDepthBufferTex.Sample(gDepthBufferSamp, uv);
+			#endif
+			
+			float currentDepth = input.position.z * gNDCToDeviceZ.x + gNDCToDeviceZ.y;
+			if(currentDepth < sceneDepth)
+				discard;
+				
+			return input.index;
+		}
+	};
+};

+ 2 - 2
Source/BansheeCore/Source/BsResources.cpp

@@ -43,7 +43,7 @@ namespace bs
 	{
 		if (!FileSystem::isFile(filePath))
 		{
-			LOGWRN_VERBOSE("Cannot load resource. Specified file: " + filePath.toString() + " doesn't exist.");
+			LOGWRN("Cannot load resource. Specified file: " + filePath.toString() + " doesn't exist.");
 
 			return HResource();
 		}
@@ -70,7 +70,7 @@ namespace bs
 	{
 		if (!FileSystem::isFile(filePath))
 		{
-			LOGWRN_VERBOSE("Cannot load resource. Specified file: " + filePath.toString() + " doesn't exist.");
+			LOGWRN("Cannot load resource. Specified file: " + filePath.toString() + " doesn't exist.");
 
 			return HResource();
 		}

+ 50 - 0
Source/RenderBeast/Include/BsLightProbes.h

@@ -6,6 +6,9 @@
 #include "BsTriangulation.h"
 #include "BsMatrix4.h"
 #include "BsMatrixNxM.h"
+#include "BsRendererMaterial.h"
+#include "BsGpuResourcePool.h"
+#include "BsParamBlocks.h"
 
 namespace bs { namespace ct
 {
@@ -16,6 +19,53 @@ namespace bs { namespace ct
 	 *  @{
 	 */
 
+	BS_PARAM_BLOCK_BEGIN(TetrahedraRenderParamDef)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gNDCToUV)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gNDCToDeviceZ)
+	BS_PARAM_BLOCK_END
+
+	extern TetrahedraRenderParamDef gTetrahedraRenderParamDef;
+
+	/** 
+	 * Shader that renders the tetrahedra used for light probe evaluation. Tetrahedra depth is compare with current scene
+	 * depth, and for each scene pixel the matching tetrahedron index is written to the output target.
+	 */
+	class TetrahedraRenderMat : public RendererMaterial<TetrahedraRenderMat>
+	{
+		RMAT_DEF("TetrahedraRender.bsl");
+
+	public:
+		TetrahedraRenderMat();
+
+		/**
+		 * Executes the material using the provided parameters.
+		 * 
+		 * @param[in]	view		View that is currently being rendered.
+		 * @param[in]	sceneDepth	Depth of scene objects that should be lit.
+		 * @param[in]	mesh		Mesh to render.
+		 * @param[in]	output		Output texture created using the descriptor returned by getOutputDesc().
+		 */
+		void execute(const RendererView& view, const SPtr<Texture>& sceneDepth, const SPtr<Mesh>& mesh, 
+			const SPtr<RenderTexture>& output);
+
+		/**
+		 * Returns the descriptors that can be used for creating the output render texture for this material. The render
+		 * texture is expected to have a single color attachment, and a depth attachment. 
+		 */
+		static void getOutputDesc(const RendererView& view, POOLED_RENDER_TEXTURE_DESC& colorDesc, 
+			POOLED_RENDER_TEXTURE_DESC& depthDesc);
+
+		/** Returns the material variation matching the provided parameters. */
+		static TetrahedraRenderMat* getVariation(bool msaa);
+	private:
+		SPtr<GpuParamBlockBuffer> mParamBuffer;
+		GpuParamTexture mDepthBufferTex;
+
+		static ShaderVariation VAR_NoMSAA;
+		static ShaderVariation VAR_MSAA;
+	};
+
 	/** Handles any pre-processing for light (irradiance) probe lighting. */
 	class LightProbes
 	{

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

@@ -303,6 +303,14 @@ namespace bs { namespace ct
 		/** Updates the light grid used for forward rendering. */
 		void updateLightGrid(const VisibleLightData& visibleLightData, const VisibleReflProbeData& visibleReflProbeData);
 
+		/**
+		 * Returns a value that can be used for transforming x, y coordinates from NDC into UV coordinates that can be used
+		 * for sampling a texture projected on the view.
+		 *
+		 * @return	Returns two 2D values that can be used to transform the coordinate as such: UV = NDC * xy + zw.
+		 */
+		Vector4 getNDCToUV() const;
+
 		/**
 		 * Extracts the necessary values from the projection matrix that allow you to transform device Z value (range [0, 1]
 		 * into view Z value.

+ 91 - 1
Source/RenderBeast/Source/BsLightProbes.cpp

@@ -5,12 +5,102 @@
 #include "BsGpuBuffer.h"
 #include "BsRendererView.h"
 #include "BsRenderBeastIBLUtility.h"
-#include "BsRenderBeast.h"
 #include "BsMesh.h"
 #include "BsVertexDataDesc.h"
+#include "BsGpuParamsSet.h"
+#include "BsRendererUtility.h"
 
 namespace bs { namespace ct 
 {
+	TetrahedraRenderParamDef gTetrahedraRenderParamDef;
+
+	ShaderVariation TetrahedraRenderMat::VAR_NoMSAA = ShaderVariation({
+		ShaderVariation::Param("MSAA", false)
+	});
+
+	ShaderVariation TetrahedraRenderMat::VAR_MSAA = ShaderVariation({
+		ShaderVariation::Param("MSAA", true)
+	});
+
+	TetrahedraRenderMat::TetrahedraRenderMat()
+	{
+		SPtr<GpuParams> params = mParamsSet->getGpuParams();
+
+		params->getTextureParam(GPT_FRAGMENT_PROGRAM, "gDepthBufferTex", mDepthBufferTex);
+
+		if(params->hasSamplerState(GPT_FRAGMENT_PROGRAM, "gDepthBufferSamp"))
+		{
+			SAMPLER_STATE_DESC pointSampDesc;
+			pointSampDesc.minFilter = FO_POINT;
+			pointSampDesc.magFilter = FO_POINT;
+			pointSampDesc.mipFilter = FO_POINT;
+			pointSampDesc.addressMode.u = TAM_CLAMP;
+			pointSampDesc.addressMode.v = TAM_CLAMP;
+			pointSampDesc.addressMode.w = TAM_CLAMP;
+
+			SPtr<SamplerState> pointSampState = SamplerState::create(pointSampDesc);
+			params->setSamplerState(GPT_FRAGMENT_PROGRAM, "gDepthBufferSamp", pointSampState);
+		}
+
+		mParamBuffer = gTetrahedraRenderParamDef.createBuffer();
+		mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
+	}
+
+	void TetrahedraRenderMat::_initVariations(ShaderVariations& variations)
+	{
+		variations.add(VAR_NoMSAA);
+		variations.add(VAR_MSAA);
+	}
+
+	void TetrahedraRenderMat::execute(const RendererView& view, const SPtr<Texture>& sceneDepth, const SPtr<Mesh>& mesh, 
+		const SPtr<RenderTexture>& output)
+	{
+		const RendererViewProperties& viewProps = view.getProperties();
+
+		Vector4 NDCtoUV = view.getNDCToUV();
+		if(mVariation.getBool("MSAA"))
+		{
+			NDCtoUV.x *= viewProps.viewRect.width;
+			NDCtoUV.y *= viewProps.viewRect.height;
+			NDCtoUV.z *= viewProps.viewRect.width;
+			NDCtoUV.w *= viewProps.viewRect.height;
+		}
+
+		gTetrahedraRenderParamDef.gMatViewProj.set(mParamBuffer, viewProps.viewProjTransform);
+		gTetrahedraRenderParamDef.gNDCToUV.set(mParamBuffer, NDCtoUV);
+		gTetrahedraRenderParamDef.gNDCToDeviceZ.set(mParamBuffer, RendererView::getNDCZToDeviceZ());
+		
+		mDepthBufferTex.set(sceneDepth);
+		mParamBuffer->flushToGPU();
+
+		RenderAPI& rapi = RenderAPI::instance();
+		rapi.setRenderTarget(output);
+
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
+		gRendererUtility().draw(mesh);
+	}
+
+	void TetrahedraRenderMat::getOutputDesc(const RendererView& view, POOLED_RENDER_TEXTURE_DESC& colorDesc, 
+		POOLED_RENDER_TEXTURE_DESC& depthDesc)
+	{
+		const RendererViewProperties& viewProps = view.getProperties();
+		UINT32 width = viewProps.viewRect.width;
+		UINT32 height = viewProps.viewRect.height;
+		UINT32 numSamples = viewProps.numSamples;
+
+		colorDesc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R16I, width, height, TU_RENDERTARGET, numSamples);
+		depthDesc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_D16, width, height, TU_DEPTHSTENCIL, numSamples);
+	}
+
+	TetrahedraRenderMat* TetrahedraRenderMat::getVariation(bool msaa)
+	{
+		if (msaa)
+			return get(VAR_MSAA);
+
+		return get(VAR_NoMSAA);
+	}
+
 	LightProbes::LightProbes()
 		:mTetrahedronVolumeDirty(false), mMaxCoefficients(0), mMaxTetrahedra(0)
 	{

+ 22 - 13
Source/RenderBeast/Source/BsRendererView.cpp

@@ -395,7 +395,6 @@ namespace bs { namespace ct
 	void RendererView::updatePerViewBuffer()
 	{
 		RenderAPI& rapi = RenderAPI::instance();
-		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
 
 		Matrix4 viewProj = mProperties.projTransform * mProperties.viewTransform;
 		Matrix4 invViewProj = viewProj.inverse();
@@ -438,28 +437,38 @@ namespace bs { namespace ct
 
 		gPerCameraParamDef.gViewportRectangle.set(mParamBuffer, viewportRect);
 
+		Vector4 ndcToUV = getNDCToUV();
+		gPerCameraParamDef.gClipToUVScaleOffset.set(mParamBuffer, ndcToUV);
+
+		if (!mRenderSettings->enableLighting)
+			gPerCameraParamDef.gAmbientFactor.set(mParamBuffer, 100.0f);
+		else
+			gPerCameraParamDef.gAmbientFactor.set(mParamBuffer, 0.0f);
+	}
+
+	Vector4 RendererView::getNDCToUV() const
+	{
+		RenderAPI& rapi = RenderAPI::instance();
+		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
+		const Rect2I& viewRect = mTargetDesc.viewRect;
+		
 		float halfWidth = viewRect.width * 0.5f;
 		float halfHeight = viewRect.height * 0.5f;
 
 		float rtWidth = mTargetDesc.targetWidth != 0 ? (float)mTargetDesc.targetWidth : 20.0f;
 		float rtHeight = mTargetDesc.targetHeight != 0 ? (float)mTargetDesc.targetHeight : 20.0f;
 
-		Vector4 clipToUVScaleOffset;
-		clipToUVScaleOffset.x = halfWidth / rtWidth;
-		clipToUVScaleOffset.y = -halfHeight / rtHeight;
-		clipToUVScaleOffset.z = viewRect.x / rtWidth + (halfWidth + rapiInfo.getHorizontalTexelOffset()) / rtWidth;
-		clipToUVScaleOffset.w = viewRect.y / rtHeight + (halfHeight + rapiInfo.getVerticalTexelOffset()) / rtHeight;
+		Vector4 ndcToUV;
+		ndcToUV.x = halfWidth / rtWidth;
+		ndcToUV.y = -halfHeight / rtHeight;
+		ndcToUV.z = viewRect.x / rtWidth + (halfWidth + rapiInfo.getHorizontalTexelOffset()) / rtWidth;
+		ndcToUV.w = viewRect.y / rtHeight + (halfHeight + rapiInfo.getVerticalTexelOffset()) / rtHeight;
 
 		// Either of these flips the Y axis, but if they're both true they cancel out
 		if (rapiInfo.isFlagSet(RenderAPIFeatureFlag::UVYAxisUp) ^ rapiInfo.isFlagSet(RenderAPIFeatureFlag::NDCYAxisDown))
-			clipToUVScaleOffset.y = -clipToUVScaleOffset.y;
-
-		gPerCameraParamDef.gClipToUVScaleOffset.set(mParamBuffer, clipToUVScaleOffset);
+			ndcToUV.y = -ndcToUV.y;
 
-		if (!mRenderSettings->enableLighting)
-			gPerCameraParamDef.gAmbientFactor.set(mParamBuffer, 100.0f);
-		else
-			gPerCameraParamDef.gAmbientFactor.set(mParamBuffer, 0.0f);
+		return ndcToUV;
 	}
 
 	void RendererView::updateLightGrid(const VisibleLightData& visibleLightData,