Browse Source

Added the ability to sort cameras and render targets

Marko Pintera 12 years ago
parent
commit
a7eff80522

+ 76 - 73
BansheeEngine/Include/BsCamera.h

@@ -105,79 +105,6 @@ namespace BansheeEngine {
     */
     */
     class BS_EXPORT Camera : public CM::Component
     class BS_EXPORT Camera : public CM::Component
     {
     {
-	protected:
-        /// Orthographic or perspective?
-        ProjectionType mProjType;
-
-        /// y-direction field-of-view (default 45)
-        CM::Radian mHorzFOV;
-        /// Far clip distance - default 10000
-        float mFarDist;
-        /// Near clip distance - default 100
-        float mNearDist;
-        /// x/y viewport ratio - default 1.3333
-        float mAspect;
-		/// Ortho height size (world units)
-		float mOrthoHeight;
-        /// Off-axis frustum center offset - default (0.0, 0.0)
-        CM::Vector2 mFrustumOffset;
-        /// Focal length of frustum (for stereo rendering, defaults to 1.0)
-        float mFocalLength;
-
-        /// The 6 main clipping planes
-        mutable CM::Plane mFrustumPlanes[6];
-
-        /// Stored versions of parent orientation / position
-        mutable CM::Quaternion mLastParentOrientation;
-        mutable CM::Vector3 mLastParentPosition;
-
-        /// Pre-calced projection matrix for the specific render system
-        mutable CM::Matrix4 mProjMatrixRS;
-        /// Pre-calced standard projection matrix but with render system depth range
-        mutable CM::Matrix4 mProjMatrixRSDepth;
-        /// Pre-calced standard projection matrix
-        mutable CM::Matrix4 mProjMatrix;
-        /// Pre-calced view matrix
-        mutable CM::Matrix4 mViewMatrix;
-        /// Something's changed in the frustum shape?
-        mutable bool mRecalcFrustum;
-        /// Something re the frustum planes has changed
-        mutable bool mRecalcFrustumPlanes;
-        /// Something re the world space corners has changed
-        mutable bool mRecalcWorldSpaceCorners;
-        /// Something re the vertex data has changed
-        mutable bool mRecalcVertexData;
-		/// Are we using a custom view matrix?
-		bool mCustomViewMatrix;
-		/// Are we using a custom projection matrix?
-		bool mCustomProjMatrix;
-		/// Have the frustum extents been manually set?
-		bool mFrustumExtentsManuallySet;
-		bool mIgnoreSceneRenderables;
-		/// Frustum extents
-		mutable float mLeft, mRight, mTop, mBottom;
-		
-        // Internal functions for calcs
-        virtual void calcProjectionParameters(float& left, float& right, float& bottom, float& top) const;
-		/// Update frustum if out of date
-        virtual void updateFrustum(void) const;
-		/// Implementation of updateFrustum (called if out of date)
-		virtual void updateFrustumImpl(void) const;
-        virtual void updateFrustumPlanes(void) const;
-		/// Implementation of updateFrustumPlanes (called if out of date)
-		virtual void updateFrustumPlanesImpl(void) const;
-        virtual void updateWorldSpaceCorners(void) const;
-		/// Implementation of updateWorldSpaceCorners (called if out of date)
-		virtual void updateWorldSpaceCornersImpl(void) const;
-		virtual void updateView(void) const;
-        virtual bool isFrustumOutOfDate(void) const;
-        /// Signal to update frustum information.
-        virtual void invalidateFrustum(void) const;
-
-        mutable CM::AxisAlignedBox mBoundingBox;
-
-        mutable CM::Vector3 mWorldSpaceCorners[8];
-
     public:
     public:
         /** Sets the Y-dimension Field Of View (FOV) of the frustum.
         /** Sets the Y-dimension Field Of View (FOV) of the frustum.
             @remarks
             @remarks
@@ -494,11 +421,87 @@ namespace BansheeEngine {
 		void setIgnoreSceneRenderables(bool value) { mIgnoreSceneRenderables = true; }
 		void setIgnoreSceneRenderables(bool value) { mIgnoreSceneRenderables = true; }
 		bool getIgnoreSceneRenderables() const { return mIgnoreSceneRenderables; }
 		bool getIgnoreSceneRenderables() const { return mIgnoreSceneRenderables; }
 
 
+		CM::INT32 getPriority() const { return mPriority; }
+		void setPriority(CM::INT32 priority) { mPriority = priority; }
+
         /// Small constant used to reduce far plane projection to avoid inaccuracies
         /// Small constant used to reduce far plane projection to avoid inaccuracies
         static const float INFINITE_FAR_PLANE_ADJUST;
         static const float INFINITE_FAR_PLANE_ADJUST;
     protected:
     protected:
 		CM::ViewportPtr mViewport;
 		CM::ViewportPtr mViewport;
 
 
+		/// Orthographic or perspective?
+		ProjectionType mProjType;
+
+		/// y-direction field-of-view (default 45)
+		CM::Radian mHorzFOV;
+		/// Far clip distance - default 10000
+		float mFarDist;
+		/// Near clip distance - default 100
+		float mNearDist;
+		/// x/y viewport ratio - default 1.3333
+		float mAspect;
+		/// Ortho height size (world units)
+		float mOrthoHeight;
+		/// Off-axis frustum center offset - default (0.0, 0.0)
+		CM::Vector2 mFrustumOffset;
+		/// Focal length of frustum (for stereo rendering, defaults to 1.0)
+		float mFocalLength;
+		CM::INT32 mPriority;
+
+		/// The 6 main clipping planes
+		mutable CM::Plane mFrustumPlanes[6];
+
+		/// Stored versions of parent orientation / position
+		mutable CM::Quaternion mLastParentOrientation;
+		mutable CM::Vector3 mLastParentPosition;
+
+		/// Pre-calced projection matrix for the specific render system
+		mutable CM::Matrix4 mProjMatrixRS;
+		/// Pre-calced standard projection matrix but with render system depth range
+		mutable CM::Matrix4 mProjMatrixRSDepth;
+		/// Pre-calced standard projection matrix
+		mutable CM::Matrix4 mProjMatrix;
+		/// Pre-calced view matrix
+		mutable CM::Matrix4 mViewMatrix;
+		/// Something's changed in the frustum shape?
+		mutable bool mRecalcFrustum;
+		/// Something re the frustum planes has changed
+		mutable bool mRecalcFrustumPlanes;
+		/// Something re the world space corners has changed
+		mutable bool mRecalcWorldSpaceCorners;
+		/// Something re the vertex data has changed
+		mutable bool mRecalcVertexData;
+		/// Are we using a custom view matrix?
+		bool mCustomViewMatrix;
+		/// Are we using a custom projection matrix?
+		bool mCustomProjMatrix;
+		/// Have the frustum extents been manually set?
+		bool mFrustumExtentsManuallySet;
+		bool mIgnoreSceneRenderables;
+		/// Frustum extents
+		mutable float mLeft, mRight, mTop, mBottom;
+
+		// Internal functions for calcs
+		virtual void calcProjectionParameters(float& left, float& right, float& bottom, float& top) const;
+		/// Update frustum if out of date
+		virtual void updateFrustum(void) const;
+		/// Implementation of updateFrustum (called if out of date)
+		virtual void updateFrustumImpl(void) const;
+		virtual void updateFrustumPlanes(void) const;
+		/// Implementation of updateFrustumPlanes (called if out of date)
+		virtual void updateFrustumPlanesImpl(void) const;
+		virtual void updateWorldSpaceCorners(void) const;
+		/// Implementation of updateWorldSpaceCorners (called if out of date)
+		virtual void updateWorldSpaceCornersImpl(void) const;
+		virtual void updateView(void) const;
+		virtual bool isFrustumOutOfDate(void) const;
+		/// Signal to update frustum information.
+		virtual void invalidateFrustum(void) const;
+
+		mutable CM::AxisAlignedBox mBoundingBox;
+
+		mutable CM::Vector3 mWorldSpaceCorners[8];
+
     public:
     public:
         /** Standard destructor.
         /** Standard destructor.
         */
         */

+ 2 - 1
BansheeEngine/Source/BsCamera.cpp

@@ -66,7 +66,8 @@ namespace BansheeEngine
 		mCustomViewMatrix(false),
 		mCustomViewMatrix(false),
 		mCustomProjMatrix(false),
 		mCustomProjMatrix(false),
 		mFrustumExtentsManuallySet(false),
 		mFrustumExtentsManuallySet(false),
-		mIgnoreSceneRenderables(false)
+		mIgnoreSceneRenderables(false),
+		mPriority(0)
     {
     {
 		updateView();
 		updateView();
 		updateFrustum();
 		updateFrustum();

+ 45 - 21
BansheeForwardRenderer/Source/BsForwardRenderer.cpp

@@ -36,44 +36,68 @@ namespace BansheeEngine
 		CoreAccessor& coreAccessor = gMainCA();
 		CoreAccessor& coreAccessor = gMainCA();
 		const Vector<HCamera>::type& allCameras = gSceneManager().getAllCameras();
 		const Vector<HCamera>::type& allCameras = gSceneManager().getAllCameras();
 
 
+		struct RenderTargetRenderInfo
+		{
+			RenderTargetPtr target;
+			Vector<HCamera>::type cameras;
+		};
+
 		// Find all unique render targets
 		// Find all unique render targets
-		UnorderedSet<RenderTargetPtr>::type renderTargets;
+		Vector<RenderTargetRenderInfo>::type camerasPerRenderTarget;
 		for(auto& camera : allCameras)
 		for(auto& camera : allCameras)
 		{
 		{
 			RenderTargetPtr target = camera->getViewport()->getTarget();
 			RenderTargetPtr target = camera->getViewport()->getTarget();
-			auto findIter = renderTargets.find(target);
+			auto findIter = std::find_if(begin(camerasPerRenderTarget), end(camerasPerRenderTarget), [&target] (const RenderTargetRenderInfo& x) { return x.target == target; });
 
 
-			if(findIter == renderTargets.end())
+			if(findIter == camerasPerRenderTarget.end())
 			{
 			{
-				renderTargets.insert(target);
+				camerasPerRenderTarget.push_back(RenderTargetRenderInfo());
+				camerasPerRenderTarget[camerasPerRenderTarget.size() - 1].target = target;
+				camerasPerRenderTarget[camerasPerRenderTarget.size() - 1].cameras.push_back(camera);
 			}
 			}
+			else
+				findIter->cameras.push_back(camera);
 		}
 		}
 
 
-		// Clear all targets
-		for(auto& target : renderTargets)
-			coreAccessor.clear(target, FBT_COLOR | FBT_DEPTH, Color::Blue);
+		// Sort everything based on priority
+		auto cameraComparer = [&] (const HCamera& a, const HCamera& b) { return a->getPriority() > b->getPriority(); };
+		auto renderTargetInfoComparer = [&] (const RenderTargetRenderInfo& a, const RenderTargetRenderInfo& b) { return a.target->getPriority() > b.target->getPriority(); };
+		std::sort(begin(camerasPerRenderTarget), end(camerasPerRenderTarget), renderTargetInfoComparer);
 
 
-		coreAccessor.beginFrame();
+		for(auto& camerasPerTarget : camerasPerRenderTarget)
+		{
+			Vector<HCamera>::type& cameras = camerasPerTarget.cameras;
 
 
-		// TODO - Attempt to render all different elements in such a way that there is only 1 render target switch per render target
+			std::sort(begin(cameras), end(cameras), cameraComparer);
+		}
 
 
-		// Render all cameras
-		for(auto& camera : allCameras)
-			render(camera);
+		// Clear all targets
+		for(auto& camerasPerTarget : camerasPerRenderTarget)
+		{
+			RenderTargetPtr target = camerasPerTarget.target;
+			const Vector<HCamera>::type& cameras = camerasPerTarget.cameras;
 
 
-		// Render overlays for all targets
-		for(auto& camera : allCameras)
-			OverlayManager::instance().render(camera->getViewport(), coreAccessor);
+			coreAccessor.clear(target, FBT_COLOR | FBT_DEPTH, Color::Blue);
+			coreAccessor.beginFrame();
 
 
-		// Render all GUI elements
-		for(auto& camera : allCameras)
-			GUIManager::instance().render(camera->getViewport(), coreAccessor);
+			for(auto& camera : cameras)
+			{
+				// Render all cameras
+				for(auto& camera : cameras)
+					render(camera);
+
+				// Render overlays for all targets
+				for(auto& camera : cameras)
+					OverlayManager::instance().render(camera->getViewport(), coreAccessor);
 
 
-		coreAccessor.endFrame();
+				// Render all GUI elements
+				for(auto& camera : cameras)
+					GUIManager::instance().render(camera->getViewport(), coreAccessor);
+			}
 
 
-		// Swap all targets
-		for(auto& target : renderTargets)
+			coreAccessor.endFrame();
 			coreAccessor.swapBuffers(target);
 			coreAccessor.swapBuffers(target);
+		}
 	}
 	}
 
 
 	void ForwardRenderer::render(const HCamera& camera) 
 	void ForwardRenderer::render(const HCamera& camera) 

+ 5 - 0
CamelotCore/Include/CmRenderTarget.h

@@ -80,6 +80,9 @@ namespace CamelotFramework
 
 
 		virtual void setActive(bool state) { mActive = state; }
 		virtual void setActive(bool state) { mActive = state; }
 
 
+		INT32 getPriority() const { return mPriority; }
+		void setPriority(INT32 priority) { mPriority = priority; }
+
         /**
         /**
          * @brief	Swaps the frame buffers to display the next frame.
          * @brief	Swaps the frame buffers to display the next frame.
          * 			
          * 			
@@ -98,6 +101,8 @@ namespace CamelotFramework
         UINT32 mWidth;
         UINT32 mWidth;
         UINT32 mHeight;
         UINT32 mHeight;
         UINT32 mColorDepth;
         UINT32 mColorDepth;
+		
+		INT32 mPriority;
 
 
         bool mActive;
         bool mActive;
 		bool mHwGamma;
 		bool mHwGamma;

+ 1 - 1
CamelotCore/Source/CmRenderTarget.cpp

@@ -35,7 +35,7 @@ namespace CamelotFramework {
 
 
     RenderTarget::RenderTarget()
     RenderTarget::RenderTarget()
 		:mActive(true), mHwGamma(false), mVSync(false), mFSAA(0),
 		:mActive(true), mHwGamma(false), mVSync(false), mFSAA(0),
-		mWidth(0), mHeight(0), mColorDepth(0)
+		mWidth(0), mHeight(0), mColorDepth(0), mPriority(0)
     {
     {
     }
     }