Explorar o código

Added additional per-camera parameters required for deferred rendering

BearishSun %!s(int64=10) %!d(string=hai) anos
pai
achega
90c5f7e0dd

+ 23 - 0
RenderBeast/Include/BsRenderBeast.h

@@ -46,6 +46,21 @@ namespace BansheeEngine
 		float worldDeterminantSign;
 	};
 
+	/**
+	 * @brief	Data bound to the shader when rendering a with a specific camera.
+	 */
+	struct CameraShaderData
+	{
+		Vector3 viewDir;
+		Vector3 viewOrigin;
+		Matrix4 view;
+		Matrix4 proj;
+		Matrix4 viewProj;
+		Matrix4 invProj;
+		Vector2 deviceZToWorldZ;
+		Vector4 clipToUVScaleOffset;
+	};
+
 	/**
 	 * @copydoc	RenderableElement
 	 *
@@ -250,6 +265,14 @@ namespace BansheeEngine
 		 */
 		static Vector2 getDeviceZTransform(const Matrix4& projMatrix);
 
+		/**
+		 * @brief	Populates the provided camera shader data object with data from the provided camera. The object can
+		 * 			then be used for populating per-camera parameter buffers.
+		 * 			
+		 * @note	Core thread.
+		 */
+		static CameraShaderData getCameraShaderData(const CameraCore& camera);
+
 		/**
 		 * @brief	Activates the specified pass on the pipeline.
 		 *

+ 5 - 1
RenderBeast/Include/BsStaticRenderableHandler.h

@@ -16,9 +16,13 @@ namespace BansheeEngine
 
 	BS_PARAM_BLOCK_BEGIN(PerCameraParamBuffer)
 		BS_PARAM_BLOCK_ENTRY(Vector3, gViewDir)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gViewOrigin)
 		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
 		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatView)
 		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvProj)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gDeviceZToWorldZ)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gClipToUVScaleOffset)
 	BS_PARAM_BLOCK_END
 
 	BS_PARAM_BLOCK_BEGIN(PerObjectParamBuffer)
@@ -67,7 +71,7 @@ namespace BansheeEngine
 		 * @brief	Updates global per frame parameter buffers with new values. 
 		 *			To be called at the start of rendering for every camera.
 		 */
-		void updatePerCameraBuffers(const Matrix4& vpMatrix, const Matrix4& vMatrix, const Matrix4& pMatrix, const Vector3& viewDir);
+		void updatePerCameraBuffers(const CameraShaderData& cameraData);
 
 		/**
 		 * @brief	Updates object specific parameter buffers with new values.

+ 39 - 15
RenderBeast/Source/BsRenderBeast.cpp

@@ -485,14 +485,11 @@ namespace BansheeEngine
 	{
 		const CameraCore* camera = rtData.cameras[camIdx];
 		CameraData& camData = mCameraData[camera];
-		SPtr<ViewportCore> viewport = camera->getViewport();
-
-		Matrix4 projMatrix = camera->getProjectionMatrixRS();
-		Matrix4 viewMatrix = camera->getViewMatrix();
 
-		Matrix4 viewProjMatrix = projMatrix * viewMatrix;
+		SPtr<ViewportCore> viewport = camera->getViewport();
+		CameraShaderData cameraShaderData = getCameraShaderData(*camera);
 
-		mStaticHandler->updatePerCameraBuffers(viewProjMatrix, viewMatrix, projMatrix, camera->getForward());
+		mStaticHandler->updatePerCameraBuffers(cameraShaderData);
 
 		// Render scene objects to g-buffer if there are any
 		const Vector<RenderQueueElement>& opaqueElements = camData.opaqueQueue->getSortedElements();
@@ -528,7 +525,7 @@ namespace BansheeEngine
 				SPtr<MaterialCore> material = renderElem->material;
 
 				UINT32 rendererId = renderElem->renderableId;
-				Matrix4 worldViewProjMatrix = viewProjMatrix * mRenderableShaderData[rendererId].worldTransform;
+				Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
 
 				mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
 				mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
@@ -633,7 +630,7 @@ namespace BansheeEngine
 			SPtr<MaterialCore> material = renderElem->material;
 
 			UINT32 rendererId = renderElem->renderableId;
-			Matrix4 worldViewProjMatrix = viewProjMatrix * mRenderableShaderData[rendererId].worldTransform;
+			Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
 
 			mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
 			mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
@@ -678,10 +675,7 @@ namespace BansheeEngine
 		RenderAPICore& rs = RenderAPICore::instance();
 		CameraData& cameraData = mCameraData[&camera];
 
-		Matrix4 projMatrix = camera.getProjectionMatrixRS();
-		Matrix4 viewMatrix = camera.getViewMatrix();
-
-		Matrix4 viewProjMatrix = projMatrix * viewMatrix;
+		CameraShaderData cameraShaderData = getCameraShaderData(camera);
 
 		// Trigger pre-render callbacks
 		auto iterCameraCallbacks = mRenderCallbacks.find(&camera);
@@ -699,7 +693,7 @@ namespace BansheeEngine
 		// Render opaque
 
 		//// Update global per-frame hardware buffers
-		mStaticHandler->updatePerCameraBuffers(viewProjMatrix, viewMatrix, projMatrix, camera.getForward());
+		mStaticHandler->updatePerCameraBuffers(cameraShaderData);
 
 		// TODO - This bit can be removed once I fully switch to deferred
 		const Vector<RenderQueueElement>& opaqueElements = cameraData.opaqueQueue->getSortedElements();
@@ -709,7 +703,7 @@ namespace BansheeEngine
 			SPtr<MaterialCore> material = renderElem->material;
 
 			UINT32 rendererId = renderElem->renderableId;
-			Matrix4 worldViewProjMatrix = viewProjMatrix * mRenderableShaderData[rendererId].worldTransform;
+			Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
 
 			mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
 			mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
@@ -741,7 +735,7 @@ namespace BansheeEngine
 			SPtr<MaterialCore> material = renderElem->material;
 
 			UINT32 rendererId = renderElem->renderableId;
-			Matrix4 worldViewProjMatrix = viewProjMatrix * mRenderableShaderData[rendererId].worldTransform;
+			Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
 
 			mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
 			mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
@@ -837,6 +831,36 @@ namespace BansheeEngine
 		return output;
 	}
 
+	CameraShaderData RenderBeast::getCameraShaderData(const CameraCore& camera)
+	{
+		CameraShaderData data;
+		data.proj = camera.getProjectionMatrixRS();
+		data.view = camera.getViewMatrix();
+		data.viewProj = data.proj * data.view;
+		data.invProj = data.proj.inverse();
+		data.viewDir = camera.getForward();
+		data.viewOrigin = camera.getPosition();
+		data.deviceZToWorldZ = getDeviceZTransform(data.proj);
+
+		SPtr<ViewportCore> viewport = camera.getViewport();
+		SPtr<RenderTargetCore> rt = viewport->getTarget();
+
+		float halfWidth = viewport->getWidth() / 2.0f;
+		float halfHeight = viewport->getHeight() / 2.0f;
+
+		float rtWidth = (float)rt->getProperties().getWidth();
+		float rtHeight = (float)rt->getProperties().getHeight();
+
+		RenderAPICore& rapi = RenderAPICore::instance();
+
+		data.clipToUVScaleOffset.x = (halfWidth / 2.0f) / rtWidth;
+		data.clipToUVScaleOffset.y = (halfHeight / 2.0f) / rtHeight;
+		data.clipToUVScaleOffset.z = (viewport->getX() + halfWidth + rapi.getHorizontalTexelOffset()) / rtWidth;
+		data.clipToUVScaleOffset.w = (viewport->getY() + halfHeight + rapi.getHorizontalTexelOffset()) / rtHeight;
+
+		return data;
+	}
+
 	void RenderBeast::refreshSamplerOverrides(bool force)
 	{
 		for (auto& entry : mSamplerOverrides)

+ 9 - 5
RenderBeast/Source/BsStaticRenderableHandler.cpp

@@ -109,12 +109,16 @@ namespace BansheeEngine
 		mPerFrameParams.gTime.set(time);
 	}
 
-	void StaticRenderableHandler::updatePerCameraBuffers(const Matrix4& vpMatrix, const Matrix4& vMatrix, const Matrix4& pMatrix, const Vector3& viewDir)
+	void StaticRenderableHandler::updatePerCameraBuffers(const CameraShaderData& cameraData)
 	{
-		mPerCameraParams.gMatViewProj.set(vpMatrix);
-		mPerCameraParams.gMatView.set(vMatrix);
-		mPerCameraParams.gMatProj.set(pMatrix);
-		mPerCameraParams.gViewDir.set(viewDir);
+		mPerCameraParams.gViewDir.set(cameraData.viewDir);
+		mPerCameraParams.gViewOrigin.set(cameraData.viewOrigin);
+		mPerCameraParams.gMatView.set(cameraData.view);
+		mPerCameraParams.gMatProj.set(cameraData.proj);
+		mPerCameraParams.gMatViewProj.set(cameraData.viewProj);
+		mPerCameraParams.gMatViewProj.set(cameraData.invProj);
+		mPerCameraParams.gDeviceZToWorldZ.set(cameraData.deviceZToWorldZ);
+		mPerCameraParams.gClipToUVScaleOffset.set(cameraData.clipToUVScaleOffset);
 	}
 
 	void StaticRenderableHandler::updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix)