Forráskód Böngészése

Added LightProbeVolume component

BearishSun 8 éve
szülő
commit
f5b3f4f653

+ 3 - 0
Source/BansheeCore/CMakeSources.cmake

@@ -23,6 +23,7 @@ set(BS_BANSHEECORE_INC_COMPONENTS
 	"Include/BsCBone.h"	
 	"Include/BsCReflectionProbe.h"
 	"Include/BsCSkybox.h"
+	"Include/BsCLightProbeVolume.h"
 )
 
 set(BS_BANSHEECORE_INC_PHYSICS
@@ -264,6 +265,7 @@ set(BS_BANSHEECORE_SRC_COMPONENTS
 	"Source/BsCBone.cpp"	
 	"Source/BsCReflectionProbe.cpp"
 	"Source/BsCSkybox.cpp"
+	"Source/BsCLightProbeVolume.cpp"
 )
 
 set(BS_BANSHEECORE_SRC_IMPORTER
@@ -364,6 +366,7 @@ set(BS_BANSHEECORE_INC_RTTI
 	"Include/BsCReflectionProbeRTTI.h"
 	"Include/BsSkyboxRTTI.h"
 	"Include/BsLightProbeVolumeRTTI.h"
+	"Include/BsCLightProbeVolumeRTTI.h"
 )
 
 set(BS_BANSHEECORE_SRC_RENDERER

+ 19 - 19
Source/BansheeCore/Include/BsCLight.h

@@ -17,25 +17,25 @@ namespace bs
 	 *
 	 * Wraps Light as a Component.
 	 */
-    class BS_CORE_EXPORT CLight : public Component
-    {
-    public:
+	class BS_CORE_EXPORT CLight : public Component
+	{
+	public:
 		CLight(const HSceneObject& parent, LightType type = LightType::Radial, Color color = Color::White, 
 			float intensity = 100.0f, float range = 1.0f, bool castsShadows = false, Degree spotAngle = Degree(45), 
 			Degree spotFalloffAngle = Degree(40));
 
 		virtual ~CLight();
 
-	    /** @copydoc Light::getType */
+		/** @copydoc Light::getType */
 		LightType getType() const { return mInternal->getType(); }
 
-	    /** @copydoc Light::setType */
+		/** @copydoc Light::setType */
 		void setType(LightType type) { mInternal->setType(type); }
 
-	    /** @copydoc Light::getCastsShadow */
+		/** @copydoc Light::getCastsShadow */
 		bool getCastsShadow() const { return mInternal->getCastsShadow(); }
 
-	    /** @copydoc Light::setCastsShadow */
+		/** @copydoc Light::setCastsShadow */
 		void setCastsShadow(bool castsShadow) { mInternal->setCastsShadow(castsShadow); }
 
 		/** @copydoc Light::setShadowBias */
@@ -44,16 +44,16 @@ namespace bs
 		/** @copydoc Light::setShadowBias() */
 		float getShadowBias() const { return mInternal->getShadowBias(); }
 
-	    /** @copydoc Light::getColor */
+		/** @copydoc Light::getColor */
 		Color getColor() const { return mInternal->getColor(); }
 
-	    /** @copydoc Light::setColor */
+		/** @copydoc Light::setColor */
 		void setColor(const Color& color) { mInternal->setColor(color); }
 
-	    /** @copydoc Light::getAttenuationRadius */
+		/** @copydoc Light::getAttenuationRadius */
 		float getAttenuationRadius() const { return mInternal->getAttenuationRadius(); }
 
-	    /** @copydoc Light::setAttenuationRadius */
+		/** @copydoc Light::setAttenuationRadius */
 		void setAttenuationRadius(float radius) { mInternal->setAttenuationRadius(radius); }
 
 		/** @copydoc Light::getSourceRadius */
@@ -62,16 +62,16 @@ namespace bs
 		/** @copydoc Light::setSourceRadius */
 		void setSourceRadius(float radius) { mInternal->setSourceRadius(radius); }
 
-	    /** @copydoc Light::getIntensity */
+		/** @copydoc Light::getIntensity */
 		float getIntensity() const { return mInternal->getIntensity(); }
 
-	    /** @copydoc Light::setIntensity */
+		/** @copydoc Light::setIntensity */
 		void setIntensity(float intensity) { mInternal->setIntensity(intensity); }
 
-	    /** @copydoc Light::getSpotAngle */
+		/** @copydoc Light::getSpotAngle */
 		Degree getSpotAngle() const { return mInternal->getSpotAngle(); }
 
-	    /** @copydoc Light::setSpotAngle */
+		/** @copydoc Light::setSpotAngle */
 		void setSpotAngle(const Degree& spotAngle) { mInternal->setSpotAngle(spotAngle); }
 
 		/** @copydoc Light::getSpotFalloffAngle */
@@ -86,19 +86,19 @@ namespace bs
 		/**  @copydoc Light::setUseAutoAttenuation  */
 		void setUseAutoAttenuation(bool enabled) { mInternal->setUseAutoAttenuation(enabled); }
 
-	    /** @copydoc Light::getBounds  */
+		/** @copydoc Light::getBounds  */
 		Sphere getBounds() const;
 
 		/** @name Internal 
 		 *  @{
 		 */
 
-	    /**	Returns the light that this component wraps. */
+		 /** Returns the light that this component wraps. */
 		SPtr<Light> _getLight() const { return mInternal; }
 
 		/** @} */
 
-    protected:
+	protected:
 		mutable SPtr<Light> mInternal;
 
 		// Only valid during construction
@@ -135,7 +135,7 @@ namespace bs
 
 	protected:
 		CLight(); // Serialization only
-     };
+	 };
 
 	 /** @} */
 }

+ 98 - 0
Source/BansheeCore/Include/BsCLightProbeVolume.h

@@ -0,0 +1,98 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsLightProbeVolume.h"
+#include "BsComponent.h"
+
+namespace bs 
+{
+	/** @addtogroup Components
+	 *  @{
+	 */
+
+	/**
+	 * @copydoc	LightProbeVolume
+	 *
+	 * Wraps LightProbeVolume as a Component.
+	 */
+	class BS_CORE_EXPORT CLightProbeVolume : public Component
+	{
+	public:
+		CLightProbeVolume(const HSceneObject& parent, const AABox& volume = AABox::UNIT_BOX, 
+			const Vector3I& cellCount = {1, 1, 1});
+		virtual ~CLightProbeVolume();
+
+		/** @copydoc LightProbeVolume::addProbe() */
+		UINT32 addProbe(const Vector3& position) { return mInternal->addProbe(position); }
+
+		/** @copydoc LightProbeVolume::setProbePosition() */
+		void setProbePosition(UINT32 handle, const Vector3& position) { mInternal->setProbePosition(handle, position); }
+
+		/** @copydoc LightProbeVolume::getProbePosition() */
+		Vector3 getProbePosition(UINT32 handle) const { return mInternal->getProbePosition(handle); }
+
+		/** @copydoc LightProbeVolume::removeProbe() */
+		void removeProbe(UINT32 handle) { mInternal->removeProbe(handle); }
+
+		/** @copydoc LightProbeVolume::renderProbe() */
+		void renderProbe(UINT32 handle);
+
+		/** @copydoc LightProbeVolume::renderProbes() */
+		void renderProbes();
+
+		/** @copydoc LightProbeVolume::resize() */
+		void resize(const AABox& volume, const Vector3I& cellCount = { 1, 1, 1 }) { mInternal->resize(volume, cellCount); }
+
+		/** @copydoc LightProbeVolume::clip() */
+		void clip() { mInternal->clip(); }
+
+		/** @copydoc LightProbeVolume::reset() */
+		void reset() { mInternal->reset(); }
+
+		/** @name Internal 
+		 *  @{
+		 */
+
+		/**	Returns the light probe volume that this component wraps. */
+		SPtr<LightProbeVolume> _getInternal() const { return mInternal; }
+
+		/** @} */
+
+	protected:
+		mutable SPtr<LightProbeVolume> mInternal;
+
+		// Only valid during construction
+		AABox mVolume;
+		Vector3I mCellCount;
+
+		/************************************************************************/
+		/* 						COMPONENT OVERRIDES                      		*/
+		/************************************************************************/
+	protected:
+		friend class SceneObject;
+
+		/** @copydoc Component::onInitialized */
+		void onInitialized() override;
+
+		/** @copydoc Component::onDestroyed */
+		void onDestroyed() override;
+
+		/** @copydoc Component::update */
+		void update() override { }
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class CLightProbeVolumeRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+
+	protected:
+		CLightProbeVolume(); // Serialization only
+	};
+
+	 /** @} */
+}

+ 48 - 0
Source/BansheeCore/Include/BsCLightProbeVolumeRTTI.h

@@ -0,0 +1,48 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsRTTIType.h"
+#include "BsCLightProbeVolume.h"
+#include "BsGameObjectRTTI.h"
+
+namespace bs
+{
+	/** @cond RTTI */
+	/** @addtogroup RTTI-Impl-Engine
+	 *  @{
+	 */
+
+	class BS_CORE_EXPORT CLightProbeVolumeRTTI : public RTTIType <CLightProbeVolume, Component, CLightProbeVolumeRTTI>
+	{
+	private:
+		BS_BEGIN_RTTI_MEMBERS
+			BS_RTTI_MEMBER_REFLPTR(mInternal, 0)
+		BS_END_RTTI_MEMBERS
+
+	public:
+		CLightProbeVolumeRTTI()
+			:mInitMembers(this)
+		{ }
+
+		const String& getRTTIName() override
+		{
+			static String name = "CLightProbeVolume";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_CLightProbeVolume;
+		}
+
+		SPtr<IReflectable> newRTTIObject() override
+		{
+			return GameObjectRTTI::createGameObject<CLightProbeVolume>();
+		}
+	};
+
+	/** @} */
+	/** @endcond */
+}

+ 1 - 0
Source/BansheeCore/Include/BsCorePrerequisites.h

@@ -573,6 +573,7 @@ namespace bs
 		TID_CSkybox = 1135,
 		TID_LightProbeVolume = 1136,
 		TID_SavedLightProbeInfo = 1137,
+		TID_CLightProbeVolume = 1138,
 
 		// Moved from Engine layer
 		TID_CCamera = 30000,

+ 11 - 1
Source/BansheeCore/Include/BsLightProbeVolume.h

@@ -162,7 +162,7 @@ namespace bs
 		 * Resets all probes to match the original grid pattern. This will reset probe positions, as well as add/remove
 		 * probes as necessary, essentially losing any custom changes to the probes.
 		 */
-		void reset();		
+		void reset();
 
 		/**	Retrieves an implementation of the object usable only from the core thread. */
 		SPtr<ct::LightProbeVolume> getCore() const;
@@ -176,6 +176,15 @@ namespace bs
 		 *							volume in an uniform way.
 		 */
 		static SPtr<LightProbeVolume> create(const AABox& volume = AABox::UNIT_BOX, const Vector3I& cellCount = {1, 1, 1});
+
+		/**	Returns the hash value that can be used to identify if the internal data needs an update. */
+		UINT32 _getLastModifiedHash() const { return mLastUpdateHash; }
+
+		/**	Sets the hash value that can be used to identify if the internal data needs an update. */
+		void _setLastModifiedHash(UINT32 hash) { mLastUpdateHash = hash; }
+
+		/** Updates the transfrom from the provided scene object, if the scene object's data is detected to be dirty. */
+		void _updateTransform(const HSceneObject& so, bool force = false);
 	protected:
 		friend class ct::LightProbeVolume;
 
@@ -206,6 +215,7 @@ namespace bs
 		UnorderedMap<UINT32, ProbeInfo> mProbes;
 		AABox mVolume = AABox::UNIT_BOX;
 		Vector3I mCellCount;
+		UINT32 mLastUpdateHash;
 
 		UINT32 mNextProbeId = 0;
 		SPtr<ct::RendererTask> mRendererTask;

+ 21 - 0
Source/BansheeCore/Include/BsSceneManager.h

@@ -8,6 +8,8 @@
 
 namespace bs
 {
+	class LightProbeVolume;
+
 	/** @addtogroup Scene-Internal
 	 *  @{
 	 */
@@ -63,6 +65,18 @@ namespace bs
 		HSceneObject sceneObject;
 	};
 
+	/**	Contains information about a light probe volume managed by the scene manager. */
+	struct SceneLightProbeVolumeData
+	{
+		SceneLightProbeVolumeData() { }
+		SceneLightProbeVolumeData(const SPtr<LightProbeVolume>& volume, const HSceneObject& sceneObject)
+			:volume(volume), sceneObject(sceneObject)
+		{ }
+
+		SPtr<LightProbeVolume> volume;
+		HSceneObject sceneObject;
+	};
+
 	/** Possible states components can be in. Controls which component callbacks are triggered. */
 	enum class ComponentState
 	{
@@ -139,6 +153,12 @@ namespace bs
 		/**	Notifies the scene manager that a reflection probe was removed. */
 		void _unregisterReflectionProbe(const SPtr<ReflectionProbe>& probe);
 
+		/**	Notifies the scene manager that a new light probe volume was created. */
+		void _registerLightProbeVolume(const SPtr<LightProbeVolume>& volume, const HSceneObject& so);
+
+		/**	Notifies the scene manager that a light proble volume was removed. */
+		void _unregisterLightProbeVolume(const SPtr<LightProbeVolume>& volume);
+
 		/**	Notifies the scene manager that a camera either became the main camera, or has stopped being main camera. */
 		void _notifyMainCameraStateChanged(const SPtr<Camera>& camera);
 
@@ -215,6 +235,7 @@ namespace bs
 		Map<Renderable*, SceneRenderableData> mRenderables;
 		Map<Light*, SceneLightData> mLights;
 		Map<ReflectionProbe*, SceneReflectionProbeData> mReflectionProbes;
+		Map<LightProbeVolume*, SceneLightProbeVolumeData> mLightProbeVolumes;
 
 		Vector<HComponent> mActiveComponents;
 		Vector<HComponent> mInactiveComponents;

+ 2 - 1
Source/BansheeCore/Source/BsCLight.cpp

@@ -23,7 +23,8 @@ namespace bs
 
 	CLight::~CLight()
 	{
-		mInternal->destroy();
+		if(mInternal != nullptr)
+			mInternal->destroy();
 	}
 
 	Sphere CLight::getBounds() const

+ 72 - 0
Source/BansheeCore/Source/BsCLightProbeVolume.cpp

@@ -0,0 +1,72 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsCLightProbeVolume.h"
+#include "BsCLightProbeVolumeRTTI.h"
+#include "BsSceneManager.h"
+
+namespace bs
+{
+	CLightProbeVolume::CLightProbeVolume()
+	{
+		setFlag(ComponentFlag::AlwaysRun, true);
+		setName("LightProbeVolume");
+	}
+
+	CLightProbeVolume::CLightProbeVolume(const HSceneObject& parent, const AABox& volume, const Vector3I& cellCount)
+		:Component(parent), mVolume(volume), mCellCount(cellCount)
+	{
+		setFlag(ComponentFlag::AlwaysRun, true);
+		setName("Light");
+	}
+
+	CLightProbeVolume::~CLightProbeVolume()
+	{
+		if(mInternal != nullptr)
+			mInternal->destroy();
+	}
+
+	void CLightProbeVolume::renderProbe(UINT32 handle)
+	{
+		if (mInternal != nullptr && SO()->getActive())
+		{
+			mInternal->_updateTransform(SO());
+			mInternal->renderProbe(handle);
+		}
+	}
+
+	void CLightProbeVolume::renderProbes()
+	{
+		if (mInternal != nullptr && SO()->getActive())
+		{
+			mInternal->_updateTransform(SO());
+			mInternal->renderProbes();
+		}
+	}
+
+	void CLightProbeVolume::onInitialized()
+	{
+		// If mInternal already exists this means this object was deserialized,
+		// so all we need to do is initialize it.
+		if (mInternal != nullptr)
+			mInternal->initialize();
+		else
+			mInternal = LightProbeVolume::create(mVolume, mCellCount);
+
+		gSceneManager()._registerLightProbeVolume(mInternal, sceneObject());
+	}
+
+	void CLightProbeVolume::onDestroyed()
+	{
+		gSceneManager()._unregisterLightProbeVolume(mInternal);
+	}
+	
+	RTTITypeBase* CLightProbeVolume::getRTTIStatic()
+	{
+		return CLightProbeVolumeRTTI::instance();
+	}
+
+	RTTITypeBase* CLightProbeVolume::getRTTI() const
+	{
+		return CLightProbeVolume::getRTTIStatic();
+	}
+}

+ 16 - 2
Source/BansheeCore/Source/BsLightProbeVolume.cpp

@@ -8,6 +8,7 @@
 #include "BsGpuBuffer.h"
 #include "BsTexture.h"
 #include "BsIBLUtility.h"
+#include "BsSceneObject.h"
 
 namespace bs
 {
@@ -16,11 +17,11 @@ namespace bs
 	{ }
 
 	LightProbeVolume::LightProbeVolume()
-		: mVolume(AABox::UNIT_BOX), mCellCount { 1, 1, 1 }
+		: mVolume(AABox::UNIT_BOX), mCellCount { 1, 1, 1 }, mLastUpdateHash(0)
 	{ }
 
 	LightProbeVolume::LightProbeVolume(const AABox& volume, const Vector3I& cellCount)
-		:mVolume(volume), mCellCount(cellCount)
+		:mVolume(volume), mCellCount(cellCount), mLastUpdateHash(0)
 	{
 		reset();
 	}
@@ -196,6 +197,19 @@ namespace bs
 		}
 	}
 
+	void LightProbeVolume::_updateTransform(const HSceneObject& so, bool force)
+	{
+		UINT32 curHash = so->getTransformHash();
+		if (curHash != _getLastModifiedHash() || force)
+		{
+			mPosition = so->getWorldPosition();
+			mRotation = so->getWorldRotation();
+
+			_markCoreDirty();
+			_setLastModifiedHash(curHash);
+		}
+	}
+
 	void LightProbeVolume::runRenderProbeTask()
 	{
 		// If a task is already running cancel it

+ 23 - 1
Source/BansheeCore/Source/BsSceneManager.cpp

@@ -10,6 +10,7 @@
 #include "BsViewport.h"
 #include "BsGameObjectManager.h"
 #include "BsRenderTarget.h"
+#include "BsLightProbeVolume.h"
 
 namespace bs
 {
@@ -133,6 +134,16 @@ namespace bs
 		mReflectionProbes.erase(probe.get());
 	}
 
+	void SceneManager::_registerLightProbeVolume(const SPtr<LightProbeVolume>& volume, const HSceneObject& so)
+	{
+		mLightProbeVolumes[volume.get()] = SceneLightProbeVolumeData(volume, so);
+	}
+
+	void SceneManager::_unregisterLightProbeVolume(const SPtr<LightProbeVolume>& volume)
+	{
+		mLightProbeVolumes.erase(volume.get());
+	}
+
 	void SceneManager::_notifyMainCameraStateChanged(const SPtr<Camera>& camera)
 	{
 		auto iterFind = std::find_if(mMainCameras.begin(), mMainCameras.end(),
@@ -237,6 +248,17 @@ namespace bs
 				probe->setIsActive(so->getActive());
 			}
 		}
+
+		for (auto& volumePair : mLightProbeVolumes)
+		{
+			SPtr<LightProbeVolume> volume = volumePair.second.volume;
+			HSceneObject so = volumePair.second.sceneObject;
+
+			volume->_updateTransform(so);
+
+			if (so->getActive() != volume->getIsActive())
+				volume->setIsActive(so->getActive());
+		}
 	}
 
 	SceneCameraData SceneManager::getMainCamera() const
@@ -582,4 +604,4 @@ namespace bs
 	{
 		return SceneManager::instance();
 	}
-}
+}