Browse Source

Added support for irradiance map caching
Renamed ReflectionCubemapCache -> LightProbeCache

BearishSun 8 years ago
parent
commit
dafc97f073

+ 2 - 2
Source/BansheeEngine/CMakeSources.cmake

@@ -88,7 +88,7 @@ set(BS_BANSHEEENGINE_INC_RENDERER
 	"Include/BsRenderQueue.h"
 	"Include/BsRendererUtility.h"
 	"Include/BsStandardPostProcessSettings.h"	
-	"Include/BsReflectionCubemapCache.h"
+	"Include/BsLightProbeCache.h"
 	"Include/BsReflectionProbes.h"
 )
 
@@ -177,7 +177,7 @@ set(BS_BANSHEEENGINE_SRC_RENDERER
 	"Source/BsRenderQueue.cpp"
 	"Source/BsRendererUtility.cpp"
 	"Source/BsStandardPostProcessSettings.cpp"
-	"Source/BsReflectionCubemapCache.cpp"
+	"Source/BsLightProbeCache.cpp"
 	"Source/BsReflectionProbes.cpp"
 )
 

+ 94 - 0
Source/BansheeEngine/Include/BsLightProbeCache.h

@@ -0,0 +1,94 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsParamBlocks.h"
+#include "BsRendererMaterial.h"
+#include "BsModule.h"
+
+namespace bs { namespace ct
+{
+	/** @addtogroup Renderer-Engine-Internal
+	 *  @{
+	 */
+
+	/** 
+	 * Keeps a cache of all textures used by light probes so they may be generated during development time, and then just
+	 * loaded during runtime.
+	 */
+	class BS_EXPORT LightProbeCache : public Module<LightProbeCache>
+	{
+	public:
+		~LightProbeCache();
+
+		/** Initializes the cache with a path at which it can find the saved textures. */
+		void initCache(const Path& path);
+
+		/** Notifies the manager that the probe with the provided UUID is dirty and needs to be re-created. */
+		void notifyDirty(const String& uuid);
+
+		/** 
+		 * Checks if the radiance texture for the probe with the specified UUID is marked as dirty, or if it hasn't been
+		 * cached yet at all. 
+		 */
+		bool isRadianceDirty(const String& uuid) const;
+
+		/** 
+		 * Checks if the radiance texture for the probe with the specified UUID is marked as dirty, or if it hasn't been
+		 * cached yet at all. 
+		 */
+		bool isIrradianceDirty(const String& uuid) const;
+
+		/** Sets a cached radiance texture and associates it with the provided UUID. */
+		void setCachedRadianceTexture(const String& uuid, const SPtr<Texture>& texture);
+
+		/** Sets a cached irradiance texture and associates it with the provided UUID. */
+		void setCachedIrradianceTexture(const String& uuid, const SPtr<Texture>& texture);
+
+		/** 
+		 * Returns an radiance texture that was assigned to the specified UUID with setCachedRadianceTexture() was
+		 * called. 
+		 */
+		SPtr<Texture> getCachedRadianceTexture(const String& uuid) const;
+
+		/** 
+		 * Returns an irradiance texture that was assigned to the specified UUID with setCachedIrradianceTexture() was
+		 * called. 
+		 */
+		SPtr<Texture> getCachedIrradianceTexture(const String& uuid) const;
+
+		/** Unloads in-memory data for a probe with the specified UUID. */
+		void unloadCachedTexture(const String& uuid);
+
+		/** Saves all cached textures in a folder at the provided path. */
+		void saveCache(const Path& path);
+
+	private:
+		/** Information about a single light probe texture. */
+		struct TextureInfo
+		{
+			SPtr<Texture> texture = nullptr;
+			bool dirty = false;
+			bool needsSaving = false;
+		};
+
+		/** Information about textures for a single light probe. */
+		struct ProbeInfo
+		{
+			TextureInfo radiance;
+			TextureInfo irradiance;
+		};
+
+		/** Loads a saved cached texture at the specified path. */
+		SPtr<Texture> loadCachedTexture(const Path& path) const;
+
+		/** Saves cached texture data at the specified path. */
+		void saveCachedTexture(const TextureInfo& texInfo, const Path& path);
+
+		Path mDataPath;
+		mutable UnorderedMap<String, ProbeInfo> mProbeInfos;
+	};
+
+	/** @} */
+}}

+ 0 - 60
Source/BansheeEngine/Include/BsReflectionCubemapCache.h

@@ -1,60 +0,0 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsParamBlocks.h"
-#include "BsRendererMaterial.h"
-#include "BsModule.h"
-
-namespace bs { namespace ct
-{
-	/** @addtogroup Renderer-Engine-Internal
-	 *  @{
-	 */
-
-	/** 
-	 * Keeps track of all reflection probes and maintains a cache of their textures so they may be generated during
-	 * development time, and then just loaded during runtime.
-	 */
-	class BS_EXPORT ReflectionCubemapCache : public Module<ReflectionCubemapCache>
-	{
-	public:
-		~ReflectionCubemapCache();
-
-		/** Initializes the cache with a path at which it can find the saved textures. */
-		void initCache(const Path& path);
-
-		/** Notifies the manager that the probe with the provided UUID is dirty and needs to be re-created. */
-		void notifyDirty(const String& uuid);
-
-		/** Checks if the texture with the specified UUID is marked as dirty, or if it hasn't been cached yet at all. */
-		bool isDirty(const String& uuid) const;
-
-		/** Sets a cached texture and associates it with the provided UUID. */
-		void setCachedTexture(const String& uuid, const SPtr<Texture>& texture);
-
-		/** Returns a texture that was assigned to the specified UUID when createCachedTexture() was called. */
-		SPtr<Texture> getCachedTexture(const String& uuid) const;
-
-		/** Unloads in-memory data for a texture mapped with the specified UUID. */
-		void unloadCachedTexture(const String& uuid);
-
-		/** Saves all cached textures in a folder at the provided path. */
-		void saveCache(const Path& path);
-
-	private:
-		/** Information about a single loaded texture. */
-		struct TextureInfo
-		{
-			SPtr<Texture> texture;
-			bool dirty;
-			bool needsSaving;
-		};
-
-		Path mDataPath;
-		mutable UnorderedMap<String, TextureInfo> mTextureInfos;
-	};
-
-	/** @} */
-}}

+ 3 - 3
Source/BansheeEngine/Source/BsApplication.cpp

@@ -21,7 +21,7 @@
 #include "BsPlatform.h"
 #include "BsEngineShaderIncludeHandler.h"
 #include "BsEngineConfig.h"
-#include "BsReflectionCubemapCache.h"
+#include "BsLightProbeCache.h"
 
 namespace bs
 {
@@ -43,7 +43,7 @@ namespace bs
 		ShortcutManager::shutDown();
 		GUIManager::shutDown();
 		SpriteManager::shutDown();
-		ct::ReflectionCubemapCache::shutDown();
+		ct::LightProbeCache::shutDown();
 		BuiltinResources::shutDown();
 		RendererMaterialManager::shutDown();
 		VirtualInput::shutDown();
@@ -58,7 +58,7 @@ namespace bs
 
 		VirtualInput::startUp();
 		BuiltinResources::startUp();
-		ct::ReflectionCubemapCache::startUp();
+		ct::LightProbeCache::startUp();
 		RendererMaterialManager::startUp();
 		RendererManager::instance().initialize();
 		SpriteManager::startUp();

+ 271 - 0
Source/BansheeEngine/Source/BsLightProbeCache.cpp

@@ -0,0 +1,271 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsLightProbeCache.h"
+#include "BsFileSystem.h"
+#include "BsIReflectable.h"
+#include "BsRTTIType.h"
+#include "BsFileSerializer.h"
+
+namespace bs { namespace ct
+{
+	struct CachedTextureData : IReflectable
+	{
+		TextureType type;
+		UINT32 numFaces;
+		UINT32 numMips;
+		Vector<SPtr<PixelData>> pixelData;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class CachedTextureDataRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+	};
+
+	class CachedTextureDataRTTI : public RTTIType <CachedTextureData, IReflectable, CachedTextureDataRTTI>
+	{
+	private:
+		BS_BEGIN_RTTI_MEMBERS
+			BS_RTTI_MEMBER_PLAIN(type, 0)
+			BS_RTTI_MEMBER_PLAIN(numFaces, 1)
+			BS_RTTI_MEMBER_PLAIN(numMips, 2)
+			BS_RTTI_MEMBER_REFLPTR_ARRAY(pixelData, 3)
+		BS_END_RTTI_MEMBERS
+	public:
+		CachedTextureDataRTTI()
+			:mInitMembers(this)
+		{ }
+
+		const String& getRTTIName() override
+		{
+			static String name = "CachedTextureData";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_CachedTextureData;
+		}
+
+		SPtr<IReflectable> newRTTIObject() override
+		{
+			return bs_shared_ptr_new<CachedTextureData>();
+		}
+	};
+
+	RTTITypeBase* CachedTextureData::getRTTIStatic()
+	{
+		return CachedTextureDataRTTI::instance();
+	}
+
+	RTTITypeBase* CachedTextureData::getRTTI() const
+	{
+		return getRTTIStatic();
+	}
+
+	LightProbeCache::~LightProbeCache()
+	{
+		for (auto& entry : mProbeInfos)
+		{
+			if(entry.second.radiance.needsSaving || entry.second.irradiance.needsSaving)
+			{
+				LOGWRN("Shutting down reflection cubemap cache manager but not all textures were saved on disk before "
+					   "shutdown.");
+				break;
+			}
+		}
+	}
+
+	void LightProbeCache::initCache(const Path& path)
+	{
+		mDataPath = path;
+
+		auto visitFile = [&](const Path& filePath) -> bool
+		{
+			String uuid = filePath.getFilename(false);
+			mProbeInfos.insert(std::make_pair(uuid, ProbeInfo()));
+
+			return true;
+		};
+
+		FileSystem::iterate(path, visitFile, nullptr, false);
+	}
+
+	void LightProbeCache::notifyDirty(const String& uuid)
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind != mProbeInfos.end())
+		{
+			iterFind->second.radiance.dirty = true;
+			iterFind->second.irradiance.dirty = true;
+		}
+	}
+
+	bool LightProbeCache::isRadianceDirty(const String& uuid) const
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind != mProbeInfos.end())
+			return iterFind->second.radiance.dirty;
+
+		return true;
+	}
+
+	bool LightProbeCache::isIrradianceDirty(const String& uuid) const
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind != mProbeInfos.end())
+			return iterFind->second.irradiance.dirty;
+
+		return true;
+	}
+
+	void LightProbeCache::setCachedRadianceTexture(const String& uuid, const SPtr<Texture>& texture)
+	{
+		ProbeInfo& probeInfo = mProbeInfos[uuid];
+		TextureInfo& texInfo = probeInfo.radiance;
+		texInfo.texture = texture;
+		texInfo.needsSaving = true;
+		texInfo.dirty = false;
+	}
+
+	void LightProbeCache::setCachedIrradianceTexture(const String& uuid, const SPtr<Texture>& texture)
+	{
+		ProbeInfo& probeInfo = mProbeInfos[uuid];
+		TextureInfo& texInfo = probeInfo.irradiance;
+		texInfo.texture = texture;
+		texInfo.needsSaving = true;
+		texInfo.dirty = false;
+	}
+
+	SPtr<Texture> LightProbeCache::getCachedRadianceTexture(const String& uuid) const
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind == mProbeInfos.end())
+			return nullptr;
+
+		TextureInfo& texInfo = iterFind->second.radiance;
+		if (texInfo.texture != nullptr)
+			return texInfo.texture;
+
+		Path filePath = mDataPath + "R_" + uuid + ".asset";
+		texInfo.texture = loadCachedTexture(filePath);
+		
+		return texInfo.texture;
+	}
+
+	SPtr<Texture> LightProbeCache::getCachedIrradianceTexture(const String& uuid) const
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind == mProbeInfos.end())
+			return nullptr;
+
+		TextureInfo& texInfo = iterFind->second.irradiance;
+		if (texInfo.texture != nullptr)
+			return texInfo.texture;
+
+		Path filePath = mDataPath + "IRR_" + uuid + ".asset";
+		texInfo.texture = loadCachedTexture(filePath);
+
+		return texInfo.texture;
+	}
+
+	void LightProbeCache::unloadCachedTexture(const String& uuid)
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind != mProbeInfos.end())
+		{
+			// Not allowed to unload if it requires saving (should only happen during development time)
+			if (!iterFind->second.radiance.needsSaving)
+				iterFind->second.radiance.texture = nullptr;
+
+			if (!iterFind->second.irradiance.needsSaving)
+				iterFind->second.irradiance.texture = nullptr;
+		}
+	}
+
+	void LightProbeCache::saveCache(const Path& path)
+	{
+		for(auto& entry : mProbeInfos)
+		{
+			ProbeInfo& probeInfo = entry.second;
+
+			Path radiancePath = path + "R_" + entry.first + ".asset";
+			saveCachedTexture(probeInfo.radiance, radiancePath);
+			probeInfo.radiance.needsSaving = false;
+
+			Path irradiancePath = path + "IRRR_" + entry.first + ".asset";
+			saveCachedTexture(probeInfo.irradiance, irradiancePath);
+			probeInfo.irradiance.needsSaving = false;
+		}
+	}
+
+	SPtr<Texture> LightProbeCache::loadCachedTexture(const Path& path) const
+	{
+		if (!FileSystem::exists(path))
+			return nullptr;
+
+		FileDecoder fd(path);
+		SPtr<CachedTextureData> textureData = std::static_pointer_cast<CachedTextureData>(fd.decode());
+
+		if (textureData == nullptr || textureData->pixelData.size() == 0 || textureData->pixelData[0] == nullptr)
+			return nullptr;
+
+		TEXTURE_DESC desc;
+		desc.type = textureData->type;
+		desc.format = textureData->pixelData[0]->getFormat();
+		desc.width = textureData->pixelData[0]->getWidth();
+		desc.height = textureData->pixelData[0]->getHeight();
+		desc.depth = textureData->pixelData[0]->getDepth();
+
+		if (desc.type == TEX_TYPE_CUBE_MAP)
+			desc.numArraySlices = textureData->numFaces / 6;
+		else
+			desc.numArraySlices = textureData->numFaces;
+
+		desc.numMips = textureData->numMips;
+
+		SPtr<Texture> texture = Texture::create(desc);
+		for (UINT32 face = 0; face < textureData->numFaces; face++)
+		{
+			for (UINT32 mip = 0; mip < textureData->numMips; mip++)
+			{
+				UINT32 srcIdx = face * textureData->numMips + mip;
+				if (srcIdx >= textureData->pixelData.size())
+					continue;
+
+				texture->writeData(*textureData->pixelData[srcIdx], mip, face, true);
+			}
+		}
+
+		return texture;
+	}
+
+	void LightProbeCache::saveCachedTexture(const TextureInfo& texInfo, const Path& path)
+	{
+		if (!texInfo.needsSaving)
+			return;
+
+		auto& texProps = texInfo.texture->getProperties();
+
+		SPtr<CachedTextureData> textureData = bs_shared_ptr_new<CachedTextureData>();
+		textureData->type = texProps.getTextureType();
+		textureData->numFaces = texProps.getNumFaces();
+		textureData->numMips = texProps.getNumMipmaps() + 1;
+
+		for (UINT32 face = 0; face < textureData->numFaces; face++)
+		{
+			for (UINT32 mip = 0; mip < textureData->numMips; mip++)
+			{
+				SPtr<PixelData> pixelData = texProps.allocBuffer(face, mip);
+				texInfo.texture->readData(*pixelData, mip, face);
+
+				textureData->pixelData.push_back(pixelData);
+			}
+		}
+;
+		FileEncoder fe(path);
+		fe.encode(textureData.get());
+	}
+}}

+ 119 - 67
Source/BansheeEngine/Source/BsReflectionCubemapCache.cpp

@@ -1,6 +1,6 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsReflectionCubemapCache.h"
+#include "BsLightProbeCache.h"
 #include "BsFileSystem.h"
 #include "BsIReflectable.h"
 #include "BsRTTIType.h"
@@ -65,11 +65,11 @@ namespace bs { namespace ct
 		return getRTTIStatic();
 	}
 
-	ReflectionCubemapCache::~ReflectionCubemapCache()
+	LightProbeCache::~LightProbeCache()
 	{
-		for (auto& entry : mTextureInfos)
+		for (auto& entry : mProbeInfos)
 		{
-			if(entry.second.needsSaving)
+			if(entry.second.radiance.needsSaving || entry.second.irradiance.needsSaving)
 			{
 				LOGWRN("Shutting down reflection cubemap cache manager but not all textures were saved on disk before "
 					   "shutdown.");
@@ -78,18 +78,14 @@ namespace bs { namespace ct
 		}
 	}
 
-	void ReflectionCubemapCache::initCache(const Path& path)
+	void LightProbeCache::initCache(const Path& path)
 	{
 		mDataPath = path;
 
 		auto visitFile = [&](const Path& filePath) -> bool
 		{
 			String uuid = filePath.getFilename(false);
-
-			TextureInfo& texInfo = mTextureInfos[uuid];
-			texInfo.texture = nullptr;
-			texInfo.needsSaving = false;
-			texInfo.dirty = false;
+			mProbeInfos.insert(std::make_pair(uuid, ProbeInfo()));
 
 			return true;
 		};
@@ -97,45 +93,120 @@ namespace bs { namespace ct
 		FileSystem::iterate(path, visitFile, nullptr, false);
 	}
 
-	void ReflectionCubemapCache::notifyDirty(const String& uuid)
+	void LightProbeCache::notifyDirty(const String& uuid)
 	{
-		auto iterFind = mTextureInfos.find(uuid);
-		if (iterFind != mTextureInfos.end())
-			iterFind->second.dirty = true;
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind != mProbeInfos.end())
+		{
+			iterFind->second.radiance.dirty = true;
+			iterFind->second.irradiance.dirty = true;
+		}
+	}
+
+	bool LightProbeCache::isRadianceDirty(const String& uuid) const
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind != mProbeInfos.end())
+			return iterFind->second.radiance.dirty;
+
+		return true;
 	}
 
-	bool ReflectionCubemapCache::isDirty(const String& uuid) const
+	bool LightProbeCache::isIrradianceDirty(const String& uuid) const
 	{
-		auto iterFind = mTextureInfos.find(uuid);
-		if (iterFind != mTextureInfos.end())
-			return iterFind->second.dirty;
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind != mProbeInfos.end())
+			return iterFind->second.irradiance.dirty;
 
 		return true;
 	}
 
-	void ReflectionCubemapCache::setCachedTexture(const String& uuid, const SPtr<Texture>& texture)
+	void LightProbeCache::setCachedRadianceTexture(const String& uuid, const SPtr<Texture>& texture)
+	{
+		ProbeInfo& probeInfo = mProbeInfos[uuid];
+		TextureInfo& texInfo = probeInfo.radiance;
+		texInfo.texture = texture;
+		texInfo.needsSaving = true;
+		texInfo.dirty = false;
+	}
+
+	void LightProbeCache::setCachedIrradianceTexture(const String& uuid, const SPtr<Texture>& texture)
 	{
-		TextureInfo& texInfo = mTextureInfos[uuid];
+		ProbeInfo& probeInfo = mProbeInfos[uuid];
+		TextureInfo& texInfo = probeInfo.irradiance;
 		texInfo.texture = texture;
 		texInfo.needsSaving = true;
 		texInfo.dirty = false;
 	}
 
-	SPtr<Texture> ReflectionCubemapCache::getCachedTexture(const String& uuid) const
+	SPtr<Texture> LightProbeCache::getCachedRadianceTexture(const String& uuid) const
 	{
-		auto iterFind = mTextureInfos.find(uuid);
-		if (iterFind == mTextureInfos.end())
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind == mProbeInfos.end())
 			return nullptr;
 
-		TextureInfo& texInfo = iterFind->second;
+		TextureInfo& texInfo = iterFind->second.radiance;
 		if (texInfo.texture != nullptr)
 			return texInfo.texture;
 
-		Path filePath = mDataPath + uuid + ".asset";
-		if (!FileSystem::exists(filePath))
+		Path filePath = mDataPath + "R_" + uuid + ".asset";
+		texInfo.texture = loadCachedTexture(filePath);
+		
+		return texInfo.texture;
+	}
+
+	SPtr<Texture> LightProbeCache::getCachedIrradianceTexture(const String& uuid) const
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind == mProbeInfos.end())
 			return nullptr;
 
-		FileDecoder fd(filePath);
+		TextureInfo& texInfo = iterFind->second.irradiance;
+		if (texInfo.texture != nullptr)
+			return texInfo.texture;
+
+		Path filePath = mDataPath + "IRR_" + uuid + ".asset";
+		texInfo.texture = loadCachedTexture(filePath);
+
+		return texInfo.texture;
+	}
+
+	void LightProbeCache::unloadCachedTexture(const String& uuid)
+	{
+		auto iterFind = mProbeInfos.find(uuid);
+		if (iterFind != mProbeInfos.end())
+		{
+			// Not allowed to unload if it requires saving (should only happen during development time)
+			if (!iterFind->second.radiance.needsSaving)
+				iterFind->second.radiance.texture = nullptr;
+
+			if (!iterFind->second.irradiance.needsSaving)
+				iterFind->second.irradiance.texture = nullptr;
+		}
+	}
+
+	void LightProbeCache::saveCache(const Path& path)
+	{
+		for(auto& entry : mProbeInfos)
+		{
+			ProbeInfo& probeInfo = entry.second;
+
+			Path radiancePath = path + "R_" + entry.first + ".asset";
+			saveCachedTexture(probeInfo.radiance, radiancePath);
+			probeInfo.radiance.needsSaving = false;
+
+			Path irradiancePath = path + "IRRR_" + entry.first + ".asset";
+			saveCachedTexture(probeInfo.irradiance, irradiancePath);
+			probeInfo.irradiance.needsSaving = false;
+		}
+	}
+
+	SPtr<Texture> LightProbeCache::loadCachedTexture(const Path& path) const
+	{
+		if (!FileSystem::exists(path))
+			return nullptr;
+
+		FileDecoder fd(path);
 		SPtr<CachedTextureData> textureData = std::static_pointer_cast<CachedTextureData>(fd.decode());
 
 		if (textureData == nullptr || textureData->pixelData.size() == 0 || textureData->pixelData[0] == nullptr)
@@ -154,11 +225,11 @@ namespace bs { namespace ct
 			desc.numArraySlices = textureData->numFaces;
 
 		desc.numMips = textureData->numMips;
-		
+
 		SPtr<Texture> texture = Texture::create(desc);
-		for(UINT32 face = 0; face < textureData->numFaces; face++)
+		for (UINT32 face = 0; face < textureData->numFaces; face++)
 		{
-			for(UINT32 mip = 0; mip < textureData->numMips; mip++)
+			for (UINT32 mip = 0; mip < textureData->numMips; mip++)
 			{
 				UINT32 srcIdx = face * textureData->numMips + mip;
 				if (srcIdx >= textureData->pixelData.size())
@@ -168,52 +239,33 @@ namespace bs { namespace ct
 			}
 		}
 
-		texInfo.texture = texture;
 		return texture;
 	}
 
-	void ReflectionCubemapCache::unloadCachedTexture(const String& uuid)
+	void LightProbeCache::saveCachedTexture(const TextureInfo& texInfo, const Path& path)
 	{
-		auto iterFind = mTextureInfos.find(uuid);
-		if (iterFind != mTextureInfos.end())
-		{
-			// Not allowed to unload if it requires saving (should only happen during development time)
-			if (!iterFind->second.needsSaving)
-				iterFind->second.texture = nullptr;
-		}
-	}
+		if (!texInfo.needsSaving)
+			return;
 
-	void ReflectionCubemapCache::saveCache(const Path& path)
-	{
-		for(auto& entry : mTextureInfos)
+		auto& texProps = texInfo.texture->getProperties();
+
+		SPtr<CachedTextureData> textureData = bs_shared_ptr_new<CachedTextureData>();
+		textureData->type = texProps.getTextureType();
+		textureData->numFaces = texProps.getNumFaces();
+		textureData->numMips = texProps.getNumMipmaps() + 1;
+
+		for (UINT32 face = 0; face < textureData->numFaces; face++)
 		{
-			TextureInfo& texInfo = entry.second;
-			if (!texInfo.needsSaving)
-				continue;
-
-			auto& texProps = texInfo.texture->getProperties();
-			
-			SPtr<CachedTextureData> textureData = bs_shared_ptr_new<CachedTextureData>();
-			textureData->type = texProps.getTextureType();
-			textureData->numFaces = texProps.getNumFaces();
-			textureData->numMips = texProps.getNumMipmaps() + 1;
-
-			for (UINT32 face = 0; face < textureData->numFaces; face++)
+			for (UINT32 mip = 0; mip < textureData->numMips; mip++)
 			{
-				for (UINT32 mip = 0; mip < textureData->numMips; mip++)
-				{
-					SPtr<PixelData> pixelData = texProps.allocBuffer(face, mip);
-					texInfo.texture->readData(*pixelData, mip, face);
+				SPtr<PixelData> pixelData = texProps.allocBuffer(face, mip);
+				texInfo.texture->readData(*pixelData, mip, face);
 
-					textureData->pixelData.push_back(pixelData);
-				}
+				textureData->pixelData.push_back(pixelData);
 			}
-
-			Path filePath = path + entry.first + ".asset";
-			FileEncoder fe(filePath);
-			fe.encode(textureData.get());
-
-			texInfo.needsSaving = false;
 		}
+;
+		FileEncoder fe(path);
+		fe.encode(textureData.get());
 	}
 }}

+ 2 - 2
Source/RenderBeast/Source/BsReflectionProbeSampling.cpp

@@ -6,7 +6,7 @@
 #include "BsRenderBeast.h"
 #include "BsGpuBuffer.h"
 #include "BsReflectionProbe.h"
-#include "BsReflectionCubemapCache.h"
+#include "BsLightProbeCache.h"
 
 namespace bs { namespace ct
 {
@@ -54,7 +54,7 @@ namespace bs { namespace ct
 		arrayIdx = -1;
 		texture = nullptr;
 		customTexture = probe->getCustomTexture() != nullptr;
-		textureDirty = ReflectionCubemapCache::instance().isDirty(probe->getUUID());
+		textureDirty = LightProbeCache::instance().isRadianceDirty(probe->getUUID());
 		arrayDirty = true;
 		errorFlagged = false;
 	}

+ 27 - 25
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -31,7 +31,7 @@
 #include "BsGpuBuffer.h"
 #include "BsGpuParamsSet.h"
 #include "BsRendererExtension.h"
-#include "BsReflectionCubemapCache.h"
+#include "BsLightProbeCache.h"
 #include "BsReflectionProbe.h"
 #include "BsReflectionProbes.h"
 #include "BsMeshData.h"
@@ -512,7 +512,7 @@ namespace bs { namespace ct
 		RendererReflectionProbe& probeInfo = mReflProbes[probeId];
 		probeInfo.arrayDirty = true;
 
-		ReflectionCubemapCache::instance().notifyDirty(probe->getUUID());
+		LightProbeCache::instance().notifyDirty(probe->getUUID());
 		probeInfo.textureDirty = true;
 	}
 
@@ -540,7 +540,7 @@ namespace bs { namespace ct
 		if (arrayIdx != -1)
 			mCubemapArrayUsedSlots[arrayIdx] = false;
 
-		ReflectionCubemapCache::instance().unloadCachedTexture(probe->getUUID());
+		LightProbeCache::instance().unloadCachedTexture(probe->getUUID());
 	}
 
 	void RenderBeast::notifySkyboxAdded(Skybox* skybox)
@@ -557,7 +557,7 @@ namespace bs { namespace ct
 
 	void RenderBeast::notifySkyboxTextureChanged(Skybox* skybox)
 	{
-		ReflectionCubemapCache::instance().notifyDirty(skybox->getUUID());
+		LightProbeCache::instance().notifyDirty(skybox->getUUID());
 
 		if (mSkybox == skybox)
 		{
@@ -569,7 +569,7 @@ namespace bs { namespace ct
 
 	void RenderBeast::notifySkyboxRemoved(Skybox* skybox)
 	{
-		ReflectionCubemapCache::instance().unloadCachedTexture(skybox->getUUID());
+		LightProbeCache::instance().unloadCachedTexture(skybox->getUUID());
 
 		if (mSkybox == skybox)
 			mSkyboxTexture = nullptr;
@@ -1274,7 +1274,7 @@ namespace bs { namespace ct
 				if (probeInfo.probe->getType() != ReflectionProbeType::Plane)
 				{
 					if (probeInfo.texture == nullptr)
-						probeInfo.texture = ReflectionCubemapCache::instance().getCachedTexture(probeInfo.probe->getUUID());
+						probeInfo.texture = LightProbeCache::instance().getCachedRadianceTexture(probeInfo.probe->getUUID());
 
 					if (probeInfo.texture == nullptr || probeInfo.textureDirty)
 					{
@@ -1291,7 +1291,7 @@ namespace bs { namespace ct
 						}
 
 						ReflectionProbes::filterCubemapForSpecular(probeInfo.texture, scratchCubemap);
-						ReflectionCubemapCache::instance().setCachedTexture(probeInfo.probe->getUUID(), probeInfo.texture);
+						LightProbeCache::instance().setCachedRadianceTexture(probeInfo.probe->getUUID(), probeInfo.texture);
 					}
 				}
 
@@ -1336,35 +1336,37 @@ namespace bs { namespace ct
 				// If haven't assigned them already, do it now
 				if (mSkyboxFilteredReflections == nullptr)
 				{
-					if (!ReflectionCubemapCache::instance().isDirty(mSkybox->getUUID()))
-						mSkyboxFilteredReflections = ReflectionCubemapCache::instance().getCachedTexture(mSkybox->getUUID());
+					if (!LightProbeCache::instance().isRadianceDirty(mSkybox->getUUID()))
+						mSkyboxFilteredReflections = LightProbeCache::instance().getCachedRadianceTexture(mSkybox->getUUID());
 					else
 					{
 						mSkyboxFilteredReflections = Texture::create(cubemapDesc);
 
 						ReflectionProbes::scaleCubemap(mSkyboxTexture, 0, mSkyboxFilteredReflections, 0);
 						ReflectionProbes::filterCubemapForSpecular(mSkyboxFilteredReflections, scratchCubemap);
-						ReflectionCubemapCache::instance().setCachedTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
+						LightProbeCache::instance().setCachedRadianceTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
 					}
 				}
 
 				if(mSkyboxIrradiance == nullptr)
 				{
-					// TODO - Not uisng cache
-
-
-					TEXTURE_DESC irradianceCubemapDesc;
-					irradianceCubemapDesc.type = TEX_TYPE_CUBE_MAP;
-					irradianceCubemapDesc.format = PF_FLOAT_R11G11B10;
-					irradianceCubemapDesc.width = 32;
-					irradianceCubemapDesc.height = 32;
-					irradianceCubemapDesc.numMips = 0;
-					irradianceCubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
-
-					mSkyboxIrradiance = Texture::create(irradianceCubemapDesc);
-
-					ReflectionProbes::filterCubemapForIrradiance(mSkyboxFilteredReflections, mSkyboxIrradiance);
-					//ReflectionCubemapCache::instance().setCachedTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
+					if (!LightProbeCache::instance().isIrradianceDirty(mSkybox->getUUID()))
+						mSkyboxIrradiance = LightProbeCache::instance().getCachedIrradianceTexture(mSkybox->getUUID());
+					else
+					{
+						TEXTURE_DESC irradianceCubemapDesc;
+						irradianceCubemapDesc.type = TEX_TYPE_CUBE_MAP;
+						irradianceCubemapDesc.format = PF_FLOAT_R11G11B10;
+						irradianceCubemapDesc.width = 32;
+						irradianceCubemapDesc.height = 32;
+						irradianceCubemapDesc.numMips = 0;
+						irradianceCubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
+
+						mSkyboxIrradiance = Texture::create(irradianceCubemapDesc);
+
+						ReflectionProbes::filterCubemapForIrradiance(mSkyboxFilteredReflections, mSkyboxIrradiance);
+						LightProbeCache::instance().setCachedIrradianceTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
+					}
 				}
 			}
 			else