Browse Source

When sycing core changes sync dependencies before dependants (WIP - Broke rendering)
Started work on deferred rendering path - cameras now reference and create gbuffers

BearishSun 10 years ago
parent
commit
0a188aad0b

+ 3 - 1
BansheeCore/Source/BsCoreObject.cpp

@@ -124,8 +124,10 @@ namespace BansheeEngine
 		std::function<void(const Vector<IndividualCoreSyncData>&)> callback =
 		std::function<void(const Vector<IndividualCoreSyncData>&)> callback =
 			[](const Vector<IndividualCoreSyncData>& data)
 			[](const Vector<IndividualCoreSyncData>& data)
 		{
 		{
-			for (auto& entry : data)
+			// Traverse in reverse to sync dependencies before dependants
+			for (auto& riter = data.rbegin(); riter != data.rend(); ++riter)
 			{
 			{
+				const IndividualCoreSyncData& entry = *riter;
 				entry.destination->syncToCore(entry.syncData);
 				entry.destination->syncToCore(entry.syncData);
 
 
 				UINT8* dataPtr = entry.syncData.getBuffer();
 				UINT8* dataPtr = entry.syncData.getBuffer();

+ 35 - 7
BansheeCore/Source/BsCoreObjectManager.cpp

@@ -80,17 +80,44 @@ namespace BansheeEngine
 		CoreStoredSyncData& syncData = mCoreSyncData.back();
 		CoreStoredSyncData& syncData = mCoreSyncData.back();
 
 
 		syncData.alloc = allocator;
 		syncData.alloc = allocator;
+
+		Vector<SPtr<CoreObject>> dependencies;
+		Vector<CoreObject*> todo;
+		UINT32 stackPos = 0;
+
 		for (auto& objectData : mObjects)
 		for (auto& objectData : mObjects)
 		{
 		{
 			CoreObject* object = objectData.second;
 			CoreObject* object = objectData.second;
-			SPtr<CoreObjectCore> objectCore = object->getCore();
-			if (objectCore != nullptr && object->isCoreDirty())
+			
+			todo.push_back(object);
+			while (stackPos < todo.size())
 			{
 			{
-				CoreSyncData objSyncData = object->syncToCore(allocator);
-				object->markCoreClean();
+				CoreObject* curObj = todo[stackPos];
+				stackPos++;
+
+				if (curObj->isCoreDirty())
+				{
+					SPtr<CoreObjectCore> objectCore = curObj->getCore();
+					if (objectCore == nullptr)
+						continue;
+
+					CoreSyncData objSyncData = curObj->syncToCore(allocator);
+					curObj->markCoreClean();
 
 
-				syncData.entries[object->getInternalID()] = CoreStoredSyncObjData(objectCore.get(), objSyncData);
+					syncData.entries[curObj->getInternalID()] = CoreStoredSyncObjData(objectCore.get(), objSyncData);
+				}
+
+				// Note: I don't check for recursion. Possible infinite loop if two objects
+				// are dependent on one another.
+				curObj->getCoreDependencies(dependencies);
+				for (auto& dependency : dependencies)
+					todo.push_back(dependency.get());
+
+				dependencies.clear();
 			}
 			}
+
+			todo.clear();
+			stackPos = 0;
 		}
 		}
 	}
 	}
 
 
@@ -103,9 +130,10 @@ namespace BansheeEngine
 
 
 		CoreStoredSyncData& syncData = mCoreSyncData.front();
 		CoreStoredSyncData& syncData = mCoreSyncData.front();
 
 
-		for (auto& objectData : syncData.entries)
+		// Traverse in reverse to sync dependencies before dependants
+		for (auto& riter = syncData.entries.rbegin(); riter != syncData.entries.rend(); ++riter)
 		{
 		{
-			const CoreStoredSyncObjData& objSyncData = objectData.second;
+			const CoreStoredSyncObjData& objSyncData = riter->second;
 			objSyncData.destinationObj->syncToCore(objSyncData.syncData);
 			objSyncData.destinationObj->syncToCore(objSyncData.syncData);
 
 
 			UINT8* data = objSyncData.syncData.getBuffer();
 			UINT8* data = objSyncData.syncData.getBuffer();

+ 4 - 0
BansheeEngine/Source/BsCamera.cpp

@@ -705,6 +705,8 @@ namespace BansheeEngine
 
 
 	void CameraCore::syncToCore(const CoreSyncData& data)
 	void CameraCore::syncToCore(const CoreSyncData& data)
 	{
 	{
+		RendererManager::instance().getActive()->_notifyCameraRemoved(this);
+
 		char* dataPtr = (char*)data.getBuffer();
 		char* dataPtr = (char*)data.getBuffer();
 
 
 		dataPtr = rttiReadElem(mLayers, dataPtr);
 		dataPtr = rttiReadElem(mLayers, dataPtr);
@@ -724,6 +726,8 @@ namespace BansheeEngine
 		mRecalcFrustum = true;
 		mRecalcFrustum = true;
 		mRecalcFrustumPlanes = true;
 		mRecalcFrustumPlanes = true;
 		mRecalcView = true;
 		mRecalcView = true;
+
+		RendererManager::instance().getActive()->_notifyCameraAdded(this);
 	}
 	}
 
 
 	Camera::Camera(RenderTargetPtr target, float left, float top, float width, float height)
 	Camera::Camera(RenderTargetPtr target, float left, float top, float width, float height)

+ 13 - 1
RenderBeast/Include/BsRenderBeast.h

@@ -73,6 +73,8 @@ namespace BansheeEngine
 		{
 		{
 			RenderQueuePtr opaqueQueue;
 			RenderQueuePtr opaqueQueue;
 			RenderQueuePtr transparentQueue;
 			RenderQueuePtr transparentQueue;
+
+			SPtr<RenderTargets> gbuffer;
 		};
 		};
 
 
 		/**
 		/**
@@ -181,6 +183,16 @@ namespace BansheeEngine
 		 */
 		 */
 		void determineVisible(const CameraCore& camera);
 		void determineVisible(const CameraCore& camera);
 
 
+		/**
+		 * @brief	Renders all objects visible by the provided camera.
+		 *
+		 * @param	rtData	Render target data containing the camera to render.
+		 * @param	camIdx	Index of the camera to render.
+		 * 					
+		 * @note	Core thread only.
+		 */
+		void render(RenderTargetData& rtData, UINT32 camIdx);
+
 		/**
 		/**
 		 * @brief	Renders all objects visible by the provided camera.
 		 * @brief	Renders all objects visible by the provided camera.
 		 *
 		 *
@@ -188,7 +200,7 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @note	Core thread only.
 		 * @note	Core thread only.
 		 */
 		 */
-		virtual void render(const CameraCore& camera);
+		void renderOLD(const CameraCore& camera);
 
 
 		/**
 		/**
 		 * @brief	Creates data used by the renderer on the core thread.
 		 * @brief	Creates data used by the renderer on the core thread.

+ 11 - 0
RenderBeast/Include/BsRenderTargets.h

@@ -39,6 +39,16 @@ namespace BansheeEngine
 		 */
 		 */
 		void unbind();
 		void unbind();
 
 
+		/**
+		 * @brief	Checks if the targets support HDR rendering.
+		 */
+		bool getHDR() const { return mHDR; }
+
+		/**
+		 * @brief	Returns the number of samples per pixel supported by the targets.
+		 */
+		UINT32 getNumSamples() const { return mNumSamples; }
+
 	private:
 	private:
 		RenderTargets(const ViewportCore& viewport, bool hdr, UINT32 numSamples);
 		RenderTargets(const ViewportCore& viewport, bool hdr, UINT32 numSamples);
 
 
@@ -53,5 +63,6 @@ namespace BansheeEngine
 		PixelFormat mDiffuseFormat;
 		PixelFormat mDiffuseFormat;
 		PixelFormat mNormalFormat;
 		PixelFormat mNormalFormat;
 		UINT32 mNumSamples;
 		UINT32 mNumSamples;
+		bool mHDR;
 	};
 	};
 }
 }

+ 266 - 82
RenderBeast/Source/BsRenderBeast.cpp

@@ -32,6 +32,7 @@
 #include "BsSamplerOverrides.h"
 #include "BsSamplerOverrides.h"
 #include "BsLight.h"
 #include "BsLight.h"
 #include "BsRenderTexturePool.h"
 #include "BsRenderTexturePool.h"
+#include "BsRenderTargets.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -251,11 +252,65 @@ namespace BansheeEngine
 			transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
 			transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
 
 
 		camData.transparentQueue = bs_shared_ptr_new<RenderQueue>(transparentStateReduction);
 		camData.transparentQueue = bs_shared_ptr_new<RenderQueue>(transparentStateReduction);
+
+		// Register in render target list
+		SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
+		if (renderTarget == nullptr)
+			return;
+
+		auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), 
+			[&](const RenderTargetData& x) { return x.target == renderTarget; });
+
+		if (findIter != mRenderTargets.end())
+		{
+			findIter->cameras.push_back(camera);
+		}
+		else
+		{
+			mRenderTargets.push_back(RenderTargetData());
+			RenderTargetData& renderTargetData = mRenderTargets.back();
+
+			renderTargetData.target = renderTarget;
+			renderTargetData.cameras.push_back(camera);
+		}
+
+		// Sort render targets based on priority
+		auto cameraComparer = [&](const CameraCore* a, const CameraCore* b) { return a->getPriority() > b->getPriority(); };
+		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
+		{ return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
+		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
+
+		for (auto& camerasPerTarget : mRenderTargets)
+		{
+			Vector<const CameraCore*>& cameras = camerasPerTarget.cameras;
+
+			std::sort(begin(cameras), end(cameras), cameraComparer);
+		}
 	}
 	}
 
 
 	void RenderBeast::_notifyCameraRemoved(const CameraCore* camera)
 	void RenderBeast::_notifyCameraRemoved(const CameraCore* camera)
 	{
 	{
 		mCameraData.erase(camera);
 		mCameraData.erase(camera);
+
+		// Remove from render target list
+		for (auto iterTarget = mRenderTargets.begin(); iterTarget != mRenderTargets.end(); ++iterTarget)
+		{
+			RenderTargetData& target = *iterTarget;
+			for (auto iterCam = target.cameras.begin(); iterCam != target.cameras.end(); ++iterCam)
+			{
+				if (camera == *iterCam)
+				{
+					target.cameras.erase(iterCam);
+					break;
+				}
+			}
+
+			if (target.cameras.empty())
+			{
+				mRenderTargets.erase(iterTarget);
+				break;
+			}
+		}
 	}
 	}
 
 
 	void RenderBeast::setOptions(const SPtr<CoreRendererOptions>& options)
 	void RenderBeast::setOptions(const SPtr<CoreRendererOptions>& options)
@@ -318,43 +373,6 @@ namespace BansheeEngine
 		// Update global per-frame hardware buffers
 		// Update global per-frame hardware buffers
 		mStaticHandler->updatePerFrameBuffers(time);
 		mStaticHandler->updatePerFrameBuffers(time);
 
 
-		// Sort cameras by render target
-		for (auto& cameraData : mCameraData)
-		{
-			const CameraCore* camera = cameraData.first;
-			SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
-
-			if (renderTarget == nullptr)
-				continue;
-
-			auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), [&](const RenderTargetData& x) { return x.target == renderTarget; });
-			if (findIter != mRenderTargets.end())
-			{
-				findIter->cameras.push_back(camera);
-			}
-			else
-			{
-				mRenderTargets.push_back(RenderTargetData());
-				RenderTargetData& renderTargetData = mRenderTargets.back();
-
-				renderTargetData.target = renderTarget;
-				renderTargetData.cameras.push_back(camera);
-			}
-		}
-
-		// Sort everything based on priority
-		auto cameraComparer = [&](const CameraCore* a, const CameraCore* b) { return a->getPriority() > b->getPriority(); };
-		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
-		{ return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
-		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
-
-		for (auto& camerasPerTarget : mRenderTargets)
-		{
-			Vector<const CameraCore*>& cameras = camerasPerTarget.cameras;
-
-			std::sort(begin(cameras), end(cameras), cameraComparer);
-		}
-
 		// Generate render queues per camera
 		// Generate render queues per camera
 		for (auto& cameraData : mCameraData)
 		for (auto& cameraData : mCameraData)
 		{
 		{
@@ -369,8 +387,13 @@ namespace BansheeEngine
 			Vector<const CameraCore*>& cameras = renderTargetData.cameras;
 			Vector<const CameraCore*>& cameras = renderTargetData.cameras;
 
 
 			RenderAPICore::instance().beginFrame();
 			RenderAPICore::instance().beginFrame();
-			RenderAPICore::instance().setRenderTarget(target);
 
 
+			//UINT32 numCameras = (UINT32)cameras.size();
+			//for (UINT32 i = 0; i < numCameras; i++)
+			//	render(renderTargetData, i);
+
+			// BEGIN OLD STUFF
+			RenderAPICore::instance().setRenderTarget(target);
 			for(auto& camera : cameras)
 			for(auto& camera : cameras)
 			{
 			{
 				SPtr<ViewportCore> viewport = camera->getViewport();
 				SPtr<ViewportCore> viewport = camera->getViewport();
@@ -389,66 +412,179 @@ namespace BansheeEngine
 				if(clearBuffers != 0)
 				if(clearBuffers != 0)
 					RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(), viewport->getClearDepthValue(), viewport->getClearStencilValue());
 					RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(), viewport->getClearDepthValue(), viewport->getClearStencilValue());
 
 
-				render(*camera);
+				renderOLD(*camera);
 			}
 			}
+			// END OLD STUFF
 
 
 			RenderAPICore::instance().endFrame();
 			RenderAPICore::instance().endFrame();
 			RenderAPICore::instance().swapBuffers(target);
 			RenderAPICore::instance().swapBuffers(target);
 		}
 		}
-
-		mRenderTargets.clear();
 	}
 	}
 
 
-	void RenderBeast::determineVisible(const CameraCore& camera)
+	void RenderBeast::render(RenderTargetData& rtData, UINT32 camIdx)
 	{
 	{
-		CameraData& cameraData = mCameraData[&camera];
+		const CameraCore* camera = rtData.cameras[camIdx];
+		CameraData& camData = mCameraData[camera];
+		SPtr<ViewportCore> viewport = camera->getViewport();
 
 
-		UINT64 cameraLayers = camera.getLayers();
-		ConvexVolume worldFrustum = camera.getWorldFrustum();
+		Matrix4 projMatrixCstm = camera->getProjectionMatrixRS();
+		Matrix4 viewMatrixCstm = camera->getViewMatrix();
 
 
-		// Update per-object param buffers and queue render elements
-		for (auto& renderableData : mRenderables)
+		Matrix4 viewProjMatrix = projMatrixCstm * viewMatrixCstm;
+
+		mStaticHandler->updatePerCameraBuffers(camera->getForward());
+
+		// Render scene object to g-buffer if there are any
+		const Vector<RenderQueueElement>& opaqueElements = camData.opaqueQueue->getSortedElements();
+		bool hasGBuffer = opaqueElements.size() > 0;
+
+		if (hasGBuffer)
 		{
 		{
-			RenderableCore* renderable = renderableData.renderable;
-			RenderableHandler* controller = renderableData.controller;
-			UINT32 renderableType = renderable->getRenderableType();
-			UINT32 rendererId = renderable->getRendererId();
+			bool createGBuffer = camData.gbuffer == nullptr ||
+				camData.gbuffer->getHDR() != mCoreOptions->hdr ||
+				camData.gbuffer->getNumSamples() != mCoreOptions->msaa;
 
 
-			if ((renderable->getLayer() & cameraLayers) == 0)
-				continue;
+			if (createGBuffer)
+				camData.gbuffer = RenderTargets::create(*viewport, mCoreOptions->hdr, mCoreOptions->msaa);
 
 
-			// Do frustum culling
-			// TODO - This is bound to be a bottleneck at some point. When it is ensure that intersect
-			// methods use vector operations, as it is trivial to update them.
-			const Sphere& boundingSphere = mWorldBounds[rendererId].getSphere();
-			if (worldFrustum.intersects(boundingSphere))
+			camData.gbuffer->bind();
+
+			UINT32 clearBuffers = 0;
+			if (viewport->getRequiresColorClear())
+				clearBuffers |= FBT_COLOR;
+
+			if (viewport->getRequiresDepthClear())
+				clearBuffers |= FBT_DEPTH;
+
+			if (viewport->getRequiresStencilClear())
+				clearBuffers |= FBT_STENCIL;
+
+			if (clearBuffers != 0)
+				RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(), viewport->getClearDepthValue(), viewport->getClearStencilValue());
+
+			for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
 			{
 			{
-				// More precise with the box
-				const AABox& boundingBox = mWorldBounds[rendererId].getBox();
+				BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
+				SPtr<MaterialCore> material = renderElem->material;
 
 
-				if (worldFrustum.intersects(boundingBox))
-				{
-					float distanceToCamera = (camera.getPosition() - boundingBox.getCenter()).length();
+				UINT32 rendererId = renderElem->renderableId;
+				Matrix4 worldViewProjMatrix = viewProjMatrix * mWorldTransforms[rendererId];
 
 
-					for (auto& renderElem : renderableData.elements)
-					{
-						bool isTransparent = (renderElem.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
+				mStaticHandler->updatePerObjectBuffers(*renderElem, 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);
 
 
-						if (isTransparent)
-							cameraData.transparentQueue->add(&renderElem, distanceToCamera);
-						else
-							cameraData.opaqueQueue->add(&renderElem, distanceToCamera);
-					}
-						
+				if (iter->applyPass)
+				{
+					SPtr<PassCore> pass = material->getPass(iter->passIdx);
+					setPass(pass);
 				}
 				}
+
+				SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
+
+				if (renderElem->samplerOverrides != nullptr)
+					setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
+				else
+					setPassParams(passParams, nullptr);
+
+				draw(iter->renderElem->mesh, iter->renderElem->subMesh);
 			}
 			}
 		}
 		}
+		else
+			camData.gbuffer = nullptr;
 
 
-		cameraData.opaqueQueue->sort();
-		cameraData.transparentQueue->sort();
+		// Prepare final render target
+		SPtr<RenderTargetCore> target = rtData.target;
+
+		// If first camera in render target, prepare the RT
+		if (camIdx == 0)
+		{
+			RenderAPICore::instance().setRenderTarget(target);
+			RenderAPICore::instance().setViewport(viewport->getNormArea());
+
+			UINT32 clearBuffers = 0;
+			if (viewport->getRequiresColorClear())
+				clearBuffers |= FBT_COLOR;
+
+			if (viewport->getRequiresDepthClear())
+				clearBuffers |= FBT_DEPTH;
+
+			if (viewport->getRequiresStencilClear())
+				clearBuffers |= FBT_STENCIL;
+
+			if (clearBuffers != 0)
+				RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(), viewport->getClearDepthValue(), viewport->getClearStencilValue());
+		}
+
+		// Trigger pre-scene callbacks
+		auto iterCameraCallbacks = mRenderCallbacks.find(camera);
+		if (iterCameraCallbacks != mRenderCallbacks.end())
+		{
+			for (auto& callbackPair : iterCameraCallbacks->second)
+			{
+				if (callbackPair.first >= 0)
+					break;
+
+				callbackPair.second();
+			}
+		}
+
+		// Resolve gbuffer if there is one
+		if (hasGBuffer)
+		{
+			// TODO - Render lights
+			// TODO - Resolve to render target
+			
+			camData.gbuffer->unbind();
+		}
+
+		// Render transparent objects
+		const Vector<RenderQueueElement>& transparentElements = camData.transparentQueue->getSortedElements();
+		for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
+		{
+			BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
+			SPtr<MaterialCore> material = renderElem->material;
+
+			UINT32 rendererId = renderElem->renderableId;
+			Matrix4 worldViewProjMatrix = viewProjMatrix * mWorldTransforms[rendererId];
+
+			mStaticHandler->updatePerObjectBuffers(*renderElem, 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);
+
+			if (iter->applyPass)
+			{
+				SPtr<PassCore> pass = material->getPass(iter->passIdx);
+				setPass(pass);
+			}
+
+			SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
+
+			if (renderElem->samplerOverrides != nullptr)
+				setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
+			else
+				setPassParams(passParams, nullptr);
+
+			draw(iter->renderElem->mesh, iter->renderElem->subMesh);
+		}
+
+		camData.opaqueQueue->clear();
+		camData.transparentQueue->clear();
+
+		// Render post-scene callbacks
+		if (iterCameraCallbacks != mRenderCallbacks.end())
+		{
+			for (auto& callbackPair : iterCameraCallbacks->second)
+			{
+				if (callbackPair.first < 0)
+					continue;
+
+				callbackPair.second();
+			}
+		}
 	}
 	}
 
 
-	void RenderBeast::render(const CameraCore& camera)
+	void RenderBeast::renderOLD(const CameraCore& camera)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -478,6 +614,7 @@ namespace BansheeEngine
 		//// Update global per-frame hardware buffers
 		//// Update global per-frame hardware buffers
 		mStaticHandler->updatePerCameraBuffers(camera.getForward());
 		mStaticHandler->updatePerCameraBuffers(camera.getForward());
 
 
+		// TODO - This bit can be removed once I fully switch to deferred
 		const Vector<RenderQueueElement>& opaqueElements = cameraData.opaqueQueue->getSortedElements();
 		const Vector<RenderQueueElement>& opaqueElements = cameraData.opaqueQueue->getSortedElements();
 		for(auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
 		for(auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
 		{
 		{
@@ -529,14 +666,12 @@ namespace BansheeEngine
 				setPass(pass);
 				setPass(pass);
 			}
 			}
 
 
-			{
-				SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
+			SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
 
 
-				if (renderElem->samplerOverrides != nullptr)
-					setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
-				else
-					setPassParams(passParams, nullptr);
-			}
+			if (renderElem->samplerOverrides != nullptr)
+				setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
+			else
+				setPassParams(passParams, nullptr);
 
 
 			draw(iter->renderElem->mesh, iter->renderElem->subMesh);
 			draw(iter->renderElem->mesh, iter->renderElem->subMesh);
 		}
 		}
@@ -557,6 +692,55 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
+	void RenderBeast::determineVisible(const CameraCore& camera)
+	{
+		CameraData& cameraData = mCameraData[&camera];
+
+		UINT64 cameraLayers = camera.getLayers();
+		ConvexVolume worldFrustum = camera.getWorldFrustum();
+
+		// Update per-object param buffers and queue render elements
+		for (auto& renderableData : mRenderables)
+		{
+			RenderableCore* renderable = renderableData.renderable;
+			RenderableHandler* controller = renderableData.controller;
+			UINT32 renderableType = renderable->getRenderableType();
+			UINT32 rendererId = renderable->getRendererId();
+
+			if ((renderable->getLayer() & cameraLayers) == 0)
+				continue;
+
+			// Do frustum culling
+			// TODO - This is bound to be a bottleneck at some point. When it is ensure that intersect
+			// methods use vector operations, as it is trivial to update them.
+			const Sphere& boundingSphere = mWorldBounds[rendererId].getSphere();
+			if (worldFrustum.intersects(boundingSphere))
+			{
+				// More precise with the box
+				const AABox& boundingBox = mWorldBounds[rendererId].getBox();
+
+				if (worldFrustum.intersects(boundingBox))
+				{
+					float distanceToCamera = (camera.getPosition() - boundingBox.getCenter()).length();
+
+					for (auto& renderElem : renderableData.elements)
+					{
+						bool isTransparent = (renderElem.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
+
+						if (isTransparent)
+							cameraData.transparentQueue->add(&renderElem, distanceToCamera);
+						else
+							cameraData.opaqueQueue->add(&renderElem, distanceToCamera);
+					}
+
+				}
+			}
+		}
+
+		cameraData.opaqueQueue->sort();
+		cameraData.transparentQueue->sort();
+	}
+
 	void RenderBeast::refreshSamplerOverrides(bool force)
 	void RenderBeast::refreshSamplerOverrides(bool force)
 	{
 	{
 		for (auto& entry : mSamplerOverrides)
 		for (auto& entry : mSamplerOverrides)

+ 3 - 2
RenderBeast/Source/BsRenderTargets.cpp

@@ -7,7 +7,7 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	RenderTargets::RenderTargets(const ViewportCore& viewport, bool hdr, UINT32 numSamples)
 	RenderTargets::RenderTargets(const ViewportCore& viewport, bool hdr, UINT32 numSamples)
-		:mNumSamples(numSamples)
+		:mNumSamples(numSamples), mHDR(hdr)
 	{
 	{
 		// TODO - Round up width/height so it's divisible by 8?
 		// TODO - Round up width/height so it's divisible by 8?
 		mWidth = (UINT32)viewport.getWidth();
 		mWidth = (UINT32)viewport.getWidth();
@@ -60,7 +60,8 @@ namespace BansheeEngine
 		RenderAPICore& rapi = RenderAPICore::instance();
 		RenderAPICore& rapi = RenderAPICore::instance();
 		rapi.setRenderTarget(mGBuffer);
 		rapi.setRenderTarget(mGBuffer);
 
 
-		// TODO - Clear gbuffer?
+		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
+		rapi.setViewport(area);
 	}
 	}
 
 
 	void RenderTargets::unbind()
 	void RenderTargets::unbind()

+ 2 - 0
TODO.txt

@@ -53,6 +53,8 @@ Code quality improvements:
 Polish
 Polish
 
 
 Ribek use:
 Ribek use:
+ - When performing core sync it doesn't handle it in hierarchical order. E.g. if a camera depends on viewport, then it should
+   sync the viewport first, then camera
  - Opening complex array entries causes inspector to get screwed up
  - Opening complex array entries causes inspector to get screwed up
  - Hook up color picker to guicolor field
  - Hook up color picker to guicolor field
  - Camera, Renderable, Material, Texture inspector
  - Camera, Renderable, Material, Texture inspector

+ 1 - 0
TODOExperimentation.txt

@@ -13,6 +13,7 @@ Next week:
  - Think about how to handle post-processing shaders (HDR tone mapping)
  - Think about how to handle post-processing shaders (HDR tone mapping)
  - Add cube and 3D support for render texture pool
  - Add cube and 3D support for render texture pool
 
 
+When doing viewport clear in DX11 it will only clear the first render target
 RenderTexturePool needs support for cube and 3D textures
 RenderTexturePool needs support for cube and 3D textures
 Lights need getLightMesh() method
 Lights need getLightMesh() method
  - Need cone to use when rendering spot light, sphere otherwise
  - Need cone to use when rendering spot light, sphere otherwise