Browse Source

Adding more per-object parameters for rendering

BearishSun 10 years ago
parent
commit
6138f391bf

+ 4 - 0
BansheeCore/Include/BsCoreRenderer.h

@@ -26,6 +26,10 @@ namespace BansheeEngine
 	static StringID RPS_ProjTfrm = "P";
 	static StringID RPS_ViewTfrm = "V";
 	static StringID RPS_WorldTfrm = "W";
+	static StringID RPS_InvWorldTfrm = "IW";
+	static StringID RPS_WorldNoScaleTfrm = "WNoScale";
+	static StringID RPS_InvWorldNoScaleTfrm = "IWNoScale";
+	static StringID RPS_WorldDeterminantSign = "WorldDeterminantSign";
 	static StringID RPS_Diffuse = "Diffuse";
 	static StringID RPS_ViewDir = "ViewDir";
 

+ 1 - 1
BansheeEditorExec/BsEditorExec.cpp

@@ -72,7 +72,7 @@ int CALLBACK WinMain(
 
 	__try
 	{
-		EditorApplication::startUp(RenderAPIPlugin::DX11);
+		EditorApplication::startUp(RenderAPIPlugin::OpenGL);
 		EditorApplication::instance().runMainLoop();
 		EditorApplication::shutDown();
 	}

+ 7 - 0
BansheeEngine/Include/BsRenderable.h

@@ -122,6 +122,13 @@ namespace BansheeEngine
 		 */
 		Matrix4 getTransform() const { return mTransform; }
 
+		/**
+		 * @brief	Returns the transform matrix that is applied to the object
+		 *			when its being rendered. This transform matrix does not
+		 *			include scale values.
+		 */
+		Matrix4 getTransformNoScale() const { return mTransform; /* TODO - Not implemented. */ }
+
 		/**
 		 * @brief	Gets whether the object should be rendered or not.
 		 */

+ 5 - 0
BansheeUtility/Include/BsMatrix4.h

@@ -270,6 +270,11 @@ namespace BansheeEngine
 		 */
 		float determinant() const;
 
+		/**
+		 * @brief	Calculates the determinant of the 3x3 sub-matrix.
+		 */
+		float determinant3x3() const;
+
 		/**
 		 * @brief	Calculates the inverse of the matrix.
 		 */

+ 11 - 0
BansheeUtility/Source/BsMatrix4.cpp

@@ -57,6 +57,17 @@ namespace BansheeEngine
             m[0][3] * MINOR(*this, 1, 2, 3, 0, 1, 2);
     }
 
+	float Matrix4::determinant3x3() const
+	{
+		float cofactor00 = m[1][1] * m[2][2] - m[1][2] * m[2][1];
+		float cofactor10 = m[1][2] * m[2][0] - m[1][0] * m[2][2];
+		float cofactor20 = m[1][0] * m[2][1] - m[1][1] * m[2][0];
+
+		float det = m[0][0] * cofactor00 + m[0][1] * cofactor10 + m[0][2] * cofactor20;
+
+		return det;
+	}
+
     Matrix4 Matrix4::inverse() const
     {
         float m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], m03 = m[0][3];

+ 13 - 1
RenderBeast/Include/BsRenderBeast.h

@@ -26,6 +26,18 @@ namespace BansheeEngine
 		RenderableHandler* controller;
 	};
 
+	/**
+	 * @brief	Data bound to the shader when rendering a specific renderable.
+	 */
+	struct RenderableShaderData
+	{
+		Matrix4 worldTransform;
+		Matrix4 invWorldTransform;
+		Matrix4 worldNoScaleTransform;
+		Matrix4 invWorldNoScaleTransform;
+		float worldDeterminantSign;
+	};
+
 	/**
 	 * @copydoc	RenderableElement
 	 *
@@ -261,7 +273,7 @@ namespace BansheeEngine
 		SPtr<MaterialCore> mDummyMaterial; // Core thread
 
 		Vector<RenderableData> mRenderables; // Core thread
-		Vector<Matrix4> mWorldTransforms; // Core thread
+		Vector<RenderableShaderData> mRenderableShaderData; // Core thread
 		Vector<Bounds> mWorldBounds; // Core thread
 
 		Vector<LightData> mLights; // Core thread

+ 13 - 3
RenderBeast/Include/BsStaticRenderableHandler.h

@@ -5,6 +5,7 @@
 #include "BsGpuParamDesc.h"
 #include "BsGpuParam.h"
 #include "BsRenderableElement.h"
+#include "BsRenderBeast.h"
 
 namespace BansheeEngine
 {
@@ -22,6 +23,10 @@ namespace BansheeEngine
 		{
 			GpuParamMat4Core wvpParam;
 			GpuParamMat4Core wParam;
+			GpuParamMat4Core iwParam;
+			GpuParamMat4Core wNoScaleParam;
+			GpuParamMat4Core iwNoScaleParam;
+			GpuParamFloatCore worldDeterminantSignParam;
 
 			Vector<RenderableElement::BufferBindInfo> perObjectBuffers;
 		};
@@ -54,7 +59,7 @@ namespace BansheeEngine
 		 * @brief	Updates object specific parameter buffers with new values.
 		 *			To be called whenever object specific values change.
 		 */
-		void updatePerObjectBuffers(RenderableElement& element, const Matrix4& worldMatrix, const Matrix4& wvpMatrix);
+		void updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix);
 
 	protected:
 		/**
@@ -72,13 +77,18 @@ namespace BansheeEngine
 		GpuParamBlockDesc perObjectParamBlockDesc;
 
 		GpuParamDataDesc timeParamDesc;
-		GpuParamDataDesc wvpParamDesc;
 		GpuParamDataDesc vpParamDesc;
-		GpuParamDataDesc wParamDesc;
 		GpuParamDataDesc vParamDesc;
 		GpuParamDataDesc pParamDesc;
 		GpuParamDataDesc viewDirParamDesc;
 
+		GpuParamDataDesc wvpParamDesc;
+		GpuParamDataDesc wParamDesc;
+		GpuParamDataDesc iwParamDesc;
+		GpuParamDataDesc wNoScaleParamDesc;
+		GpuParamDataDesc iwNoScaleParamDesc;
+		GpuParamDataDesc worldDeterminantSignParamDesc;
+
 		SPtr<GpuParamBlockBufferCore> perFrameParamBuffer;
 		SPtr<GpuParamBlockBufferCore> perCameraParamBuffer;
 		SPtr<GpuParamBlockBufferCore> perObjectParamBuffer;

+ 41 - 15
RenderBeast/Source/BsRenderBeast.cpp

@@ -99,12 +99,19 @@ namespace BansheeEngine
 		renderable->setRendererId(renderableId);
 
 		mRenderables.push_back(RenderableData());
-		mWorldTransforms.push_back(renderable->getTransform());
+		mRenderableShaderData.push_back(RenderableShaderData());
 		mWorldBounds.push_back(renderable->getBounds());
 
 		RenderableData& renderableData = mRenderables.back();
 		renderableData.renderable = renderable;
 
+		RenderableShaderData& shaderData = mRenderableShaderData.back();
+		shaderData.worldTransform = renderable->getTransform();
+		shaderData.invWorldTransform = shaderData.worldTransform.inverseAffine();
+		shaderData.worldNoScaleTransform = renderable->getTransformNoScale();
+		shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
+		shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
+
 		if (renderable->getRenderableType() == RenType_LitTextured)
 			renderableData.controller = mStaticHandler;
 		else
@@ -179,7 +186,7 @@ namespace BansheeEngine
 			// Swap current last element with the one we want to erase
 			std::swap(mRenderables[renderableId], mRenderables[lastRenderableId]);
 			std::swap(mWorldBounds[renderableId], mWorldBounds[lastRenderableId]);
-			std::swap(mWorldTransforms[renderableId], mWorldTransforms[lastRenderableId]);
+			std::swap(mRenderableShaderData[renderableId], mRenderableShaderData[lastRenderableId]);
 
 			lastRenerable->setRendererId(renderableId);
 
@@ -191,14 +198,20 @@ namespace BansheeEngine
 		// Last element is the one we want to erase
 		mRenderables.erase(mRenderables.end() - 1);
 		mWorldBounds.erase(mWorldBounds.end() - 1);
-		mWorldTransforms.erase(mWorldTransforms.end() - 1);
+		mRenderableShaderData.erase(mRenderableShaderData.end() - 1);
 	}
 
 	void RenderBeast::_notifyRenderableUpdated(RenderableCore* renderable)
 	{
 		UINT32 renderableId = renderable->getRendererId();
 
-		mWorldTransforms[renderableId] = renderable->getTransform();
+		RenderableShaderData& shaderData = mRenderableShaderData[renderableId];
+		shaderData.worldTransform = renderable->getTransform();
+		shaderData.invWorldTransform = shaderData.worldTransform.inverseAffine();
+		shaderData.worldNoScaleTransform = renderable->getTransformNoScale();
+		shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
+		shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
+
 		mWorldBounds[renderableId] = renderable->getBounds();
 	}
 
@@ -468,9 +481,9 @@ namespace BansheeEngine
 				SPtr<MaterialCore> material = renderElem->material;
 
 				UINT32 rendererId = renderElem->renderableId;
-				Matrix4 worldViewProjMatrix = viewProjMatrix * mWorldTransforms[rendererId];
+				Matrix4 worldViewProjMatrix = viewProjMatrix * mRenderableShaderData[rendererId].worldTransform;
 
-				mStaticHandler->updatePerObjectBuffers(*renderElem, mWorldTransforms[rendererId], worldViewProjMatrix);
+				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
 				mStaticHandler->bindPerObjectBuffers(*renderElem);
 
@@ -546,9 +559,9 @@ namespace BansheeEngine
 			SPtr<MaterialCore> material = renderElem->material;
 
 			UINT32 rendererId = renderElem->renderableId;
-			Matrix4 worldViewProjMatrix = viewProjMatrix * mWorldTransforms[rendererId];
+			Matrix4 worldViewProjMatrix = viewProjMatrix * mRenderableShaderData[rendererId].worldTransform;
 
-			mStaticHandler->updatePerObjectBuffers(*renderElem, mWorldTransforms[rendererId], worldViewProjMatrix);
+			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
 			mStaticHandler->bindPerObjectBuffers(*renderElem);
 
@@ -622,9 +635,9 @@ namespace BansheeEngine
 			SPtr<MaterialCore> material = renderElem->material;
 
 			UINT32 rendererId = renderElem->renderableId;
-			Matrix4 worldViewProjMatrix = viewProjMatrix * mWorldTransforms[rendererId];
+			Matrix4 worldViewProjMatrix = viewProjMatrix * mRenderableShaderData[rendererId].worldTransform;
 
-			mStaticHandler->updatePerObjectBuffers(*renderElem, mWorldTransforms[rendererId], worldViewProjMatrix);
+			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
 			mStaticHandler->bindPerObjectBuffers(*renderElem);
 
@@ -654,9 +667,9 @@ namespace BansheeEngine
 			SPtr<MaterialCore> material = renderElem->material;
 
 			UINT32 rendererId = renderElem->renderableId;
-			Matrix4 worldViewProjMatrix = viewProjMatrix * mWorldTransforms[rendererId];
+			Matrix4 worldViewProjMatrix = viewProjMatrix * mRenderableShaderData[rendererId].worldTransform;
 
-			mStaticHandler->updatePerObjectBuffers(*renderElem, mWorldTransforms[rendererId], worldViewProjMatrix);
+			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
 			mStaticHandler->bindPerObjectBuffers(*renderElem);
 
@@ -942,6 +955,10 @@ namespace BansheeEngine
 				{
 					float4x4 gMatWorldViewProj;
 					float4x4 gMatWorld;
+					float4x4 gMatInvWorld;
+					float4x4 gMatWorldNoScale;
+					float4x4 gMatInvWorldNoScale;
+					float gWorldDeterminantSign;
 				}
 
 				void vs_main(
@@ -979,9 +996,14 @@ namespace BansheeEngine
 		else if (rsName == RenderAPIDX9)
 		{
 			String vsCode = R"(
-				 BS_PARAM_BLOCK PerObject { gMatWorldViewProj, gMatWorld }
-				 float4x4 gMatWorldViewProj;
-				 float4x4 gMatWorld;
+				BS_PARAM_BLOCK PerObject { gMatWorldViewProj, gMatWorld, gMatInvWorld, gMatWorldNoScale, gMatInvWorldNoScale, gMatWorldDeterminantSign }
+
+				float4x4 gMatWorldViewProj;
+				float4x4 gMatWorld;
+				float4x4 gMatInvWorld;
+				float4x4 gMatWorldNoScale;
+				float4x4 gMatInvWorldNoScale;
+				float gWorldDeterminantSign;
 
 				 void vs_main(
 					in float3 inPos : POSITION,
@@ -1020,6 +1042,10 @@ namespace BansheeEngine
 				{
 					mat4 gMatWorldViewProj;
 					mat4 gMatWorld;
+					mat4 gMatInvWorld;
+					mat4 gMatWorldNoScale;
+					mat4 gMatInvWorldNoScale;
+					float gWorldDeterminantSign;
 				};
 
 				in vec3 bs_position;

+ 139 - 11
RenderBeast/Source/BsStaticRenderableHandler.cpp

@@ -25,13 +25,20 @@ namespace BansheeEngine
 		GpuParamDescPtr perObjectParamsDesc = bs_shared_ptr_new<GpuParamDesc>();
 		GpuParamDescPtr perCameraParamsDesc = bs_shared_ptr_new<GpuParamDesc>();
 
+		// TODO - Refactor this code so it is less redundant
 		bool foundTime = false;
-		bool foundWVP = false;
 		bool foundVP = false;
-		bool foundW = false;
 		bool foundV = false;
 		bool foundP = false;
 		bool foundViewDir = false;
+
+		bool foundWVP = false;
+		bool foundW = false;
+		bool foundIW = false;
+		bool foundWNoScale = false;
+		bool foundIWNoScale = false;
+		bool foundWorldDeterminantSign = false;
+
 		bool foundPerFrame = false;
 		bool foundPerObject = false;
 		bool foundPerCamera = false;
@@ -69,6 +76,46 @@ namespace BansheeEngine
 				perObjectParamsDesc->params[iterFind->first] = iterFind->second;
 				foundW = true;
 			}
+			else if (!foundIW && param.second.rendererSemantic == RPS_InvWorldTfrm)
+			{
+				auto iterFind = vertParamDesc->params.find(param.second.gpuVariableName);
+				if (iterFind == vertParamDesc->params.end())
+					continue;
+
+				iwParamDesc = iterFind->second;
+				perObjectParamsDesc->params[iterFind->first] = iterFind->second;
+				foundIW = true;
+			}
+			else if (!foundWNoScale && param.second.rendererSemantic == RPS_WorldNoScaleTfrm)
+			{
+				auto iterFind = vertParamDesc->params.find(param.second.gpuVariableName);
+				if (iterFind == vertParamDesc->params.end())
+					continue;
+
+				wNoScaleParamDesc = iterFind->second;
+				perObjectParamsDesc->params[iterFind->first] = iterFind->second;
+				foundWNoScale = true;
+			}
+			else if (!foundIWNoScale && param.second.rendererSemantic == RPS_InvWorldNoScaleTfrm)
+			{
+				auto iterFind = vertParamDesc->params.find(param.second.gpuVariableName);
+				if (iterFind == vertParamDesc->params.end())
+					continue;
+
+				iwNoScaleParamDesc = iterFind->second;
+				perObjectParamsDesc->params[iterFind->first] = iterFind->second;
+				foundIWNoScale = true;
+			}
+			else if (!foundWorldDeterminantSign && param.second.rendererSemantic == RPS_WorldDeterminantSign)
+			{
+				auto iterFind = vertParamDesc->params.find(param.second.gpuVariableName);
+				if (iterFind == vertParamDesc->params.end())
+					continue;
+
+				worldDeterminantSignParamDesc = iterFind->second;
+				perObjectParamsDesc->params[iterFind->first] = iterFind->second;
+				foundWorldDeterminantSign = true;
+			}
 			else if (!foundVP && param.second.rendererSemantic == RPS_ViewProjTfrm)
 			{
 				auto iterFind = fragParamDesc->params.find(param.second.gpuVariableName);
@@ -146,8 +193,11 @@ namespace BansheeEngine
 			}
 		}
 
-		if (!foundTime || !foundWVP || !foundVP || !foundW || !foundV || !foundP || !foundViewDir || !foundPerFrame || !foundPerCamera || !foundPerObject)
+		if (!foundTime || !foundWVP || !foundVP || !foundW || !foundIW || !foundWNoScale || !foundIWNoScale || !foundWorldDeterminantSign
+			| !foundV || !foundP || !foundViewDir || !foundPerFrame || !foundPerCamera || !foundPerObject)
+		{
 			BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+		}
 
 		// Create global GPU param buffers and get parameter handles
 		perFrameParams = GpuParamsCore::create(perFrameParamsDesc, false);
@@ -190,6 +240,10 @@ namespace BansheeEngine
 
 		String wvpParamName;
 		String wParamName;
+		String iwParamName;
+		String wNoScaleParamName;
+		String iwNoScaleParamName;
+		String worldDeterminanemtSignParamName;
 
 		for (auto& paramBlockDesc : paramBlockDescs)
 		{
@@ -201,12 +255,21 @@ namespace BansheeEngine
 				perObjectBlockName = paramBlockDesc.second.name;
 		}
 
+		// TODO - Refactor this code so it is less redundant
 		for (auto& paramDesc : dataParamDescs)
 		{
 			if (paramDesc.second.rendererSemantic == RPS_WorldViewProjTfrm)
 				wvpParamName = paramDesc.second.gpuVariableName;
 			else if (paramDesc.second.rendererSemantic == RPS_WorldTfrm)
 				wParamName = paramDesc.second.gpuVariableName;
+			else if (paramDesc.second.rendererSemantic == RPS_InvWorldTfrm)
+				iwParamName = paramDesc.second.gpuVariableName;
+			else if (paramDesc.second.rendererSemantic == RPS_WorldNoScaleTfrm)
+				wNoScaleParamName = paramDesc.second.gpuVariableName;
+			else if (paramDesc.second.rendererSemantic == RPS_InvWorldNoScaleTfrm)
+				iwNoScaleParamName = paramDesc.second.gpuVariableName;
+			else if (paramDesc.second.rendererSemantic == RPS_WorldDeterminantSign)
+				worldDeterminanemtSignParamName = paramDesc.second.gpuVariableName;
 		}
 
 		UINT32 numPasses = element.material->getNumPasses();
@@ -278,6 +341,46 @@ namespace BansheeEngine
 										gpuParams->getParam(wParamName, rendererData->wParam);
 								}
 							}
+
+							if (rendererData->iwParam == nullptr && iwParamName != "")
+							{
+								auto findIter2 = paramsDesc.params.find(iwParamName);
+								if (findIter2 != paramsDesc.params.end())
+								{
+									if (paramsMatch(findIter2->second, iwParamDesc))
+										gpuParams->getParam(iwParamName, rendererData->iwParam);
+								}
+							}
+
+							if (rendererData->wNoScaleParam == nullptr && wNoScaleParamName != "")
+							{
+								auto findIter2 = paramsDesc.params.find(wNoScaleParamName);
+								if (findIter2 != paramsDesc.params.end())
+								{
+									if (paramsMatch(findIter2->second, wNoScaleParamDesc))
+										gpuParams->getParam(wNoScaleParamName, rendererData->wNoScaleParam);
+								}
+							}
+
+							if (rendererData->iwNoScaleParam == nullptr && iwNoScaleParamName != "")
+							{
+								auto findIter2 = paramsDesc.params.find(iwNoScaleParamName);
+								if (findIter2 != paramsDesc.params.end())
+								{
+									if (paramsMatch(findIter2->second, iwNoScaleParamDesc))
+										gpuParams->getParam(iwNoScaleParamName, rendererData->iwNoScaleParam);
+								}
+							}
+
+							if (rendererData->worldDeterminantSignParam == nullptr && worldDeterminanemtSignParamName != "")
+							{
+								auto findIter2 = paramsDesc.params.find(worldDeterminanemtSignParamName);
+								if (findIter2 != paramsDesc.params.end())
+								{
+									if (paramsMatch(findIter2->second, worldDeterminantSignParamDesc))
+										gpuParams->getParam(worldDeterminanemtSignParamName, rendererData->worldDeterminantSignParam);
+								}
+							}
 						}
 					}
 				}
@@ -313,11 +416,16 @@ namespace BansheeEngine
 		perCameraParams->updateHardwareBuffers();
 	}
 
-	void StaticRenderableHandler::updatePerObjectBuffers(RenderableElement& element, const Matrix4& worldMatrix, const Matrix4& wvpMatrix)
+	void StaticRenderableHandler::updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix)
 	{
 		PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
 
-		rendererData->wParam.set(worldMatrix);
+		// TODO - If I kept all the values in the same structure maybe a simple memcpy directly into the constant buffer would be better (i.e. faster)?
+		rendererData->wParam.set(data.worldTransform);
+		rendererData->iwParam.set(data.invWorldTransform);
+		rendererData->wNoScaleParam.set(data.worldNoScaleTransform);
+		rendererData->iwNoScaleParam.set(data.invWorldNoScaleTransform);
+		rendererData->worldDeterminantSignParam.set(data.worldDeterminantSign);
 		rendererData->wvpParam.set(wvpMatrix);
 	}
 
@@ -340,12 +448,17 @@ namespace BansheeEngine
 			{
 				float4x4 gMatWorldViewProj;
 				float4x4 gMatWorld;
+				float4x4 gMatInvWorld;
+				float4x4 gMatWorldNoScale;
+				float4x4 gMatInvWorldNoScale;
+				float gWorldDeterminantSign;
 			}
 
 			void vs_main(in float3 inPos : POSITION,
 					     out float4 oPosition : SV_Position)
 			{
-				 oPosition = mul(gMatWorldViewProj, float4(inPos.xyz + float3(sin(gTime), 0, 0), 1));
+				 oPosition = mul(gMatWorldViewProj * gMatWorld * gMatInvWorld * gMatWorldNoScale * gMatInvWorldNoScale,
+					 float4(inPos.xyz + float3(sin(gTime), gWorldDeterminantSign, 0), 1));
 			})";
 
 			String psCode = R"(
@@ -369,16 +482,21 @@ namespace BansheeEngine
 		{
 			String vsCode = R"(
 			BS_PARAM_BLOCK PerFrame { gTime }
-			BS_PARAM_BLOCK PerObject { gMatWorldViewProj, gMatWorld }
+			BS_PARAM_BLOCK PerObject { gMatWorldViewProj, gMatWorld, gMatInvWorld, gMatWorldNoScale, gMatInvWorldNoScale, gMatWorldDeterminantSign }
 
 			float gTime;
 			float4x4 gMatWorldViewProj;
 			float4x4 gMatWorld;
+			float4x4 gMatInvWorld;
+			float4x4 gMatWorldNoScale;
+			float4x4 gMatInvWorldNoScale;
+			float gWorldDeterminantSign;
 
 			void vs_main(in float3 inPos : POSITION,
 						out float4 oPosition : POSITION)
 			{
-				oPosition = mul(mul(gMatWorld, gMatWorldViewProj), float4(inPos.xyz + float3(sin(gTime), 0, 0), 1));
+				oPosition = mul(gMatWorld * gMatWorldViewProj * gMatInvWorld * gMatWorldNoScale * gMatInvWorldNoScale, 
+					float4(inPos.xyz + float3(sin(gTime), gWorldDeterminantSign, 0), 1));
 			})";
 
 			String psCode = R"(
@@ -411,6 +529,10 @@ namespace BansheeEngine
 			{
 				mat4 gMatWorldViewProj;
 				mat4 gMatWorld;
+				mat4 gMatInvWorld;
+				mat4 gMatWorldNoScale;
+				mat4 gMatInvWorldNoScale;
+				float gWorldDeterminantSign;
 			};
 
 			in vec3 bs_position;
@@ -422,7 +544,8 @@ namespace BansheeEngine
 
 			void main()
 			{
-				gl_Position = gMatWorld * gMatWorldViewProj * vec4(bs_position.xyz + vec3(sin(gTime), 0, 0), 1);
+				gl_Position = gMatWorld * gMatInvWorld * gMatWorldNoScale * gMatInvWorldNoScale * gMatWorldViewProj 
+					* vec4(bs_position.xyz + vec3(sin(gTime), gWorldDeterminantSign, 0), 1);
 			})";
 
 			String psCode = R"(
@@ -459,12 +582,17 @@ namespace BansheeEngine
 
 		shaderDesc.addParameter("gTime", "gTime", GPDT_FLOAT1, RPS_Time);
 		shaderDesc.addParameter("gViewDir", "gViewDir", GPDT_FLOAT4, RPS_ViewDir);
-		shaderDesc.addParameter("gMatWorldViewProj", "gMatWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
 		shaderDesc.addParameter("gMatViewProj", "gMatViewProj", GPDT_MATRIX_4X4, RPS_ViewProjTfrm);
-		shaderDesc.addParameter("gMatWorld", "gMatWorld", GPDT_MATRIX_4X4, RPS_WorldTfrm);
 		shaderDesc.addParameter("gMatView", "gMatView", GPDT_MATRIX_4X4, RPS_ViewTfrm);
 		shaderDesc.addParameter("gMatProj", "gMatProj", GPDT_MATRIX_4X4, RPS_ProjTfrm);
 
+		shaderDesc.addParameter("gMatWorld", "gMatWorld", GPDT_MATRIX_4X4, RPS_WorldTfrm);
+		shaderDesc.addParameter("gMatInvWorld", "gMatInvWorld", GPDT_MATRIX_4X4, RPS_InvWorldTfrm);
+		shaderDesc.addParameter("gMatWorldNoScale", "gMatWorldNoScale", GPDT_MATRIX_4X4, RPS_WorldNoScaleTfrm);
+		shaderDesc.addParameter("gMatInvWorldNoScale", "gMatInvWorldNoScale", GPDT_MATRIX_4X4, RPS_InvWorldNoScaleTfrm);
+		shaderDesc.addParameter("gWorldDeterminantSign", "gWorldDeterminantSign", GPDT_FLOAT1, RPS_WorldDeterminantSign);
+		shaderDesc.addParameter("gMatWorldViewProj", "gMatWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
+
 		SPtr<ShaderCore> defaultShader = ShaderCore::create("LitTexDefault", shaderDesc, { newTechnique });
 
 		return defaultShader;

+ 10 - 1
TODOExperimentation.txt

@@ -6,9 +6,18 @@ Determine how is light bleeding handled (if at all)
 
 ---------------------- IMPLEMENTATION ---------------------------
 
+When I update SceneObject transforms I must concatenate child/parent transforms by using position/rotation/scale separately,
+then assemble the world matrix from them. This ensures I can easily remove scaling factor from the matrix when needed,
+which is needed for transforming tangents in the shader. Currently Renderable::getTransformNoScale is not implemented.
+
+Assign ViewOrigin, PreViewTranslation, TransViewProj
+ - Dont use pre-view translation for ortographic
+ - Modify view and view projecion matrices so othey use translated 
+ - Apply PreViewTranslation when generating world position in shader (multiply 3x3 rotation col by col, then add translation to last col and add that to rotated position)
+ - Perhaps do all these modifcations outside of shader (i.e. have the world matrix be pre-transformed)
+
 Next week:
  - Finish up DefferedPointLightPass by generating cone geometry in shader
- - Ensure all shaders compile
  - Generate C++ code for populating cbuffers for deferred shaders (2+ days)
  - Modify Light so it generated adequate number of vertices required for cone geometry, without actually creating the cone
  - Think about how to handle post-processing shaders (HDR tone mapping)