瀏覽代碼

Added a flag to perform reflection filtering on imported cubemaps

BearishSun 8 年之前
父節點
當前提交
ac912bfc61

+ 11 - 0
Source/BansheeCore/Include/BsTextureImportOptions.h

@@ -81,6 +81,16 @@ namespace bs
 		 */
 		CubemapSourceType getCubemapSourceType() const { return mCubemapSourceType; }
 
+		/**
+		 * Marks the cubemap as a reflection cubemap and perform special filtering on the cubemap mip-maps. Only relevant
+		 * when texture is imported as a cubemap. This will override texture size and mip levels to match the requirements
+		 * needed for reflection cubemaps.
+		 */
+		void setCubemapIsReflection(bool reflection) { mCubemapIsReflection = reflection; }
+
+		/** Checks is the specified cubemap used for reflections. See setCubemapIsReflection(). */
+		bool getCubemapIsReflection() const { return mCubemapIsReflection; }
+
 		/** Creates a new import options object that allows you to customize how are textures imported. */
 		static SPtr<TextureImportOptions> create();
 
@@ -100,6 +110,7 @@ namespace bs
 		bool mSRGB;
 		bool mCubemap;
 		CubemapSourceType mCubemapSourceType;
+		bool mCubemapIsReflection;
 	};
 
 	/** @} */

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

@@ -24,6 +24,7 @@ namespace bs
 			BS_RTTI_MEMBER_PLAIN(mSRGB, 4)
 			BS_RTTI_MEMBER_PLAIN(mCubemap, 5)
 			BS_RTTI_MEMBER_PLAIN(mCubemapSourceType, 6)
+			BS_RTTI_MEMBER_PLAIN(mCubemapIsReflection, 7)
 		BS_END_RTTI_MEMBERS
 
 	public:

+ 2 - 0
Source/BansheeEngine/CMakeSources.cmake

@@ -89,6 +89,7 @@ set(BS_BANSHEEENGINE_INC_RENDERER
 	"Include/BsRendererUtility.h"
 	"Include/BsStandardPostProcessSettings.h"	
 	"Include/BsReflectionCubemapCache.h"
+	"Include/BsReflectionProbes.h"
 )
 
 set(BS_BANSHEEENGINE_SRC_RTTI
@@ -177,6 +178,7 @@ set(BS_BANSHEEENGINE_SRC_RENDERER
 	"Source/BsRendererUtility.cpp"
 	"Source/BsStandardPostProcessSettings.cpp"
 	"Source/BsReflectionCubemapCache.cpp"
+	"Source/BsReflectionProbes.cpp"
 )
 
 set(BS_BANSHEEENGINE_SRC_INPUT

+ 3 - 3
Source/RenderBeast/Include/BsReflectionProbes.h → Source/BansheeEngine/Include/BsReflectionProbes.h

@@ -2,7 +2,7 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #pragma once
 
-#include "BsRenderBeastPrerequisites.h"
+#include "BsPrerequisites.h"
 #include "BsRendererMaterial.h"
 #include "BsParamBlocks.h"
 
@@ -63,7 +63,7 @@ namespace bs { namespace ct
 
 
 	/** Helper class that handles generation and processing of textures used for reflection probes. */
-	class ReflectionProbes
+	class BS_EXPORT ReflectionProbes
 	{
 	public:
 		/**
@@ -73,7 +73,7 @@ namespace bs { namespace ct
 		 * @param[in, out]	cubemap		Cubemap to filter. Its mip level 0 will be read, filtered and written into
 		 *								other mip levels.
 		 * @param[in]		scratch		Temporary cubemap texture to use for the filtering process. Must match the size of
-		 *								the source cubemap.
+		 *								the source cubemap. Provide null to automatically create a scratch cubemap.
 		 */
 		static void filterCubemapForSpecular(const SPtr<Texture>& cubemap, const SPtr<Texture>& scratch);
 

+ 20 - 6
Source/RenderBeast/Source/BsReflectionProbes.cpp → Source/BansheeEngine/Source/BsReflectionProbes.cpp

@@ -3,7 +3,6 @@
 #include "BsReflectionProbes.h"
 #include "BsTexture.h"
 #include "BsGpuParamsSet.h"
-#include "BsRendererCamera.h"
 #include "BsRendererUtility.h"
 
 namespace bs { namespace ct
@@ -83,8 +82,23 @@ namespace bs { namespace ct
 		static ReflectionCubeDownsampleMat downsampleMat;
 		static ReflectionCubeImportanceSampleMat importanceSampleMat;
 
+		auto& props = cubemap->getProperties();
+
+		SPtr<Texture> scratchCubemap = scratch;
+		if (scratchCubemap == nullptr)
+		{
+			TEXTURE_DESC cubemapDesc;
+			cubemapDesc.type = TEX_TYPE_CUBE_MAP;
+			cubemapDesc.format = props.getFormat();
+			cubemapDesc.width = props.getWidth();
+			cubemapDesc.height = props.getHeight();
+			cubemapDesc.numMips = PixelUtil::getMaxMipmaps(cubemapDesc.width, cubemapDesc.height, 1, cubemapDesc.format);
+
+			scratchCubemap = Texture::create(cubemapDesc);
+		}
+
 		// We sample the cubemaps using importance sampling to generate roughness
-		UINT32 numMips = cubemap->getProperties().getNumMipmaps();
+		UINT32 numMips = props.getNumMipmaps();
 
 		// Before importance sampling the cubemaps we first create box filtered versions for each mip level. This helps fix
 		// the aliasing artifacts that would otherwise be noticeable on importance sampled cubemaps. The aliasing happens
@@ -96,7 +110,7 @@ namespace bs { namespace ct
 
 		// Copy base mip level to scratch cubemap
 		for (UINT32 face = 0; face < 6; face++)
-			cubemap->copy(scratch, face, 0, face, 0);
+			cubemap->copy(scratchCubemap, face, 0, face, 0);
 
 		// Fill out remaining scratch mip levels by downsampling
 		for (UINT32 mip = 1; mip < numMips; mip++)
@@ -104,7 +118,7 @@ namespace bs { namespace ct
 			for (UINT32 face = 0; face < 6; face++)
 			{
 				RENDER_TEXTURE_DESC cubeFaceRTDesc;
-				cubeFaceRTDesc.colorSurfaces[0].texture = scratch;
+				cubeFaceRTDesc.colorSurfaces[0].texture = scratchCubemap;
 				cubeFaceRTDesc.colorSurfaces[0].face = face;
 				cubeFaceRTDesc.colorSurfaces[0].numFaces = 1;
 				cubeFaceRTDesc.colorSurfaces[0].mipLevel = mip;
@@ -113,7 +127,7 @@ namespace bs { namespace ct
 
 				UINT32 sourceMip = mip - 1;
 				TextureSurface sourceSurface(sourceMip, 1, 0, 6);
-				downsampleMat.execute(scratch, face, sourceSurface, target);
+				downsampleMat.execute(scratchCubemap, face, sourceSurface, target);
 			}
 		}
 
@@ -130,7 +144,7 @@ namespace bs { namespace ct
 
 				SPtr<RenderTarget> target = RenderTexture::create(cubeFaceRTDesc);
 
-				importanceSampleMat.execute(scratch, face, mip, target);
+				importanceSampleMat.execute(scratchCubemap, face, mip, target);
 			}
 		}
 	}

+ 2 - 1
Source/BansheeFreeImgImporter/CMakeLists.txt

@@ -6,6 +6,7 @@ set(BansheeFreeImgImporter_INC
 	"Include" 
 	"../BansheeUtility/Include" 
 	"../BansheeCore/Include"
+	"../BansheeEngine/Include"
 	"../../Dependencies/freeimg/include")
 
 include_directories(${BansheeFreeImgImporter_INC})	
@@ -21,7 +22,7 @@ target_compile_definitions(BansheeFreeImgImporter PRIVATE -DBS_FREEIMG_EXPORTS -
 add_library_per_config(BansheeFreeImgImporter freeimg Release/FreeImage Debug/FreeImage)
 
 ## Local libs
-target_link_libraries(BansheeFreeImgImporter PUBLIC BansheeUtility BansheeCore)
+target_link_libraries(BansheeFreeImgImporter PUBLIC BansheeUtility BansheeCore BansheeEngine)
 
 # IDE specific
 set_property(TARGET BansheeFreeImgImporter PROPERTY FOLDER Plugins)

+ 1 - 1
Source/BansheeFreeImgImporter/Include/BsFreeImgPrerequisites.h

@@ -2,7 +2,7 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #pragma once
 
-#include "BsCorePrerequisites.h"
+#include "BsPrerequisites.h"
 
 /** @addtogroup Plugins
  *  @{

+ 26 - 4
Source/BansheeFreeImgImporter/Source/BsFreeImgImporter.cpp

@@ -15,6 +15,8 @@
 #include "BsVector3.h"
 #include "FreeImage.h"
 #include "BsBitwise.h"
+#include "BsRenderer.h"
+#include "BsReflectionProbes.h"
 
 using namespace std::placeholders;
 
@@ -141,13 +143,26 @@ namespace bs
 		Vector<SPtr<PixelData>> faceData;
 
 		TextureType texType;
+		bool filterForReflections = false;
 		if(textureImportOptions->getIsCubemap())
 		{
 			texType = TEX_TYPE_CUBE_MAP;
 
+			if(textureImportOptions->getCubemapIsReflection())
+			{
+				SPtr<PixelData> scaledImgData = PixelData::create(ct::ReflectionProbes::REFLECTION_CUBEMAP_SIZE, 
+					ct::ReflectionProbes::REFLECTION_CUBEMAP_SIZE, 0, imgData->getFormat());
+
+				PixelUtil::scale(*imgData, *scaledImgData);
+				imgData = scaledImgData;
+			}
+
 			std::array<SPtr<PixelData>, 6> cubemapFaces;
 			if (generateCubemap(imgData, textureImportOptions->getCubemapSourceType(), cubemapFaces))
+			{
 				faceData.insert(faceData.begin(), cubemapFaces.begin(), cubemapFaces.end());
+				filterForReflections = textureImportOptions->getCubemapIsReflection();
+			}
 			else // Fall-back to 2D texture
 			{
 				texType = TEX_TYPE_2D;
@@ -161,13 +176,13 @@ namespace bs
 		}
 
 		UINT32 numMips = 0;
-		if (textureImportOptions->getGenerateMipmaps() && Bitwise::isPow2(faceData[0]->getWidth()) && 
-			Bitwise::isPow2(faceData[0]->getHeight()))
+		if ((textureImportOptions->getGenerateMipmaps() || filterForReflections) && 
+			Bitwise::isPow2(faceData[0]->getWidth()) && Bitwise::isPow2(faceData[0]->getHeight()))
 		{
 			UINT32 maxPossibleMip = PixelUtil::getMaxMipmaps(faceData[0]->getWidth(), faceData[0]->getHeight(), 
 				faceData[0]->getDepth(), faceData[0]->getFormat());
 
-			if (textureImportOptions->getMaxMip() == 0)
+			if (textureImportOptions->getMaxMip() == 0 || filterForReflections)
 				numMips = maxPossibleMip;
 			else
 				numMips = std::min(maxPossibleMip, textureImportOptions->getMaxMip());
@@ -194,7 +209,7 @@ namespace bs
 		for (UINT32 i = 0; i < numFaces; i++)
 		{
 			Vector<SPtr<PixelData>> mipLevels;
-			if (numMips > 0)
+			if (numMips > 0 && !filterForReflections)
 				mipLevels = PixelUtil::genMipmaps(*faceData[i], MipMapGenOptions());
 			else
 				mipLevels.push_back(faceData[i]);
@@ -210,6 +225,13 @@ namespace bs
 
 		fileData->close();
 
+		if(filterForReflections)
+		{
+			SPtr<ct::Texture> coreCubemap = newTexture->getCore();
+			gCoreThread().queueCommand(std::bind(&ct::ReflectionProbes::filterCubemapForSpecular, coreCubemap, nullptr));
+			gCoreThread().submit(true);
+		}
+
 		WString fileName = filePath.getWFilename(false);
 		newTexture->setName(fileName);
 

+ 5 - 0
Source/MBansheeEditor/Inspectors/Texture2DInspector.cs

@@ -23,6 +23,7 @@ namespace BansheeEditor
         private GUIToggleField isCubemapField = new GUIToggleField(new LocEdString("Cubemap"));
         private GUIEnumField cubemapSourceTypeField = 
             new GUIEnumField(typeof(CubemapSourceType), new LocEdString("Cubemap source"));
+        private GUIToggleField isReflectionCubemapField = new GUIToggleField(new LocEdString("Reflection cubemap"));
 
         private GUIButton reimportButton = new GUIButton(new LocEdString("Reimport"));
 
@@ -42,6 +43,7 @@ namespace BansheeEditor
                 cpuCachedField.OnChanged += x => importOptions.CPUCached = x;
                 isCubemapField.OnChanged += x => importOptions.IsCubemap = x;
                 cubemapSourceTypeField.OnSelectionChanged += x => importOptions.CubemapSourceType = (CubemapSourceType)x;
+                isReflectionCubemapField.OnChanged += x => importOptions.IsCubemapReflection = x;
                 reimportButton.OnClick += TriggerReimport;
 
                 Layout.AddElement(formatField);
@@ -51,6 +53,7 @@ namespace BansheeEditor
                 Layout.AddElement(cpuCachedField);
                 Layout.AddElement(isCubemapField);
                 Layout.AddElement(cubemapSourceTypeField);
+                Layout.AddElement(isReflectionCubemapField);
                 Layout.AddSpace(10);
 
                 GUILayout reimportButtonLayout = Layout.AddLayoutX();
@@ -71,8 +74,10 @@ namespace BansheeEditor
             cpuCachedField.Value = newImportOptions.CPUCached;
             isCubemapField.Value = newImportOptions.IsCubemap;
             cubemapSourceTypeField.Value = (ulong) newImportOptions.CubemapSourceType;
+            isReflectionCubemapField.Value = newImportOptions.IsCubemapReflection;
 
             cubemapSourceTypeField.Active = importOptions.IsCubemap;
+            isReflectionCubemapField.Active = importOptions.IsCubemap;
 
             importOptions = newImportOptions;
 

+ 17 - 0
Source/MBansheeEditor/Windows/Library/ImportOptions.cs

@@ -124,6 +124,17 @@ namespace BansheeEditor
             set { Internal_SetCubemapSourceType(mCachedPtr, value); }
         }
 
+        /// <summary>
+        /// If true makrs the cubemap as a reflection cubemap and perform special filtering on the cubemap mip-maps. Only
+        /// relevant when texture is imported as a cubemap.This will override texture size and mip levels to match the
+        /// requirements needed for reflection cubemaps.
+        /// </summary>
+        public bool IsCubemapReflection
+        {
+            get { return Internal_GetIsCubemapReflection(mCachedPtr); }
+            set { Internal_SetIsCubemapReflection(mCachedPtr, value); }
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_CreateInstance(TextureImportOptions instance);
 
@@ -168,6 +179,12 @@ namespace BansheeEditor
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetCubemapSourceType(IntPtr thisPtr, CubemapSourceType value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_GetIsCubemapReflection(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetIsCubemapReflection(IntPtr thisPtr, bool value);
     }
 
     /// <summary>

+ 0 - 2
Source/RenderBeast/CMakeSources.cmake

@@ -12,7 +12,6 @@ set(BS_RENDERBEAST_INC_NOFILTER
 	"Include/BsRendererCamera.h"
 	"Include/BsRendererObject.h"
 	"Include/BsLightGrid.h"
-	"Include/BsReflectionProbes.h"
 )
 
 set(BS_RENDERBEAST_SRC_NOFILTER
@@ -28,7 +27,6 @@ set(BS_RENDERBEAST_SRC_NOFILTER
 	"Source/BsRendererCamera.cpp"
 	"Source/BsRendererObject.cpp"
 	"Source/BsLightGrid.cpp"
-	"Source/BsReflectionProbes.cpp"
 )
 
 source_group("Header Files" FILES ${BS_RENDERBEAST_INC_NOFILTER})

+ 2 - 0
Source/SBansheeEditor/Include/BsScriptImportOptions.h

@@ -80,6 +80,8 @@ namespace bs
 		static void internal_SetIsCubemap(ScriptTextureImportOptions* thisPtr, bool value);
 		static CubemapSourceType internal_GetCubemapSourceType(ScriptTextureImportOptions* thisPtr);
 		static void internal_SetCubemapSourceType(ScriptTextureImportOptions* thisPtr, CubemapSourceType value);
+		static bool internal_GetIsCubemapReflection(ScriptTextureImportOptions* thisPtr);
+		static void internal_SetIsCubemapReflection(ScriptTextureImportOptions* thisPtr, bool value);
 	};
 
 	/**	Interop class between C++ & CLR for MeshImportOptions. */

+ 11 - 0
Source/SBansheeEditor/Source/BsScriptImportOptions.cpp

@@ -85,6 +85,8 @@ namespace bs
 		metaData.scriptClass->addInternalCall("Internal_SetIsCubemap", &ScriptTextureImportOptions::internal_SetIsCubemap);
 		metaData.scriptClass->addInternalCall("Internal_GetCubemapSourceType", &ScriptTextureImportOptions::internal_GetCubemapSourceType);
 		metaData.scriptClass->addInternalCall("Internal_SetCubemapSourceType", &ScriptTextureImportOptions::internal_SetCubemapSourceType);
+		metaData.scriptClass->addInternalCall("Internal_GetIsCubemapReflection", &ScriptTextureImportOptions::internal_GetIsCubemapReflection);
+		metaData.scriptClass->addInternalCall("Internal_SetIsCubemapReflection", &ScriptTextureImportOptions::internal_SetIsCubemapReflection);
 	}
 
 	SPtr<TextureImportOptions> ScriptTextureImportOptions::getTexImportOptions()
@@ -182,6 +184,15 @@ namespace bs
 		thisPtr->getTexImportOptions()->setCubemapSourceType(value);
 	}
 
+	bool ScriptTextureImportOptions::internal_GetIsCubemapReflection(ScriptTextureImportOptions* thisPtr)
+	{
+		return thisPtr->getTexImportOptions()->getCubemapIsReflection();
+	}
+
+	void ScriptTextureImportOptions::internal_SetIsCubemapReflection(ScriptTextureImportOptions* thisPtr, bool value)
+	{
+		thisPtr->getTexImportOptions()->setCubemapIsReflection(value);
+	}
 
 	ScriptMeshImportOptions::ScriptMeshImportOptions(MonoObject* instance)
 		:ScriptObject(instance)