Kaynağa Gözat

Added skeleton code for reflection probes

BearishSun 8 yıl önce
ebeveyn
işleme
f04992fbd4

+ 6 - 0
Source/BansheeCore/CMakeSources.cmake

@@ -21,6 +21,7 @@ set(BS_BANSHEECORE_INC_COMPONENTS
 	"Include/BsCLight.h"
 	"Include/BsCAnimation.h"
 	"Include/BsCBone.h"	
+	"Include/BsCReflectionProbe.h"
 )
 
 set(BS_BANSHEECORE_INC_PHYSICS
@@ -97,6 +98,7 @@ set(BS_BANSHEECORE_INC_RENDERER
 	"Include/BsCamera.h"
 	"Include/BsPostProcessSettings.h"
 	"Include/BsRendererExtension.h"
+	"Include/BsReflectionProbe.h"
 )
 
 set(BS_BANSHEECORE_SRC_LOCALIZATION
@@ -256,6 +258,7 @@ set(BS_BANSHEECORE_SRC_COMPONENTS
 	"Source/BsCLight.cpp"
 	"Source/BsCAnimation.cpp"
 	"Source/BsCBone.cpp"	
+	"Source/BsCReflectionProbe.cpp"
 )
 
 set(BS_BANSHEECORE_SRC_IMPORTER
@@ -352,6 +355,8 @@ set(BS_BANSHEECORE_INC_RTTI
 	"Include/BsCBoneRTTI.h"
 	"Include/BsRenderableRTTI.h"
 	"Include/BsLightRTTI.h"	
+	"Include/BsReflectionProbeRTTI.h"
+	"Include/BsCReflectionProbeRTTI.h"
 )
 
 set(BS_BANSHEECORE_SRC_RENDERER
@@ -364,6 +369,7 @@ set(BS_BANSHEECORE_SRC_RENDERER
 	"Source/BsCamera.cpp"
 	"Source/BsPostProcessSettings.cpp"
 	"Source/BsRendererExtension.cpp"
+	"Source/BsReflectionProbe.cpp"
 )
 
 set(BS_BANSHEECORE_SRC_RESOURCES

+ 87 - 0
Source/BansheeCore/Include/BsCReflectionProbe.h

@@ -0,0 +1,87 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsReflectionProbe.h"
+#include "BsComponent.h"
+
+namespace bs 
+{
+	/** @addtogroup Components
+	 *  @{
+	 */
+
+	/**
+	 * @copydoc	ReflectionProbe
+	 *
+	 * Wraps ReflectionProbe as a Component.
+	 */
+    class BS_CORE_EXPORT CReflectionProbe : public Component
+    {
+    public:
+		CReflectionProbe(const HSceneObject& parent);
+		virtual ~CReflectionProbe();
+
+	    /** @copydoc ReflectionProbe::getType */
+		ReflectionProbeType getType() const { return mInternal->getType(); }
+
+	    /** @copydoc ReflectionProbe::setType */
+		void setType(ReflectionProbeType type) { mInternal->setType(type); }
+
+	    /** @copydoc ReflectionProbe::getRadius */
+		float getRadius() const { return mInternal->getRadius(); }
+
+	    /** @copydoc ReflectionProbe::setRadius  */
+		void setRadius(float radius) { mInternal->setRadius(radius); }
+
+	    /** @copydoc ReflectionProbe::getExtents */
+		Vector3 getExtents() const { return mInternal->getExtents(); }
+
+	    /** @copydoc ReflectionProbe::setExtents */
+		void setExtents(const Vector3& extents) { mInternal->setExtents(extents); }
+
+	    /** @copydoc ReflectionProbe::getBounds  */
+		Sphere getBounds() const;
+
+		/** @name Internal 
+		 *  @{
+		 */
+
+	    /**	Returns the reflection probe that this component wraps. */
+		SPtr<ReflectionProbe> _getReflectionProbe() const { return mInternal; }
+
+		/** @} */
+
+    protected:
+		mutable SPtr<ReflectionProbe> mInternal;
+
+		/************************************************************************/
+		/* 						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 CReflectionProbeRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+
+	protected:
+		CReflectionProbe(); // Serialization only
+     };
+
+	 /** @} */
+}

+ 48 - 0
Source/BansheeCore/Include/BsCReflectionProbeRTTI.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 "BsCReflectionProbe.h"
+#include "BsGameObjectRTTI.h"
+
+namespace bs
+{
+	/** @cond RTTI */
+	/** @addtogroup RTTI-Impl-Engine
+	 *  @{
+	 */
+
+	class BS_CORE_EXPORT CReflectionProbeRTTI : public RTTIType <CReflectionProbe, Component, CReflectionProbeRTTI>
+	{
+	private:
+		SPtr<ReflectionProbe> getInternal(CReflectionProbe* obj) { return obj->mInternal; }
+		void setInternal(CReflectionProbe* obj, SPtr<ReflectionProbe> val) { obj->mInternal = val; }
+
+	public:
+		CReflectionProbeRTTI()
+		{
+			addReflectablePtrField("mInternal", 0, &CReflectionProbeRTTI::getInternal, &CReflectionProbeRTTI::setInternal);
+		}
+
+		const String& getRTTIName() override
+		{
+			static String name = "CReflectionProbe";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_CReflectionProbe;
+		}
+
+		SPtr<IReflectable> newRTTIObject() override
+		{
+			return GameObjectRTTI::createGameObject<CReflectionProbe>();
+		}
+	};
+
+	/** @} */
+	/** @endcond */
+}

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

@@ -350,6 +350,7 @@ namespace bs
 	class MorphChannel;
 	class GraphicsPipelineState;
 	class ComputePipelineState;
+	class ReflectionProbe;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -568,6 +569,8 @@ namespace bs
 		TID_MorphShape = 1128,
 		TID_MorphShapes = 1129,
 		TID_MorphChannel = 1130,
+		TID_ReflectionProbe = 1131,
+		TID_CReflectionProbe = 1132,
 
 		// Moved from Engine layer
 		TID_CCamera = 30000,

+ 9 - 17
Source/BansheeCore/Include/BsLight.h

@@ -24,7 +24,7 @@ namespace bs
 		Spot
 	};
 
-	/**	Signals which portion of a LightInternal is dirty. */
+	/**	Signals which portion of a light is dirty. */
 	enum class LightDirtyFlag
 	{
 		Transform = 0x01,
@@ -37,9 +37,7 @@ namespace bs
 	 *  @{
 	 */
 
-	/**
-	 * Illuminates a portion of the scene covered by a light. Base class for both sim and core thread Light implementations.
-	 */
+	/** Base class for both sim and core thread Light implementations. */
 	class BS_CORE_EXPORT LightBase
 	{
 	public:
@@ -53,13 +51,15 @@ namespace bs
 		Vector3 getPosition() const { return mPosition; }
 
 		/**	Sets the position of the light, in world space. */
-		void setPosition(const Vector3& position) { mPosition = position; _markCoreDirty(); updateBounds(); }
+		void setPosition(const Vector3& position) 
+			{ mPosition = position; _markCoreDirty(LightDirtyFlag::Transform); updateBounds(); }
 
 		/**	Returns the rotation of the light, in world space. */
 		Quaternion getRotation() const { return mRotation; }
 
 		/**	Sets the rotation of the light, in world space. */
-		void setRotation(const Quaternion& rotation) { mRotation = rotation; _markCoreDirty(); updateBounds(); }
+		void setRotation(const Quaternion& rotation) 
+			{ mRotation = rotation; _markCoreDirty(LightDirtyFlag::Transform); updateBounds(); }
 
 		/**	Returns the type of the light. */
 		LightType getType() const { return mType; }
@@ -188,15 +188,11 @@ namespace bs
 
 	namespace ct { class Light; }
 
-	/**
-	 * Sim thread usable version of a light.
-	 *
-	 * @see		LightBase
-	 */
+	/** Illuminates a portion of the scene covered by a light. */
 	class BS_CORE_EXPORT Light : public IReflectable, public CoreObject, public LightBase
 	{
 	public:
-		/**	Retrieves an implementation of a light usable only from the core thread. */
+		/**	Retrieves an implementation of the light usable only from the core thread. */
 		SPtr<ct::Light> getCore() const;
 
 		/** Returns the hash value that can be used to identify if the internal data needs an update. */
@@ -261,11 +257,7 @@ namespace bs
 
 	namespace ct
 	{
-	/**
-	 * Core thread usable version of a light.
-	 *
-	 * @see		LightBase
-	 */
+	/** Core thread usable version of bs::Light. */
 	class BS_CORE_EXPORT Light : public CoreObject, public LightBase
 	{
 	public:

+ 259 - 0
Source/BansheeCore/Include/BsReflectionProbe.h

@@ -0,0 +1,259 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsIReflectable.h"
+#include "BsCoreObject.h"
+#include "BsVector3.h"
+#include "BsQuaternion.h"
+#include "BsSphere.h"
+
+namespace bs
+{
+	/** @addtogroup Renderer-Engine-Internal
+	 *  @{
+	 */
+
+	/** Light type that determines how is light information parsed by the renderer and other systems. */
+	enum class ReflectionProbeType
+	{
+		/**
+		 * Reflection probe cubemap is generated, and box extents are used for calculating influence ranges and box 
+		 * geometry.
+		 */
+		Box,
+		/** 
+		 * Reflection probe cubemap is generated, but sphere is used for calculating the influence radius and
+		 * proxy geometry. 
+		 */
+		Sphere,
+		/**
+		 * Reflection probe 2D texture is generated instead of a cubemap. This texture corresponds to the -Z direction face
+		 * of the cubemap.
+		 */
+		Plane
+	};
+
+	/**	Signals which portion of a reflection probe is dirty. */
+	enum class ReflectionProbeDirtyFlag
+	{
+		Transform = 0x01,
+		Everything = 0x02
+	};
+
+	/** @} */
+
+	/** @addtogroup Implementation
+	 *  @{
+	 */
+
+	/** Base class for both core and sim thread implementations of a reflection probe. */
+	class BS_CORE_EXPORT ReflectionProbeBase
+	{
+	public:
+		ReflectionProbeBase();
+		ReflectionProbeBase(ReflectionProbeType type, float radius, const Vector3& extents);
+		virtual ~ReflectionProbeBase() { }
+
+		/**	Returns the position of the probe, in world space. */
+		Vector3 getPosition() const { return mPosition; }
+
+		/**	Sets the position of the probe, in world space. */
+		void setPosition(const Vector3& position) 
+			{ mPosition = position; _markCoreDirty(ReflectionProbeDirtyFlag::Transform); updateBounds(); }
+
+		/**	Returns the rotation of the probe, in world space. */
+		Quaternion getRotation() const { return mRotation; }
+
+		/**	Sets the rotation of the probe, in world space. */
+		void setRotation(const Quaternion& rotation) 
+			{ mRotation = rotation; _markCoreDirty(ReflectionProbeDirtyFlag::Transform); updateBounds(); }
+
+		/**	Returns the type of the probe. */
+		ReflectionProbeType getType() const { return mType; }
+
+		/**	Changes the type of the probe. */
+		void setType(ReflectionProbeType type) { mType = type; _markCoreDirty(); updateBounds(); }
+
+		/** Returns the radius of a sphere reflection probe. Determines range of influence. */
+		float getRadius() const { return mRadius; }
+
+		/** Sets the radius of a sphere reflection probe. */
+		void setRadius(float radius) { mRadius = radius; _markCoreDirty(); updateBounds(); }
+
+		/** Returns the extents of a box or plane reflection probe. */
+		Vector3 getExtents() const { return mExtents; }
+
+		/** Sets the extents of a box or a plane reflection probe. Determines range of influence. */
+		void setExtents(const Vector3& extents) { mExtents = extents; _markCoreDirty(); updateBounds(); }
+
+		/**	Returns world space bounds that completely encompass the probe's area of influence. */
+		Sphere getBounds() const { return mBounds; }
+		
+		/**	Checks whether the probe should be used or not. */
+		bool getIsActive() const { return mIsActive; }
+
+		/**	Sets whether the probe should be used or not. */
+		void setIsActive(bool active) { mIsActive = active; _markCoreDirty(); }
+
+		/** 
+		 * Marks the simulation thread object as dirty and notifies the system its data should be synced with its core 
+		 * thread counterpart. 
+		 */
+		virtual void _markCoreDirty(ReflectionProbeDirtyFlag flags = ReflectionProbeDirtyFlag::Everything) { }
+
+	protected:
+		/** Updates the internal bounds for the probe. Call this whenever a property affecting the bounds changes. */
+		void updateBounds();
+
+		Vector3 mPosition; /**< World space position. */
+		Quaternion mRotation; /**< World space rotation. */
+
+		ReflectionProbeType mType; /**< Type of probe that determines how are the rest of the parameters interpreted. */
+		float mRadius; /**< Radius used for sphere reflection probes. */
+		Vector3 mExtents; /**< Extents used by box & plane reflection probes. */
+
+		bool mIsActive; /**< Whether the light should be rendered or not. */
+		Sphere mBounds; /**< Sphere that bounds the light area of influence. */
+	};
+
+	/** Templated base class for both core and sim thread implementations of a reflection probe. */
+	template<bool Core>
+	class BS_CORE_EXPORT TReflectionProbe : public ReflectionProbeBase
+	{
+		typedef typename TTextureType<Core>::Type TextureType;
+
+	public:
+		TReflectionProbe();
+		TReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents);
+		virtual ~TReflectionProbe() { }
+
+		/** 
+		 * Allows you assign a custom texture to use as a reflection map. This will disable automatic generation of
+		 * reflections. To re-enable auto-generation call this with a null parameter.
+		 */
+		void setCustomTexture(const TextureType& texture) { mCustomTexture = texture; _markCoreDirty(); }
+
+		/** Gets the custom texture assigned through setCustomTexture(). */
+		TextureType getCustomTexture() const { return mCustomTexture; }
+
+	protected:
+		TextureType mCustomTexture;
+	};
+
+
+	/** @} */
+	/** @addtogroup Renderer-Engine-Internal
+	 *  @{
+	 */
+
+	namespace ct { class ReflectionProbe; }
+
+	/**
+	 * Specifies a location at which a pre-computed texture containing scene radiance will be generated. This texture will
+	 * then be used by the renderer to provide specular reflections.
+	 */
+	class BS_CORE_EXPORT ReflectionProbe : public IReflectable, public CoreObject, public TReflectionProbe<false>
+	{
+	public:
+		/**	Retrieves an implementation of the reflection probe usable only from the core thread. */
+		SPtr<ct::ReflectionProbe> getCore() const;
+
+		/** 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 internal transform values from the specified scene object, in case that scene object's transform changed
+		 * since the last call.
+		 *
+		 * @note	Assumes the same scene object will be provided every time.
+		 */
+		void _updateTransform(const HSceneObject& parent);
+
+		/**
+		 * Creates a new sphere reflection probe.
+		 *
+		 * @param[in]	radius	Radius in which the reflection probe will be rendered within. 
+		 * @returns				New reflection probe.
+		 */
+		static SPtr<ReflectionProbe> createSphere(float radius);
+
+		/**
+		 * Creates a new box reflection probe.
+		 *
+		 * @param[in]	extents	Extents of the box in which the reflection probe will be rendered within. 
+		 * @returns				New reflection probe.
+		 */
+		static SPtr<ReflectionProbe> createBox(const Vector3& extents);
+
+		/**
+		 * Creates a new plane reflection probe.
+		 *
+		 * @param[in]	extents	Extents of the box in which the reflection probe will be rendered within.
+		 * @returns				New reflection probe.
+		 */
+		static SPtr<ReflectionProbe> createPlane(const Vector3& extents);
+
+	protected:
+		ReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents);
+
+		/** @copydoc CoreObject::createCore */
+		SPtr<ct::CoreObject> createCore() const override;
+
+		/** @copydoc ReflectionProbeBase::_markCoreDirty */
+		void _markCoreDirty(ReflectionProbeDirtyFlag flags = ReflectionProbeDirtyFlag::Everything) override;
+
+		/** @copydoc CoreObject::syncToCore */
+		CoreSyncData syncToCore(FrameAlloc* allocator) override;
+
+		/**	Creates a light with without initializing it. Used for serialization. */
+		static SPtr<ReflectionProbe> createEmpty();
+
+		UINT32 mLastUpdateHash;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ReflectionProbeRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+
+	protected:
+		ReflectionProbe(); // Serialization only
+	};
+
+	namespace ct
+	{
+	/** Core thread usable version of a bs::ReflectionProbe */
+	class BS_CORE_EXPORT ReflectionProbe : public CoreObject, public TReflectionProbe<true>
+	{
+	public:
+		~ReflectionProbe();
+
+		/**	Sets an ID that can be used for uniquely identifying this object by the renderer. */
+		void setRendererId(UINT32 id) { mRendererId = id; }
+
+		/**	Retrieves an ID that can be used for uniquely identifying this object by the renderer. */
+		UINT32 getRendererId() const { return mRendererId; }
+	protected:
+		friend class bs::ReflectionProbe;
+
+		ReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents);
+
+		/** @copydoc CoreObject::initialize */
+		void initialize() override;
+
+		/** @copydoc CoreObject::syncToCore */
+		void syncToCore(const CoreSyncData& data) override;
+
+		UINT32 mRendererId;
+	};
+	}
+
+	/** @} */
+}

+ 59 - 0
Source/BansheeCore/Include/BsReflectionProbeRTTI.h

@@ -0,0 +1,59 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsRTTIType.h"
+#include "BsReflectionProbe.h"
+
+namespace bs
+{
+	/** @cond RTTI */
+	/** @addtogroup RTTI-Impl-Engine
+	 *  @{
+	 */
+
+	class BS_CORE_EXPORT ReflectionProbeRTTI : public RTTIType <ReflectionProbe, IReflectable, ReflectionProbeRTTI>
+	{
+	private:
+		BS_BEGIN_RTTI_MEMBERS
+			BS_RTTI_MEMBER_PLAIN(mPosition, 0)
+			BS_RTTI_MEMBER_PLAIN(mRotation, 1)
+			BS_RTTI_MEMBER_PLAIN(mType, 2)
+			BS_RTTI_MEMBER_PLAIN(mRadius, 3)
+			BS_RTTI_MEMBER_PLAIN(mExtents, 4)
+			BS_RTTI_MEMBER_REFL(mCustomTexture, 5)
+		BS_END_RTTI_MEMBERS
+	public:
+		ReflectionProbeRTTI()
+			:mInitMembers(this)
+		{ }
+
+		void onDeserializationEnded(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
+		{
+			// Note: Since this is a CoreObject I should call initialize() right after deserialization,
+			// but since this specific type is used in Components we delay initialization until Component
+			// itself does it. Keep this is mind in case this ever needs to be deserialized for non-Component 
+			// purposes (you'll need to call initialize manually).
+		}
+
+		const String& getRTTIName() override
+		{
+			static String name = "ReflectionProbe";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_ReflectionProbe;
+		}
+
+		SPtr<IReflectable> newRTTIObject() override
+		{
+			return ReflectionProbe::createEmpty();
+		}
+	};
+
+	/** @} */
+	/** @endcond */
+}

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

@@ -145,6 +145,27 @@ namespace bs
 		 */
 		virtual void notifyLightRemoved(Light* light) { }
 
+		/**
+		 * Called whenever a new reflection probe is created.
+		 *
+		 * @note	Core thread.
+		 */
+		virtual void notifyReflectionProbeAdded(ReflectionProbe* probe) { }
+
+		/**
+		 * Called whenever a reflection probe is updated.
+		 *
+		 * @note	Core thread.
+		 */
+		virtual void notifyReflectionProbeUpdated(ReflectionProbe* probe) { }
+
+		/**
+		 * Called whenever a reflection probe is destroyed.
+		 *
+		 * @note	Core thread.
+		 */
+		virtual void notifyReflectionProbeRemoved(ReflectionProbe* probe) { }
+
 		/**
 		 * Creates a new empty renderer mesh data.
 		 *

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

@@ -51,6 +51,18 @@ namespace bs
 		HSceneObject sceneObject;
 	};
 
+	/**	Contains information about a reflection probe managed by the scene manager. */
+	struct SceneReflectionProbeData
+	{
+		SceneReflectionProbeData() { }
+		SceneReflectionProbeData(const SPtr<ReflectionProbe>& probe, const HSceneObject& sceneObject)
+			:probe(probe), sceneObject(sceneObject)
+		{ }
+
+		SPtr<ReflectionProbe> probe;
+		HSceneObject sceneObject;
+	};
+
 	/** Possible states components can be in. Controls which component callbacks are triggered. */
 	enum class ComponentState
 	{
@@ -121,6 +133,12 @@ namespace bs
 		/**	Notifies the scene manager that a camera was removed. */
 		void _unregisterCamera(const SPtr<Camera>& camera);
 
+		/**	Notifies the scene manager that a new reflection probe was created. */
+		void _registerReflectionProbe(const SPtr<ReflectionProbe>& probe, const HSceneObject& so);
+
+		/**	Notifies the scene manager that a reflection probe was removed. */
+		void _unregisterReflectionProbe(const SPtr<ReflectionProbe>& probe);
+
 		/**	Notifies the scene manager that a camera either became the main camera, or has stopped being main camera. */
 		void _notifyMainCameraStateChanged(const SPtr<Camera>& camera);
 
@@ -196,6 +214,7 @@ namespace bs
 
 		Map<Renderable*, SceneRenderableData> mRenderables;
 		Map<Light*, SceneLightData> mLights;
+		Map<ReflectionProbe*, SceneReflectionProbeData> mReflectionProbes;
 
 		Vector<HComponent> mActiveComponents;
 		Vector<HComponent> mInactiveComponents;

+ 60 - 0
Source/BansheeCore/Source/BsCReflectionProbe.cpp

@@ -0,0 +1,60 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsCReflectionProbe.h"
+#include "BsCReflectionProbeRTTI.h"
+#include "BsSceneManager.h"
+
+namespace bs
+{
+	CReflectionProbe::CReflectionProbe()
+	{
+		setFlag(ComponentFlag::AlwaysRun, true);
+		setName("ReflectionProbe");
+	}
+
+	CReflectionProbe::CReflectionProbe(const HSceneObject& parent)
+		: Component(parent)
+	{
+		setFlag(ComponentFlag::AlwaysRun, true);
+		setName("Light");
+	}
+
+	CReflectionProbe::~CReflectionProbe()
+	{
+		mInternal->destroy();
+	}
+
+	Sphere CReflectionProbe::getBounds() const
+	{
+		mInternal->_updateTransform(SO());
+
+		return mInternal->getBounds();
+	}
+
+	void CReflectionProbe::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 = ReflectionProbe::createBox(Vector3::ONE);
+
+		gSceneManager()._registerReflectionProbe(mInternal, sceneObject());
+	}
+
+	void CReflectionProbe::onDestroyed()
+	{
+		gSceneManager()._unregisterReflectionProbe(mInternal);
+	}
+
+	RTTITypeBase* CReflectionProbe::getRTTIStatic()
+	{
+		return CReflectionProbeRTTI::instance();
+	}
+
+	RTTITypeBase* CReflectionProbe::getRTTI() const
+	{
+		return CReflectionProbe::getRTTIStatic();
+	}
+}

+ 254 - 0
Source/BansheeCore/Source/BsReflectionProbe.cpp

@@ -0,0 +1,254 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsReflectionProbe.h"
+#include "BsReflectionProbeRTTI.h"
+#include "BsSceneObject.h"
+#include "BsFrameAlloc.h"
+#include "BsTexture.h"
+#include "BsRenderer.h"
+
+namespace bs
+{
+	ReflectionProbeBase::ReflectionProbeBase()
+		: mPosition(BsZero), mRotation(BsIdentity), mType(ReflectionProbeType::Box), mRadius(1.0f)
+		, mExtents(1.0f, 1.0f, 1.0f), mIsActive(true), mBounds(Vector3::ZERO, 1.0f)
+	{ }
+
+	ReflectionProbeBase::ReflectionProbeBase(ReflectionProbeType type, float radius, const Vector3& extents)
+		: mPosition(BsZero), mRotation(BsIdentity), mType(type), mRadius(radius)
+		, mExtents(extents), mIsActive(true), mBounds(Vector3::ZERO, 1.0f)
+	{ }
+
+	void ReflectionProbeBase::updateBounds()
+	{
+		switch (mType)
+		{
+		case ReflectionProbeType::Sphere:
+			mBounds = Sphere(mPosition, mRadius);
+			break;
+		case ReflectionProbeType::Box:
+		case ReflectionProbeType::Plane:
+			mBounds = Sphere(mPosition, mExtents.length());
+			break;
+		}
+	}
+
+	template <bool Core>
+	TReflectionProbe<Core>::TReflectionProbe()
+		:ReflectionProbeBase()
+	{ }
+
+	template <bool Core>
+	TReflectionProbe<Core>::TReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents)
+		: ReflectionProbeBase(type, radius, extents)
+	{ }
+
+	template class TReflectionProbe<true>;
+	template class TReflectionProbe<false>;
+
+	ReflectionProbe::ReflectionProbe()
+		:mLastUpdateHash(0)
+	{
+
+	}
+
+	ReflectionProbe::ReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents)
+		: TReflectionProbe(type, radius, extents), mLastUpdateHash(0)
+	{
+		// Calling virtual method is okay here because this is the most derived type
+		updateBounds();
+	}
+
+	SPtr<ct::ReflectionProbe> ReflectionProbe::getCore() const
+	{
+		return std::static_pointer_cast<ct::ReflectionProbe>(mCoreSpecific);
+	}
+
+	SPtr<ReflectionProbe> ReflectionProbe::createSphere(float radius)
+	{
+		ReflectionProbe* probe = new (bs_alloc<ReflectionProbe>()) ReflectionProbe(ReflectionProbeType::Sphere, radius, Vector3::ZERO);
+		SPtr<ReflectionProbe> probePtr = bs_core_ptr<ReflectionProbe>(probe);
+		probePtr->_setThisPtr(probePtr);
+		probePtr->initialize();
+
+		return probePtr;
+	}
+
+	SPtr<ReflectionProbe> ReflectionProbe::createBox(const Vector3& extents)
+	{
+		ReflectionProbe* probe = new (bs_alloc<ReflectionProbe>()) ReflectionProbe(ReflectionProbeType::Box, 0.0f, extents);
+		SPtr<ReflectionProbe> probePtr = bs_core_ptr<ReflectionProbe>(probe);
+		probePtr->_setThisPtr(probePtr);
+		probePtr->initialize();
+
+		return probePtr;
+	}
+
+	SPtr<ReflectionProbe> ReflectionProbe::createPlane(const Vector3& extents)
+	{
+		ReflectionProbe* probe = new (bs_alloc<ReflectionProbe>()) ReflectionProbe(ReflectionProbeType::Plane, 0.0f, extents);
+		SPtr<ReflectionProbe> probePtr = bs_core_ptr<ReflectionProbe>(probe);
+		probePtr->_setThisPtr(probePtr);
+		probePtr->initialize();
+
+		return probePtr;
+	}
+
+	SPtr<ReflectionProbe> ReflectionProbe::createEmpty()
+	{
+		ReflectionProbe* probe = new (bs_alloc<ReflectionProbe>()) ReflectionProbe();
+		SPtr<ReflectionProbe> probePtr = bs_core_ptr<ReflectionProbe>(probe);
+		probePtr->_setThisPtr(probePtr);
+
+		return probePtr;
+	}
+
+	SPtr<ct::CoreObject> ReflectionProbe::createCore() const
+	{
+		ct::ReflectionProbe* probe = new (bs_alloc<ct::ReflectionProbe>()) ct::ReflectionProbe(mType, mRadius, mExtents);
+		SPtr<ct::ReflectionProbe> probePtr = bs_shared_ptr<ct::ReflectionProbe>(probe);
+		probePtr->_setThisPtr(probePtr);
+
+		return probePtr;
+	}
+
+	CoreSyncData ReflectionProbe::syncToCore(FrameAlloc* allocator)
+	{
+		UINT32 size = 0;
+		size += rttiGetElemSize(mPosition);
+		size += rttiGetElemSize(mRotation);
+		size += rttiGetElemSize(mType);
+		size += rttiGetElemSize(mRadius);
+		size += rttiGetElemSize(mExtents);
+		size += rttiGetElemSize(mIsActive);
+		size += rttiGetElemSize(getCoreDirtyFlags());
+		size += rttiGetElemSize(mBounds);
+		size += rttiGetElemSize(sizeof(SPtr<ct::Texture>));
+
+		UINT8* buffer = allocator->alloc(size);
+
+		char* dataPtr = (char*)buffer;
+		dataPtr = rttiWriteElem(mPosition, dataPtr);
+		dataPtr = rttiWriteElem(mRotation, dataPtr);
+		dataPtr = rttiWriteElem(mType, dataPtr);
+		dataPtr = rttiWriteElem(mRadius, dataPtr);
+		dataPtr = rttiWriteElem(mExtents, dataPtr);
+		dataPtr = rttiWriteElem(mIsActive, dataPtr);
+		dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
+		dataPtr = rttiWriteElem(mBounds, dataPtr);
+
+		SPtr<ct::Texture>* customTexture = new (dataPtr)SPtr<ct::Texture>();
+		if (mCustomTexture.isLoaded(false))
+			*customTexture = mCustomTexture->getCore();
+		else
+			*customTexture = nullptr;
+
+		dataPtr += sizeof(SPtr<ct::Texture>);
+
+		return CoreSyncData(buffer, size);
+	}
+
+	void ReflectionProbe::_updateTransform(const HSceneObject& parent)
+	{
+		UINT32 curHash = parent->getTransformHash();
+		if (curHash != _getLastModifiedHash())
+		{
+			setPosition(parent->getWorldPosition());
+			setRotation(parent->getWorldRotation());
+			_setLastModifiedHash(curHash);
+		}
+	}
+
+	void ReflectionProbe::_markCoreDirty(ReflectionProbeDirtyFlag flags)
+	{
+		markCoreDirty((UINT32)flags);
+	}
+
+	RTTITypeBase* ReflectionProbe::getRTTIStatic()
+	{
+		return ReflectionProbeRTTI::instance();
+	}
+
+	RTTITypeBase* ReflectionProbe::getRTTI() const
+	{
+		return ReflectionProbe::getRTTIStatic();
+	}
+
+	namespace ct
+	{
+	ReflectionProbe::ReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents)
+			: TReflectionProbe(type, radius, extents), mRendererId(0)
+	{
+
+	}
+
+	ReflectionProbe::~ReflectionProbe()
+	{
+		gRenderer()->notifyReflectionProbeRemoved(this);
+	}
+
+	void ReflectionProbe::initialize()
+	{
+		updateBounds();
+		gRenderer()->notifyReflectionProbeAdded(this);
+
+		CoreObject::initialize();
+	}
+
+	void ReflectionProbe::syncToCore(const CoreSyncData& data)
+	{
+		char* dataPtr = (char*)data.getBuffer();
+
+		UINT32 dirtyFlags = 0;
+		bool oldIsActive = mIsActive;
+		ReflectionProbeType oldType = mType;
+
+		dataPtr = rttiReadElem(mPosition, dataPtr);
+		dataPtr = rttiReadElem(mRotation, dataPtr);
+		dataPtr = rttiReadElem(mType, dataPtr);
+		dataPtr = rttiReadElem(mRadius, dataPtr);
+		dataPtr = rttiReadElem(mExtents, dataPtr);
+		dataPtr = rttiReadElem(mIsActive, dataPtr);
+		dataPtr = rttiReadElem(dirtyFlags, dataPtr);
+		dataPtr = rttiReadElem(mBounds, dataPtr);
+
+		SPtr<Texture>* texture = (SPtr<Texture>*)dataPtr;
+
+		mCustomTexture = *texture;
+		texture->~SPtr<Texture>();
+		dataPtr += sizeof(SPtr<Texture>);
+
+		updateBounds();
+
+		if (dirtyFlags == (UINT32)ReflectionProbeDirtyFlag::Transform)
+		{
+			if (mIsActive)
+				gRenderer()->notifyReflectionProbeUpdated(this);
+		}
+		else
+		{
+			if (oldIsActive != mIsActive)
+			{
+				if (mIsActive)
+					gRenderer()->notifyReflectionProbeAdded(this);
+				else
+				{
+					ReflectionProbeType newType = mType;
+					mType = oldType;
+					gRenderer()->notifyReflectionProbeRemoved(this);
+					mType = newType;
+				}
+			}
+			else
+			{
+				ReflectionProbeType newType = mType;
+				mType = oldType;
+				gRenderer()->notifyReflectionProbeRemoved(this);
+				mType = newType;
+
+				gRenderer()->notifyReflectionProbeAdded(this);
+			}
+		}
+	}
+
+}}

+ 31 - 0
Source/BansheeCore/Source/BsSceneManager.cpp

@@ -6,6 +6,7 @@
 #include "BsRenderable.h"
 #include "BsCamera.h"
 #include "BsLight.h"
+#include "BsReflectionProbe.h"
 #include "BsViewport.h"
 #include "BsGameObjectManager.h"
 #include "BsRenderTarget.h"
@@ -122,6 +123,16 @@ namespace bs
 			mMainCameras.erase(iterFind);
 	}
 
+	void SceneManager::_registerReflectionProbe(const SPtr<ReflectionProbe>& probe, const HSceneObject& so)
+	{
+		mReflectionProbes[probe.get()] = SceneReflectionProbeData(probe, so);
+	}
+
+	void SceneManager::_unregisterReflectionProbe(const SPtr<ReflectionProbe>& probe)
+	{
+		mReflectionProbes.erase(probe.get());
+	}
+
 	void SceneManager::_notifyMainCameraStateChanged(const SPtr<Camera>& camera)
 	{
 		auto iterFind = std::find_if(mMainCameras.begin(), mMainCameras.end(),
@@ -200,6 +211,26 @@ namespace bs
 				handler->setIsActive(so->getActive());
 			}
 		}
+
+		for (auto& probePair : mReflectionProbes)
+		{
+			SPtr<ReflectionProbe> probe = probePair.second.probe;
+			HSceneObject so = probePair.second.sceneObject;
+
+			UINT32 curHash = so->getTransformHash();
+			if (curHash != probe->_getLastModifiedHash())
+			{
+				probe->setPosition(so->getWorldPosition());
+				probe->setRotation(so->getWorldRotation());
+
+				probe->_setLastModifiedHash(curHash);
+			}
+
+			if (so->getActive() != probe->getIsActive())
+			{
+				probe->setIsActive(so->getActive());
+			}
+		}
 	}
 
 	SceneCameraData SceneManager::getMainCamera() const