Преглед изворни кода

Modifying camera properties no longer causes a full rebuild of camera's data in the renderer
- This prevents exposure being reset every time a property changes (e.g. like during render target resize)

BearishSun пре 9 година
родитељ
комит
e06ac4cab3

+ 3 - 17
Source/BansheeEngine/Source/BsCamera.cpp

@@ -727,11 +727,7 @@ namespace BansheeEngine
 		mRecalcFrustumPlanes = true;
 		mRecalcView = true;
 
-		if (dirtyFlag == CameraDirtyFlag::Transform)
-		{
-			RendererManager::instance().getActive()->notifyCameraUpdated(this, (UINT32)dirtyFlag);
-		}
-		else 
+		if (dirtyFlag != CameraDirtyFlag::Transform)
 		{
 			dataPtr = rttiReadElem(mLayers, dataPtr);
 			dataPtr = rttiReadElem(mProjType, dataPtr);
@@ -748,19 +744,9 @@ namespace BansheeEngine
 			dataPtr = rttiReadElem(mIsActive, dataPtr);
 			dataPtr = rttiReadElem(mMSAA, dataPtr);
 			dataPtr = rttiReadElem(mPPSettings, dataPtr);
-
-			if(dirtyFlag == CameraDirtyFlag::PostProcess)
-			{
-				RendererManager::instance().getActive()->notifyCameraUpdated(this, (UINT32)dirtyFlag);
-			}
-			else
-			{
-				RendererManager::instance().getActive()->notifyCameraRemoved(this);
-
-				if (mIsActive)
-					RendererManager::instance().getActive()->notifyCameraAdded(this);
-			}
 		}
+
+		RendererManager::instance().getActive()->notifyCameraUpdated(this, (UINT32)dirtyFlag);
 	}
 
 	Camera::Camera(SPtr<RenderTarget> target, float left, float top, float width, float height)

+ 9 - 0
Source/RenderBeast/Include/BsRenderBeast.h

@@ -159,6 +159,15 @@ namespace BansheeEngine
 		/** @copydoc Renderer::notifyRenderableRemoved */
 		void notifyRenderableRemoved(RenderableCore* renderable) override;
 
+		/** 
+		 * Updates (or adds) renderer specific data for the specified camera. Should be called whenever camera properties
+		 * change. 
+		 *
+		 * @param[in]	camera		Camera whose data to update.
+		 * @param[in]	forceRemove	If true, the camera data will be removed instead of updated.
+		 */
+		void updateCameraData(const CameraCore* camera, bool forceRemove = false);
+
 		/**
 		 * Updates the render options on the core thread.
 		 *

+ 73 - 48
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -328,68 +328,52 @@ namespace BansheeEngine
 
 	void RenderBeast::notifyCameraAdded(const CameraCore* camera)
 	{
-		SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
-		if (renderTarget == nullptr)
-			return;
-
-		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;
-
-		// Register in render target list
-		auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), 
-			[&](const RenderTargetData& x) { return x.target == renderTarget; });
+		updateCameraData(camera);
+	}
 
-		if (findIter != mRenderTargets.end())
+	void RenderBeast::notifyCameraUpdated(const CameraCore* camera, UINT32 updateFlag)
+	{
+		if((updateFlag & (UINT32)CameraDirtyFlag::Everything) != 0)
 		{
-			findIter->cameras.push_back(camera);
+			updateCameraData(camera);
 		}
-		else
+		else if((updateFlag & (UINT32)CameraDirtyFlag::PostProcess) != 0)
 		{
-			mRenderTargets.push_back(RenderTargetData());
-			RenderTargetData& renderTargetData = mRenderTargets.back();
-
-			renderTargetData.target = renderTarget;
-			renderTargetData.cameras.push_back(camera);
-		}
-
-		// Sort render targets based on priority
-		auto cameraComparer = [&](const CameraCore* a, const CameraCore* b) { return a->getPriority() > b->getPriority(); };
-		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
-		{ return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
-		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
-
-		for (auto& camerasPerTarget : mRenderTargets)
-		{
-			Vector<const CameraCore*>& cameras = camerasPerTarget.cameras;
+			CameraData& camData = mCameraData[camera];
+			camData.postProcessInfo.settings = camera->getPostProcessSettings();
+			camData.postProcessInfo.settingDirty = true;
+		} 
+	}
 
-			std::sort(begin(cameras), end(cameras), cameraComparer);
-		}
+	void RenderBeast::notifyCameraRemoved(const CameraCore* camera)
+	{
+		updateCameraData(camera, true);
 	}
 
-	void RenderBeast::notifyCameraUpdated(const CameraCore* camera, UINT32 updateFlag)
+	void RenderBeast::updateCameraData(const CameraCore* camera, bool forceRemove)
 	{
-		CameraDirtyFlag dirtyFlag = (CameraDirtyFlag)updateFlag;
-		if(dirtyFlag == CameraDirtyFlag::PostProcess)
+		SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
+		if(forceRemove)
+		{
+			mCameraData.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;
 		}
-	}
-
-	void RenderBeast::notifyCameraRemoved(const CameraCore* camera)
-	{
-		mCameraData.erase(camera);
 
 		// Remove from render target list
+		int rtChanged = 0; // 0 - No RT, 1 - RT found, 2 - RT changed
 		for (auto iterTarget = mRenderTargets.begin(); iterTarget != mRenderTargets.end(); ++iterTarget)
 		{
 			RenderTargetData& target = *iterTarget;
@@ -397,7 +381,15 @@ namespace BansheeEngine
 			{
 				if (camera == *iterCam)
 				{
-					target.cameras.erase(iterCam);
+					if (renderTarget != target.target)
+					{
+						target.cameras.erase(iterCam);
+						rtChanged = 2;
+
+					}
+					else
+						rtChanged = 1;
+
 					break;
 				}
 			}
@@ -408,6 +400,39 @@ namespace BansheeEngine
 				break;
 			}
 		}
+
+		// Register in render target list
+		if (renderTarget != nullptr && (rtChanged == 0 || rtChanged == 2))
+		{
+			auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(),
+				[&](const RenderTargetData& x) { return x.target == renderTarget; });
+
+			if (findIter != mRenderTargets.end())
+			{
+				findIter->cameras.push_back(camera);
+			}
+			else
+			{
+				mRenderTargets.push_back(RenderTargetData());
+				RenderTargetData& renderTargetData = mRenderTargets.back();
+
+				renderTargetData.target = renderTarget;
+				renderTargetData.cameras.push_back(camera);
+			}
+
+			// Sort render targets based on priority
+			auto cameraComparer = [&](const CameraCore* a, const CameraCore* b) { return a->getPriority() > b->getPriority(); };
+			auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
+			{ return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
+			std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
+
+			for (auto& camerasPerTarget : mRenderTargets)
+			{
+				Vector<const CameraCore*>& cameras = camerasPerTarget.cameras;
+
+				std::sort(begin(cameras), end(cameras), cameraComparer);
+			}
+		}
 	}
 
 	void RenderBeast::setOptions(const SPtr<CoreRendererOptions>& options)