Browse Source

Refactoring renderer in order to make it cleaner, easier to understand and modify

BearishSun 9 years ago
parent
commit
1a60bbfc1d

+ 0 - 2
Source/BansheeEngine/CMakeSources.cmake

@@ -92,7 +92,6 @@ set(BS_BANSHEEENGINE_INC_RENDERER
 	"Include/BsLight.h"
 	"Include/BsRenderable.h"
 	"Include/BsRenderableElement.h"
-	"Include/BsRenderableHandler.h"
 	"Include/BsRenderer.h"
 	"Include/BsRendererMaterial.h"
 	"Include/BsRendererMaterialManager.h"
@@ -197,7 +196,6 @@ set(BS_BANSHEEENGINE_SRC_RENDERER
 	"Source/BsCamera.cpp"
 	"Source/BsLight.cpp"
 	"Source/BsRenderable.cpp"
-	"Source/BsRenderableHandler.cpp"
 	"Source/BsRenderer.cpp"
 	"Source/BsRendererMaterial.cpp"
 	"Source/BsRendererMaterialManager.cpp"

+ 0 - 9
Source/BansheeEngine/Include/BsEnums.h

@@ -26,15 +26,6 @@ namespace BansheeEngine
 		Count
 	};
 
-	/**
-	 * Contains a basic sent of renderable types that may be supported by a renderer. These can be used just as a guide 
-	 * since renderer plugins can use their own types as needed.
-	 */
-	enum RenderableType
-	{
-		RenType_LitTextured
-	};
-
 	/**	Type of scaling modes for GUI images. */
 	enum class TextureScaleMode
 	{

+ 0 - 3
Source/BansheeEngine/Include/BsRenderable.h

@@ -161,9 +161,6 @@ namespace BansheeEngine
 		/**	Gets world bounds of the mesh rendered by this object. */
 		Bounds getBounds() const;
 
-		/**	Returns the type that controls how is this object rendered. */
-		RenderableType getRenderableType() const { return RenType_LitTextured; }
-
 		/**	Sets an ID that can be used for uniquely identifying this handler by the renderer. */
 		void setRendererId(UINT32 id) { mRendererId = id; }
 

+ 0 - 20
Source/BansheeEngine/Include/BsRenderableElement.h

@@ -3,8 +3,6 @@
 #pragma once
 
 #include "BsPrerequisites.h"
-#include "BsBounds.h"
-#include "BsMatrix4.h"
 #include "BsSubMesh.h"
 
 namespace BansheeEngine
@@ -17,19 +15,6 @@ namespace BansheeEngine
 	class BS_EXPORT RenderableElement
 	{
 	public:
-		/**	Contains a hardware GPU parameter buffer and index of the parameters and the slot it binds to in a material. */
-		struct BS_EXPORT BufferBindInfo
-		{
-			BufferBindInfo(UINT32 passIdx, UINT32 paramsIdx, UINT32 slotIdx, const SPtr<GpuParamBlockBufferCore>& buffer)
-				:passIdx(passIdx), paramsIdx(paramsIdx), slotIdx(slotIdx), buffer(buffer)
-			{ }
-
-			UINT32 passIdx;
-			UINT32 paramsIdx;
-			UINT32 slotIdx;
-			SPtr<GpuParamBlockBufferCore> buffer;
-		};
-
 		/**	Reference to the mesh to render. */
 		SPtr<MeshCore> mesh;
 
@@ -38,11 +23,6 @@ namespace BansheeEngine
 
 		/**	Material to render the mesh with. */
 		SPtr<MaterialCore> material;
-
-		/**	Custom data that may optionally be set by the RenderableHandler. */
-		Any rendererData;
-
-		Vector<BufferBindInfo> rendererBuffers;
 	};
 
 	/** @} */

+ 0 - 39
Source/BansheeEngine/Include/BsRenderableHandler.h

@@ -1,39 +0,0 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Renderer-Engine-Internal
-	 *  @{
-	 */
-
-	/**
-	 * Abstract class that provides an interface for initializing renderable elements of a certain type, along with their
-	 * GPU parameter buffers.
-	 *
-	 * Essentially this class holds all the information that is needed for rendering an element of a certain renderable 
-	 * type.
-	 */
-	class BS_EXPORT RenderableHandler
-	{
-	public:
-		virtual ~RenderableHandler() {}
-
-		/**
-		 * Initializes the specified renderable element, making it ready to be used. Caller must ensure the renderable
-		 * element actually supports this handler.
-		 */
-		virtual void initializeRenderElem(RenderableElement& element) = 0;
-
-		/**	Binds per object GPU parameter buffers to the provided element. */
-		virtual void bindPerObjectBuffers(const RenderableElement& element) = 0;
-
-		/** Binds global GPU parameter buffers used for this Renderable type to the provided element. */
-		virtual void bindGlobalBuffers(const RenderableElement& element);
-	};
-
-	/** @} */
-}

+ 0 - 18
Source/BansheeEngine/Source/BsRenderableHandler.cpp

@@ -1,18 +0,0 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsRenderableHandler.h"
-#include "BsGpuParams.h"
-#include "BsMaterial.h"
-#include "BsRenderableElement.h"
-
-namespace BansheeEngine
-{
-	void RenderableHandler::bindGlobalBuffers(const RenderableElement& element)
-	{
-		for (auto& rendererBuffer : element.rendererBuffers)
-		{
-			SPtr<PassParametersCore> passParams = element.material->getPassParameters(rendererBuffer.passIdx);
-			passParams->getParamByIdx(rendererBuffer.paramsIdx)->setParamBlockBuffer(rendererBuffer.slotIdx, rendererBuffer.buffer);
-		}
-	}
-}

+ 5 - 2
Source/RenderBeast/CMakeSources.cmake

@@ -6,9 +6,11 @@ set(BS_RENDERBEAST_INC_NOFILTER
 	"Include/BsRenderBeastFactory.h"
 	"Include/BsRenderBeastPrerequisites.h"
 	"Include/BsRenderTargets.h"
-	"Include/BsStaticRenderableHandler.h"
+	"Include/BsObjectRendering.h"
 	"Include/BsLightRendering.h"
 	"Include/BsPostProcessing.h"
+	"Include/BsRendererCamera.h"
+	"Include/BsRendererObject.h"
 )
 
 set(BS_RENDERBEAST_SRC_NOFILTER
@@ -18,9 +20,10 @@ set(BS_RENDERBEAST_SRC_NOFILTER
 	"Source/BsRenderBeastFactory.cpp"
 	"Source/BsRenderBeastPlugin.cpp"
 	"Source/BsRenderTargets.cpp"
-	"Source/BsStaticRenderableHandler.cpp"
+	"Source/BsObjectRendering.cpp"
 	"Source/BsLightRendering.cpp"
 	"Source/BsPostProcessing.cpp"
+	"Source/BsRendererCamera.cpp"
 )
 
 source_group("Header Files" FILES ${BS_RENDERBEAST_INC_NOFILTER})

+ 104 - 86
Source/RenderBeast/Include/BsStaticRenderableHandler.h → Source/RenderBeast/Include/BsObjectRendering.h

@@ -1,87 +1,105 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsRenderBeastPrerequisites.h"
-#include "BsRenderableHandler.h"
-#include "BsGpuParamDesc.h"
-#include "BsGpuParam.h"
-#include "BsRenderableElement.h"
-#include "BsRenderBeast.h"
-#include "BsParamBlocks.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup RenderBeast
-	 *  @{
-	 */
-
-	BS_PARAM_BLOCK_BEGIN(PerFrameParamBuffer)
-		BS_PARAM_BLOCK_ENTRY(float, gTime)
-	BS_PARAM_BLOCK_END
-
-	BS_PARAM_BLOCK_BEGIN(PerCameraParamBuffer)
-		BS_PARAM_BLOCK_ENTRY(Vector3, gViewDir)
-		BS_PARAM_BLOCK_ENTRY(Vector3, gViewOrigin)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatView)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatProj)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvProj)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvViewProj)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatScreenToWorld)
-		BS_PARAM_BLOCK_ENTRY(Vector2, gDeviceZToWorldZ)
-		BS_PARAM_BLOCK_ENTRY(Vector4, gClipToUVScaleOffset)
-	BS_PARAM_BLOCK_END
-
-	BS_PARAM_BLOCK_BEGIN(PerObjectParamBuffer)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorldViewProj)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorld)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvWorld)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorldNoScale)
-		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvWorldNoScale)
-		BS_PARAM_BLOCK_ENTRY(float, gWorldDeterminantSign)
-	BS_PARAM_BLOCK_END
-
-	/** Renderable handler that manages initializing, updating and rendering of static renderable objects. */
-	class BS_BSRND_EXPORT StaticRenderableHandler : public RenderableHandler
-	{
-	public:
-		/** Contains lit tex renderable data unique for each object. */
-		struct PerObjectData
-		{
-			Vector<RenderableElement::BufferBindInfo> perObjectBuffers;
-		};
-
-		StaticRenderableHandler();
-
-		/** @copydoc RenderableHandler::initializeRenderElem */
-		void initializeRenderElem(RenderableElement& element) override;
-
-		/** @copydoc RenderableHandler::bindPerObjectBuffers */
-		void bindPerObjectBuffers(const RenderableElement& element) override;
-
-		/** Updates global per frame parameter buffers with new values. To be called at the start of every frame. */
-		void updatePerFrameBuffers(float time);
-
-		/**
-		 * Updates global per frame parameter buffers with new values. To be called at the start of rendering for every 
-		 * camera.
-		 */
-		void updatePerCameraBuffers(const CameraShaderData& cameraData);
-
-		/**
-		 * Updates object specific parameter buffers with new values. To be called whenever object specific values change.
-		 */
-		void updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix);
-
-		/** Returns a buffer that stores per-camera parameters. */
-		const PerCameraParamBuffer& getPerCameraParams() const { return mPerCameraParams; }
-
-	protected:
-		PerFrameParamBuffer mPerFrameParams;
-		PerCameraParamBuffer mPerCameraParams;
-		PerObjectParamBuffer mPerObjectParams;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsRenderBeastPrerequisites.h"
+#include "BsGpuParamDesc.h"
+#include "BsGpuParam.h"
+#include "BsRenderableElement.h"
+#include "BsRendererMaterial.h"
+#include "BsParamBlocks.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RenderBeast
+	 *  @{
+	 */
+
+	BS_PARAM_BLOCK_BEGIN(PerFrameParamBuffer)
+		BS_PARAM_BLOCK_ENTRY(float, gTime)
+	BS_PARAM_BLOCK_END
+
+	BS_PARAM_BLOCK_BEGIN(PerCameraParamBuffer)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gViewDir)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gViewOrigin)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatView)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvViewProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatScreenToWorld)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gDeviceZToWorldZ)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gClipToUVScaleOffset)
+	BS_PARAM_BLOCK_END
+
+	BS_PARAM_BLOCK_BEGIN(PerObjectParamBuffer)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorldViewProj)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorld)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvWorld)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatWorldNoScale)
+		BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvWorldNoScale)
+		BS_PARAM_BLOCK_ENTRY(float, gWorldDeterminantSign)
+	BS_PARAM_BLOCK_END
+
+	/**	Data bound to the shader when rendering a specific renderable object. */
+	struct RenderableShaderData
+	{
+		Matrix4 worldTransform;
+		Matrix4 invWorldTransform;
+		Matrix4 worldNoScaleTransform;
+		Matrix4 invWorldNoScaleTransform;
+		float worldDeterminantSign;
+	};
+
+	/**	Data bound to the shader when rendering a with a specific camera. */
+	struct CameraShaderData
+	{
+		Vector3 viewDir;
+		Vector3 viewOrigin;
+		Matrix4 view;
+		Matrix4 proj;
+		Matrix4 viewProj;
+		Matrix4 invProj;
+		Matrix4 invViewProj;
+		Matrix4 screenToWorld;
+		Vector2 deviceZToWorldZ;
+		Vector4 clipToUVScaleOffset;
+	};
+
+	/** Manages initialization and rendering of individual renderable object, represented as RenderableElement%s. */
+	class BS_BSRND_EXPORT ObjectRenderer
+	{
+	public:
+		ObjectRenderer();
+
+		/** Initializes the specified renderable element, making it ready to be used. */
+		void initElement(RenderableElement& element);
+
+		/** Updates global per frame parameter buffers with new values. To be called at the start of every frame. */
+		void updatePerFrameBuffers(float time);
+
+		/**
+		 * Updates global per frame parameter buffers with new values. To be called at the start of rendering for every 
+		 * camera.
+		 */
+		void updatePerCameraBuffers(const CameraShaderData& cameraData);
+
+		/**
+		 * Updates object specific parameter buffers with new values. To be called whenever object specific values change.
+		 */
+		void updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix);
+
+		/** Returns a buffer that stores per-camera parameters. */
+		const PerCameraParamBuffer& getPerCameraParams() const { return mPerCameraParams; }
+
+	protected:
+		PerFrameParamBuffer mPerFrameParams;
+		PerCameraParamBuffer mPerCameraParams;
+		PerObjectParamBuffer mPerObjectParams;
+	};
+
+	/** Basic shader that is used when no other is available. */
+	class DefaultMaterial : public RendererMaterial<DefaultMaterial> { RMAT_DEF("Default.bsl"); };
+
+	/** @} */
 }

+ 8 - 96
Source/RenderBeast/Include/BsRenderBeast.h

@@ -5,11 +5,13 @@
 #include "BsRenderBeastPrerequisites.h"
 #include "BsRenderer.h"
 #include "BsBounds.h"
-#include "BsRenderableElement.h"
 #include "BsSamplerOverrides.h"
 #include "BsRendererMaterial.h"
 #include "BsLightRendering.h"
+#include "BsObjectRendering.h"
 #include "BsPostProcessing.h"
+#include "BsRendererCamera.h"
+#include "BsRendererObject.h"
 
 namespace BansheeEngine
 {
@@ -17,74 +19,18 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	class BeastRenderableElement;
-
 	/** Semantics that may be used for signaling the renderer for what is a certain shader parameter used for. */
 	static StringID RPS_GBufferA = "GBufferA";
 	static StringID RPS_GBufferB = "GBufferB";
 	static StringID RPS_GBufferDepth = "GBufferDepth";
 
-	/** Basic shader that is used when no other is available. */
-	class DefaultMaterial : public RendererMaterial<DefaultMaterial> { RMAT_DEF("Default.bsl"); };
-
-	/**	Data used by the renderer when rendering renderable handlers. */
-	struct RenderableData
-	{
-		RenderableCore* renderable;
-		Vector<BeastRenderableElement> elements;
-		RenderableHandler* controller;
-	};
-
-	/**	Data bound to the shader when rendering a specific renderable. */
-	struct RenderableShaderData
-	{
-		Matrix4 worldTransform;
-		Matrix4 invWorldTransform;
-		Matrix4 worldNoScaleTransform;
-		Matrix4 invWorldNoScaleTransform;
-		float worldDeterminantSign;
-	};
-
-	/**	Data bound to the shader when rendering a with a specific camera. */
-	struct CameraShaderData
-	{
-		Vector3 viewDir;
-		Vector3 viewOrigin;
-		Matrix4 view;
-		Matrix4 proj;
-		Matrix4 viewProj;
-		Matrix4 invProj;
-		Matrix4 invViewProj;
-		Matrix4 screenToWorld;
-		Vector2 deviceZToWorldZ;
-		Vector4 clipToUVScaleOffset;
-	};
-
-	/**
-	 * @copydoc	RenderableElement
-	 *
-	 * Contains additional data specific to RenderBeast renderer.
-	 */
-	class BS_BSRND_EXPORT BeastRenderableElement : public RenderableElement
-	{
-	public:
-		/**
-		 * Optional overrides for material sampler states. Used when renderer wants to override certain sampling properties
-		 * on a global scale (for example filtering most commonly).
-		 */
-		MaterialSamplerOverrides* samplerOverrides;
-
-		/**	Identifier of the owner renderable. */
-		UINT32 renderableId;
-	};
-
 	/**
 	 * Default renderer for Banshee. Performs frustum culling, sorting and renders objects in custom ways determine by
 	 * renderable handlers.
 	 *
 	 * @note	Sim thread unless otherwise noted.
 	 */
-	class BS_BSRND_EXPORT RenderBeast : public Renderer
+	class RenderBeast : public Renderer
 	{
 		/**	Render data for a single render target. */
 		struct RenderTargetData
@@ -93,16 +39,6 @@ namespace BansheeEngine
 			Vector<const CameraCore*> cameras;
 		};
 
-		/**	Data used by the renderer for a camera. */
-		struct CameraData
-		{
-			SPtr<RenderQueue> opaqueQueue;
-			SPtr<RenderQueue> transparentQueue;
-
-			SPtr<RenderTargets> target;
-			PostProcessInfo postProcessInfo;
-		};
-
 		/**	Data used by the renderer for lights. */
 		struct LightData
 		{
@@ -185,13 +121,6 @@ namespace BansheeEngine
 		 */
 		void renderAllCore(float time, float delta);
 
-		/**
-		 * Populates camera render queues by determining visible renderable object.
-		 *
-		 * @param[in]	camera	The camera to determine visibility for.
-		 */
-		void determineVisible(const CameraCore& camera);
-
 		/**
 		 * Renders all objects visible by the provided camera.
 		 *
@@ -228,24 +157,6 @@ namespace BansheeEngine
 		 */
 		void refreshSamplerOverrides(bool force = false);
 
-		/**
-		 * Extracts the necessary values from the projection matrix that allow you to transform device Z value into
-		 * world Z value.
-		 * 			
-		 * @param[in]	projMatrix	Projection matrix that was used to create the device Z value to transform.
-		 * @return					Returns two values that can be used to transform device z to world z using this formula:
-		 * 							z = (deviceZ + y) * x.
-		 */
-		static Vector2 getDeviceZTransform(const Matrix4& projMatrix);
-
-		/**
-		 * Populates the provided camera shader data object with data from the provided camera. The object can then be used
-		 * for populating per-camera parameter buffers.
-		 * 			
-		 * @note	Core thread.
-		 */
-		static CameraShaderData getCameraShaderData(const CameraCore& camera);
-
 		/**
 		 * Sets parameters (textures, samplers, buffers) for the currently active pass.
 		 *
@@ -259,10 +170,10 @@ namespace BansheeEngine
 
 		// Core thread only fields
 		Vector<RenderTargetData> mRenderTargets;
-		UnorderedMap<const CameraCore*, CameraData> mCameraData;
+		UnorderedMap<const CameraCore*, RendererCamera> mCameras;
 		UnorderedMap<SPtr<MaterialCore>, MaterialSamplerOverrides*> mSamplerOverrides;
 
-		Vector<RenderableData> mRenderables;
+		Vector<RendererObject> mRenderables;
 		Vector<RenderableShaderData> mRenderableShaderData;
 		Vector<Bounds> mWorldBounds;
 
@@ -277,8 +188,9 @@ namespace BansheeEngine
 		PointLightOutMat* mPointLightOutMat;
 		DirectionalLightMat* mDirLightMat;
 
+		ObjectRenderer* mObjectRenderer;
+
 		// Sim thread only fields
-		StaticRenderableHandler* mStaticHandler;
 		SPtr<RenderBeastOptions> mOptions;
 		bool mOptionsDirty;
 	};

+ 1 - 1
Source/RenderBeast/Include/BsRenderBeastPrerequisites.h

@@ -32,7 +32,7 @@
 
 namespace BansheeEngine
 {
-	class StaticRenderableHandler;
+	class ObjectRenderer;
 	struct RenderBeastOptions;
 	struct PooledRenderTexture;
 	class RenderTargets;

+ 90 - 0
Source/RenderBeast/Include/BsRendererCamera.h

@@ -0,0 +1,90 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsRenderBeastPrerequisites.h"
+#include "BsPostProcessing.h"
+#include "BsObjectRendering.h"
+#include "BsRenderQueue.h"
+#include "BsRendererObject.h"
+#include "BsBounds.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RenderBeast
+	 *  @{
+	 */
+
+	/** Contains information about a Camera, used by the Renderer. */
+	class RendererCamera
+	{
+	public:
+		RendererCamera();
+		RendererCamera(const CameraCore* camera, StateReduction reductionMode);
+
+		/** Updates the internal camera data, usually called after source camera changes. */
+		void update(StateReduction reductionMode);
+
+		/** Updates the internal camera post-processing data. */
+		void updatePP();
+
+		/** 
+		 * Prepares camera render targets for rendering. When done call endRendering().
+		 *
+		 * @param[in]	useRenderTargets	If using the internal render targets containing the GBuffer (retrieved via
+		 *									getRenderTargets()) while rendering you must set this to true.
+		 */
+		void beginRendering(bool useRenderTargets);
+
+		/** Ends rendering and frees any acquired resources. */
+		void endRendering();
+
+		/** Returns the camera's renderTargets. Only valid if called in-between beginRendering() and endRendering() calls. */
+		SPtr<RenderTargets> getRenderTargets() const { return mRenderTargets; }
+
+		/** 
+		 * Returns a render queue containing all opaque objects. Make sure to call determineVisible() beforehand if camera 
+		 * or object transforms changed since the last time it was called.
+		 */
+		const SPtr<RenderQueue>& getOpaqueQueue() const { return mOpaqueQueue; }
+		
+		/** 
+		 * Returns a render queue containing all transparent objects. Make sure to call determineVisible() beforehand if 
+		 * camera or object transforms changed since the last time it was called.
+		 */
+		const SPtr<RenderQueue>& getTransparentQueue() const { return mTransparentQueue; }
+
+		/** Populates camera render queues by determining visible renderable objects. */
+		void determineVisible(Vector<RendererObject>& renderables, const Vector<Bounds>& renderableBounds);
+
+		/** 
+		 * Returns a structure containing information about post-processing effects. This structure will be modified and
+		 * maintained by the post-processing system.
+		 */
+		PostProcessInfo& getPPInfo() { return mPostProcessInfo; }
+
+		/** Returns an object with camera's information, used for populating per-camera parameter buffers. */
+		CameraShaderData getShaderData();
+
+	private:
+		/**
+		 * Extracts the necessary values from the projection matrix that allow you to transform device Z value into
+		 * world Z value.
+		 * 			
+		 * @param[in]	projMatrix	Projection matrix that was used to create the device Z value to transform.
+		 * @return					Returns two values that can be used to transform device z to world z using this formula:
+		 * 							z = (deviceZ + y) * x.
+		 */
+		Vector2 getDeviceZTransform(const Matrix4& projMatrix);
+
+		const CameraCore* mCamera;
+		SPtr<RenderQueue> mOpaqueQueue;
+		SPtr<RenderQueue> mTransparentQueue;
+
+		SPtr<RenderTargets> mRenderTargets;
+		PostProcessInfo mPostProcessInfo;
+		bool mUsingRenderTargets;
+	};
+
+	/** @} */
+}

+ 42 - 0
Source/RenderBeast/Include/BsRendererObject.h

@@ -0,0 +1,42 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsRenderBeastPrerequisites.h"
+#include "BsRenderableElement.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RenderBeast
+	 *  @{
+	 */
+
+	struct MaterialSamplerOverrides;
+
+	/**
+	 * @copydoc	RenderableElement
+	 *
+	 * Contains additional data specific to RenderBeast renderer.
+	 */
+	class BeastRenderableElement : public RenderableElement
+	{
+	public:
+		/**
+		 * Optional overrides for material sampler states. Used when renderer wants to override certain sampling properties
+		 * on a global scale (for example filtering most commonly).
+		 */
+		MaterialSamplerOverrides* samplerOverrides;
+
+		/**	Identifier of the owner renderable. */
+		UINT32 renderableId;
+	};
+
+	 /** Contains information about a Renderable, used by the Renderer. */
+	struct RendererObject
+	{
+		RenderableCore* renderable;
+		Vector<BeastRenderableElement> elements;
+	};
+
+	/** @} */
+}

+ 26 - 26
Source/RenderBeast/Source/BsStaticRenderableHandler.cpp → Source/RenderBeast/Source/BsObjectRendering.cpp

@@ -1,6 +1,6 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsStaticRenderableHandler.h"
+#include "BsObjectRendering.h"
 #include "BsShader.h"
 #include "BsGpuParams.h"
 #include "BsRenderBeast.h"
@@ -8,14 +8,11 @@
 
 namespace BansheeEngine
 {
-	StaticRenderableHandler::StaticRenderableHandler()
+	ObjectRenderer::ObjectRenderer()
 	{ }
 
-	void StaticRenderableHandler::initializeRenderElem(RenderableElement& element)
+	void ObjectRenderer::initElement(RenderableElement& element)
 	{
-		element.rendererData = PerObjectData();
-		PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
-
 		SPtr<ShaderCore> shader = element.material->getShader();
 		if (shader == nullptr)
 		{
@@ -51,17 +48,20 @@ namespace BansheeEngine
 
 				const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
 
+				// Note: We only validate buffer size and not buffer contents. We should check the contents as well, but
+				// likely on a higher level rather than here.
+				
 				if (perFrameBlockName != "")
 				{
 					auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
 					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 == mPerFrameParams.getDesc().blockSize)
 						{
+							SPtr<GpuParamsCore> params = element.material->getPassParameters(i)->getParamByIdx(j);
+
 							UINT32 slotIdx = findIter->second.slot;
-							element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerFrameParams.getBuffer()));
+							params->setParamBlockBuffer(slotIdx, mPerFrameParams.getBuffer());
 						}
 					}
 				}
@@ -73,8 +73,10 @@ namespace BansheeEngine
 					{
 						if (findIter->second.blockSize == mPerCameraParams.getDesc().blockSize)
 						{
+							SPtr<GpuParamsCore> params = element.material->getPassParameters(i)->getParamByIdx(j);
+
 							UINT32 slotIdx = findIter->second.slot;
-							element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerCameraParams.getBuffer()));
+							params->setParamBlockBuffer(slotIdx, mPerCameraParams.getBuffer());
 						}
 					}
 				}
@@ -86,8 +88,10 @@ namespace BansheeEngine
 					{
 						if (findIter->second.blockSize == mPerObjectParams.getDesc().blockSize)
 						{
+							SPtr<GpuParamsCore> params = element.material->getPassParameters(i)->getParamByIdx(j);
+
 							UINT32 slotIdx = findIter->second.slot;
-							rendererData->perObjectBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, mPerObjectParams.getBuffer()));
+							params->setParamBlockBuffer(slotIdx, mPerObjectParams.getBuffer());
 						}
 					}
 				}
@@ -95,23 +99,12 @@ namespace BansheeEngine
 		}
 	}
 
-	void StaticRenderableHandler::bindPerObjectBuffers(const RenderableElement& element)
-	{
-		const PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
-		for (auto& perObjectBuffer : rendererData->perObjectBuffers)
-		{
-			SPtr<GpuParamsCore> params = element.material->getPassParameters(perObjectBuffer.passIdx)->getParamByIdx(perObjectBuffer.paramsIdx);
-
-			params->setParamBlockBuffer(perObjectBuffer.slotIdx, perObjectBuffer.buffer);
-		}
-	}
-
-	void StaticRenderableHandler::updatePerFrameBuffers(float time)
+	void ObjectRenderer::updatePerFrameBuffers(float time)
 	{
 		mPerFrameParams.gTime.set(time);
 	}
 
-	void StaticRenderableHandler::updatePerCameraBuffers(const CameraShaderData& cameraData)
+	void ObjectRenderer::updatePerCameraBuffers(const CameraShaderData& cameraData)
 	{
 		mPerCameraParams.gViewDir.set(cameraData.viewDir);
 		mPerCameraParams.gViewOrigin.set(cameraData.viewOrigin);
@@ -127,9 +120,11 @@ namespace BansheeEngine
 		mPerCameraParams.flushToGPU();
 	}
 
-	void StaticRenderableHandler::updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, const Matrix4& wvpMatrix)
+	void ObjectRenderer::updatePerObjectBuffers(RenderableElement& element, const RenderableShaderData& data, 
+		const Matrix4& wvpMatrix)
 	{
-		// TODO - If I kept all the values in the same structure maybe a simple memcpy directly into the constant buffer would be better (i.e. faster)?
+		// Note: If I kept all the values in the same structure maybe a simple memcpy directly into the constant buffer
+		// would be better (i.e. faster)?
 		mPerObjectParams.gMatWorld.set(data.worldTransform);
 		mPerObjectParams.gMatInvWorld.set(data.invWorldTransform);
 		mPerObjectParams.gMatWorldNoScale.set(data.worldNoScaleTransform);
@@ -137,4 +132,9 @@ namespace BansheeEngine
 		mPerObjectParams.gWorldDeterminantSign.set(data.worldDeterminantSign);
 		mPerObjectParams.gMatWorldViewProj.set(wvpMatrix);
 	}
+
+	void DefaultMaterial::_initDefines(ShaderDefines& defines)
+	{
+		// Do nothing
+	}
 }

+ 46 - 232
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -6,9 +6,6 @@
 #include "BsMaterial.h"
 #include "BsMesh.h"
 #include "BsPass.h"
-#include "BsBlendState.h"
-#include "BsRasterizerState.h"
-#include "BsDepthStencilState.h"
 #include "BsSamplerState.h"
 #include "BsCoreApplication.h"
 #include "BsViewport.h"
@@ -19,7 +16,6 @@
 #include "BsProfilerCPU.h"
 #include "BsShader.h"
 #include "BsGpuParamBlockBuffer.h"
-#include "BsStaticRenderableHandler.h"
 #include "BsTime.h"
 #include "BsRenderableElement.h"
 #include "BsCoreObjectManager.h"
@@ -29,7 +25,6 @@
 #include "BsRenderTexturePool.h"
 #include "BsRenderTargets.h"
 #include "BsRendererUtility.h"
-#include "BsRenderStateManager.h"
 
 using namespace std::placeholders;
 
@@ -37,7 +32,7 @@ namespace BansheeEngine
 {
 	RenderBeast::RenderBeast()
 		: mDefaultMaterial(nullptr), mPointLightInMat(nullptr), mPointLightOutMat(nullptr), mDirLightMat(nullptr)
-		, mStaticHandler(nullptr), mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true)
+		, mObjectRenderer(nullptr), mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true)
 	{
 
 	}
@@ -68,7 +63,7 @@ namespace BansheeEngine
 		RendererUtility::startUp();
 
 		mCoreOptions = bs_shared_ptr_new<RenderBeastOptions>();
-		mStaticHandler = bs_new<StaticRenderableHandler>();
+		mObjectRenderer = bs_new<ObjectRenderer>();
 
 		mDefaultMaterial = bs_new<DefaultMaterial>();
 		mPointLightInMat = bs_new<PointLightInMat>();
@@ -81,11 +76,11 @@ namespace BansheeEngine
 
 	void RenderBeast::destroyCore()
 	{
-		if (mStaticHandler != nullptr)
-			bs_delete(mStaticHandler);
+		if (mObjectRenderer != nullptr)
+			bs_delete(mObjectRenderer);
 
 		mRenderTargets.clear();
-		mCameraData.clear();
+		mCameras.clear();
 		mRenderables.clear();
 
 		PostProcessing::shutDown();
@@ -107,12 +102,12 @@ namespace BansheeEngine
 
 		renderable->setRendererId(renderableId);
 
-		mRenderables.push_back(RenderableData());
+		mRenderables.push_back(RendererObject());
 		mRenderableShaderData.push_back(RenderableShaderData());
 		mWorldBounds.push_back(renderable->getBounds());
 
-		RenderableData& renderableData = mRenderables.back();
-		renderableData.renderable = renderable;
+		RendererObject& rendererObject = mRenderables.back();
+		rendererObject.renderable = renderable;
 
 		RenderableShaderData& shaderData = mRenderableShaderData.back();
 		shaderData.worldTransform = renderable->getTransform();
@@ -121,11 +116,6 @@ namespace BansheeEngine
 		shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
 		shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
 
-		if (renderable->getRenderableType() == RenType_LitTextured)
-			renderableData.controller = mStaticHandler;
-		else
-			renderableData.controller = nullptr;
-
 		SPtr<MeshCore> mesh = renderable->getMesh();
 		if (mesh != nullptr)
 		{
@@ -134,8 +124,8 @@ namespace BansheeEngine
 
 			for (UINT32 i = 0; i < meshProps.getNumSubMeshes(); i++)
 			{
-				renderableData.elements.push_back(BeastRenderableElement());
-				BeastRenderableElement& renElement = renderableData.elements.back();
+				rendererObject.elements.push_back(BeastRenderableElement());
+				BeastRenderableElement& renElement = rendererObject.elements.back();
 
 				renElement.mesh = mesh;
 				renElement.subMesh = meshProps.getSubMesh(i);
@@ -192,8 +182,7 @@ namespace BansheeEngine
 					samplerOverrides->refCount++;
 				}
 
-				if (renderableData.controller != nullptr)
-					renderableData.controller->initializeRenderElem(renElement);
+				mObjectRenderer->initElement(renElement);
 			}
 		}
 	}
@@ -339,9 +328,8 @@ namespace BansheeEngine
 		}
 		else if((updateFlag & (UINT32)CameraDirtyFlag::PostProcess) != 0)
 		{
-			CameraData& camData = mCameraData[camera];
-			camData.postProcessInfo.settings = camera->getPostProcessSettings();
-			camData.postProcessInfo.settingDirty = true;
+			RendererCamera& rendererCam = mCameras[camera];
+			rendererCam.updatePP();
 		} 
 	}
 
@@ -355,21 +343,12 @@ namespace BansheeEngine
 		SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
 		if(forceRemove)
 		{
-			mCameraData.erase(camera);
+			mCameras.erase(camera);
 			renderTarget = nullptr;
 		}
 		else
 		{
-			CameraData& camData = mCameraData[camera];
-			camData.opaqueQueue = bs_shared_ptr_new<RenderQueue>(mCoreOptions->stateReductionMode);
-
-			StateReduction transparentStateReduction = mCoreOptions->stateReductionMode;
-			if (transparentStateReduction == StateReduction::Material)
-				transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
-
-			camData.transparentQueue = bs_shared_ptr_new<RenderQueue>(transparentStateReduction);
-			camData.postProcessInfo.settings = camera->getPostProcessSettings();
-			camData.postProcessInfo.settingDirty = true;
+			mCameras[camera] = RendererCamera(camera, mCoreOptions->stateReductionMode);
 		}
 
 		// Remove from render target list
@@ -457,15 +436,10 @@ namespace BansheeEngine
 
 		*mCoreOptions = options;
 
-		for (auto& cameraData : mCameraData)
+		for (auto& entry : mCameras)
 		{
-			cameraData.second.opaqueQueue->setStateReduction(mCoreOptions->stateReductionMode);
-
-			StateReduction transparentStateReduction = mCoreOptions->stateReductionMode;
-			if (transparentStateReduction == StateReduction::Material)
-				transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
-
-			cameraData.second.transparentQueue->setStateReduction(transparentStateReduction);
+			RendererCamera& rendererCam = entry.second;
+			rendererCam.update(mCoreOptions->stateReductionMode);
 		}
 	}
 
@@ -495,14 +469,11 @@ namespace BansheeEngine
 		refreshSamplerOverrides();
 
 		// Update global per-frame hardware buffers
-		mStaticHandler->updatePerFrameBuffers(time);
+		mObjectRenderer->updatePerFrameBuffers(time);
 
 		// Generate render queues per camera
-		for (auto& cameraData : mCameraData)
-		{
-			const CameraCore* camera = cameraData.first;
-			determineVisible(*camera);
-		}
+		for (auto& entry : mCameras)
+			entry.second.determineVisible(mRenderables, mWorldBounds);
 
 		// Render everything, target by target
 		for (auto& renderTargetData : mRenderTargets)
@@ -534,28 +505,16 @@ namespace BansheeEngine
 		gProfilerCPU().beginSample("Render");
 
 		const CameraCore* camera = rtData.cameras[camIdx];
-		CameraData& camData = mCameraData[camera];
-
-		SPtr<ViewportCore> viewport = camera->getViewport();
-		CameraShaderData cameraShaderData = getCameraShaderData(*camera);
+		RendererCamera& rendererCam = mCameras[camera];
+		CameraShaderData cameraShaderData = rendererCam.getShaderData();
 
 		assert(!camera->getFlags().isSet(CameraFlag::Overlay));
 
-		mStaticHandler->updatePerCameraBuffers(cameraShaderData);
-
-		bool useHDR = camera->getFlags().isSet(CameraFlag::HDR);
-		UINT32 msaaCount = camera->getMSAACount();
+		mObjectRenderer->updatePerCameraBuffers(cameraShaderData);
+		rendererCam.beginRendering(true);
 
-		// Render scene objects to g-buffer
-		bool createGBuffer = camData.target == nullptr ||
-			camData.target->getHDR() != useHDR ||
-			camData.target->getNumSamples() != msaaCount;
-
-		if (createGBuffer)
-			camData.target = RenderTargets::create(viewport, useHDR, msaaCount);
-
-		camData.target->allocate();
-		camData.target->bindGBuffer();
+		SPtr<RenderTargets> renderTargets = rendererCam.getRenderTargets();
+		renderTargets->bindGBuffer();
 
 		//// Trigger pre-scene callbacks
 		auto iterCameraCallbacks = mRenderCallbacks.find(camera);
@@ -576,7 +535,7 @@ namespace BansheeEngine
 		}
 		
 		//// Render base pass
-		const Vector<RenderQueueElement>& opaqueElements = camData.opaqueQueue->getSortedElements();
+		const Vector<RenderQueueElement>& opaqueElements = rendererCam.getOpaqueQueue()->getSortedElements();
 		for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
 		{
 			BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
@@ -585,9 +544,7 @@ namespace BansheeEngine
 			UINT32 rendererId = renderElem->renderableId;
 			Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
 
-			mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
-			mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
-			mStaticHandler->bindPerObjectBuffers(*renderElem);
+			mObjectRenderer->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
 
 			if (iter->applyPass)
 				RendererUtility::instance().setPass(material, iter->passIdx, false);
@@ -602,13 +559,13 @@ namespace BansheeEngine
 			gRendererUtility().draw(iter->renderElem->mesh, iter->renderElem->subMesh);
 		}
 
-		camData.target->bindSceneColor(true);
+		renderTargets->bindSceneColor(true);
 
 		//// Render light pass
 		{
-			SPtr<GpuParamBlockBufferCore> perCameraBuffer = mStaticHandler->getPerCameraParams().getBuffer();
+			SPtr<GpuParamBlockBufferCore> perCameraBuffer = mObjectRenderer->getPerCameraParams().getBuffer();
 
-			mDirLightMat->bind(camData.target, perCameraBuffer);
+			mDirLightMat->bind(renderTargets, perCameraBuffer);
 			for (auto& light : mDirectionalLights)
 			{
 				if (!light.internal->getIsActive())
@@ -620,7 +577,7 @@ namespace BansheeEngine
 
 			// Draw point lights which our camera is within
 			// TODO - Possibly use instanced drawing here as only two meshes are drawn with various properties
-			mPointLightInMat->bind(camData.target, perCameraBuffer);
+			mPointLightInMat->bind(renderTargets, perCameraBuffer);
 
 			// TODO - Cull lights based on visibility, right now I just iterate over all of them. 
 			for (auto& light : mPointLights)
@@ -642,7 +599,7 @@ namespace BansheeEngine
 			}
 
 			// Draw other point lights
-			mPointLightOutMat->bind(camData.target, perCameraBuffer);
+			mPointLightOutMat->bind(renderTargets, perCameraBuffer);
 
 			for (auto& light : mPointLights)
 			{
@@ -663,10 +620,10 @@ namespace BansheeEngine
 			}
 		}
 
-		camData.target->bindSceneColor(false);
+		renderTargets->bindSceneColor(false);
 		
 		// Render transparent objects (TODO - No lighting yet)
-		const Vector<RenderQueueElement>& transparentElements = camData.transparentQueue->getSortedElements();
+		const Vector<RenderQueueElement>& transparentElements = rendererCam.getTransparentQueue()->getSortedElements();
 		for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
 		{
 			BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
@@ -675,9 +632,7 @@ namespace BansheeEngine
 			UINT32 rendererId = renderElem->renderableId;
 			Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
 
-			mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
-			mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
-			mStaticHandler->bindPerObjectBuffers(*renderElem);
+			mObjectRenderer->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
 
 			if (iter->applyPass)
 				RendererUtility::instance().setPass(material, iter->passIdx, false);
@@ -692,9 +647,6 @@ namespace BansheeEngine
 			gRendererUtility().draw(iter->renderElem->mesh, iter->renderElem->subMesh);
 		}
 
-		camData.opaqueQueue->clear();
-		camData.transparentQueue->clear();
-
 		// Render non-overlay post-scene callbacks
 		if (iterCameraCallbacks != mRenderCallbacks.end())
 		{
@@ -710,8 +662,8 @@ namespace BansheeEngine
 		}
 
 		// TODO - If GBuffer has multiple samples, I should resolve them before post-processing
-		PostProcessing::instance().postProcess(camData.target->getSceneColorRT(), 
-			camera, camData.postProcessInfo, delta);
+		PostProcessing::instance().postProcess(renderTargets->getSceneColorRT(),
+			camera, rendererCam.getPPInfo(), delta);
 
 		// Render overlay post-scene callbacks
 		if (iterCameraCallbacks != mRenderCallbacks.end())
@@ -727,7 +679,7 @@ namespace BansheeEngine
 			}
 		}
 
-		camData.target->release();
+		rendererCam.endRendering();
 
 		gProfilerCPU().endSample("Render");
 	}
@@ -740,9 +692,11 @@ namespace BansheeEngine
 		assert(camera->getFlags().isSet(CameraFlag::Overlay));
 
 		SPtr<ViewportCore> viewport = camera->getViewport();
-		CameraShaderData cameraShaderData = getCameraShaderData(*camera);
+		RendererCamera& rendererCam = mCameras[camera];
+		CameraShaderData cameraShaderData = rendererCam.getShaderData();
 
-		mStaticHandler->updatePerCameraBuffers(cameraShaderData);
+		mObjectRenderer->updatePerCameraBuffers(cameraShaderData);
+		rendererCam.beginRendering(false);
 
 		SPtr<RenderTargetCore> target = rtData.target;
 
@@ -784,146 +738,11 @@ namespace BansheeEngine
 			}
 		}
 
+		rendererCam.endRendering();
+
 		gProfilerCPU().endSample("RenderOverlay");
 	}
 	
-	void RenderBeast::determineVisible(const CameraCore& camera)
-	{
-		bool isOverlayCamera = camera.getFlags().isSet(CameraFlag::Overlay);
-		if (isOverlayCamera)
-			return;
-
-		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;
-			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();
-	}
-
-	Vector2 RenderBeast::getDeviceZTransform(const Matrix4& projMatrix)
-	{
-		// Returns a set of values that will transform depth buffer values (e.g. [0, 1] in DX, [-1, 1] in GL) to a distance
-		// in world space. This involes applying the inverse projection transform to the depth value. When you multiply
-		// a vector with the projection matrix you get [clipX, clipY, Az + B, C * z], where we don't care about clipX/clipY.
-		// A is [2, 2], B is [2, 3] and C is [3, 2] elements of the projection matrix (only ones that matter for our depth 
-		// value). The hardware will also automatically divide the z value with w to get the depth, therefore the final 
-		// formula is:
-		// depth = (Az + B) / (C * z)
-
-		// To get the z coordinate back we simply do the opposite: 
-		// z = B / (depth * C - A)
-
-		// However some APIs will also do a transformation on the depth values before storing them to the texture 
-		// (e.g. OpenGL will transform from [-1, 1] to [0, 1]). And we need to reverse that as well. Therefore the final 
-		// formula is:
-		// z = B / ((depth * (maxDepth - minDepth) + minDepth) * C - A)
-
-		// Are we reorganize it because it needs to fit the "(1.0f / (depth + y)) * x" format used in the shader:
-		// z = 1.0f / (depth + minDepth/(maxDepth - minDepth) - A/((maxDepth - minDepth) * C)) * B/((maxDepth - minDepth) * C)
-
-		RenderAPICore& rapi = RenderAPICore::instance();
-		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
-
-		float depthRange = rapiInfo.getMaximumDepthInputValue() - rapiInfo.getMinimumDepthInputValue();
-		float minDepth = rapiInfo.getMinimumDepthInputValue();
-
-		float a = projMatrix[2][2];
-		float b = projMatrix[2][3];
-		float c = projMatrix[3][2];
-
-		Vector2 output;
-		output.x = b / (depthRange * c);
-		output.y = minDepth / depthRange - a / (depthRange * c);
-
-		return output;
-	}
-
-	CameraShaderData RenderBeast::getCameraShaderData(const CameraCore& camera)
-	{
-		CameraShaderData data;
-		data.proj = camera.getProjectionMatrixRS();
-		data.view = camera.getViewMatrix();
-		data.viewProj = data.proj * data.view;
-		data.invProj = data.proj.inverse();
-		data.invViewProj = data.viewProj.inverse(); // Note: Calculate inverses separately (better precision possibly)
-
-		// Construct a special inverse view-projection matrix that had projection entries that affect z and w eliminated.
-		// Used to transform a vector(clip_x, clip_y, view_z, view_w), where clip_x/clip_y are in clip space, and 
-		// view_z/view_w in view space, into world space.
-
-		// Only projects z/w coordinates
-		Matrix4 projZ = Matrix4::IDENTITY;
-		projZ[2][2] = data.proj[2][2];
-		projZ[2][3] = data.proj[2][3];
-		projZ[3][2] = data.proj[3][2];
-		projZ[3][3] = 0.0f;
-
-		data.screenToWorld = data.invViewProj * projZ;
-		data.viewDir = camera.getForward();
-		data.viewOrigin = camera.getPosition();
-		data.deviceZToWorldZ = getDeviceZTransform(data.proj);
-
-		SPtr<ViewportCore> viewport = camera.getViewport();
-		SPtr<RenderTargetCore> rt = viewport->getTarget();
-
-		float halfWidth = viewport->getWidth() * 0.5f;
-		float halfHeight = viewport->getHeight() * 0.5f;
-
-		float rtWidth = (float)rt->getProperties().getWidth();
-		float rtHeight = (float)rt->getProperties().getHeight();
-
-		RenderAPICore& rapi = RenderAPICore::instance();
-		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
-
-		data.clipToUVScaleOffset.x = halfWidth / rtWidth;
-		data.clipToUVScaleOffset.y = -halfHeight / rtHeight;
-		data.clipToUVScaleOffset.z = viewport->getX() / rtWidth + (halfWidth + rapiInfo.getHorizontalTexelOffset()) / rtWidth;
-		data.clipToUVScaleOffset.w = viewport->getY() / rtHeight + (halfHeight + rapiInfo.getVerticalTexelOffset()) / rtHeight;
-
-		if (!rapiInfo.getNDCYAxisDown())
-			data.clipToUVScaleOffset.y = -data.clipToUVScaleOffset.y;
-
-		return data;
-	}
-
 	void RenderBeast::refreshSamplerOverrides(bool force)
 	{
 		for (auto& entry : mSamplerOverrides)
@@ -1051,9 +870,4 @@ namespace BansheeEngine
 			}
 		}
 	}
-
-	void DefaultMaterial::_initDefines(ShaderDefines& defines)
-	{
-		// Do nothing
-	}
 }

+ 207 - 0
Source/RenderBeast/Source/BsRendererCamera.cpp

@@ -0,0 +1,207 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsRendererCamera.h"
+#include "BsCamera.h"
+#include "BsRenderable.h"
+#include "BsMaterial.h"
+#include "BsShader.h"
+#include "BsRenderTargets.h"
+
+namespace BansheeEngine
+{
+	RendererCamera::RendererCamera()
+		:mCamera(nullptr), mUsingRenderTargets(false)
+	{ }
+
+	RendererCamera::RendererCamera(const CameraCore* camera, StateReduction reductionMode)
+		:mCamera(camera), mUsingRenderTargets(false)
+	{
+		update(reductionMode);
+	}
+
+	void RendererCamera::update(StateReduction reductionMode)
+	{
+		mOpaqueQueue = bs_shared_ptr_new<RenderQueue>(reductionMode);
+
+		StateReduction transparentStateReduction = reductionMode;
+		if (transparentStateReduction == StateReduction::Material)
+			transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
+
+		mTransparentQueue = bs_shared_ptr_new<RenderQueue>(transparentStateReduction);
+		updatePP();
+	}
+
+	void RendererCamera::updatePP()
+	{
+		mPostProcessInfo.settings = mCamera->getPostProcessSettings();
+		mPostProcessInfo.settingDirty = true;
+	}
+
+	void RendererCamera::beginRendering(bool useGBuffer)
+	{
+		if (useGBuffer)
+		{
+			SPtr<ViewportCore> viewport = mCamera->getViewport();
+			bool useHDR = mCamera->getFlags().isSet(CameraFlag::HDR);
+			UINT32 msaaCount = mCamera->getMSAACount();
+
+			// Render scene objects to g-buffer
+			bool createGBuffer = mRenderTargets == nullptr ||
+				mRenderTargets->getHDR() != useHDR ||
+				mRenderTargets->getNumSamples() != msaaCount;
+
+			if (createGBuffer)
+				mRenderTargets = RenderTargets::create(viewport, useHDR, msaaCount);
+
+			mRenderTargets->allocate();
+			mUsingRenderTargets = true;
+		}
+	}
+
+	void RendererCamera::endRendering()
+	{
+		mOpaqueQueue->clear();
+		mTransparentQueue->clear();
+
+		if(mUsingRenderTargets)
+		{
+			mRenderTargets->release();
+			mUsingRenderTargets = false;
+		}
+	}
+
+	void RendererCamera::determineVisible(Vector<RendererObject>& renderables, const Vector<Bounds>& renderableBounds)
+	{
+		bool isOverlayCamera = mCamera->getFlags().isSet(CameraFlag::Overlay);
+		if (isOverlayCamera)
+			return;
+
+		UINT64 cameraLayers = mCamera->getLayers();
+		ConvexVolume worldFrustum = mCamera->getWorldFrustum();
+
+		// Update per-object param buffers and queue render elements
+		for (auto& renderableData : renderables)
+		{
+			RenderableCore* renderable = renderableData.renderable;
+			UINT32 rendererId = renderable->getRendererId();
+
+			if ((renderable->getLayer() & cameraLayers) == 0)
+				continue;
+
+			// Do frustum culling
+			// Note: 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. Also consider spatial partitioning.
+			const Sphere& boundingSphere = renderableBounds[rendererId].getSphere();
+			if (worldFrustum.intersects(boundingSphere))
+			{
+				// More precise with the box
+				const AABox& boundingBox = renderableBounds[rendererId].getBox();
+
+				if (worldFrustum.intersects(boundingBox))
+				{
+					float distanceToCamera = (mCamera->getPosition() - boundingBox.getCenter()).length();
+
+					for (auto& renderElem : renderableData.elements)
+					{
+						bool isTransparent = (renderElem.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
+
+						if (isTransparent)
+							mTransparentQueue->add(&renderElem, distanceToCamera);
+						else
+							mOpaqueQueue->add(&renderElem, distanceToCamera);
+					}
+
+				}
+			}
+		}
+
+		mOpaqueQueue->sort();
+		mTransparentQueue->sort();
+	}
+
+	Vector2 RendererCamera::getDeviceZTransform(const Matrix4& projMatrix)
+	{
+		// Returns a set of values that will transform depth buffer values (e.g. [0, 1] in DX, [-1, 1] in GL) to a distance
+		// in world space. This involes applying the inverse projection transform to the depth value. When you multiply
+		// a vector with the projection matrix you get [clipX, clipY, Az + B, C * z], where we don't care about clipX/clipY.
+		// A is [2, 2], B is [2, 3] and C is [3, 2] elements of the projection matrix (only ones that matter for our depth 
+		// value). The hardware will also automatically divide the z value with w to get the depth, therefore the final 
+		// formula is:
+		// depth = (Az + B) / (C * z)
+
+		// To get the z coordinate back we simply do the opposite: 
+		// z = B / (depth * C - A)
+
+		// However some APIs will also do a transformation on the depth values before storing them to the texture 
+		// (e.g. OpenGL will transform from [-1, 1] to [0, 1]). And we need to reverse that as well. Therefore the final 
+		// formula is:
+		// z = B / ((depth * (maxDepth - minDepth) + minDepth) * C - A)
+
+		// Are we reorganize it because it needs to fit the "(1.0f / (depth + y)) * x" format used in the shader:
+		// z = 1.0f / (depth + minDepth/(maxDepth - minDepth) - A/((maxDepth - minDepth) * C)) * B/((maxDepth - minDepth) * C)
+
+		RenderAPICore& rapi = RenderAPICore::instance();
+		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
+
+		float depthRange = rapiInfo.getMaximumDepthInputValue() - rapiInfo.getMinimumDepthInputValue();
+		float minDepth = rapiInfo.getMinimumDepthInputValue();
+
+		float a = projMatrix[2][2];
+		float b = projMatrix[2][3];
+		float c = projMatrix[3][2];
+
+		Vector2 output;
+		output.x = b / (depthRange * c);
+		output.y = minDepth / depthRange - a / (depthRange * c);
+
+		return output;
+	}
+
+	CameraShaderData RendererCamera::getShaderData()
+	{
+		CameraShaderData data;
+		data.proj = mCamera->getProjectionMatrixRS();
+		data.view = mCamera->getViewMatrix();
+		data.viewProj = data.proj * data.view;
+		data.invProj = data.proj.inverse();
+		data.invViewProj = data.viewProj.inverse(); // Note: Calculate inverses separately (better precision possibly)
+
+		// Construct a special inverse view-projection matrix that had projection entries that affect z and w eliminated.
+		// Used to transform a vector(clip_x, clip_y, view_z, view_w), where clip_x/clip_y are in clip space, and 
+		// view_z/view_w in view space, into world space.
+
+		// Only projects z/w coordinates
+		Matrix4 projZ = Matrix4::IDENTITY;
+		projZ[2][2] = data.proj[2][2];
+		projZ[2][3] = data.proj[2][3];
+		projZ[3][2] = data.proj[3][2];
+		projZ[3][3] = 0.0f;
+
+		data.screenToWorld = data.invViewProj * projZ;
+		data.viewDir = mCamera->getForward();
+		data.viewOrigin = mCamera->getPosition();
+		data.deviceZToWorldZ = getDeviceZTransform(data.proj);
+
+		SPtr<ViewportCore> viewport = mCamera->getViewport();
+		SPtr<RenderTargetCore> rt = viewport->getTarget();
+
+		float halfWidth = viewport->getWidth() * 0.5f;
+		float halfHeight = viewport->getHeight() * 0.5f;
+
+		float rtWidth = (float)rt->getProperties().getWidth();
+		float rtHeight = (float)rt->getProperties().getHeight();
+
+		RenderAPICore& rapi = RenderAPICore::instance();
+		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
+
+		data.clipToUVScaleOffset.x = halfWidth / rtWidth;
+		data.clipToUVScaleOffset.y = -halfHeight / rtHeight;
+		data.clipToUVScaleOffset.z = viewport->getX() / rtWidth + (halfWidth + rapiInfo.getHorizontalTexelOffset()) / rtWidth;
+		data.clipToUVScaleOffset.w = viewport->getY() / rtHeight + (halfHeight + rapiInfo.getVerticalTexelOffset()) / rtHeight;
+
+		if (!rapiInfo.getNDCYAxisDown())
+			data.clipToUVScaleOffset.y = -data.clipToUVScaleOffset.y;
+
+		return data;
+	}
+}