소스 검색

Added reflection cubemap filtering for skybox
Removed skybox texture from Camera

BearishSun 8 년 전
부모
커밋
a4c6d018cb

+ 0 - 6
Source/BansheeCore/Include/BsCCamera.h

@@ -142,12 +142,6 @@ namespace bs
 		/** @copydoc Camera::setMSAACount */
 		void setMSAACount(UINT32 count) { mInternal->setMSAACount(count); }
 
-		/** @copydoc Camera::setSkybox */
-		void setSkybox(const HTexture& texture) { mInternal->setSkybox(texture); }
-
-		/** @copydoc Camera::getSkybox */
-		HTexture getSkybox() const { return mInternal->getSkybox(); }
-
 		/** Returns settings that are used for controling post-process operations like tonemapping. */
 		const SPtr<PostProcessSettings>& getPostProcessSettings() const { return mInternal->getPostProcessSettings(); }
 

+ 2 - 22
Source/BansheeCore/Include/BsCamera.h

@@ -500,26 +500,6 @@ namespace bs
 		mutable AABox mBoundingBox; /**< Frustum bounding box. */
      };
 
-	 /** @copydoc CameraBase */
-	 template<bool Core>
-	 class TCamera : public CameraBase
-	 {
-	 public:
-		 typedef typename TTextureType<Core>::Type TextureType;
-
-		/** 
-		 * Sets a texture that will be used for rendering areas of the camera's render target not covered by any geometry. 
-		 * If not set a clear color will be used instead.
-		 */
-		void setSkybox(const TextureType& texture) { mSkyTexture = texture; _markCoreDirty(); }
-
-		/** @see setSkybox() */
-		TextureType getSkybox() const { return mSkyTexture; }
-
-	 protected:
-		 TextureType mSkyTexture;
-	 };
-
 	/** @} */
 
 	/** @addtogroup Renderer-Engine-Internal
@@ -527,7 +507,7 @@ namespace bs
 	 */
 
 	/** @copydoc CameraBase */
-	class BS_CORE_EXPORT Camera : public IReflectable, public CoreObject, public TCamera<false>
+	class BS_CORE_EXPORT Camera : public IReflectable, public CoreObject, public CameraBase
     {
     public:
 		/**	Returns the viewport used by the camera. */	
@@ -602,7 +582,7 @@ namespace bs
 	namespace ct
 	{
 	/** @copydoc CameraBase */
-	class BS_CORE_EXPORT Camera : public CoreObject, public TCamera<true>
+	class BS_CORE_EXPORT Camera : public CoreObject, public CameraBase
 	{
 	public:
 		~Camera();

+ 1 - 1
Source/BansheeCore/Include/BsCameraRTTI.h

@@ -42,7 +42,7 @@ namespace bs
 			BS_RTTI_MEMBER_PLAIN(mMSAA, 23)
 			/** BS_RTTI_MEMBER_PLAIN(mPPSettings, 24) */
 			BS_RTTI_MEMBER_REFLPTR(mPPSettings, 25)
-			BS_RTTI_MEMBER_REFL(mSkyTexture, 26)
+			/** BS_RTTI_MEMBER_REFL(mSkyTexture, 26) */
 		BS_END_RTTI_MEMBERS
 			
 	public:

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

@@ -173,6 +173,13 @@ namespace bs
 		 */
 		virtual void notifySkyboxAdded(Skybox* skybox) { }
 
+		/**
+		 * Called whenever the texture assigned to a skybox is changed.
+		 *
+		 * @note	Core thread.
+		 */
+		virtual void notifySkyboxTextureChanged(Skybox* skybox) { }
+
 		/**
 		 * Called whenever a skybox is destroyed.
 		 *

+ 10 - 3
Source/BansheeCore/Include/BsSkybox.h

@@ -12,6 +12,13 @@ namespace bs
 	 *  @{
 	 */
 
+	/**	Signals which portion of a skybox is dirty. */
+	enum class SkyboxDirtyFlag
+	{
+		Texture = 0x01,
+		Everything = 0x02
+	};
+
 	/** Base class for both core and sim thread implementations of a skybox. */
 	class BS_CORE_EXPORT SkyboxBase
 	{
@@ -32,7 +39,7 @@ namespace bs
 		 * Marks the simulation thread object as dirty and notifies the system its data should be synced with its core 
 		 * thread counterpart. 
 		 */
-		virtual void _markCoreDirty() { }
+		virtual void _markCoreDirty(SkyboxDirtyFlag flags = SkyboxDirtyFlag::Everything) { }
 
 	protected:
 		String mUUID; /**< Identifier that uniquely identifies the skybox. */
@@ -53,7 +60,7 @@ namespace bs
 		 * Assigns an environment map to use for sampling skybox radiance. Must be a cube-map texture, and should ideally
 		 * contain HDR data.
 		 */
-		void setTexture(const TextureType& texture) { mTexture = texture; _markCoreDirty(); }
+		void setTexture(const TextureType& texture) { mTexture = texture; _markCoreDirty(SkyboxDirtyFlag::Texture); }
 
 		/** Gets the texture assigned through setTexture(). */
 		TextureType getTexture() const { return mTexture; }
@@ -86,7 +93,7 @@ namespace bs
 		SPtr<ct::CoreObject> createCore() const override;
 
 		/** @copydoc SkyboxBase::_markCoreDirty */
-		void _markCoreDirty() override;
+		void _markCoreDirty(SkyboxDirtyFlag flags = SkyboxDirtyFlag::Everything) override;
 
 		/** @copydoc CoreObject::syncToCore */
 		CoreSyncData syncToCore(FrameAlloc* allocator) override;

+ 0 - 14
Source/BansheeCore/Source/BsCamera.cpp

@@ -733,10 +733,6 @@ namespace bs
 	{
 		UINT32 dirtyFlag = getCoreDirtyFlags();
 
-		SPtr<ct::Texture> skyTexture;
-		if (mSkyTexture.isLoaded())
-			skyTexture = mSkyTexture->getCore();
-
 		UINT32 size = 0;
 		size += rttiGetElemSize(dirtyFlag);
 		size += rttiGetElemSize(mPosition);
@@ -759,7 +755,6 @@ namespace bs
 			size += rttiGetElemSize(mCameraFlags);
 			size += rttiGetElemSize(mIsActive);
 			size += rttiGetElemSize(mMSAA);
-			size += sizeof(SPtr<ct::Texture>);
 			size += sizeof(UINT32);
 
 			if(mPPSettings != nullptr)
@@ -793,10 +788,6 @@ namespace bs
 			dataPtr = rttiWriteElem(mIsActive, dataPtr);
 			dataPtr = rttiWriteElem(mMSAA, dataPtr);
 
-			SPtr<ct::Texture>* skyTexDest = new (dataPtr) SPtr<ct::Texture>();
-			*skyTexDest = skyTexture;
-			dataPtr += sizeof(skyTexture);
-
 			dataPtr = rttiWriteElem(ppSize, dataPtr);
 
 			if(mPPSettings != nullptr)
@@ -887,11 +878,6 @@ namespace bs
 			dataPtr = rttiReadElem(mIsActive, dataPtr);
 			dataPtr = rttiReadElem(mMSAA, dataPtr);
 
-			SPtr<Texture>* skyTexture = (SPtr<Texture>*)dataPtr;
-			mSkyTexture = *skyTexture;
-			skyTexture->~SPtr<Texture>();
-			dataPtr += sizeof(SPtr<Texture>);
-
 			UINT32 ppSize = 0;
 			dataPtr = rttiReadElem(ppSize, dataPtr);
 

+ 13 - 4
Source/BansheeCore/Source/BsSkybox.cpp

@@ -57,12 +57,14 @@ namespace bs
         size += rttiGetElemSize(mIsActive);
         size += rttiGetElemSize(sizeof(SPtr<ct::Texture>));
         size += rttiGetElemSize(mUUID);
+        size += rttiGetElemSize(getCoreDirtyFlags());
 
         UINT8* buffer = allocator->alloc(size);
 
         char* dataPtr = (char*)buffer;
         dataPtr = rttiWriteElem(mIsActive, dataPtr);
         dataPtr = rttiWriteElem(mUUID, dataPtr);
+        dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
 
         SPtr<ct::Texture>* texture = new (dataPtr) SPtr<ct::Texture>();
         if (mTexture.isLoaded(false))
@@ -75,9 +77,9 @@ namespace bs
         return CoreSyncData(buffer, size);
     }
 
-    void Skybox::_markCoreDirty()
+    void Skybox::_markCoreDirty(SkyboxDirtyFlag flags)
     {
-        markCoreDirty();
+        markCoreDirty((UINT32)flags);
     }
 
     RTTITypeBase* Skybox::getRTTIStatic()
@@ -111,10 +113,12 @@ namespace bs
         {
             char* dataPtr = (char*)data.getBuffer();
 
+            SkyboxDirtyFlag dirtyFlags;
             bool oldIsActive = mIsActive;
 
             dataPtr = rttiReadElem(mIsActive, dataPtr);
             dataPtr = rttiReadElem(mUUID, dataPtr);
+            dataPtr = rttiReadElem(dirtyFlags, dataPtr);
 
             SPtr<Texture>* texture = (SPtr<Texture>*)dataPtr;
 
@@ -131,8 +135,13 @@ namespace bs
             }
             else
             {
-                gRenderer()->notifySkyboxRemoved(this);
-                gRenderer()->notifySkyboxAdded(this);
+                if (dirtyFlags == SkyboxDirtyFlag::Texture)
+                    gRenderer()->notifySkyboxTextureChanged(this);
+                else
+                {
+                    gRenderer()->notifySkyboxRemoved(this);
+                    gRenderer()->notifySkyboxAdded(this);
+                }
             }
         }
     }

+ 0 - 12
Source/MBansheeEditor/Inspectors/CameraInspector.cs

@@ -33,7 +33,6 @@ namespace BansheeEditor
         private GUIListBoxField layersField = new GUIListBoxField(Layers.Names, true, new LocEdString("Layers"));
         private GUIToggleField hdrField = new GUIToggleField(new LocEdString("HDR"));
         private GUIToggleField mainField = new GUIToggleField(new LocEdString("Main"));
-        private GUITextureField skyboxField = new GUITextureField(new LocEdString("Skybox"));
 
         private GUIToggle postProcessFoldout = new GUIToggle(new LocEdString("Post processing"), EditorStyles.Foldout);
         private PostProcessSettingsGUI postProcessGUI;
@@ -78,7 +77,6 @@ namespace BansheeEditor
             priorityField.Value = camera.Priority;
             mainField.Value = camera.Main;
             hdrField.Value = camera.HDR;
-            skyboxField.Value = camera.Skybox;
             postProcessGUI.Settings = camera.PostProcess;
 
             if (layersValue != camera.Layers)
@@ -232,15 +230,6 @@ namespace BansheeEditor
                     ConfirmModify();
                 };
 
-                skyboxField.OnChanged += x =>
-                {
-                    Texture skyboxTex = Resources.Load<Texture>(x);
-
-                    camera.Skybox = skyboxTex as TextureCube;
-                    MarkAsModified();
-                    ConfirmModify();
-                };
-
                 Layout.AddElement(projectionTypeField);
                 Layout.AddElement(fieldOfView);
                 Layout.AddElement(orthoHeight);
@@ -267,7 +256,6 @@ namespace BansheeEditor
                 Layout.AddElement(layersField);
                 Layout.AddElement(mainField);
                 Layout.AddElement(hdrField);
-                Layout.AddElement(skyboxField);
 
                 postProcessFoldout.OnToggled += x =>
                 {

+ 0 - 18
Source/MBansheeEngine/Interop/NativeCamera.cs

@@ -137,19 +137,6 @@ namespace BansheeEngine
             set { Internal_SetNoLighting(mCachedPtr, value); }
         }
 
-        public TextureCube skybox
-        {
-            get { return Internal_GetSkybox(mCachedPtr); }
-            set
-            {
-                IntPtr texturePtr = IntPtr.Zero;
-                if (value != null)
-                    texturePtr = value.GetCachedPtr();
-
-                Internal_SetSkybox(mCachedPtr, texturePtr);
-            }
-        }
-
         internal PostProcessSettings PostProcess
         {
             get { return Internal_GetPostProcessSettings(mCachedPtr); }
@@ -452,11 +439,6 @@ namespace BansheeEngine
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetNoLighting(IntPtr instance, bool value);
 
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern TextureCube Internal_GetSkybox(IntPtr instance);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetSkybox(IntPtr instance, IntPtr value);
-
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern PostProcessSettings Internal_GetPostProcessSettings(IntPtr instance);
         [MethodImpl(MethodImplOptions.InternalCall)]

+ 0 - 11
Source/MBansheeEngine/Rendering/Camera.cs

@@ -177,16 +177,6 @@ namespace BansheeEngine
             set { native.noLighting = value; serializableData.noLighting = value; }
         }
 
-        /// <summary>
-        /// Texture that will be used for rendering areas of the camera's render target not covered by any geometry. 
-        /// If not set a clear color will be used instead.
-        /// </summary>
-        public TextureCube Skybox
-        {
-            get { return serializableData.skybox; }
-            set { Native.skybox = value; serializableData.skybox = value; }
-        }
-
         /// <summary>
         /// Allows you to customize various post process operations that will be executed on the image produced by this 
         /// camera.
@@ -489,7 +479,6 @@ namespace BansheeEngine
             public PostProcessSettings postProcessSettings;
             public ulong layers = 0xFFFFFFFFFFFFFFFF;
             public bool main;
-            public TextureCube skybox;
         }
     }
 

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

@@ -128,6 +128,15 @@ namespace bs
 		/** @copydoc Renderer::notifyReflectionProbeRemoved */
 		void notifyReflectionProbeRemoved(ReflectionProbe* probe) override;
 
+        /** @copydoc Renderer::notifySkyboxAdded */
+        void notifySkyboxAdded(Skybox* skybox) override;
+
+        /** @copydoc Renderer::notifySkyboxTextureChanged */
+        void notifySkyboxTextureChanged(Skybox* skybox) override;
+
+        /** @copydoc Renderer::notifySkyboxRemoved */
+        void notifySkyboxRemoved(Skybox* skybox) override;
+
 		/** 
 		 * Updates (or adds) renderer specific data for the specified camera. Should be called whenever camera properties
 		 * change. 
@@ -242,6 +251,10 @@ namespace bs
 		SkyboxMat<false>* mSkyboxMat;
 		SkyboxMat<true>* mSkyboxSolidColorMat;
 
+        Skybox* mSkybox;
+        SPtr<Texture> mSkyboxTexture;
+        SPtr<Texture> mSkyboxFilteredReflections;
+
 		GPULightData* mGPULightData;
 		GPUReflProbeData* mGPUReflProbeData;
 		LightGrid* mLightGrid;

+ 0 - 4
Source/RenderBeast/Include/BsRendererCamera.h

@@ -102,7 +102,6 @@ namespace bs { namespace ct
 		StateReduction stateReduction;
 
 		const Camera* sceneCamera;
-		SPtr<Texture> skyboxTexture;
 	};
 
 	/** Information whether certain scene objects are visible in a view, per object type. */
@@ -163,9 +162,6 @@ namespace bs { namespace ct
 		/** Returns true if the view should be rendered with no lighting. */
 		bool renderWithNoLighting() const { return mViewDesc.noLighting; }
 
-		/** Returns the texture to use for the skybox (if any). */
-		SPtr<Texture> getSkybox() const { return mViewDesc.skyboxTexture; }
-
 		/** Returns the final render target the rendered contents should be output to. */
 		SPtr<RenderTarget> getFinalTarget() const { return mViewDesc.target.target; }
 

+ 69 - 18
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -36,6 +36,7 @@
 #include "BsReflectionProbes.h"
 #include "BsMeshData.h"
 #include "BsLightGrid.h"
+#include "BsSkybox.h"
 
 using namespace std::placeholders;
 
@@ -121,6 +122,8 @@ namespace bs { namespace ct
 		mRenderableVisibility.clear();
 
 		mCubemapArrayTex = nullptr;
+        mSkyboxTexture = nullptr;
+        mSkyboxFilteredReflections = nullptr;
 
 		PostProcessing::shutDown();
 		GpuResourcePool::shutDown();
@@ -542,6 +545,33 @@ namespace bs { namespace ct
 		ReflectionCubemapCache::instance().unloadCachedTexture(probe->getUUID());
 	}
 
+    void RenderBeast::notifySkyboxAdded(Skybox* skybox)
+	{
+        mSkybox = skybox;
+
+        SPtr<Texture> skyTex = skybox->getTexture();
+        if (skyTex != nullptr && skyTex->getProperties().getTextureType() == TEX_TYPE_CUBE_MAP)
+            mSkyboxTexture = skyTex;
+
+        mSkyboxFilteredReflections = nullptr;
+	}
+
+    void RenderBeast::notifySkyboxTextureChanged(Skybox* skybox)
+	{
+        ReflectionCubemapCache::instance().notifyDirty(skybox->getUUID());
+
+        if (mSkybox == skybox)
+            mSkyboxFilteredReflections = nullptr;
+	}
+
+    void RenderBeast::notifySkyboxRemoved(Skybox* skybox)
+	{
+        ReflectionCubemapCache::instance().unloadCachedTexture(skybox->getUUID());
+
+        if (mSkybox == skybox)
+            mSkyboxTexture = nullptr;
+	}
+
 	SPtr<PostProcessSettings> RenderBeast::createPostProcessSettings() const
 	{
 		return bs_shared_ptr_new<StandardPostProcessSettings>();
@@ -623,7 +653,6 @@ namespace bs { namespace ct
 			viewDesc.viewTransform = camera->getViewMatrix();
 
 			viewDesc.stateReduction = mCoreOptions->stateReductionMode;
-			viewDesc.skyboxTexture = camera->getSkybox();
 			viewDesc.sceneCamera = camera;
 
 			if (iterFind != mCameras.end())
@@ -1041,11 +1070,10 @@ namespace bs { namespace ct
 		}
 
 		// Render skybox (if any)
-		SPtr<Texture> skyTexture = viewInfo->getSkybox();
-		if (skyTexture != nullptr && skyTexture->getProperties().getTextureType() == TEX_TYPE_CUBE_MAP)
+		if (mSkyboxTexture != nullptr)
 		{
 			mSkyboxMat->bind(perCameraBuffer);
-			mSkyboxMat->setParams(skyTexture, Color::White);
+			mSkyboxMat->setParams(mSkyboxTexture, Color::White);
 		}
 		else
 		{
@@ -1325,6 +1353,43 @@ namespace bs { namespace ct
 
 				// Note: Consider pruning the reflection cubemap array if empty slot count becomes too high
 			}
+
+            // Get reflections for skybox if needed/available
+            if (mSkybox != nullptr && mSkyboxTexture != nullptr)
+            {
+                // If haven't assigned them already, do it now
+                if(mSkyboxFilteredReflections == nullptr)
+                {
+                    if (!ReflectionCubemapCache::instance().isDirty(mSkybox->getUUID()))
+                        mSkyboxFilteredReflections = ReflectionCubemapCache::instance().getCachedTexture(mSkybox->getUUID());
+                    else
+                    {
+                        mSkyboxFilteredReflections = Texture::create(cubemapDesc);
+
+                        // Note: If the Texture class supported scale on copy we could avoid using CPU reads & buffers
+                        auto& texProps = mSkyboxFilteredReflections->getProperties();
+                        SPtr<PixelData> scaledFaceData = texProps.allocBuffer(0, 0);
+
+                        auto& skyboxTex = mSkyboxTexture->getProperties();
+                        SPtr<PixelData> originalFaceData = skyboxTex.allocBuffer(0, 0);
+                        for (UINT32 j = 0; j < 6; j++)
+                        {
+                            if (j < skyboxTex.getNumFaces())
+                                mSkyboxTexture->readData(*originalFaceData, 0, j);
+
+                            PixelUtil::scale(*originalFaceData, *scaledFaceData);
+
+                            mSkyboxFilteredReflections->writeData(*scaledFaceData, 0, j);
+                        }
+
+                        ReflectionProbes::filterCubemapForSpecular(mSkyboxFilteredReflections, scratchCubemap);
+                        ReflectionCubemapCache::instance().setCachedTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
+                    }
+                }
+            }
+            else
+                mSkyboxFilteredReflections = nullptr;
+
 		}
 		bs_frame_clear();
 	}
@@ -1366,20 +1431,6 @@ namespace bs { namespace ct
 		viewDesc.stateReduction = mCoreOptions->stateReductionMode;
 		viewDesc.sceneCamera = nullptr;
 
-		// Note: Find a camera to receive skybox from. Skybox should probably be a global property instead of a per-camera
-		// one.
-		for(auto& entry : mRenderTargets)
-		{
-			for(auto& camera : entry.cameras)
-			{
-				if (camera->getSkybox() != nullptr)
-				{
-					viewDesc.skyboxTexture = camera->getSkybox();
-					break;
-				}
-			}
-		}
-
 		Matrix4 viewOffsetMat = Matrix4::translation(-position);
 
 		RendererCamera views[6];

+ 0 - 3
Source/SBansheeEngine/Include/BsScriptCamera.h

@@ -93,9 +93,6 @@ namespace bs
 		static bool internal_GetNoLighting(ScriptCamera* instance);
 		static void internal_SetNoLighting(ScriptCamera* instance, bool value);
 
-		static MonoObject* internal_GetSkybox(ScriptCamera* instance);
-		static void internal_SetSkybox(ScriptCamera* instance, ScriptTextureCube* value);
-
 		static MonoObject* internal_GetPostProcessSettings(ScriptCamera* instance);
 		static void internal_SetPostProcessSettings(ScriptCamera* instance, MonoObject* value);
 

+ 0 - 24
Source/SBansheeEngine/Source/BsScriptCamera.cpp

@@ -81,9 +81,6 @@ namespace bs
 		metaData.scriptClass->addInternalCall("Internal_GetNoLighting", &ScriptCamera::internal_GetNoLighting);
 		metaData.scriptClass->addInternalCall("Internal_SetNoLighting", &ScriptCamera::internal_SetNoLighting);
 
-		metaData.scriptClass->addInternalCall("Internal_GetSkybox", &ScriptCamera::internal_GetSkybox);
-		metaData.scriptClass->addInternalCall("Internal_SetSkybox", &ScriptCamera::internal_SetSkybox);
-
 		metaData.scriptClass->addInternalCall("Internal_GetPostProcessSettings", &ScriptCamera::internal_GetPostProcessSettings);
 		metaData.scriptClass->addInternalCall("Internal_SetPostProcessSettings", &ScriptCamera::internal_SetPostProcessSettings);
 
@@ -319,27 +316,6 @@ namespace bs
 		instance->mCamera->setFlag(CameraFlag::NoLighting, value);
 	}
 
-	MonoObject* ScriptCamera::internal_GetSkybox(ScriptCamera* instance)
-	{
-		HTexture texture = instance->mCamera->getSkybox();
-		if (texture == nullptr || texture->getProperties().getTextureType() != TEX_TYPE_CUBE_MAP)
-			return nullptr;
-
-		ScriptTextureCube* scriptTexture;
-		ScriptResourceManager::instance().getScriptResource(texture, &scriptTexture, true);
-
-		return scriptTexture->getManagedInstance();
-	}
-
-	void ScriptCamera::internal_SetSkybox(ScriptCamera* instance, ScriptTextureCube* value)
-	{
-		HTexture texture;
-		if (value != nullptr)
-			texture = value->getHandle();
-
-		instance->mCamera->setSkybox(texture);
-	}
-
 	MonoObject* ScriptCamera::internal_GetPostProcessSettings(ScriptCamera* instance)
 	{
 		SPtr<PostProcessSettings> ppSettings = instance->mCamera->getPostProcessSettings();