Ver código fonte

Refactoring renderer camera so it may be more easily used on its own for various rendering helper tasks

BearishSun 9 anos atrás
pai
commit
10558a89b0

+ 2 - 2
Source/BansheeEngine/Source/BsDropDownAreaPlacement.cpp

@@ -77,7 +77,7 @@ namespace bs
 		}
 
 		// Determine x position and whether to align to left or right side of the drop down list
-		UINT32 availableRightwardWidth = (UINT32)std::max(0, (availableArea.x + availableArea.width) - potentialRightStart);
+		UINT32 availableRightwardWidth = (UINT32)std::max(0, (availableArea.x + (INT32)availableArea.width) - potentialRightStart);
 		UINT32 availableLeftwardWidth = (UINT32)std::max(0, potentialLeftStart - availableArea.x);
 
 		//// Prefer right if possible
@@ -104,7 +104,7 @@ namespace bs
 		}
 
 		// Determine y position and whether to open upward or downward
-		UINT32 availableDownwardHeight = (UINT32)std::max(0, (availableArea.y + availableArea.height) - potentialBottomStart);
+		UINT32 availableDownwardHeight = (UINT32)std::max(0, (availableArea.y + (INT32)availableArea.height) - potentialBottomStart);
 		UINT32 availableUpwardHeight = (UINT32)std::max(0, potentialTopStart - availableArea.y);
 
 		//// Prefer down if possible

+ 3 - 3
Source/BansheeEngine/Source/BsGUIButtonBase.cpp

@@ -241,7 +241,7 @@ namespace bs
 			
 			if (textBounds.width == 0)
 			{
-				UINT32 freeWidth = (UINT32)std::max(0, contentBounds.width - textBounds.width - imageBounds.width);
+				UINT32 freeWidth = (UINT32)std::max(0, (INT32)contentBounds.width - (INT32)textBounds.width - (INT32)imageBounds.width);
 				imageXOffset = (INT32)(freeWidth / 2);
 			}
 			else
@@ -249,7 +249,7 @@ namespace bs
 
 			if(_getStyle()->imagePosition == GUIImagePosition::Right)
 			{
-				INT32 imageReservedWidth = std::max(0, contentBounds.width - textBounds.width);
+				INT32 imageReservedWidth = std::max(0, (INT32)contentBounds.width - (INT32)textBounds.width);
 
 				textOffset = Vector2I(contentBounds.x, contentBounds.y);
 				textClipRect = contentClipRect;
@@ -266,7 +266,7 @@ namespace bs
 				imageOffset = Vector2I(contentBounds.x + imageXOffset, contentBounds.y);
 				imageClipRect = contentClipRect;
 				imageClipRect.x -= imageXOffset;
-				imageClipRect.width = std::min(imageReservedWidth, imageClipRect.width);
+				imageClipRect.width = std::min(imageReservedWidth, (INT32)imageClipRect.width);
 
 				textOffset = Vector2I(contentBounds.x + imageReservedWidth + textImageSpacing, contentBounds.y);
 				textClipRect = contentClipRect;

+ 2 - 2
Source/BansheeEngine/Source/BsGUICanvas.cpp

@@ -539,9 +539,9 @@ namespace bs
 			std::array<Plane2D, 4> clipPlanes =
 			{
 				Plane2D(Vector2(1.0f, 0.0f), (float)clipRect.x),
-				Plane2D(Vector2(-1.0f, 0.0f), (float)-(clipRect.x + clipRect.width)),
+				Plane2D(Vector2(-1.0f, 0.0f), (float)-(clipRect.x + (INT32)clipRect.width)),
 				Plane2D(Vector2(0.0f, 1.0f), (float)clipRect.y),
-				Plane2D(Vector2(0.0f, -1.0f), (float)-(clipRect.y + clipRect.height))
+				Plane2D(Vector2(0.0f, -1.0f), (float)-(clipRect.y + (INT32)clipRect.height))
 			};
 
 			element.clippedVertexStart = (UINT32)mClippedLineVertices.size();

+ 2 - 2
Source/BansheeEngine/Source/BsGUILayoutUtility.cpp

@@ -77,8 +77,8 @@ namespace bs
 			min.x = std::min(min.x, childArea.x);
 			min.y = std::min(min.y, childArea.y);
 
-			max.x = std::max(max.x, childArea.x + childArea.width);
-			max.y = std::max(max.y, childArea.y + childArea.height);
+			max.x = std::max(max.x, childArea.x + (INT32)childArea.width);
+			max.y = std::max(max.y, childArea.y + (INT32)childArea.height);
 		}
 
 		Vector2I actualSize = max - min;

+ 2 - 2
Source/BansheeEngine/Source/BsSprite.cpp

@@ -329,9 +329,9 @@ namespace bs
 		Vector<Plane> clipPlanes =
 		{
 			Plane(Vector3(1.0f, 0.0f, 0.0f), (float)clipRect.x),
-			Plane(Vector3(-1.0f, 0.0f, 0.0f), (float)-(clipRect.x + clipRect.width)),
+			Plane(Vector3(-1.0f, 0.0f, 0.0f), (float)-(clipRect.x + (INT32)clipRect.width)),
 			Plane(Vector3(0.0f, 1.0f, 0.0f), (float)clipRect.y),
-			Plane(Vector3(0.0f, -1.0f, 0.0f), (float)-(clipRect.y + clipRect.height))
+			Plane(Vector3(0.0f, -1.0f, 0.0f), (float)-(clipRect.y + (INT32)clipRect.height))
 		};
 
 		MeshUtility::clip2D(vertices, uv, numTris, vertStride, clipPlanes, writeCallback);

+ 5 - 4
Source/BansheeUtility/Include/BsRect2I.h

@@ -15,9 +15,10 @@ namespace bs
 	{
 	public:
 		Rect2I();
-		Rect2I(int _x, int _y, int _width, int _height);
+		Rect2I(INT32 x, INT32 y, UINT32 width, UINT32 height);
 
-		int x, y, width, height;
+		INT32 x, y;
+		UINT32 width, height;
 
 		/** Returns true if the rectangle contains the provided point. */
 		bool contains(const Vector2I& point) const;
@@ -56,12 +57,12 @@ namespace bs
 		 */
 		void transform(const Matrix4& matrix);
 
-		inline bool operator== (const Rect2I& rhs) const
+		bool operator== (const Rect2I& rhs) const
 		{
 			return x == rhs.x && y == rhs.y && width == rhs.width && height == rhs.height;
 		}
 
-		inline bool operator!= (const Rect2I& rhs) const
+		bool operator!= (const Rect2I& rhs) const
 		{
 			return !(*this == rhs);
 		}

+ 24 - 24
Source/BansheeUtility/Source/BsRect2I.cpp

@@ -13,15 +13,15 @@ namespace bs
 		:x(0), y(0), width(0), height(0)
 	{ }
 
-	Rect2I::Rect2I(int _x, int _y, int _width, int _height)
-		:x(_x), y(_y), width(_width), height(_height)
+	Rect2I::Rect2I(INT32 x, INT32 y, UINT32 width, UINT32 height)
+		:x(x), y(y), width(width), height(height)
 	{ }
 
 	bool Rect2I::contains(const Vector2I& point) const
 	{
-		if(point.x >= x && point.x < (x + width))
+		if(point.x >= x && point.x < (x + (INT32)width))
 		{
-			if(point.y >= y && point.y < (y + height))
+			if(point.y >= y && point.y < (y + (INT32)height))
 				return true;
 		}
 
@@ -30,11 +30,11 @@ namespace bs
 
 	bool Rect2I::overlaps(const Rect2I& other) const
 	{
-		INT32 otherRight = other.x + other.width;
-		INT32 myRight = x + width;
+		INT32 otherRight = other.x + (INT32)other.width;
+		INT32 myRight = x + (INT32)width;
 
-		INT32 otherBottom = other.y + other.height;
-		INT32 myBottom = y + height;
+		INT32 otherBottom = other.y + (INT32)other.height;
+		INT32 myBottom = y + (INT32)height;
 
 		if(x < otherRight && myRight > other.x &&
 			y < otherBottom && myBottom > other.y)
@@ -45,10 +45,10 @@ namespace bs
 
 	void Rect2I::encapsulate(const Rect2I& other)
 	{
-		int myRight = x + width;
-		int myBottom = y + height;
-		int otherRight = other.x + other.width;
-		int otherBottom = other.y + other.height;
+		int myRight = x + (INT32)width;
+		int myBottom = y + (INT32)height;
+		int otherRight = other.x + (INT32)other.width;
+		int otherBottom = other.y + (INT32)other.height;
 
 		if(other.x < x)
 			x = other.x;
@@ -72,8 +72,8 @@ namespace bs
 		int newLeft = std::max(x, clipRect.x);
 		int newTop = std::max(y, clipRect.y);
 
-		int newRight = std::min(x + width, clipRect.x + clipRect.width);
-		int newBottom = std::min(y + height, clipRect.y + clipRect.height);
+		int newRight = std::min(x + (INT32)width, clipRect.x + (INT32)clipRect.width);
+		int newBottom = std::min(y + (INT32)height, clipRect.y + (INT32)clipRect.height);
 
 		x = std::min(newLeft, newRight);
 		y = std::min(newTop, newBottom);
@@ -86,7 +86,7 @@ namespace bs
 		UINT32 initialPieces = (UINT32)pieces.size();
 
 		// Cut horizontal
-		if (cutRect.x > x && cutRect.x < (x + width))
+		if (cutRect.x > x && cutRect.x < (x + (INT32)width))
 		{
 			Rect2I leftPiece;
 			leftPiece.x = x;
@@ -97,7 +97,7 @@ namespace bs
 			pieces.push_back(leftPiece);
 		}
 
-		if ((cutRect.x + cutRect.width) > x && (cutRect.x + cutRect.width) < (x + width))
+		if ((cutRect.x + (INT32)cutRect.width) > x && (cutRect.x + (INT32)cutRect.width) < (x + (INT32)width))
 		{
 			Rect2I rightPiece;
 			rightPiece.x = cutRect.x + cutRect.width;
@@ -109,12 +109,12 @@ namespace bs
 		}
 
 		// Cut vertical
-		INT32 cutLeft = std::min(std::max(x, cutRect.x), x + width);
-		INT32 cutRight = std::max(std::min(x + width, cutRect.x + cutRect.width), x);
+		INT32 cutLeft = std::min(std::max(x, cutRect.x), x + (INT32)width);
+		INT32 cutRight = std::max(std::min(x + (INT32)width, cutRect.x + (INT32)cutRect.width), x);
 
 		if (cutLeft != cutRight)
 		{
-			if (cutRect.y > y && cutRect.y < (y + height))
+			if (cutRect.y > y && cutRect.y < (y + (INT32)height))
 			{
 				Rect2I topPiece;
 				topPiece.y = y;
@@ -125,7 +125,7 @@ namespace bs
 				pieces.push_back(topPiece);
 			}
 
-			if ((cutRect.y + cutRect.height) > y && (cutRect.y + cutRect.height) < (y + height))
+			if ((cutRect.y + (INT32)cutRect.height) > y && (cutRect.y + (INT32)cutRect.height) < (y + (INT32)height))
 			{
 				Rect2I bottomPiece;
 				bottomPiece.y = cutRect.y + cutRect.height;
@@ -140,8 +140,8 @@ namespace bs
 		// No cut
 		if (initialPieces == (UINT32)pieces.size())
 		{
-			if (cutRect.x <= x && (cutRect.x + cutRect.width) >= (x + width) &&
-				cutRect.y <= y && (cutRect.y + cutRect.height) >= (y + height))
+			if (cutRect.x <= x && (cutRect.x + (INT32)cutRect.width) >= (x + (INT32)width) &&
+				cutRect.y <= y && (cutRect.y + (INT32)cutRect.height) >= (y + (INT32)height))
 			{
 				// Cut rectangle completely encompasses this one
 			}
@@ -204,7 +204,7 @@ namespace bs
 
 		x = Math::floorToInt(minX);
 		y = Math::floorToInt(minY);
-		width = Math::ceilToInt(maxX) - x;
-		height = Math::ceilToInt(maxY) - y;
+		width = (UINT32)Math::ceilToInt(maxX) - x;
+		height = (UINT32)Math::ceilToInt(maxY) - y;
 	}
 }

+ 8 - 16
Source/RenderBeast/Include/BsRenderTargets.h

@@ -4,6 +4,7 @@
 
 #include "BsRenderBeastPrerequisites.h"
 #include "BsPixelUtil.h"
+#include "BsRendererCamera.h"
 
 namespace bs { namespace ct
 {
@@ -12,7 +13,7 @@ namespace bs { namespace ct
 	 */
 
 	/**
-	 * Allocates and handles all the required render targets for rendering a scene from a specific viewport.
+	 * Allocates and handles all the required render targets for rendering a scene from a specific view.
 	 *
 	 * @note	Core thread only.
 	 */
@@ -23,13 +24,11 @@ namespace bs { namespace ct
 		 * Creates a new set of render targets. This will not actually allocate the internal render targets - this happens
 		 * the first time you call bind().
 		 *
-		 * @param[in]	viewport		Viewport that the render targets will be used for. Determines size of the render
-		 *								targets, and the output color render target.
+		 * @param[in]	view			Information about the view that the render targets will be used for. Determines size
+		 *								of the render targets, and the output color render target.
 		 * @param[in]	hdr				Should the render targets support high dynamic range rendering.
-		 * @param[in]	numSamples		Number of samples to use if multisampling is active. Provide 0 or 1 if multisampled
-		 *								targets are not needed.
 		 */
-		static SPtr<RenderTargets> create(const SPtr<Viewport>& viewport, bool hdr, UINT32 numSamples);
+		static SPtr<RenderTargets> create(const RENDERER_VIEW_TARGET_DESC& view, bool hdr);
 
 		/**
 		 * Allocates the textures required for rendering. Allocations are pooled so this is generally a fast operation
@@ -66,18 +65,12 @@ namespace bs { namespace ct
 		bool getHDR() const { return mHDR; }
 
 		/**	Returns the number of samples per pixel supported by the targets. */
-		UINT32 getNumSamples() const { return mNumSamples; }
+		UINT32 getNumSamples() const { return mViewTarget.numSamples; }
 
 	private:
-		RenderTargets(const SPtr<Viewport>& viewport, bool hdr, UINT32 numSamples);
+		RenderTargets(const RENDERER_VIEW_TARGET_DESC& view, bool hdr);
 
-		/**	Returns the width of gbuffer textures, in pixels. */
-		UINT32 getWidth() const;
-
-		/**	Returns the height of gbuffer textures, in pixels. */
-		UINT32 getHeight() const;
-
-		SPtr<Viewport> mViewport;
+		RENDERER_VIEW_TARGET_DESC mViewTarget;
 
 		SPtr<PooledRenderTexture> mSceneColorTex;
 		SPtr<PooledRenderTexture> mAlbedoTex;
@@ -90,7 +83,6 @@ namespace bs { namespace ct
 		PixelFormat mSceneColorFormat;
 		PixelFormat mAlbedoFormat;
 		PixelFormat mNormalFormat;
-		UINT32 mNumSamples;
 		bool mHDR;
 	};
 

+ 62 - 17
Source/RenderBeast/Include/BsRendererCamera.h

@@ -8,6 +8,7 @@
 #include "BsRenderQueue.h"
 #include "BsRendererObject.h"
 #include "BsBounds.h"
+#include "BsConvexVolume.h"
 
 namespace bs { namespace ct
 {
@@ -47,21 +48,64 @@ namespace bs { namespace ct
 		GpuParamTexture mSkyTextureParam;
 	};
 
+	/** Set of properties describing the output render target used by a renderer view. */
+	struct RENDERER_VIEW_TARGET_DESC
+	{
+		Rect2I viewRect;
+		UINT32 targetWidth;
+		UINT32 targetHeight;
+		UINT32 numSamples;
+
+		UINT32 clearFlags;
+		Color clearColor;
+		float clearDepthValue;
+		UINT16 clearStencilValue;
+	};
+
+	/** Set of properties used describing a specific view that the renderer can render. */
+	struct RENDERER_VIEW_DESC
+	{
+		RENDERER_VIEW_TARGET_DESC target;
+
+		Matrix4 viewTransform;
+		Matrix4 projTransform;
+		Vector3 viewDirection;
+		Vector3 viewOrigin;
+		float nearPlane;
+
+		bool isOverlay : 1;
+		bool isHDR : 1;
+
+		UINT64 visibleLayers;
+		ConvexVolume cullFrustum;
+
+		StateReduction stateReduction;
+
+		SPtr<Texture> skyboxTexture;
+	};
+
 	/** Contains information about a Camera, used by the Renderer. */
 	class RendererCamera
 	{
 	public:
 		RendererCamera();
-		RendererCamera(const Camera* camera, StateReduction reductionMode);
+		RendererCamera(const RENDERER_VIEW_DESC& desc);
 
-		/** Updates the internal camera data, usually called after source camera changes. */
-		void update(StateReduction reductionMode);
+		/** Sets state reduction mode that determines how do render queues group & sort renderables. */
+		void setStateReductionMode(StateReduction reductionMode);
 
 		/** Updates the internal camera post-processing data. */
-		void updatePP();
+		void setPostProcessSettings(const SPtr<PostProcessSettings>& ppSettings);
+
+		/** Updates the internal information with a new view transform. */
+		void setTransform(const Vector3& origin, const Vector3& direction, const Matrix4& view,
+						  const Matrix4& proj);
+
+		/** Updates all internal information with new view information. */
+		void setView(const RENDERER_VIEW_DESC& desc);
 
 		/** 
-		 * Prepares camera render targets for rendering. When done call endRendering().
+		 * Prepares 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.
@@ -71,23 +115,23 @@ namespace bs { namespace ct
 		/** Ends rendering and frees any acquired resources. */
 		void endRendering();
 
-		/** Returns the camera's renderTargets. Only valid if called in-between beginRendering() and endRendering() calls. */
+		/** Returns the view'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 
+		 * Returns a render queue containing all opaque objects. Make sure to call determineVisible() beforehand if view 
 		 * 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.
+		 * view 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. 
+		 * Populates view render queues by determining visible renderable objects. 
 		 *
 		 * @param[in]	renderables			A set of renderable objects to iterate over and determine visibility for.
 		 * @param[in]	renderableBounds	A set of world bounds for the provided renderable objects. Must be the same size
@@ -95,16 +139,16 @@ namespace bs { namespace ct
 		 * @param[in]	visibility			Output parameter that will have the true bit set for any visible renderable
 		 *									object. If the bit for an object is already set to true, the method will never
 		 *									change it to false which allows the same bitfield to be provided to multiple
-		 *									renderer cameras. Must be the same size as the @p renderables array.
+		 *									renderer views. Must be the same size as the @p renderables array.
 		 *									
-		 *									As a side-effect, per-camera visibility data is also calculated and can be
+		 *									As a side-effect, per-view visibility data is also calculated and can be
 		 *									retrieved by calling getVisibilityMask().
 		 */
 		void determineVisible(const Vector<RendererObject*>& renderables, const Vector<Bounds>& renderableBounds, 
 			Vector<bool>& visibility);
 
 		/** Returns the visibility mask calculated with the last call to determineVisible(). */
-		const Vector<bool> getVisibilityMask() const { return mVisibility; }
+		const Vector<bool>& getVisibilityMask() const { return mVisibility; }
 
 		/** 
 		 * Returns a structure containing information about post-processing effects. This structure will be modified and
@@ -112,11 +156,11 @@ namespace bs { namespace ct
 		 */
 		PostProcessInfo& getPPInfo() { return mPostProcessInfo; }
 
-		/** Updates the GPU buffer containing per-camera information, with the latest data. */
-		void updatePerCameraBuffer();
+		/** Updates the GPU buffer containing per-view information, with the latest internal data. */
+		void updatePerViewBuffer();
 
-		/** Returns a buffer that stores per-camera parameters. */
-		SPtr<GpuParamBlockBuffer> getPerCameraBuffer() const { return mParamBuffer; }
+		/** Returns a buffer that stores per-view parameters. */
+		SPtr<GpuParamBlockBuffer> getPerViewBuffer() const { return mParamBuffer; }
 
 	private:
 		/**
@@ -129,7 +173,8 @@ namespace bs { namespace ct
 		 */
 		Vector2 getDeviceZTransform(const Matrix4& projMatrix) const;
 
-		const Camera* mCamera;
+		RENDERER_VIEW_DESC mViewDesc;
+
 		SPtr<RenderQueue> mOpaqueQueue;
 		SPtr<RenderQueue> mTransparentQueue;
 

+ 72 - 9
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -373,7 +373,7 @@ namespace bs { namespace ct
 	void RenderBeast::notifyCameraAdded(const Camera* camera)
 	{
 		RendererCamera* renCamera = updateCameraData(camera);
-		renCamera->updatePerCameraBuffer();
+		renCamera->updatePerViewBuffer();
 	}
 
 	void RenderBeast::notifyCameraUpdated(const Camera* camera, UINT32 updateFlag)
@@ -386,12 +386,21 @@ namespace bs { namespace ct
 		else if((updateFlag & (UINT32)CameraDirtyFlag::PostProcess) != 0)
 		{
 			rendererCam = mCameras[camera];
-			rendererCam->updatePP();
+
+			rendererCam->setPostProcessSettings(camera->getPostProcessSettings());
 		}
-		else
+		else // Transform
+		{
 			rendererCam = mCameras[camera];
 
-		rendererCam->updatePerCameraBuffer();
+			rendererCam->setTransform(
+				camera->getPosition(),
+				camera->getForward(),
+				camera->getViewMatrix(),
+				camera->getProjectionMatrixRS());
+		}
+
+		rendererCam->updatePerViewBuffer();
 	}
 
 	void RenderBeast::notifyCameraRemoved(const Camera* camera)
@@ -424,16 +433,70 @@ namespace bs { namespace ct
 		}
 		else
 		{
+			SPtr<Viewport> viewport = camera->getViewport();
+			RENDERER_VIEW_DESC viewDesc;
+
+			viewDesc.target.clearFlags = 0;
+			if (viewport->getRequiresColorClear())
+				viewDesc.target.clearFlags |= FBT_COLOR;
+
+			if (viewport->getRequiresDepthClear())
+				viewDesc.target.clearFlags |= FBT_DEPTH;
+
+			if (viewport->getRequiresStencilClear())
+				viewDesc.target.clearFlags |= FBT_STENCIL;
+
+			viewDesc.target.clearColor = viewport->getClearColor();
+			viewDesc.target.clearDepthValue = viewport->getClearDepthValue();
+			viewDesc.target.clearStencilValue = viewport->getClearStencilValue();
+
+			viewDesc.target.viewRect = Rect2I(
+				viewport->getX(),
+				viewport->getY(),
+				(UINT32)viewport->getWidth(),
+				(UINT32)viewport->getHeight());
+
+			SPtr<RenderTarget> rt = viewport->getTarget();
+			if (rt != nullptr)
+			{
+				viewDesc.target.targetWidth = rt->getProperties().getWidth();
+				viewDesc.target.targetHeight = rt->getProperties().getHeight();
+			}
+			else
+			{
+				viewDesc.target.targetWidth = 0;
+				viewDesc.target.targetHeight = 0;
+			}
+
+			viewDesc.target.numSamples = camera->getMSAACount();
+
+			viewDesc.isOverlay = camera->getFlags().isSet(CameraFlag::Overlay);
+			viewDesc.isHDR = camera->getFlags().isSet(CameraFlag::HDR);
+
+			viewDesc.cullFrustum = camera->getWorldFrustum();
+			viewDesc.visibleLayers = camera->getLayers();
+			viewDesc.nearPlane = camera->getNearClipDistance();
+
+			viewDesc.viewOrigin = camera->getPosition();
+			viewDesc.viewDirection = camera->getForward();
+			viewDesc.projTransform = camera->getProjectionMatrixRS();
+			viewDesc.viewTransform = camera->getViewMatrix();
+
+			viewDesc.stateReduction = mCoreOptions->stateReductionMode;
+			viewDesc.skyboxTexture = camera->getSkybox();
+
 			if (iterFind != mCameras.end())
 			{
 				output = iterFind->second;
-				output->update(mCoreOptions->stateReductionMode);
+				output->setView(viewDesc);
 			}
 			else
 			{
-				output = bs_new<RendererCamera>(camera, mCoreOptions->stateReductionMode);
+				output = bs_new<RendererCamera>(viewDesc);
 				mCameras[camera] = output;
 			}
+
+			output->setPostProcessSettings(camera->getPostProcessSettings());
 		}
 
 		// Remove from render target list
@@ -526,7 +589,7 @@ namespace bs { namespace ct
 		for (auto& entry : mCameras)
 		{
 			RendererCamera* rendererCam = entry.second;
-			rendererCam->update(mCoreOptions->stateReductionMode);
+			rendererCam->setStateReductionMode(mCoreOptions->stateReductionMode);
 		}
 	}
 
@@ -623,7 +686,7 @@ namespace bs { namespace ct
 
 		const Camera* camera = rtInfo.cameras[camIdx];
 		RendererCamera* rendererCam = mCameras[camera];
-		SPtr<GpuParamBlockBuffer> perCameraBuffer = rendererCam->getPerCameraBuffer();
+		SPtr<GpuParamBlockBuffer> perCameraBuffer = rendererCam->getPerViewBuffer();
 		perCameraBuffer->flushToGPU();
 
 		assert(!camera->getFlags().isSet(CameraFlag::Overlay));
@@ -814,7 +877,7 @@ namespace bs { namespace ct
 
 		SPtr<Viewport> viewport = camera->getViewport();
 		RendererCamera* rendererCam = mCameras[camera];
-		rendererCam->getPerCameraBuffer()->flushToGPU();
+		rendererCam->getPerViewBuffer()->flushToGPU();
 
 		rendererCam->beginRendering(false);
 

+ 14 - 33
Source/RenderBeast/Source/BsRenderTargets.cpp

@@ -9,8 +9,8 @@
 
 namespace bs { namespace ct
 {
-	RenderTargets::RenderTargets(const SPtr<Viewport>& viewport, bool hdr, UINT32 numSamples)
-		:mViewport(viewport), mNumSamples(numSamples), mHDR(hdr)
+	RenderTargets::RenderTargets(const RENDERER_VIEW_TARGET_DESC& view, bool hdr)
+		:mViewTarget(view), mHDR(hdr)
 	{
 		// Note: Consider customizable HDR format via options? e.g. smaller PF_FLOAT_R11G11B10 or larger 32-bit format
 		mSceneColorFormat = hdr ? PF_FLOAT16_RGBA : PF_R8G8B8A8;
@@ -18,30 +18,30 @@ namespace bs { namespace ct
 		mNormalFormat = PF_UNORM_R10G10B10A2; // Note: Also consider customizable format (e.g. 16-bit float?)
 	}
 
-	SPtr<RenderTargets> RenderTargets::create(const SPtr<Viewport>& viewport, bool hdr, UINT32 numSamples)
+	SPtr<RenderTargets> RenderTargets::create(const RENDERER_VIEW_TARGET_DESC& view, bool hdr)
 	{
-		return bs_shared_ptr<RenderTargets>(new (bs_alloc<RenderTargets>()) RenderTargets(viewport, hdr, numSamples));
+		return bs_shared_ptr<RenderTargets>(new (bs_alloc<RenderTargets>()) RenderTargets(view, hdr));
 	}
 
 	void RenderTargets::allocate()
 	{
 		RenderTexturePool& texPool = RenderTexturePool::instance();
 
-		UINT32 width = getWidth();
-		UINT32 height = getHeight();
+		UINT32 width = mViewTarget.viewRect.width;
+		UINT32 height = mViewTarget.viewRect.height;
 
 		// Note: Albedo is allocated as SRGB, meaning when reading from textures during depth pass we decode from sRGB into linear,
 		// then back into sRGB when writing to albedo, and back to linear when reading from albedo during light pass. This /might/ have
 		// a performance impact. In which case we could just use a higher precision albedo buffer, which can then store linear color
 		// directly (storing linear in 8bit buffer causes too much detail to be lost in the blacks).
 		SPtr<PooledRenderTexture> newColorRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width, height, TU_RENDERTARGET,
-			mNumSamples, false));
+			mViewTarget.numSamples, false));
 		SPtr<PooledRenderTexture> newAlbedoRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mAlbedoFormat, width, 
-			height, TU_RENDERTARGET, mNumSamples, true));
+			height, TU_RENDERTARGET, mViewTarget.numSamples, true));
 		SPtr<PooledRenderTexture> newNormalRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mNormalFormat, width, 
-			height, TU_RENDERTARGET, mNumSamples, false));
+			height, TU_RENDERTARGET, mViewTarget.numSamples, false));
 		SPtr<PooledRenderTexture> newDepthRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_D32_S8X24, width, height, 
-			TU_DEPTHSTENCIL, mNumSamples, false));
+			TU_DEPTHSTENCIL, mViewTarget.numSamples, false));
 
 		bool rebuildTargets = newColorRT != mSceneColorTex || newAlbedoRT != mAlbedoTex || newNormalRT != mNormalTex || newDepthRT != mDepthTex;
 
@@ -110,21 +110,12 @@ namespace bs { namespace ct
 		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
 		rapi.setViewport(area);
 
-		UINT32 clearBuffers = 0;
-		if (mViewport->getRequiresColorClear())
-			clearBuffers |= FBT_COLOR;
-
-		if (mViewport->getRequiresDepthClear())
-			clearBuffers |= FBT_DEPTH;
-
-		if (mViewport->getRequiresStencilClear())
-			clearBuffers |= FBT_STENCIL;
-
 		// Clear scene color, depth, stencil according to user defined values
-		if (clearBuffers != 0)
+		UINT32 clearFlags = mViewTarget.clearFlags;
+		if (clearFlags != 0)
 		{
-			RenderAPI::instance().clearViewport(clearBuffers, mViewport->getClearColor(),
-				mViewport->getClearDepthValue(), mViewport->getClearStencilValue(), 0x01);
+			RenderAPI::instance().clearViewport(clearFlags, mViewTarget.clearColor,
+												mViewTarget.clearDepthValue, mViewTarget.clearStencilValue, 0x01);
 		}
 
 		// Clear all others
@@ -154,14 +145,4 @@ namespace bs { namespace ct
 	{
 		return mDepthTex->texture;
 	}
-
-	UINT32 RenderTargets::getWidth() const
-	{
-		return (UINT32)mViewport->getWidth();
-	}
-
-	UINT32 RenderTargets::getHeight() const
-	{
-		return (UINT32)mViewport->getHeight();
-	}
 }}

+ 48 - 54
Source/RenderBeast/Source/BsRendererCamera.cpp

@@ -39,19 +39,20 @@ namespace bs { namespace ct
 	}
 
 	RendererCamera::RendererCamera()
-		:mCamera(nullptr), mUsingRenderTargets(false)
+		: mUsingRenderTargets(false)
 	{
 		mParamBuffer = gPerCameraParamDef.createBuffer();
 	}
 
-	RendererCamera::RendererCamera(const Camera* camera, StateReduction reductionMode)
-		:mCamera(camera), mUsingRenderTargets(false)
+	RendererCamera::RendererCamera(const RENDERER_VIEW_DESC& desc)
+		: mViewDesc(desc), mUsingRenderTargets(false)
 	{
 		mParamBuffer = gPerCameraParamDef.createBuffer();
-		update(reductionMode);
+
+		setStateReductionMode(desc.stateReduction);
 	}
 
-	void RendererCamera::update(StateReduction reductionMode)
+	void RendererCamera::setStateReductionMode(StateReduction reductionMode)
 	{
 		mOpaqueQueue = bs_shared_ptr_new<RenderQueue>(reductionMode);
 
@@ -60,38 +61,46 @@ namespace bs { namespace ct
 			transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
 
 		mTransparentQueue = bs_shared_ptr_new<RenderQueue>(transparentStateReduction);
-		updatePP();
 	}
 
-	void RendererCamera::updatePP()
+	void RendererCamera::setPostProcessSettings(const SPtr<PostProcessSettings>& ppSettings)
 	{
 		if (mPostProcessInfo.settings == nullptr)
 			mPostProcessInfo.settings = bs_shared_ptr_new<StandardPostProcessSettings>();
 
-		SPtr<StandardPostProcessSettings> ppSettings = std::static_pointer_cast<StandardPostProcessSettings>(mCamera->getPostProcessSettings());
-		if (ppSettings != nullptr)
-			*mPostProcessInfo.settings = *ppSettings;
+		SPtr<StandardPostProcessSettings> stdPPSettings = std::static_pointer_cast<StandardPostProcessSettings>(ppSettings);
+		if (stdPPSettings != nullptr)
+			*mPostProcessInfo.settings = *stdPPSettings;
 		else
 			*mPostProcessInfo.settings = StandardPostProcessSettings();
 
 		mPostProcessInfo.settingDirty = true;
 	}
 
+	void RendererCamera::setTransform(const Vector3& origin, const Vector3& direction, const Matrix4& view, const Matrix4& proj)
+	{
+		mViewDesc.viewOrigin = origin;
+		mViewDesc.viewDirection = direction;
+		mViewDesc.viewTransform = view;
+		mViewDesc.projTransform = proj;
+	}
+
+	void RendererCamera::setView(const RENDERER_VIEW_DESC& desc)
+	{
+		mViewDesc = desc;
+	}
+
 	void RendererCamera::beginRendering(bool useGBuffer)
 	{
 		if (useGBuffer)
 		{
-			SPtr<Viewport> 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;
+				mRenderTargets->getHDR() != mViewDesc.isHDR ||
+				mRenderTargets->getNumSamples() != mViewDesc.target.numSamples;
 
 			if (createGBuffer)
-				mRenderTargets = RenderTargets::create(viewport, useHDR, msaaCount);
+				mRenderTargets = RenderTargets::create(mViewDesc.target, mViewDesc.isHDR);
 
 			mRenderTargets->allocate();
 			mUsingRenderTargets = true;
@@ -116,12 +125,11 @@ namespace bs { namespace ct
 		mVisibility.clear();
 		mVisibility.resize(renderables.size(), false);
 
-		bool isOverlayCamera = mCamera->getFlags().isSet(CameraFlag::Overlay);
-		if (isOverlayCamera)
+		if (mViewDesc.isOverlay)
 			return;
 
-		UINT64 cameraLayers = mCamera->getLayers();
-		ConvexVolume worldFrustum = mCamera->getWorldFrustum();
+		UINT64 cameraLayers = mViewDesc.visibleLayers;
+		const ConvexVolume& worldFrustum = mViewDesc.cullFrustum;
 
 		// Update per-object param buffers and queue render elements
 		for(UINT32 i = 0; i < (UINT32)renderables.size(); i++)
@@ -146,7 +154,7 @@ namespace bs { namespace ct
 					visibility[i] = true;
 					mVisibility[i] = true;
 
-					float distanceToCamera = (mCamera->getPosition() - boundingBox.getCenter()).length();
+					float distanceToCamera = (mViewDesc.viewOrigin - boundingBox.getCenter()).length();
 
 					for (auto& renderElem : renderables[i]->elements)
 					{
@@ -204,18 +212,16 @@ namespace bs { namespace ct
 		return output;
 	}
 
-	void RendererCamera::updatePerCameraBuffer()
+	void RendererCamera::updatePerViewBuffer()
 	{
-		Matrix4 proj = mCamera->getProjectionMatrixRS();
-		Matrix4 view = mCamera->getViewMatrix();
-		Matrix4 viewProj = proj * view;
+		Matrix4 viewProj = mViewDesc.projTransform * mViewDesc.viewTransform;
 		Matrix4 invViewProj = viewProj.inverse();
 
-		gPerCameraParamDef.gMatProj.set(mParamBuffer, proj);
-		gPerCameraParamDef.gMatView.set(mParamBuffer, view);
+		gPerCameraParamDef.gMatProj.set(mParamBuffer, mViewDesc.projTransform);
+		gPerCameraParamDef.gMatView.set(mParamBuffer, mViewDesc.viewTransform);
 		gPerCameraParamDef.gMatViewProj.set(mParamBuffer, viewProj);
 		gPerCameraParamDef.gMatInvViewProj.set(mParamBuffer, invViewProj); // Note: Calculate inverses separately (better precision possibly)
-		gPerCameraParamDef.gMatInvProj.set(mParamBuffer, proj.inverse());
+		gPerCameraParamDef.gMatInvProj.set(mParamBuffer, mViewDesc.projTransform.inverse());
 
 		// 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 
@@ -223,35 +229,23 @@ namespace bs { namespace ct
 
 		// Only projects z/w coordinates
 		Matrix4 projZ = Matrix4::IDENTITY;
-		projZ[2][2] = proj[2][2];
-		projZ[2][3] = proj[2][3];
-		projZ[3][2] = proj[3][2];
+		projZ[2][2] = mViewDesc.projTransform[2][2];
+		projZ[2][3] = mViewDesc.projTransform[2][3];
+		projZ[3][2] = mViewDesc.projTransform[3][2];
 		projZ[3][3] = 0.0f;
 
 		gPerCameraParamDef.gMatScreenToWorld.set(mParamBuffer, invViewProj * projZ);
-		gPerCameraParamDef.gViewDir.set(mParamBuffer, mCamera->getForward());
-		gPerCameraParamDef.gViewOrigin.set(mParamBuffer, mCamera->getPosition());
-		gPerCameraParamDef.gDeviceZToWorldZ.set(mParamBuffer, getDeviceZTransform(proj));
-
-		SPtr<Viewport> viewport = mCamera->getViewport();
-		SPtr<RenderTarget> rt = viewport->getTarget();
+		gPerCameraParamDef.gViewDir.set(mParamBuffer, mViewDesc.viewDirection);
+		gPerCameraParamDef.gViewOrigin.set(mParamBuffer, mViewDesc.viewOrigin);
+		gPerCameraParamDef.gDeviceZToWorldZ.set(mParamBuffer, getDeviceZTransform(mViewDesc.projTransform));
 
-		float halfWidth = viewport->getWidth() * 0.5f;
-		float halfHeight = viewport->getHeight() * 0.5f;
+		const Rect2I& viewRect = mViewDesc.target.viewRect;
 
-		float rtWidth;
-		float rtHeight;
+		float halfWidth = viewRect.width * 0.5f;
+		float halfHeight = viewRect.height * 0.5f;
 
-		if(rt != nullptr)
-		{
-			rtWidth = (float)rt->getProperties().getWidth();
-			rtHeight = (float)rt->getProperties().getHeight();
-		}
-		else
-		{
-			rtWidth = 20.0f;
-			rtHeight = 20.0f;
-		}
+		float rtWidth = mViewDesc.target.targetWidth != 0 ? (float)mViewDesc.target.targetWidth : 20.0f;
+		float rtHeight = mViewDesc.target.targetHeight != 0 ? (float)mViewDesc.target.targetHeight : 20.0f;
 
 		RenderAPI& rapi = RenderAPI::instance();
 		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
@@ -259,8 +253,8 @@ namespace bs { namespace ct
 		Vector4 clipToUVScaleOffset;
 		clipToUVScaleOffset.x = halfWidth / rtWidth;
 		clipToUVScaleOffset.y = -halfHeight / rtHeight;
-		clipToUVScaleOffset.z = viewport->getX() / rtWidth + (halfWidth + rapiInfo.getHorizontalTexelOffset()) / rtWidth;
-		clipToUVScaleOffset.w = viewport->getY() / rtHeight + (halfHeight + rapiInfo.getVerticalTexelOffset()) / rtHeight;
+		clipToUVScaleOffset.z = viewRect.x / rtWidth + (halfWidth + rapiInfo.getHorizontalTexelOffset()) / rtWidth;
+		clipToUVScaleOffset.w = viewRect.y / rtHeight + (halfHeight + rapiInfo.getVerticalTexelOffset()) / rtHeight;
 
 		// Either of these flips the Y axis, but if they're both true they cancel out
 		if (rapiInfo.getUVYAxisUp() ^ rapiInfo.getNDCYAxisDown())