| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #include "Renderer/BsSkybox.h"
- #include "RTTI/BsSkyboxRTTI.h"
- #include "Scene/BsSceneObject.h"
- #include "Allocators/BsFrameAlloc.h"
- #include "Image/BsTexture.h"
- #include "Renderer/BsRenderer.h"
- #include "Utility/BsUUID.h"
- #include "Renderer/BsIBLUtility.h"
- namespace bs
- {
- SkyboxBase::SkyboxBase()
- : mBrightness(1.0f)
- { }
- Skybox::Skybox()
- {
- // This shouldn't normally happen, as filtered textures are generated when a radiance texture is assigned, but
- // we check for it anyway (something could have gone wrong).
- if(mTexture.isLoaded())
- {
- if (mFilteredRadiance == nullptr || mIrradiance == nullptr)
- filterTexture();
- }
- }
- Skybox::~Skybox()
- {
- if (mRendererTask != nullptr)
- mRendererTask->cancel();
- }
- void Skybox::filterTexture()
- {
- // If previous rendering task exists, cancel it
- if (mRendererTask != nullptr)
- mRendererTask->cancel();
- {
- TEXTURE_DESC cubemapDesc;
- cubemapDesc.type = TEX_TYPE_CUBE_MAP;
- cubemapDesc.format = PF_RG11B10F;
- cubemapDesc.width = ct::IBLUtility::REFLECTION_CUBEMAP_SIZE;
- cubemapDesc.height = ct::IBLUtility::REFLECTION_CUBEMAP_SIZE;
- cubemapDesc.numMips = PixelUtil::getMaxMipmaps(cubemapDesc.width, cubemapDesc.height, 1, cubemapDesc.format);
- cubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
- mFilteredRadiance = Texture::_createPtr(cubemapDesc);
- }
- {
- TEXTURE_DESC irradianceCubemapDesc;
- irradianceCubemapDesc.type = TEX_TYPE_CUBE_MAP;
- irradianceCubemapDesc.format = PF_RG11B10F;
- irradianceCubemapDesc.width = ct::IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
- irradianceCubemapDesc.height = ct::IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
- irradianceCubemapDesc.numMips = 0;
- irradianceCubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
- mIrradiance = Texture::_createPtr(irradianceCubemapDesc);
- }
- auto renderComplete = [this]()
- {
- mRendererTask = nullptr;
- };
- SPtr<ct::Skybox> coreSkybox = getCore();
- SPtr<ct::Texture> coreFilteredRadiance = mFilteredRadiance->getCore();
- SPtr<ct::Texture> coreIrradiance = mIrradiance->getCore();
- auto filterSkybox = [coreFilteredRadiance, coreIrradiance, coreSkybox]()
- {
- // Filter radiance
- ct::gIBLUtility().scaleCubemap(coreSkybox->getTexture(), 0, coreFilteredRadiance, 0);
- ct::gIBLUtility().filterCubemapForSpecular(coreFilteredRadiance, nullptr);
- coreSkybox->mFilteredRadiance = coreFilteredRadiance;
- // Generate irradiance
- ct::gIBLUtility().filterCubemapForIrradiance(coreFilteredRadiance, coreIrradiance);
- coreSkybox->mIrradiance = coreIrradiance;
- return true;
- };
- mRendererTask = ct::RendererTask::create("SkyboxFilter", filterSkybox);
- mRendererTask->onComplete.connect(renderComplete);
- ct::gRenderer()->addTask(mRendererTask);
- }
- void Skybox::setTexture(const HTexture& texture)
- {
- mTexture = texture;
- mFilteredRadiance = nullptr;
- mIrradiance = nullptr;
- if(mTexture.isLoaded())
- filterTexture();
- _markCoreDirty((ActorDirtyFlag)SkyboxDirtyFlag::Texture);
- }
- SPtr<ct::Skybox> Skybox::getCore() const
- {
- return std::static_pointer_cast<ct::Skybox>(mCoreSpecific);
- }
- SPtr<Skybox> Skybox::createEmpty()
- {
- Skybox* skybox = new (bs_alloc<Skybox>()) Skybox();
- SPtr<Skybox> skyboxPtr = bs_core_ptr<Skybox>(skybox);
- skyboxPtr->_setThisPtr(skyboxPtr);
- return skyboxPtr;
- }
- SPtr<Skybox> Skybox::create()
- {
- SPtr<Skybox> skyboxPtr = createEmpty();
- skyboxPtr->initialize();
- return skyboxPtr;
- }
- SPtr<ct::CoreObject> Skybox::createCore() const
- {
- SPtr<ct::Texture> radiance;
- if (mTexture)
- radiance = mTexture->getCore();
- SPtr<ct::Texture> filteredRadiance;
- if (mFilteredRadiance)
- filteredRadiance = mFilteredRadiance->getCore();
- SPtr<ct::Texture> irradiance;
- if (mIrradiance)
- irradiance = mIrradiance->getCore();
- ct::Skybox* skybox = new (bs_alloc<ct::Skybox>()) ct::Skybox(radiance, filteredRadiance, irradiance);
- SPtr<ct::Skybox> skyboxPtr = bs_shared_ptr<ct::Skybox>(skybox);
- skyboxPtr->_setThisPtr(skyboxPtr);
- return skyboxPtr;
- }
- CoreSyncData Skybox::syncToCore(FrameAlloc* allocator)
- {
- UINT32 size = 0;
- size += getActorSyncDataSize();
- size += rttiGetElemSize(mBrightness);
- size += sizeof(SPtr<ct::Texture>);
- size += rttiGetElemSize(getCoreDirtyFlags());
- UINT8* buffer = allocator->alloc(size);
- char* dataPtr = (char*)buffer;
- dataPtr = syncActorTo(dataPtr);
- dataPtr = rttiWriteElem(mBrightness, dataPtr);
- dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
- SPtr<ct::Texture>* texture = new (dataPtr) SPtr<ct::Texture>();
- if (mTexture.isLoaded(false))
- *texture = mTexture->getCore();
- else
- *texture = nullptr;
- dataPtr += sizeof(SPtr<ct::Texture>);
- return CoreSyncData(buffer, size);
- }
- void Skybox::_markCoreDirty(ActorDirtyFlag flags)
- {
- markCoreDirty((UINT32)flags);
- }
- RTTITypeBase* Skybox::getRTTIStatic()
- {
- return SkyboxRTTI::instance();
- }
- RTTITypeBase* Skybox::getRTTI() const
- {
- return Skybox::getRTTIStatic();
- }
- namespace ct
- {
- Skybox::Skybox(const SPtr<Texture>& radiance, const SPtr<Texture>& filteredRadiance, const SPtr<Texture>& irradiance)
- :mFilteredRadiance(filteredRadiance), mIrradiance(irradiance)
- {
- mTexture = radiance;
- }
- Skybox::~Skybox()
- {
- gRenderer()->notifySkyboxRemoved(this);
- }
- void Skybox::initialize()
- {
- gRenderer()->notifySkyboxAdded(this);
- CoreObject::initialize();
- }
- void Skybox::syncToCore(const CoreSyncData& data)
- {
- char* dataPtr = (char*)data.getBuffer();
- SkyboxDirtyFlag dirtyFlags;
- bool oldIsActive = mActive;
- dataPtr = syncActorFrom(dataPtr);
- dataPtr = rttiReadElem(mBrightness, dataPtr);
- dataPtr = rttiReadElem(dirtyFlags, dataPtr);
- SPtr<Texture>* texture = (SPtr<Texture>*)dataPtr;
- mTexture = *texture;
- texture->~SPtr<Texture>();
- dataPtr += sizeof(SPtr<Texture>);
- if (oldIsActive != mActive)
- {
- if (mActive)
- gRenderer()->notifySkyboxAdded(this);
- else
- gRenderer()->notifySkyboxRemoved(this);
- }
- else
- {
- if (dirtyFlags != SkyboxDirtyFlag::Texture)
- {
- gRenderer()->notifySkyboxRemoved(this);
- gRenderer()->notifySkyboxAdded(this);
- }
- }
- }
- }
- }
|