Browse Source

More documentation

Marko Pintera 11 years ago
parent
commit
0eecfe525d

+ 5 - 1
BansheeCore/Include/BsCameraProxy.h

@@ -7,7 +7,9 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	// TODO UNDOCUMENTED
+	/**
+	 * @brief	Contains Camera data used by the Renderer.
+	 */
 	class BS_CORE_EXPORT CameraProxy
 	class BS_CORE_EXPORT CameraProxy
 	{
 	{
 	public:
 	public:
@@ -18,6 +20,8 @@ namespace BansheeEngine
 		UINT64 layer;
 		UINT64 layer;
 		bool ignoreSceneRenderables;
 		bool ignoreSceneRenderables;
 		ConvexVolume frustum;
 		ConvexVolume frustum;
+		ConvexVolume worldFrustum;
+		Vector3 worldPosition;
 
 
 		RenderQueuePtr renderQueue;
 		RenderQueuePtr renderQueue;
 	};
 	};

+ 24 - 2
BansheeCore/Include/BsDrawList.h

@@ -5,7 +5,10 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	// TODO UNDOCUMENTED
+	/**
+	 * @brief	Represents a single drawable object
+	 *			stored in a DrawList.
+	 */
 	struct BS_CORE_EXPORT DrawOperation
 	struct BS_CORE_EXPORT DrawOperation
 	{
 	{
 		MaterialPtr material;
 		MaterialPtr material;
@@ -14,13 +17,32 @@ namespace BansheeEngine
 		Vector3 worldPosition;
 		Vector3 worldPosition;
 	};
 	};
 
 
-	// TODO UNDOCUMENTED
+	/**
+	 * @brief	A container you may use to queue
+	 *			custom drawable objects in.
+	 */
 	class BS_CORE_EXPORT DrawList
 	class BS_CORE_EXPORT DrawList
 	{
 	{
 	public:
 	public:
+		/**
+		 * @brief	Adds a new drawable object.
+		 *
+		 * @param	material		Material to draw the object with.
+		 * @param	mesh			Parent mesh of the object.
+		 * @param	submeshIdx		Index of the sub-mesh to render, in the parent mesh.
+		 * @param	worldPosForSort	World position of the object that will be used for distance
+		 *							sorting before rendering.
+		 */
 		void add(const MaterialPtr& material, const MeshBasePtr& mesh, UINT32 submeshIdx, const Vector3& worldPosForSort);
 		void add(const MaterialPtr& material, const MeshBasePtr& mesh, UINT32 submeshIdx, const Vector3& worldPosForSort);
+
+		/**
+		 * @brief	Removes all queued drawable objects.
+		 */
 		void clear();
 		void clear();
 
 
+		/**
+		 * @brief	Returns all queued drawable objects.
+		 */
 		const Vector<DrawOperation>& getDrawOperations() const;
 		const Vector<DrawOperation>& getDrawOperations() const;
 
 
 	protected:
 	protected:

+ 14 - 3
BansheeCore/Include/BsGpuParamBlockBuffer.h

@@ -54,17 +54,28 @@ namespace BansheeEngine
 
 
 		/**
 		/**
 		 * @brief	Returns	a parameter block buffer which is used for caching 
 		 * @brief	Returns	a parameter block buffer which is used for caching 
-		 *			the parameter information on the CPU. Essentially a CPU
-		 *			copy of the GPU buffer.
+		 *			the parameter information on the sim thread. Essentially a
+		 *			sim thread copy of the GPU buffer.
 		 *
 		 *
 		 * @note	Sim thread only.
 		 * @note	Sim thread only.
 		 */
 		 */
 		GpuParamBlockPtr getParamBlock() const { return mParamBlock; }
 		GpuParamBlockPtr getParamBlock() const { return mParamBlock; }
 
 
-		// TODO UNDOCUMENTED
+		/**
+		 * @brief	Returns	a parameter block buffer which is used for caching 
+		 *			the parameter information on the core thread. Essentially a CPU
+		 *			core thread copy of the GPU buffer.
+		 *
+		 * @note	Core thread only.
+		 */
 		// TODO - Keeping a core param block along with a sim param block is redundant in some cases,
 		// TODO - Keeping a core param block along with a sim param block is redundant in some cases,
 		// as it might not be used (e.g. if gpu param block buffer is only accessed from core thread)
 		// as it might not be used (e.g. if gpu param block buffer is only accessed from core thread)
 		GpuParamBlockPtr getCoreParamBlock() const { return mCoreParamBlock; }
 		GpuParamBlockPtr getCoreParamBlock() const { return mCoreParamBlock; }
+
+		/**
+		 * @brief	Sets a reference to a core thread CPU buffer that may be used for buffering
+		 *			parameter data on the core thread, before actually writing it to the buffer.
+		 */
 		void setCoreParamBlock(const GpuParamBlockPtr& paramBlock) { mCoreParamBlock = paramBlock; }
 		void setCoreParamBlock(const GpuParamBlockPtr& paramBlock) { mCoreParamBlock = paramBlock; }
 
 
 	protected:
 	protected:

+ 27 - 5
BansheeCore/Source/BsMesh.cpp

@@ -349,16 +349,38 @@ namespace BansheeEngine
 
 
 		if (mNumVertices > 0)
 		if (mNumVertices > 0)
 		{
 		{
+			Vector3 accum;
+			Vector3 min;
+			Vector3 max;
+
 			Vector3 curPosition = *(Vector3*)verticesPtr;
 			Vector3 curPosition = *(Vector3*)verticesPtr;
-			Sphere initialSphere(curPosition, 0.0f);
-			AABox initialBox(curPosition, curPosition);
+			accum = curPosition;
+			min = curPosition;
+			max = curPosition;
 
 
-			bounds.setBounds(initialBox, initialSphere);
 			for (UINT32 i = 1; i < mNumVertices; i++)
 			for (UINT32 i = 1; i < mNumVertices; i++)
 			{
 			{
-				Vector3 curPosition = *(Vector3*)(verticesPtr + stride * i);
-				bounds.merge(curPosition);
+				curPosition = *(Vector3*)(verticesPtr + stride * i);
+				accum += curPosition;
+				min = Vector3::min(min, curPosition);
+				max = Vector3::max(max, curPosition);
+			}
+
+			Vector3 center = accum / (float)mNumVertices;
+			float radiusSqrd = 0.0f;
+
+			for (UINT32 i = 0; i < mNumVertices; i++)
+			{
+				curPosition = *(Vector3*)(verticesPtr + stride * i);
+				float dist = center.squaredDistance(curPosition);
+
+				if (dist > radiusSqrd)
+					radiusSqrd = dist;
 			}
 			}
+
+			float radius = Math::sqrt(radiusSqrd);
+
+			bounds = Bounds(AABox(min, max), Sphere(center, radius));
 		}
 		}
 
 
 		return bounds;
 		return bounds;

+ 29 - 13
BansheeEngine/Include/BsRenderQueue.h

@@ -17,7 +17,6 @@ namespace BansheeEngine
 		RenderableElement* renderElem;
 		RenderableElement* renderElem;
 		MaterialProxyPtr material;
 		MaterialProxyPtr material;
 		MeshProxyPtr mesh;
 		MeshProxyPtr mesh;
-		Vector3 worldPosition;
 		UINT32 passIdx;
 		UINT32 passIdx;
 	};
 	};
 
 
@@ -28,6 +27,18 @@ namespace BansheeEngine
 	 */
 	 */
 	class BS_EXPORT RenderQueue
 	class BS_EXPORT RenderQueue
 	{
 	{
+		/**
+		 * @brief	Data used for renderable elemnt sorting.
+		 */
+		struct SortData
+		{
+			RenderQueueElement element;
+			QueueSortType sortType;
+			UINT32 seqIdx;
+			UINT32 priority;
+			float distFromCamera;
+		};
+
 	public:
 	public:
 		RenderQueue();
 		RenderQueue();
 
 
@@ -35,18 +46,23 @@ namespace BansheeEngine
 		 * @brief	Adds a new entry to the render queue.
 		 * @brief	Adds a new entry to the render queue.
 		 *
 		 *
 		 * @param	element			Renderable element to add to the queue.
 		 * @param	element			Renderable element to add to the queue.
-		 * @param	worldPosForSort	World position that will be used for distance sorting of the object.
+		 * @param	distFromCamera	Distance of this object from the camera. Used for distance sorting.
 		 */
 		 */
-		void add(RenderableElement* element, const Vector3& worldPosForSort);
+		void add(RenderableElement* element, float distFromCamera);
 
 
 		/**
 		/**
 		 * @brief	Adds a new entry to the render queue.
 		 * @brief	Adds a new entry to the render queue.
 		 *
 		 *
-		 * @param	material	Material that will be used for rendering the object.
-		 * @param	mesh		Mesh representing the geometry of the object.
-		 * @param	worldPosForSort	World position that will be used for distance sorting of the object.
+		 * @param	material		Material that will be used for rendering the object.
+		 * @param	mesh			Mesh representing the geometry of the object.
+		 * @param	distFromCamera	Distance of this object from the camera. Used for distance sorting.
+		 */
+		void add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, float distFromCamera);
+
+		/**
+		 * @brief	Adds new entries from the provided render queue to this queue.
 		 */
 		 */
-		void add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, const Vector3& worldPosForSort);
+		void add(const RenderQueue& renderQueue);
 
 
 		/**
 		/**
 		 * @brief	Clears all render operations from the queue.
 		 * @brief	Clears all render operations from the queue.
@@ -58,11 +74,6 @@ namespace BansheeEngine
 		 */
 		 */
 		virtual void sort();
 		virtual void sort();
 
 
-		/**
-		 * @brief	Returns internal list of render elements (unsorted).
-		 */
-		const Vector<RenderQueueElement>& getElements() const { return mRenderElements; }
-
 		/**
 		/**
 		 * @brief	Returns a list of sorted render elements. Caller must ensure
 		 * @brief	Returns a list of sorted render elements. Caller must ensure
 		 * 			"sort" is called before this method.
 		 * 			"sort" is called before this method.
@@ -70,7 +81,12 @@ namespace BansheeEngine
 		const Vector<RenderQueueElement>& getSortedElements() const;
 		const Vector<RenderQueueElement>& getSortedElements() const;
 
 
 	protected:
 	protected:
-		Vector<RenderQueueElement> mRenderElements;
+		/**
+		 * @brief	Callback used for sorting elements.
+		 */
+		static bool elementSorter(const SortData&, const SortData&);
+
+		Set<SortData, std::function<bool(const SortData&, const SortData&)>> mRenderElements;
 		Vector<RenderQueueElement> mSortedRenderElements;
 		Vector<RenderQueueElement> mSortedRenderElements;
 	};
 	};
 }
 }

+ 2 - 1
BansheeEngine/Source/BsCamera.cpp

@@ -482,8 +482,9 @@ namespace BansheeEngine
 		proxy->projMatrix = getProjectionMatrix();
 		proxy->projMatrix = getProjectionMatrix();
 		proxy->viewMatrix = getViewMatrix();
 		proxy->viewMatrix = getViewMatrix();
 		proxy->viewport = mViewport->clone();
 		proxy->viewport = mViewport->clone();
-		proxy->frustum = mFrustum;
+		proxy->frustum = getFrustum();
 		proxy->ignoreSceneRenderables = mIgnoreSceneRenderables;
 		proxy->ignoreSceneRenderables = mIgnoreSceneRenderables;
+		proxy->worldPosition = SO()->getWorldPosition();
 
 
 		return proxy;
 		return proxy;
 	}
 	}

+ 56 - 15
BansheeEngine/Source/BsRenderQueue.cpp

@@ -1,11 +1,13 @@
 #include "BsRenderQueue.h"
 #include "BsRenderQueue.h"
 #include "BsMaterialProxy.h"
 #include "BsMaterialProxy.h"
 #include "BsMeshProxy.h"
 #include "BsMeshProxy.h"
+#include "BsShaderProxy.h"
 #include "BsRenderableProxy.h"
 #include "BsRenderableProxy.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	RenderQueue::RenderQueue()
 	RenderQueue::RenderQueue()
+		:mRenderElements(&elementSorter)
 	{
 	{
 
 
 	}
 	}
@@ -16,35 +18,59 @@ namespace BansheeEngine
 		mSortedRenderElements.clear();
 		mSortedRenderElements.clear();
 	}
 	}
 
 
-	void RenderQueue::add(RenderableElement* element, const Vector3& worldPosForSort)
+	void RenderQueue::add(RenderableElement* element, float distFromCamera)
 	{
 	{
-		// TODO - Make sure RenderQueueElements are cached so we dont allocate memory for them every frame
-		mRenderElements.push_back(RenderQueueElement());
+		SortData sortData;
 
 
-		RenderQueueElement& renderOp = mRenderElements.back();
+		RenderQueueElement& renderOp = sortData.element;
 		renderOp.renderElem = element;
 		renderOp.renderElem = element;
 		renderOp.material = element->material;
 		renderOp.material = element->material;
 		renderOp.mesh = element->mesh;
 		renderOp.mesh = element->mesh;
-		renderOp.worldPosition = worldPosForSort;
+
+		sortData.distFromCamera = distFromCamera;
+		sortData.priority = element->material->shader->queuePriority;
+		sortData.sortType = element->material->shader->queueSortType;
+		sortData.seqIdx = (UINT32)mRenderElements.size();
+
+		// TODO - Make sure elements are cached so we dont allocate memory for them every frame
+		mRenderElements.insert(sortData);
 	}
 	}
 
 
-	void RenderQueue::add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, const Vector3& worldPosForSort)
+	void RenderQueue::add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, float distFromCamera)
 	{
 	{
-		// TODO - Make sure RenderQueueElements are cached so we dont allocate memory for them every frame
-		mRenderElements.push_back(RenderQueueElement());
+		SortData sortData;
 
 
-		RenderQueueElement& renderOp = mRenderElements.back();
+		RenderQueueElement& renderOp = sortData.element;
 		renderOp.renderElem = nullptr;
 		renderOp.renderElem = nullptr;
 		renderOp.material = material;
 		renderOp.material = material;
 		renderOp.mesh = mesh;
 		renderOp.mesh = mesh;
-		renderOp.worldPosition = worldPosForSort;
+
+		sortData.distFromCamera = distFromCamera;
+		sortData.priority = material->shader->queuePriority;
+		sortData.sortType = material->shader->queueSortType;
+		sortData.seqIdx = (UINT32)mRenderElements.size();
+
+		// TODO - Make sure elements are cached so we dont allocate memory for them every frame
+		mRenderElements.insert(sortData);
+	}
+
+	void RenderQueue::add(const RenderQueue& renderQueue)
+	{
+		for (auto& elem : renderQueue.mRenderElements)
+		{
+			if (elem.element.renderElem != nullptr)
+				add(elem.element.renderElem, elem.distFromCamera);
+			else
+				add(elem.element.material, elem.element.mesh, elem.distFromCamera);
+		}
 	}
 	}
 
 
 	void RenderQueue::sort()
 	void RenderQueue::sort()
 	{
 	{
-		// Just pass-through for now
-		for (auto& renderElem : mRenderElements)
+		// TODO - I'm ignoring "separate pass" material parameter.
+		for (auto& sortData : mRenderElements)
 		{
 		{
+			const RenderQueueElement& renderElem = sortData.element;
 			UINT32 numPasses = (UINT32)renderElem.material->passes.size();
 			UINT32 numPasses = (UINT32)renderElem.material->passes.size();
 			for (UINT32 i = 0; i < numPasses; i++)
 			for (UINT32 i = 0; i < numPasses; i++)
 			{
 			{
@@ -54,13 +80,28 @@ namespace BansheeEngine
 				sortedElem.renderElem = renderElem.renderElem;
 				sortedElem.renderElem = renderElem.renderElem;
 				sortedElem.material = renderElem.material;
 				sortedElem.material = renderElem.material;
 				sortedElem.mesh = renderElem.mesh;
 				sortedElem.mesh = renderElem.mesh;
-				sortedElem.worldPosition = renderElem.worldPosition;
 				sortedElem.passIdx = i;
 				sortedElem.passIdx = i;
 			}
 			}
 		}
 		}
+	}
+
+	bool RenderQueue::elementSorter(const SortData& a, const SortData& b)
+	{
+		if (a.priority == b.priority)
+		{
+			if (a.sortType == QueueSortType::None || a.sortType != b.sortType)
+				return a.seqIdx < b.seqIdx;
+
+			if (a.distFromCamera == b.distFromCamera)
+				return a.seqIdx < b.seqIdx;
+
+			if (a.sortType == QueueSortType::FrontToBack)
+				return a.distFromCamera < b.distFromCamera;
+			else
+				return a.distFromCamera > b.distFromCamera;
+		}
 
 
-		// TODO - Actually do some sorting. Use material options to sort (isTransparent, isOverlay(need to add this), etc.)
-		// Note: When sorting make sure not to change order of unsorted elements. Some outside managers (like overlay and GUI) will provide render ops which are already sorted
+		return a.priority > b.priority;
 	}
 	}
 
 
 	const Vector<RenderQueueElement>& RenderQueue::getSortedElements() const
 	const Vector<RenderQueueElement>& RenderQueue::getSortedElements() const

+ 30 - 1
BansheeRenderer/Include/BsBansheeLitTexRenderableHandler.h

@@ -8,10 +8,19 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	// TODO UNDOCUMENTED
+	/**
+	 * @brief	Renderer handler that manages initializing, updating
+	 *			and rendering of renderable objects with a single texture
+	 *			and a single light.
+	 *
+	 * @note	This class is DEBUG ONLY. Until a better renderer is complete.
+	 */
 	class BS_BSRND_EXPORT LitTexRenderableHandler : public RenderableHandler
 	class BS_BSRND_EXPORT LitTexRenderableHandler : public RenderableHandler
 	{
 	{
 	public:
 	public:
+		/**
+		 * @brief	Contains lit tex renderable data unique for each object.
+		 */
 		struct PerObjectData
 		struct PerObjectData
 		{
 		{
 			GpuParamBlockBufferPtr perObjectParamBuffer;
 			GpuParamBlockBufferPtr perObjectParamBuffer;
@@ -24,14 +33,34 @@ namespace BansheeEngine
 
 
 		LitTexRenderableHandler();
 		LitTexRenderableHandler();
 
 
+		/**
+		 * @copydoc	RenderableHandler::initializeRenderElem
+		 */
 		void initializeRenderElem(RenderableElement* element);
 		void initializeRenderElem(RenderableElement* element);
 
 
+		/**
+		 * @copydoc	RenderableHandler::bindPerObjectBuffers
+		 */
 		void bindPerObjectBuffers(const RenderableElement* element);
 		void bindPerObjectBuffers(const RenderableElement* element);
 
 
+		/**
+		 * @brief	Updates global parameter buffers with new values. 
+		 *			To be called whenever global values change.
+		 */
 		void updateGlobalBuffers(float time);
 		void updateGlobalBuffers(float time);
+
+		/**
+		 * @brief	Updates object specific parameter buffers with new values.
+		 *			To be called whenever object specific values change.
+		 */
 		void updatePerObjectBuffers(RenderableElement* element, const Matrix4& wvpMatrix);
 		void updatePerObjectBuffers(RenderableElement* element, const Matrix4& wvpMatrix);
 
 
 	protected:
 	protected:
+		/**
+		 * @brief	Creates a new default shader used for lit textured renderables.
+		 *			It is used for matching custom shaders and determining if they
+		 *			comply with lit textured renderable requirements.
+		 */
 		ShaderPtr createDefaultShader();
 		ShaderPtr createDefaultShader();
 
 
 		ShaderPtr defaultShader;
 		ShaderPtr defaultShader;

+ 108 - 4
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -7,6 +7,10 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	/**
+	 * @brief	Semantics that may be used for signaling the renderer
+	 *			for what is a certain shader parameter used for.
+	 */
 	enum BansheeRendererParamSemantic
 	enum BansheeRendererParamSemantic
 	{
 	{
 		RPS_Time = 1000,
 		RPS_Time = 1000,
@@ -14,13 +18,16 @@ namespace BansheeEngine
 	};
 	};
 
 
 	/**
 	/**
-	 * @brief	Default renderer for Banshee. Performs frustum culling, sorting and renders
-	 *			objects plainly according to their shaders with no fancy effects.
+	 * @brief	Default renderer for Banshee. Performs frustum culling, sorting and 
+	 *			renders objects in custom ways determine by renderable handlers.
 	 *
 	 *
+	 * @note	Sim thread unless otherwise noted.
 	 */
 	 */
-	// TODO UNDOCUMENTED
 	class BS_BSRND_EXPORT BansheeRenderer : public Renderer
 	class BS_BSRND_EXPORT BansheeRenderer : public Renderer
 	{
 	{
+		/**
+		 * @brief	Render data for a single render target.
+		 */
 		struct RenderTargetData
 		struct RenderTargetData
 		{
 		{
 			RenderTargetPtr target;
 			RenderTargetPtr target;
@@ -52,28 +59,125 @@ namespace BansheeEngine
 		virtual void _onDeactivated();
 		virtual void _onDeactivated();
 
 
 	private:
 	private:
+		/**
+		 * @brief	Adds a new renderable proxy which will be considered for rendering next frame.
+		 *
+		 * @note	Core thread only.
+		 */
 		void addRenderableProxy(RenderableProxyPtr proxy);
 		void addRenderableProxy(RenderableProxyPtr proxy);
+
+		/**
+		 * @brief	Removes a previously existing renderable proxy so it will no longer be considered
+		 *			for rendering.
+		 *
+		 * @note	Core thread only.
+		 */
 		void removeRenderableProxy(RenderableProxyPtr proxy);
 		void removeRenderableProxy(RenderableProxyPtr proxy);
+
+		/**
+		 * @brief	Updates an existing renderable proxy with new data. This includes data that changes
+		 *			often. For other data it is best to remove old proxy and add new one.
+		 *
+		 * @param	proxy			Proxy to update.
+		 * @param	localToWorld	Local to world transform of the parent Renderable.
+		 *
+		 * @note	Core thread only.
+		 */
 		void updateRenderableProxy(RenderableProxyPtr proxy, Matrix4 localToWorld);
 		void updateRenderableProxy(RenderableProxyPtr proxy, Matrix4 localToWorld);
 
 
+		/**
+		 * @brief	Adds a new camera proxy will be used for rendering renderable proxy objects.
+		 *
+		 * @note	Core thread only.
+		 */
 		void addCameraProxy(CameraProxyPtr proxy);
 		void addCameraProxy(CameraProxyPtr proxy);
+
+		/**
+		 * @brief	Removes an existing camera proxy, meaning the camera will no longer be rendered from.
+		 * 
+		 * @note	Core thread only.
+		 */
 		void removeCameraProxy(CameraProxyPtr proxy);
 		void removeCameraProxy(CameraProxyPtr proxy);
-		void updateCameraProxy(CameraProxyPtr proxy, Matrix4 viewMatrix);
 
 
+		/**
+		 * @brief	Updates an existing camera proxy with new data. This includes data that changes
+		 *			often. For other data it is best to remove old proxy and add new one.
+		 *
+		 * @param	proxy	Proxy to update.
+		 * @param	camera	World transform matrix of the camera.
+		 * @param	camera	View transform matrix of the camera.
+		 *
+		 * @note	Core thread only.
+		 */
+		void updateCameraProxy(CameraProxyPtr proxy, Matrix4 worldMatrix, Matrix4 viewMatrix);
+
+		/**
+		 * @brief	Adds a new set of objects to the cameras render queue.
+		 *
+		 * @param	proxy			Proxy of the render queues camera to add the objects to.
+		 * @param	renderQueue		Objects to add to the cameras queue.
+		 *
+		 * @note	Core thread only.
+		 */
 		void addToRenderQueue(CameraProxyPtr proxy, RenderQueuePtr renderQueue);
 		void addToRenderQueue(CameraProxyPtr proxy, RenderQueuePtr renderQueue);
+
+		/**
+		 * @brief	Updates a material proxy with new parameter data. Usually called when parameters are manually
+		 *			updated from the sim thread.
+		 *
+		 * @param	proxy		Material proxy to update.
+		 * @param	dirtyParams	A list of parameter buffers that need updating.
+		 *
+		 * @note	Core thread only.
+		 */
 		void updateMaterialProxy(MaterialProxyPtr proxy, Vector<MaterialProxy::ParamsBindInfo> dirtyParams);
 		void updateMaterialProxy(MaterialProxyPtr proxy, Vector<MaterialProxy::ParamsBindInfo> dirtyParams);
 
 
+		/**
+		 * @brief	Performs rendering over all camera proxies.
+		 *
+		 * @param	time	Current frame time in milliseconds.
+		 *
+		 * @note	Core thread only.
+		 */
 		void renderAllCore(float time);
 		void renderAllCore(float time);
 
 
 		/**
 		/**
 		 * @brief	Renders all objects visible by the provided camera.
 		 * @brief	Renders all objects visible by the provided camera.
+		 *
+		 * @param	cameraProxy		Camera used for determining destination render target and visibility.
+		 * @param	renderQueue		Optionally non-empty queue of manually added objects to render.
+		 *
+		 * @note	Core thread only.
 		 */
 		 */
 		virtual void render(const CameraProxy& cameraProxy, const RenderQueuePtr& renderQueue);
 		virtual void render(const CameraProxy& cameraProxy, const RenderQueuePtr& renderQueue);
 
 
+		/**
+		 * @brief	Activates the specified pass on the pipeline.
+		 *
+		 * @param	material	Parent material of the pass.
+		 * @param	passIdx		Index of the pass in the parent material.
+		 *
+		 * @note	Core thread only.
+		 */
 		void setPass(const MaterialProxyPtr& material, UINT32 passIdx);
 		void setPass(const MaterialProxyPtr& material, UINT32 passIdx);
+
+		/**
+		 * @brief	Draws the specified mesh proxy with last set pass.
+		 *
+		 * @note	Core thread only.
+		 */
 		void draw(const MeshProxy& mesh);
 		void draw(const MeshProxy& mesh);
 
 
+		/**
+		 * @brief	Called by the scene manager whenever a Renderable component has been
+		 *			removed from the scene.
+		 */
 		void renderableRemoved(const HRenderable& renderable);
 		void renderableRemoved(const HRenderable& renderable);
+
+		/**
+		 * @brief	Called by the scene manager whenever a Camera component has been
+		 *			removed from the scene.
+		 */
 		void cameraRemoved(const HCamera& camera);
 		void cameraRemoved(const HCamera& camera);
 
 
 		Vector<RenderableProxyPtr> mDeletedRenderableProxies;
 		Vector<RenderableProxyPtr> mDeletedRenderableProxies;

+ 21 - 12
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -170,9 +170,18 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void BansheeRenderer::updateCameraProxy(CameraProxyPtr proxy, Matrix4 viewMatrix)
+	void BansheeRenderer::updateCameraProxy(CameraProxyPtr proxy, Matrix4 worldMatrix, Matrix4 viewMatrix)
 	{
 	{
 		proxy->viewMatrix = viewMatrix;
 		proxy->viewMatrix = viewMatrix;
+
+		const Vector<Plane>& frustumPlanes = proxy->frustum.getPlanes();
+		Vector<Plane> worldPlanes;
+		for (auto& plane : frustumPlanes)
+		{
+			worldPlanes.push_back(worldMatrix.multiply3x4(plane));
+		}
+
+		proxy->worldFrustum = ConvexVolume(worldPlanes);
 	}
 	}
 
 
 	void BansheeRenderer::renderableRemoved(const HRenderable& renderable)
 	void BansheeRenderer::renderableRemoved(const HRenderable& renderable)
@@ -288,7 +297,7 @@ namespace BansheeEngine
 				CameraProxyPtr proxy = camera->_getActiveProxy();
 				CameraProxyPtr proxy = camera->_getActiveProxy();
 				assert(proxy != nullptr);
 				assert(proxy != nullptr);
 
 
-				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateCameraProxy, this, proxy, camera->getViewMatrix()));
+				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateCameraProxy, this, proxy, camera->SO()->getWorldTfrm(), camera->getViewMatrix()));
 
 
 				dirtySceneObjects.push_back(camera->SO());
 				dirtySceneObjects.push_back(camera->SO());
 			}
 			}
@@ -341,7 +350,8 @@ namespace BansheeEngine
 				MaterialProxyPtr materialProxy = drawOp.material->_getActiveProxy();
 				MaterialProxyPtr materialProxy = drawOp.material->_getActiveProxy();
 				MeshProxyPtr meshProxy = drawOp.mesh->_getActiveProxy(drawOp.submeshIdx);
 				MeshProxyPtr meshProxy = drawOp.mesh->_getActiveProxy(drawOp.submeshIdx);
 
 
-				renderQueue->add(materialProxy, meshProxy, drawOp.worldPosition);
+				float distanceToCamera = (camera->SO()->getPosition() - drawOp.worldPosition).length();
+				renderQueue->add(materialProxy, meshProxy, distanceToCamera);
 			}
 			}
 
 
 			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->_getActiveProxy(), renderQueue));
 			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->_getActiveProxy(), renderQueue));
@@ -353,12 +363,7 @@ namespace BansheeEngine
 	void BansheeRenderer::addToRenderQueue(CameraProxyPtr proxy, RenderQueuePtr renderQueue)
 	void BansheeRenderer::addToRenderQueue(CameraProxyPtr proxy, RenderQueuePtr renderQueue)
 	{
 	{
 		RenderQueuePtr cameraRenderQueue = proxy->renderQueue;
 		RenderQueuePtr cameraRenderQueue = proxy->renderQueue;
-
-		const Vector<RenderQueueElement>& queueElements = renderQueue->getElements();
-		for (auto& queueElement : queueElements)
-		{
-			cameraRenderQueue->add(queueElement.material, queueElement.mesh, queueElement.worldPosition);
-		}
+		cameraRenderQueue->add(*renderQueue);
 	}
 	}
 
 
 	void BansheeRenderer::updateMaterialProxy(MaterialProxyPtr proxy, Vector<MaterialProxy::ParamsBindInfo> dirtyParams)
 	void BansheeRenderer::updateMaterialProxy(MaterialProxyPtr proxy, Vector<MaterialProxy::ParamsBindInfo> dirtyParams)
@@ -445,13 +450,17 @@ namespace BansheeEngine
 				// TODO - This is bound to be a bottleneck at some point. When it is ensure that intersect
 				// 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.
 				// methods use vector operations, as it is trivial to update them.
 				const Sphere& boundingSphere = mWorldBounds[renderElem->id].getSphere();
 				const Sphere& boundingSphere = mWorldBounds[renderElem->id].getSphere();
-				if (cameraProxy.frustum.intersects(boundingSphere))
+				if (cameraProxy.worldFrustum.intersects(boundingSphere))
 				{
 				{
 					// More precise with the box
 					// More precise with the box
 					const AABox& boundingBox = mWorldBounds[renderElem->id].getBox();
 					const AABox& boundingBox = mWorldBounds[renderElem->id].getBox();
 
 
-					if (cameraProxy.frustum.intersects(boundingBox))
-						renderQueue->add(renderElem, boundingSphere.getCenter());
+					if (cameraProxy.worldFrustum.intersects(boundingBox))
+					{
+						float distanceToCamera = (cameraProxy.worldPosition - boundingBox.getCenter()).length();
+
+						renderQueue->add(renderElem, distanceToCamera);
+					}
 				}
 				}
 			}
 			}
 		}
 		}

+ 6 - 0
BansheeUtility/Include/BsConvexVolume.h

@@ -12,6 +12,7 @@ namespace BansheeEngine
 	class BS_UTILITY_EXPORT ConvexVolume
 	class BS_UTILITY_EXPORT ConvexVolume
 	{
 	{
 	public:
 	public:
+		ConvexVolume() {}
 		ConvexVolume(const Vector<Plane>& planes);
 		ConvexVolume(const Vector<Plane>& planes);
 
 
 		/**
 		/**
@@ -26,6 +27,11 @@ namespace BansheeEngine
 		 */
 		 */
 		bool intersects(const Sphere& sphere) const;
 		bool intersects(const Sphere& sphere) const;
 
 
+		/**
+		 * @brief	Returns the internal set of planes that represent the volume.
+		 */
+		const Vector<Plane> getPlanes() const { return mPlanes; }
+
 	private:
 	private:
 		Vector<Plane> mPlanes;
 		Vector<Plane> mPlanes;
 	};
 	};

+ 17 - 0
BansheeUtility/Include/BsMatrix4.h

@@ -357,6 +357,23 @@ namespace BansheeEngine
                 v.w);
                 v.w);
         }
         }
 
 
+        /**
+         * @brief	Transform a plane by this matrix.
+         * 			
+         * @note	Matrix must be affine.
+         */
+        Plane multiply3x4(const Plane& p) const
+        {
+			Vector4 localNormal(p.normal.x, p.normal.y, p.normal.z, 0.0f);
+			Vector4 localPoint = localNormal * p.d;
+
+			Vector4 worldNormal = inverse().transpose().multiply3x4(localNormal);
+			Vector4 worldPoint = multiply3x4(localPoint);
+
+			float d = worldNormal.dot(worldPoint);
+			return Plane(worldNormal.x, worldNormal.y, worldNormal.z, d);
+        }
+
         /**
         /**
          * @brief	Transform a 3D vector by this matrix.  
          * @brief	Transform a 3D vector by this matrix.  
          *
          *

+ 2 - 0
BansheeUtility/Source/BsConvexVolume.cpp

@@ -29,6 +29,8 @@ namespace BansheeEngine
 			if (dist > pushOut)
 			if (dist > pushOut)
 				return false;
 				return false;
 		}
 		}
+
+		return true;
 	}
 	}
 
 
 	bool ConvexVolume::intersects(const Sphere& sphere) const
 	bool ConvexVolume::intersects(const Sphere& sphere) const

+ 2 - 7
BansheeUtility/Source/BsSphere.cpp

@@ -18,13 +18,8 @@ namespace BansheeEngine
 
 
 	void Sphere::merge(const Vector3& point)
 	void Sphere::merge(const Vector3& point)
 	{
 	{
-		Vector3 newCenter = (mCenter + point) * 0.5f;
-
-		float newRadiusA = newCenter.distance(mCenter) + getRadius();
-		float newRadiusB = newCenter.distance(point);
-
-		mCenter = newCenter;
-		mRadius = std::max(newRadiusA, newRadiusB);
+		float dist = point.distance(mCenter);
+		mRadius = std::max(mRadius, dist);
 	}
 	}
 
 
 	void Sphere::transform(const Matrix4& matrix)
 	void Sphere::transform(const Matrix4& matrix)

+ 3 - 3
Polish.txt

@@ -1,6 +1,4 @@
 Polish TODO:
 Polish TODO:
- - Implement RenderQueue sorting with support for sort type, priority and separable pass
-    - Use a hash list(containing type, queue, layer, etc.) for faster sorting
  - Finalize example with resolution settings and proper GUI
  - Finalize example with resolution settings and proper GUI
  - Finish documentation (BansheeEngine + TODO UNDOCUMENTED)
  - Finish documentation (BansheeEngine + TODO UNDOCUMENTED)
 
 
@@ -8,6 +6,7 @@ Polish TODO:
  - Make a separate release branch with no editor/script stuff, and without .txt files and other development data
  - Make a separate release branch with no editor/script stuff, and without .txt files and other development data
 
 
 Re-test gamepad buttons now that XInput is active
 Re-test gamepad buttons now that XInput is active
+Test frustum culling
 
 
 -----------------
 -----------------
 
 
@@ -26,4 +25,5 @@ Not so critical
   - Compress and generate mips for texture on input (testing NVTT stuff)
   - Compress and generate mips for texture on input (testing NVTT stuff)
   - Perform optimizations as needed to get reasonable performance
   - Perform optimizations as needed to get reasonable performance
   - Consider removing SceneManager from Core? I two scene manager base classes.
   - Consider removing SceneManager from Core? I two scene manager base classes.
-  - GpuParamBlockBuffer and GpuParams::cloneForCore are very clumsy in how they deal in keeping two separate param blocks. Rethink this a bit.
+  - GpuParamBlockBuffer and GpuParams::cloneForCore are very clumsy in how they deal in keeping two separate param blocks. Rethink this a bit.
+  - Add separable pass sorting to RenderQueue