瀏覽代碼

Refactored Renderer so that render type specific elements are in a separate class
Fixed compile errors

Marko Pintera 11 年之前
父節點
當前提交
610f21b521

+ 1 - 5
BansheeCore/Include/BsCorePrerequisites.h

@@ -133,9 +133,7 @@ namespace BansheeEngine
 	struct MaterialProxy;
 	struct MaterialProxyPass;
 	struct MeshProxy;
-	class GpuParamBlockBufferProxy;
-	class GpuParamsProxy;
-	class ShaderProxy;
+	struct ShaderProxy;
 	class DrawList;
 	// Asset import
 	class SpecificImporter;
@@ -234,8 +232,6 @@ namespace BansheeEngine
 	typedef std::shared_ptr<CameraProxy> CameraProxyPtr;
 	typedef std::shared_ptr<MaterialProxy> MaterialProxyPtr;
 	typedef std::shared_ptr<MeshProxy> MeshProxyPtr;
-	typedef std::shared_ptr<GpuParamsProxy> GpuParamsProxyPtr;
-	typedef std::shared_ptr<GpuParamBlockBufferProxy> GpuParamBlockBufferProxyPtr;
 	typedef std::shared_ptr<ShaderProxy> ShaderProxyPtr;
 }
 

+ 8 - 8
BansheeCore/Source/BsMaterial.cpp

@@ -802,9 +802,9 @@ namespace BansheeEngine
 
 				idx++;
 			}
-
-			return dirtyParams;
 		}
+
+		return dirtyParams;
 	}
 
 	MaterialProxyPtr Material::_createProxy()
@@ -825,7 +825,7 @@ namespace BansheeEngine
 			if (pass->hasVertexProgram())
 			{
 				passData.vertexProg = pass->getVertexProgram();
-				passData.vertexProgParamsIdx = proxy->params.size();
+				passData.vertexProgParamsIdx = (UINT32)proxy->params.size();
 				proxy->params.push_back(params->mVertParams->_cloneForCore());
 			}
 			else
@@ -834,7 +834,7 @@ namespace BansheeEngine
 			if (pass->hasFragmentProgram())
 			{
 				passData.fragmentProg = pass->getFragmentProgram();
-				passData.fragmentProgParamsIdx = proxy->params.size();
+				passData.fragmentProgParamsIdx = (UINT32)proxy->params.size();
 				proxy->params.push_back(params->mFragParams->_cloneForCore());
 			}
 			else
@@ -843,7 +843,7 @@ namespace BansheeEngine
 			if (pass->hasGeometryProgram())
 			{
 				passData.geometryProg = pass->getGeometryProgram();
-				passData.geometryProgParamsIdx = proxy->params.size();
+				passData.geometryProgParamsIdx = (UINT32)proxy->params.size();
 				proxy->params.push_back(params->mGeomParams->_cloneForCore());
 			}
 			else
@@ -852,7 +852,7 @@ namespace BansheeEngine
 			if (pass->hasHullProgram())
 			{
 				passData.hullProg = pass->getHullProgram();
-				passData.hullProgParamsIdx = proxy->params.size();
+				passData.hullProgParamsIdx = (UINT32)proxy->params.size();
 				proxy->params.push_back(params->mHullParams->_cloneForCore());
 			}
 			else
@@ -861,7 +861,7 @@ namespace BansheeEngine
 			if (pass->hasDomainProgram())
 			{
 				passData.domainProg = pass->getDomainProgram();
-				passData.domainProgParamsIdx = proxy->params.size();
+				passData.domainProgParamsIdx = (UINT32)proxy->params.size();
 				proxy->params.push_back(params->mDomainParams->_cloneForCore());
 			}
 			else
@@ -870,7 +870,7 @@ namespace BansheeEngine
 			if (pass->hasComputeProgram())
 			{
 				passData.computeProg = pass->getComputeProgram();
-				passData.computeProgParamsIdx = proxy->params.size();
+				passData.computeProgParamsIdx = (UINT32)proxy->params.size();
 				proxy->params.push_back(params->mComputeParams->_cloneForCore());
 			}
 			else

+ 2 - 0
BansheeEngine/BansheeEngine.vcxproj

@@ -228,6 +228,7 @@
   <ItemGroup>
     <ClCompile Include="Source\BsCursor.cpp" />
     <ClCompile Include="Source\BsInputConfiguration.cpp" />
+    <ClCompile Include="Source\BsRenderableHandler.cpp" />
     <ClCompile Include="Source\BsRenderableProxy.cpp" />
     <ClCompile Include="Source\BsRenderQueue.cpp" />
     <ClCompile Include="Source\BsVirtualInput.cpp" />
@@ -289,6 +290,7 @@
     <ClInclude Include="Include\BsImageSprite.h" />
     <ClInclude Include="Include\BsProfilerOverlay.h" />
     <ClInclude Include="Include\BsRectOffset.h" />
+    <ClInclude Include="Include\BsRenderableHandler.h" />
     <ClInclude Include="Include\BsRenderableProxy.h" />
     <ClInclude Include="Include\BsRenderQueue.h" />
     <ClInclude Include="Include\BsSceneManager.h" />

+ 6 - 0
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -279,6 +279,9 @@
     <ClInclude Include="Include\BsRenderQueue.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsRenderableHandler.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsGUIElement.cpp">
@@ -482,5 +485,8 @@
     <ClCompile Include="Source\BsRenderQueue.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsRenderableHandler.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 1 - 0
BansheeEngine/Include/BsPrerequisites.h

@@ -69,6 +69,7 @@ namespace BansheeEngine
 	class GUIContextMenu;
 	class GUIDropDownHitBox;
 	class RenderableProxy;
+	class RenderableHandler;
 
 	// 2D
 	class TextSprite;

+ 4 - 3
BansheeEngine/Include/BsRenderQueue.h

@@ -1,13 +1,14 @@
 #pragma once
 
-#include "BsCorePrerequisites.h"
+#include "BsPrerequisites.h"
+#include "BsVector3.h"
 
 namespace BansheeEngine 
 {
 	/**
 	 * @brief	Contains data needed for performing a single rendering pass.
 	 */
-	struct BS_CORE_EXPORT RenderQueueElement
+	struct BS_EXPORT RenderQueueElement
 	{
 		RenderQueueElement()
 			:passIdx(0)
@@ -30,7 +31,7 @@ namespace BansheeEngine
 	 *			will need to be closely tied to the renderer used.
 	 */
 	// TODO UNDOCUMENTED
-	class BS_CORE_EXPORT RenderQueue
+	class BS_EXPORT RenderQueue
 	{
 	public:
 		RenderQueue();

+ 16 - 0
BansheeEngine/Include/BsRenderableHandler.h

@@ -0,0 +1,16 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+
+namespace BansheeEngine
+{
+	// TODO UNDOCUMENTED
+	class BS_EXPORT RenderableHandler
+	{
+	public:
+		virtual void initializeProxy(const RenderableProxyPtr& proxy) = 0;
+
+		virtual void bindPerObjectBuffers(const RenderableProxyPtr& renderable, const RenderableElement* element) = 0;
+		virtual void bindGlobalBuffers(const RenderableElement* element);
+	};
+}

+ 2 - 0
BansheeEngine/Include/BsRenderableProxy.h

@@ -36,6 +36,8 @@ namespace BansheeEngine
 		~RenderableProxy();
 
 		Vector<RenderableElement*> renderableElements;
+
+		RenderableHandler* handler;
 		RenderableType renderableType;
 	};
 }

+ 14 - 0
BansheeEngine/Source/BsRenderableHandler.cpp

@@ -0,0 +1,14 @@
+#include "BsRenderableHandler.h"
+#include "BsRenderableProxy.h"
+#include "BsGpuParams.h"
+
+namespace BansheeEngine
+{
+	void RenderableHandler::bindGlobalBuffers(const RenderableElement* element)
+	{
+		for (auto& rendererBuffer : element->material->rendererBuffers)
+		{
+			element->material->params[rendererBuffer.paramsIdx]->setParamBlockBuffer(rendererBuffer.slotIdx, rendererBuffer.buffer);
+		}
+	}
+}

+ 2 - 0
BansheeRenderer/BansheeRenderer.vcxproj

@@ -233,11 +233,13 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClInclude Include="Include\BsBansheeLitTexRenderableHandler.h" />
     <ClInclude Include="Include\BsBansheeRenderer.h" />
     <ClInclude Include="Include\BsBansheeRendererFactory.h" />
     <ClInclude Include="Include\BsBansheeRendererPrerequisites.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="Source\BsBansheeLitTexRenderableHandler.cpp" />
     <ClCompile Include="Source\BsBansheeRenderer.cpp" />
     <ClCompile Include="Source\BsBansheeRendererFactory.cpp" />
     <ClCompile Include="Source\BsBansheeRendererPlugin.cpp" />

+ 6 - 0
BansheeRenderer/BansheeRenderer.vcxproj.filters

@@ -24,6 +24,9 @@
     <ClInclude Include="Include\BsBansheeRendererPrerequisites.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsBansheeLitTexRenderableHandler.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsBansheeRenderer.cpp">
@@ -35,5 +38,8 @@
     <ClCompile Include="Source\BsBansheeRendererPlugin.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsBansheeLitTexRenderableHandler.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 54 - 0
BansheeRenderer/Include/BsBansheeLitTexRenderableHandler.h

@@ -0,0 +1,54 @@
+#pragma once
+
+#include "BsBansheeRendererPrerequisites.h"
+#include "BsRenderableHandler.h"
+#include "BsMaterialProxy.h"
+#include "BsGpuParamDesc.h"
+#include "BsGpuParam.h"
+
+namespace BansheeEngine
+{
+	// TODO UNDOCUMENTED
+	class BS_BSRND_EXPORT LitTexRenderableHandler : public RenderableHandler
+	{
+	public:
+		struct PerObjectData
+		{
+			GpuParamBlockBufferPtr perObjectParamBuffer;
+
+			bool hasWVPParam;
+			GpuParamMat4 wvpParam;
+
+			Vector<MaterialProxy::BufferBindInfo> perObjectBuffers;
+		};
+
+		LitTexRenderableHandler();
+
+		void initializeProxy(const RenderableProxyPtr& proxy);
+
+		void bindPerObjectBuffers(const RenderableProxyPtr& renderable, const RenderableElement* element);
+
+		void updateGlobalBuffers(float time);
+		void updatePerObjectBuffers(RenderableElement* element, const Matrix4& wvpMatrix);
+
+	protected:
+		ShaderPtr defaultShader;
+
+		GpuParamBlockDesc staticParamBlockDesc;
+		GpuParamBlockDesc perFrameParamBlockDesc;
+		GpuParamBlockDesc perObjectParamBlockDesc;
+
+		GpuParamDataDesc timeParamDesc;
+		GpuParamDataDesc lightDirParamDesc;
+		GpuParamDataDesc wvpParamDesc;
+
+		GpuParamBlockBufferPtr staticParamBuffer;
+		GpuParamBlockBufferPtr perFrameParamBuffer;
+
+		GpuParamsPtr staticParams;
+		GpuParamsPtr perFrameParams;
+
+		GpuParamVec4 lightDirParam;
+		GpuParamFloat timeParam;
+	};
+}

+ 2 - 43
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -2,10 +2,8 @@
 
 #include "BsBansheeRendererPrerequisites.h"
 #include "BsRenderer.h"
-#include "BsMaterial.h"
-#include "BsGpuParamDesc.h"
+#include "BsMaterialProxy.h"
 #include "BsBounds.h"
-#include "BsCameraProxy.h"
 
 namespace BansheeEngine
 {
@@ -15,38 +13,6 @@ namespace BansheeEngine
 		RPS_LightDir = 1001
 	};
 
-	struct RenderLitTexturedGlobalData
-	{
-		ShaderPtr defaultShader;
-
-		GpuParamBlockDesc staticParamBlockDesc;
-		GpuParamBlockDesc perFrameParamBlockDesc;
-		GpuParamBlockDesc perObjectParamBlockDesc;
-
-		GpuParamDataDesc timeParamDesc;
-		GpuParamDataDesc lightDirParamDesc;
-		GpuParamDataDesc wvpParamDesc;
-
-		GpuParamBlockBufferPtr staticParamBuffer;
-		GpuParamBlockBufferPtr perFrameParamBuffer;
-
-		GpuParamsPtr staticParams;
-		GpuParamsPtr perFrameParams;
-
-		GpuParamVec4 lightDirParam;
-		GpuParamFloat timeParam;
-	};
-
-	struct RenderLitTexturedPerObjectData
-	{
-		GpuParamBlockBufferPtr perObjectParamBuffer;
-
-		bool hasWVPParam;
-		GpuParamMat4 wvpParam;
-
-		Vector<MaterialProxy::BufferBindInfo> perObjectBuffers;
-	};
-
 	/**
 	 * @brief	Default renderer for Banshee. Performs frustum culling, sorting and renders
 	 *			objects plainly according to their shaders with no fancy effects.
@@ -76,8 +42,6 @@ namespace BansheeEngine
 		virtual void renderAll();
 
 	private:
-		void initRenderableLitTexturedData();
-
 		void addRenderableProxy(RenderableProxyPtr proxy);
 		void removeRenderableProxy(RenderableProxyPtr proxy);
 		void updateRenderableProxy(RenderableProxyPtr proxy, Matrix4 localToWorld);
@@ -102,11 +66,6 @@ namespace BansheeEngine
 		void renderableRemoved(const HRenderable& renderable);
 		void cameraRemoved(const HCamera& camera);
 
-		void bindGlobalBuffers(const RenderableElement* element);
-		void bindPerObjectBuffers(const RenderableProxyPtr& renderable, const RenderableElement* element);
-
-		ShaderPtr getDefaultShader(RenderableType type) const;
-
 		Vector<RenderableProxyPtr> mDeletedRenderableProxies;
 		Vector<CameraProxyPtr> mDeletedCameraProxies;
 
@@ -119,7 +78,7 @@ namespace BansheeEngine
 		Vector<Matrix4> mWorldTransforms;
 		Vector<Bounds> mWorldBounds;
 
-		RenderLitTexturedGlobalData mLitTexturedData;
+		LitTexRenderableHandler* mLitTexHandler;
 
 		HEvent mRenderableRemovedConn;
 		HEvent mCameraRemovedConn;

+ 6 - 1
BansheeRenderer/Include/BsBansheeRendererPrerequisites.h

@@ -16,4 +16,9 @@
 #    define BS_BSRND_EXPORT  __attribute__ ((visibility("default")))
 #else
 #    define BS_BSRND_EXPORT
-#endif
+#endif
+
+namespace BansheeEngine
+{
+	class LitTexRenderableHandler;
+}

+ 258 - 0
BansheeRenderer/Source/BsBansheeLitTexRenderableHandler.cpp

@@ -0,0 +1,258 @@
+#include "BsBansheeLitTexRenderableHandler.h"
+#include "BsRenderableProxy.h"
+#include "BsShader.h"
+#include "BsShaderProxy.h"
+#include "BsGpuParams.h"
+#include "BsBansheeRenderer.h"
+#include "BsHardwareBufferManager.h"
+#include "BsGpuParamBlockBuffer.h"
+#include "BsTechnique.h"
+#include "BsPass.h"
+
+namespace BansheeEngine
+{
+	LitTexRenderableHandler::LitTexRenderableHandler()
+	{
+		defaultShader = nullptr; // TODO - Get proper shader
+
+		TechniquePtr defaultTechnique = defaultShader->getBestTechnique();
+		PassPtr defaultPass = defaultTechnique->getPass(0);
+
+		bool matrixTranspose = defaultPass->getVertexProgram()->requiresMatrixTranspose(); // This is a static setting across all GPU programs
+		const GpuParamDesc& vertParamDesc = defaultPass->getVertexProgram()->getParamDesc();
+		const GpuParamDesc& fragParamDesc = defaultPass->getFragmentProgram()->getParamDesc();
+
+		GpuParamDesc staticParamsDesc;
+		GpuParamDesc perFrameParamsDesc;
+		GpuParamDesc perObjectParamsDesc;
+
+		const Map<String, SHADER_DATA_PARAM_DESC>& dataParams = defaultShader->_getDataParams();
+		for (auto& param : dataParams)
+		{
+			if (param.second.rendererSemantic == RPS_LightDir)
+			{
+				auto iterFind = fragParamDesc.params.find(param.second.gpuVariableName);
+				if (iterFind == fragParamDesc.params.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				lightDirParamDesc = iterFind->second;
+				staticParamsDesc.params[iterFind->first] = iterFind->second;
+			}
+			else if (param.second.rendererSemantic == RPS_Time)
+			{
+				auto iterFind = vertParamDesc.params.find(param.second.gpuVariableName);
+				if (iterFind == vertParamDesc.params.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				timeParamDesc = iterFind->second;
+				perFrameParamsDesc.params[iterFind->first] = iterFind->second;
+			}
+			else if (param.second.rendererSemantic == RPS_WorldViewProjTfrm)
+			{
+				auto iterFind = vertParamDesc.params.find(param.second.gpuVariableName);
+				if (iterFind == vertParamDesc.params.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				wvpParamDesc = iterFind->second;
+				perObjectParamsDesc.params[iterFind->first] = iterFind->second;
+			}
+		}
+
+		const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlocks = defaultShader->_getParamBlocks();
+		for (auto& block : paramBlocks)
+		{
+			if (block.second.rendererSemantic == RBS_Static)
+			{
+				auto iterFind = vertParamDesc.paramBlocks.find(block.second.name);
+				if (iterFind == vertParamDesc.paramBlocks.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				staticParamBlockDesc = iterFind->second;
+				staticParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
+			}
+			else if (block.second.rendererSemantic == RBS_PerFrame)
+			{
+				auto iterFind = fragParamDesc.paramBlocks.find(block.second.name);
+				if (iterFind == fragParamDesc.paramBlocks.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				perFrameParamBlockDesc = iterFind->second;
+				perFrameParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
+			}
+			else if (block.second.rendererSemantic == RBS_PerObject)
+			{
+				auto iterFind = vertParamDesc.paramBlocks.find(block.second.name);
+				if (iterFind == vertParamDesc.paramBlocks.end())
+					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
+
+				perObjectParamBlockDesc = iterFind->second;
+				perObjectParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
+			}
+		}
+
+		// Create global GPU param buffers and get parameter handles
+		staticParams = bs_shared_ptr<GpuParams>(staticParamsDesc, matrixTranspose);
+		perFrameParams = bs_shared_ptr<GpuParams>(perFrameParamsDesc, matrixTranspose);
+
+		staticParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(staticParamBlockDesc.blockSize);
+		perFrameParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(perFrameParamBlockDesc.blockSize);
+
+		staticParams->setParamBlockBuffer(staticParamBlockDesc.slot, staticParamBuffer);
+		perFrameParams->setParamBlockBuffer(perFrameParamBlockDesc.slot, perFrameParamBuffer);
+
+		staticParams->getParam(lightDirParamDesc.name, lightDirParam);
+		staticParams->getParam(timeParamDesc.name, timeParam);
+
+		lightDirParam.set(Vector4(0.707f, 0.707f, 0.707f, 0.0f));
+	}
+
+	void LitTexRenderableHandler::initializeProxy(const RenderableProxyPtr& proxy)
+	{
+		static auto paramsMatch = [](const GpuParamDataDesc& a, const GpuParamDataDesc& b)
+		{
+			return a.gpuMemOffset == b.gpuMemOffset && a.elementSize == b.elementSize &&
+				a.arraySize == b.arraySize && a.arrayElementStride == b.arrayElementStride;
+		};
+
+		for (auto& element : proxy->renderableElements)
+		{
+			element->rendererData = PerObjectData();
+			PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element->rendererData);
+
+			ShaderProxyPtr shader = element->material->shader;
+
+			const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->paramBlocks;
+			const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDescs = shader->dataParams;
+			String staticBlockName;
+			String perFrameBlockName;
+			String perObjectBlockName;
+
+			String wvpParamName;
+
+			for (auto& paramBlockDesc : paramBlockDescs)
+			{
+				switch (paramBlockDesc.second.rendererSemantic)
+				{
+				case RBS_Static:
+					staticBlockName = paramBlockDesc.second.name;
+					break;
+				case RBS_PerFrame:
+					perFrameBlockName = paramBlockDesc.second.name;
+					break;
+				case RBS_PerObject:
+					perObjectBlockName = paramBlockDesc.second.name;
+					break;
+				}
+			}
+
+			for (auto& paramDesc : dataParamDescs)
+			{
+				if (paramDesc.second.rendererSemantic == RPS_WorldViewProjTfrm)
+					wvpParamName = paramDesc.second.gpuVariableName;
+			}
+
+			UINT32 idx = 0;
+			for (auto& gpuParams : element->material->params)
+			{
+				const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
+
+				if (staticBlockName != "")
+				{
+					auto findIter = paramsDesc.paramBlocks.find(staticBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
+					{
+						// TODO - We only compare block sizes but not actual contents. Should I check them too?
+						//        Probably shouldn't concern myself with that here, instead check that on a higher level.
+						if (findIter->second.blockSize == staticParamBlockDesc.blockSize)
+						{
+							UINT32 slotIdx = findIter->second.slot;
+							element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, staticParamBuffer));
+						}
+					}
+				}
+
+				if (perFrameBlockName != "")
+				{
+					auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
+					{
+						if (findIter->second.blockSize == perFrameParamBlockDesc.blockSize)
+						{
+							UINT32 slotIdx = findIter->second.slot;
+							element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, perFrameParamBuffer));
+						}
+					}
+				}
+
+				if (perObjectBlockName != "")
+				{
+					auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
+					if (findIter != paramsDesc.paramBlocks.end())
+					{
+						if (findIter->second.blockSize == perObjectParamBlockDesc.blockSize)
+						{
+							if (rendererData->perObjectParamBuffer == nullptr)
+								rendererData->perObjectParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(perObjectParamBlockDesc.blockSize);
+
+							rendererData->perObjectBuffers.push_back(MaterialProxy::BufferBindInfo(idx, findIter->second.slot, rendererData->perObjectParamBuffer));
+
+							if (!rendererData->hasWVPParam && wvpParamName != "")
+							{
+								auto findIter2 = paramsDesc.params.find(wvpParamName);
+								if (findIter2 != paramsDesc.params.end())
+								{
+									if (paramsMatch(findIter2->second, wvpParamDesc))
+									{
+										gpuParams->getParam(wvpParamName, rendererData->wvpParam);
+										rendererData->hasWVPParam = true;
+									}
+								}
+							}
+						}
+					}
+				}
+
+				idx++;
+			}
+
+			bindGlobalBuffers(element);
+		}
+	}
+
+	void LitTexRenderableHandler::bindPerObjectBuffers(const RenderableProxyPtr& renderable, const RenderableElement* element)
+	{
+		if (renderable->renderableType != RenType_LitTextured)
+			return;
+
+		const PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element->rendererData);
+		for (auto& perObjectBuffer : rendererData->perObjectBuffers)
+		{
+			GpuParamsPtr params = element->material->params[perObjectBuffer.paramsIdx];
+
+			params->setParamBlockBuffer(perObjectBuffer.slotIdx, rendererData->perObjectParamBuffer);
+		}
+	}
+
+	void LitTexRenderableHandler::updateGlobalBuffers(float time)
+	{
+		timeParam.set(time);
+
+		staticParams->updateHardwareBuffers();
+		perFrameParams->updateHardwareBuffers();
+	}
+
+	void LitTexRenderableHandler::updatePerObjectBuffers(RenderableElement* element, const Matrix4& wvpMatrix)
+	{
+		PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element->rendererData);
+
+		if (rendererData->hasWVPParam)
+			rendererData->wvpParam.set(wvpMatrix);
+
+		if (rendererData->perObjectParamBuffer != nullptr)
+		{
+			GpuParamBlockPtr paramBlock = rendererData->perObjectParamBuffer->getParamBlock();
+			if (paramBlock->isDirty())
+				paramBlock->uploadToBuffer(rendererData->perObjectParamBuffer);
+		}
+	}
+}

+ 15 - 248
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -27,6 +27,7 @@
 #include "BsGpuParamBlockBuffer.h"
 #include "BsShader.h"
 #include "BsShaderProxy.h"
+#include "BsBansheeLitTexRenderableHandler.h"
 #include "BsTime.h"
 
 using namespace std::placeholders;
@@ -38,12 +39,13 @@ namespace BansheeEngine
 		mRenderableRemovedConn = gBsSceneManager().onRenderableRemoved.connect(std::bind(&BansheeRenderer::renderableRemoved, this, _1));
 		mCameraRemovedConn = gBsSceneManager().onCameraRemoved.connect(std::bind(&BansheeRenderer::cameraRemoved, this, _1));
 
-		// Init default shaders
-		initRenderableLitTexturedData();
+		mLitTexHandler = bs_new<LitTexRenderableHandler>();
 	}
 
 	BansheeRenderer::~BansheeRenderer()
 	{
+		bs_delete(mLitTexHandler);
+
 		mRenderableRemovedConn.disconnect();
 		mCameraRemovedConn.disconnect();
 	}
@@ -54,105 +56,6 @@ namespace BansheeEngine
 		return name;
 	}
 
-	void BansheeRenderer::initRenderableLitTexturedData()
-	{
-		mLitTexturedData.defaultShader = getDefaultShader(RenType_LitTextured);
-		TechniquePtr defaultTechnique = mLitTexturedData.defaultShader->getBestTechnique();
-		PassPtr defaultPass = defaultTechnique->getPass(0);
-
-		bool matrixTranspose = defaultPass->getVertexProgram()->requiresMatrixTranspose(); // This is a static setting across all GPU programs
-		const GpuParamDesc& vertParamDesc = defaultPass->getVertexProgram()->getParamDesc();
-		const GpuParamDesc& fragParamDesc = defaultPass->getFragmentProgram()->getParamDesc();
-
-		GpuParamDesc staticParamsDesc;
-		GpuParamDesc perFrameParamsDesc;
-		GpuParamDesc perObjectParamsDesc;
-
-		const Map<String, SHADER_DATA_PARAM_DESC>& dataParams = mLitTexturedData.defaultShader->_getDataParams();
-		for (auto& param : dataParams)
-		{
-			if (param.second.rendererSemantic == RPS_LightDir)
-			{
-				auto iterFind = fragParamDesc.params.find(param.second.gpuVariableName);
-				if (iterFind == fragParamDesc.params.end())
-					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
-
-				mLitTexturedData.lightDirParamDesc = iterFind->second;
-				staticParamsDesc.params[iterFind->first] = iterFind->second;
-			}
-			else if (param.second.rendererSemantic == RPS_Time)
-			{
-				auto iterFind = vertParamDesc.params.find(param.second.gpuVariableName);
-				if (iterFind == vertParamDesc.params.end())
-					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
-
-				mLitTexturedData.timeParamDesc = iterFind->second;
-				perFrameParamsDesc.params[iterFind->first] = iterFind->second;
-			}
-			else if (param.second.rendererSemantic == RPS_WorldViewProjTfrm)
-			{
-				auto iterFind = vertParamDesc.params.find(param.second.gpuVariableName);
-				if (iterFind == vertParamDesc.params.end())
-					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
-
-				mLitTexturedData.wvpParamDesc = iterFind->second;
-				perObjectParamsDesc.params[iterFind->first] = iterFind->second;
-			}
-		}
-
-		const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlocks = mLitTexturedData.defaultShader->_getParamBlocks();
-		for (auto& block : paramBlocks)
-		{
-			if (block.second.rendererSemantic == RBS_Static)
-			{
-				auto iterFind = vertParamDesc.paramBlocks.find(block.second.name);
-				if (iterFind == vertParamDesc.paramBlocks.end())
-					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
-
-				mLitTexturedData.staticParamBlockDesc = iterFind->second;
-				staticParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
-			}
-			else if (block.second.rendererSemantic == RBS_PerFrame)
-			{
-				auto iterFind = fragParamDesc.paramBlocks.find(block.second.name);
-				if (iterFind == fragParamDesc.paramBlocks.end())
-					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
-
-				mLitTexturedData.perFrameParamBlockDesc = iterFind->second;
-				perFrameParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
-			}
-			else if (block.second.rendererSemantic == RBS_PerObject)
-			{
-				auto iterFind = vertParamDesc.paramBlocks.find(block.second.name);
-				if (iterFind == vertParamDesc.paramBlocks.end())
-					BS_EXCEPT(InternalErrorException, "Invalid default shader.");
-
-				mLitTexturedData.perObjectParamBlockDesc = iterFind->second;
-				perObjectParamsDesc.paramBlocks[iterFind->first] = iterFind->second;
-			}
-		}
-
-		// Create global GPU param buffers and get parameter handles
-		mLitTexturedData.staticParams = bs_shared_ptr<GpuParams>(staticParamsDesc, matrixTranspose);
-		mLitTexturedData.perFrameParams = bs_shared_ptr<GpuParams>(perFrameParamsDesc, matrixTranspose);
-
-		mLitTexturedData.staticParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(mLitTexturedData.staticParamBlockDesc.blockSize);
-		mLitTexturedData.perFrameParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(mLitTexturedData.perFrameParamBlockDesc.blockSize);
-
-		mLitTexturedData.staticParams->setParamBlockBuffer(mLitTexturedData.staticParamBlockDesc.slot, mLitTexturedData.staticParamBuffer);
-		mLitTexturedData.perFrameParams->setParamBlockBuffer(mLitTexturedData.perFrameParamBlockDesc.slot, mLitTexturedData.perFrameParamBuffer);
-
-		mLitTexturedData.staticParams->getParam(mLitTexturedData.lightDirParamDesc.name, mLitTexturedData.lightDirParam);
-		mLitTexturedData.staticParams->getParam(mLitTexturedData.timeParamDesc.name, mLitTexturedData.timeParam);
-
-		mLitTexturedData.lightDirParam.set(Vector4(0.707f, 0.707f, 0.707f, 0.0f));
-	}
-
-	ShaderPtr BansheeRenderer::getDefaultShader(RenderableType type) const
-	{
-		return nullptr;
-	}
-
 	void BansheeRenderer::addRenderableProxy(RenderableProxyPtr proxy)
 	{
 		for (auto& element : proxy->renderableElements)
@@ -172,111 +75,12 @@ namespace BansheeEngine
 		};
 
 		if (proxy->renderableType == RenType_LitTextured)
-		{
-			for (auto& element : proxy->renderableElements)
-			{
-				element->rendererData = RenderLitTexturedPerObjectData();
-				RenderLitTexturedPerObjectData* rendererData = any_cast_unsafe<RenderLitTexturedPerObjectData>(&element->rendererData);
-
-				ShaderProxyPtr shader = element->material->shader;
-
-				const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->paramBlocks;
-				const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDescs = shader->dataParams;
-				String staticBlockName;
-				String perFrameBlockName;
-				String perObjectBlockName;
-
-				String wvpParamName;
-
-				for (auto& paramBlockDesc : paramBlockDescs)
-				{
-					switch (paramBlockDesc.second.rendererSemantic)
-					{
-					case RBS_Static:
-						staticBlockName = paramBlockDesc.second.name;
-						break;
-					case RBS_PerFrame:
-						perFrameBlockName = paramBlockDesc.second.name;
-						break;
-					case RBS_PerObject:
-						perObjectBlockName = paramBlockDesc.second.name;
-						break;
-					}
-				}
-
-				for (auto& paramDesc : dataParamDescs)
-				{
-					if (paramDesc.second.rendererSemantic == RPS_WorldViewProjTfrm)
-						wvpParamName = paramDesc.second.gpuVariableName;
-				}
-
-				UINT32 idx = 0;
-				for (auto& gpuParams : element->material->params)
-				{
-					const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
-
-					if (staticBlockName != "")
-					{
-						auto findIter = paramsDesc.paramBlocks.find(staticBlockName);
-						if (findIter != paramsDesc.paramBlocks.end())
-						{
-							// TODO - We only compare block sizes but not actual contents. Should I check them too?
-							//        Probably shouldn't concern myself with that here, instead check that on a higher level.
-							if (findIter->second.blockSize == mLitTexturedData.staticParamBlockDesc.blockSize)
-							{
-								UINT32 slotIdx = findIter->second.slot;
-								element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, mLitTexturedData.staticParamBuffer));
-							}
-						}
-					}
-					
-					if (perFrameBlockName != "")
-					{
-						auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
-						if (findIter != paramsDesc.paramBlocks.end())
-						{
-							if (findIter->second.blockSize == mLitTexturedData.perFrameParamBlockDesc.blockSize)
-							{
-								UINT32 slotIdx = findIter->second.slot;
-								element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, mLitTexturedData.perFrameParamBuffer));
-							}
-						}
-					}
-
-					if (perObjectBlockName != "")
-					{
-						auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
-						if (findIter != paramsDesc.paramBlocks.end())
-						{
-							if (findIter->second.blockSize == mLitTexturedData.perObjectParamBlockDesc.blockSize)
-							{
-								if (rendererData->perObjectParamBuffer == nullptr)
-									rendererData->perObjectParamBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(mLitTexturedData.perObjectParamBlockDesc.blockSize);
-
-								rendererData->perObjectBuffers.push_back(MaterialProxy::BufferBindInfo(idx, findIter->second.slot, rendererData->perObjectParamBuffer));
-
-								if (!rendererData->hasWVPParam && wvpParamName != "")
-								{
-									auto findIter2 = paramsDesc.params.find(wvpParamName);
-									if (findIter2 != paramsDesc.params.end())
-									{
-										if (paramsMatch(findIter2->second, mLitTexturedData.wvpParamDesc))
-										{
-											gpuParams->getParam(wvpParamName, rendererData->wvpParam);
-											rendererData->hasWVPParam = true;
-										}
-									}
-								}
-							}
-						}
-					}
-
-					idx++;
-				}
+			proxy->handler = mLitTexHandler;
+		else
+			proxy->handler = nullptr;
 
-				bindGlobalBuffers(element);
-			}
-		}
+		if (proxy->handler != nullptr)
+			proxy->handler->initializeProxy(proxy);
 	}
 
 	void BansheeRenderer::removeRenderableProxy(RenderableProxyPtr proxy)
@@ -531,7 +335,7 @@ namespace BansheeEngine
 				renderQueue->add(materialProxy, meshProxy, drawOp.worldPosition);
 			}
 
-			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->_getActiveProxy(), drawList));
+			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->_getActiveProxy(), renderQueue));
 		}
 
 		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this, gTime().getTime()));
@@ -562,10 +366,7 @@ namespace BansheeEngine
 		THROW_IF_NOT_CORE_THREAD;
 
 		// Update global hardware buffers
-		mLitTexturedData.timeParam.set(time);
-
-		mLitTexturedData.staticParams->updateHardwareBuffers();
-		mLitTexturedData.perFrameParams->updateHardwareBuffers();
+		mLitTexHandler->updateGlobalBuffers(time);
 
 		// Render everything, target by target
 		for (auto& renderTargetData : mRenderTargets)
@@ -621,20 +422,8 @@ namespace BansheeEngine
 				{
 					if (proxy.second->renderableType == RenType_LitTextured)
 					{
-						RenderLitTexturedPerObjectData* rendererData = any_cast_unsafe<RenderLitTexturedPerObjectData>(&renderElem->rendererData);
-
-						if (rendererData->hasWVPParam)
-						{
-							Matrix4 worldViewProjMatrix = viewProjMatrix * renderElem->worldTransform;
-							rendererData->wvpParam.set(worldViewProjMatrix);
-						}
-
-						if (rendererData->perObjectParamBuffer != nullptr)
-						{
-							GpuParamBlockPtr paramBlock = rendererData->perObjectParamBuffer->getParamBlock();
-							if (paramBlock->isDirty())
-								paramBlock->uploadToBuffer(rendererData->perObjectParamBuffer);
-						}
+						Matrix4 worldViewProjMatrix = viewProjMatrix * mWorldTransforms[renderElem->id];;
+						mLitTexHandler->updatePerObjectBuffers(renderElem, worldViewProjMatrix);
 					}
 
 					for (auto& param : renderElem->material->params)
@@ -655,36 +444,14 @@ namespace BansheeEngine
 		{
 			MaterialProxyPtr materialProxy = iter->renderElem->material;
 
-			if (iter->renderable != nullptr)
-				bindPerObjectBuffers(iter->renderable, iter->renderElem);
+			if (iter->renderable != nullptr && iter->renderable->handler != nullptr)
+				iter->renderable->handler->bindPerObjectBuffers(iter->renderable, iter->renderElem);
 
 			setPass(materialProxy, iter->passIdx);
 			draw(*iter->renderElem->mesh);
 		}
 	}
 
-	void BansheeRenderer::bindGlobalBuffers(const RenderableElement* element)
-	{
-		for (auto& rendererBuffer : element->material->rendererBuffers)
-		{
-			element->material->params[rendererBuffer.paramsIdx]->setParamBlockBuffer(rendererBuffer.slotIdx, rendererBuffer.buffer);
-		}
-	}
-
-	void BansheeRenderer::bindPerObjectBuffers(const RenderableProxyPtr& renderable, const RenderableElement* element)
-	{
-		if (renderable->renderableType != RenType_LitTextured)
-			return;
-
-		const RenderLitTexturedPerObjectData* rendererData = any_cast_unsafe<RenderLitTexturedPerObjectData>(&element->rendererData);
-		for (auto& perObjectBuffer : rendererData->perObjectBuffers)
-		{
-			GpuParamsPtr params = element->material->params[perObjectBuffer.paramsIdx];
-
-			params->setParamBlockBuffer(perObjectBuffer.slotIdx, rendererData->perObjectParamBuffer);
-		}
-	}
-
 	void BansheeRenderer::setPass(const MaterialProxyPtr& material, UINT32 passIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;