diff --git a/Engine/source/T3D/lighting/reflectionProbe.cpp b/Engine/source/T3D/lighting/reflectionProbe.cpp index f96937aba..22faf0599 100644 --- a/Engine/source/T3D/lighting/reflectionProbe.cpp +++ b/Engine/source/T3D/lighting/reflectionProbe.cpp @@ -83,7 +83,7 @@ ImplementEnumType(ReflectionModeEnum, { ReflectionProbe::NoReflection, "No Reflections", "This probe does not provide any local reflection data"}, { ReflectionProbe::StaticCubemap, "Static Cubemap", "Uses a static CubemapData" }, { ReflectionProbe::BakedCubemap, "Baked Cubemap", "Uses a cubemap baked from the probe's current position" }, -//{ ReflectionProbe::DynamicCubemap, "Dynamic Cubemap", "Uses a cubemap baked from the probe's current position, updated at a set rate" }, +{ ReflectionProbe::DynamicCubemap, "Dynamic Cubemap", "Uses a cubemap baked from the probe's current position, updated at a set rate" }, EndImplementEnumType; //----------------------------------------------------------------------------- @@ -122,7 +122,7 @@ ReflectionProbe::ReflectionProbe() : mEditorShapeInst = NULL; mEditorShape = NULL; - mRefreshRateMS = 200; + mRefreshRateMS = 500; mDynamicLastBakeMS = 0; mMaxDrawDistance = 75; @@ -176,6 +176,8 @@ void ReflectionProbe::initPersistFields() addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "Cubemap used instead of reflection texture if fullReflect is off."); + addField("DynamicReflectionRefreshMS", TypeS32, Offset(mRefreshRateMS, ReflectionProbe), "How often the dynamic cubemap is refreshed in milliseconds. Only works when the ReflectionMode is set to DynamicCubemap."); + addProtectedField("Bake", TypeBool, Offset(mBake, ReflectionProbe), &_doBake, &defaultProtectedGetFn, "Regenerate Voxel Grid", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors); endGroup("Reflection"); @@ -434,6 +436,7 @@ U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream stream->write(mProbeUniqueID); stream->write((U32)mReflectionModeType); stream->write(mCubemapName); + stream->write(mRefreshRateMS); } if (stream->writeFlag(mask & EnabledMask)) @@ -487,6 +490,8 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream) if(oldReflectModeType != mReflectionModeType || oldCubemapName != mCubemapName) mCubemapDirty = true; + stream->read(&mRefreshRateMS); + mDirty = true; } @@ -582,7 +587,7 @@ void ReflectionProbe::updateProbeParams() void ReflectionProbe::processDynamicCubemap() { - //if (!mProbeInfo) + /*if (!mProbeInfo) return; mEnabled = false; @@ -591,7 +596,18 @@ void ReflectionProbe::processDynamicCubemap() { mProbeInfo->mPrefilterCubemap = mDynamicCubemap; - //mCubeReflector.registerReflector(this, reflectorDesc); //need to decide how we wanna do the reflectorDesc. static name or a field + if (reflectorDesc == nullptr) + { + //find it + if (!Sim::findObject("DefaultCubeDesc", reflectorDesc)) + { + mProbeInfo->mIsEnabled = false; + return; + } + } + + mCubeReflector.unregisterReflector(); + mCubeReflector.registerReflector(this, reflectorDesc); //need to decide how we wanna do the reflectorDesc. static name or a field } if (mEnabled) @@ -603,7 +619,68 @@ void ReflectionProbe::processDynamicCubemap() //Update the probe manager with our new texture! //if (!mProbeInfo->mIsSkylight && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized()) - // PROBEMGR->updateProbeTexture(mProbeInfo->mProbeIdx); + // PROBEMGR->updateProbeTexture(mProbeInfo->mProbeIdx);*/ + + if (!mProbeInfo) + return; + + mProbeInfo->mIsEnabled = false; + + if (mReflectionModeType != DynamicCubemap) + return; + + if (reflectorDesc == nullptr) + { + //find it + if (!Sim::findObject("DefaultCubeDesc", reflectorDesc)) + { + mProbeInfo->mIsEnabled = false; + return; + } + + mCubeReflector.unregisterReflector(); + mCubeReflector.registerReflector(this, reflectorDesc); //need to decide how we wanna do the reflectorDesc. static name or a field + } + + if (mCubeReflector.getCubemap()) + { + U32 resolution = Con::getIntVariable("$pref::ReflectionProbes::BakeResolution", 64); + U32 prefilterMipLevels = mLog2(F32(resolution)); + + //Prep it with whatever resolution we've dictated for our bake + mIrridianceMap->mCubemap->initDynamic(resolution, PROBEMGR->PROBE_FORMAT); + mPrefilterMap->mCubemap->initDynamic(resolution, PROBEMGR->PROBE_FORMAT); + + GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false); + + IBLUtilities::GenerateIrradianceMap(renderTarget, mCubeReflector.getCubemap(), mIrridianceMap->mCubemap); + IBLUtilities::GeneratePrefilterMap(renderTarget, mCubeReflector.getCubemap(), prefilterMipLevels, mPrefilterMap->mCubemap); + } + + if (mIrridianceMap == nullptr || mIrridianceMap->mCubemap.isNull()) + { + Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str()); + return; + } + + if (mPrefilterMap == nullptr || mPrefilterMap->mCubemap.isNull()) + { + Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str()); + return; + } + + mProbeInfo->mPrefilterCubemap = mPrefilterMap->mCubemap; + mProbeInfo->mIrradianceCubemap = mIrridianceMap->mCubemap; + + if (mEnabled && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized()) + { + mProbeInfo->mIsEnabled = true; + + mCubemapDirty = false; + + //Update the probe manager with our new texture! + PROBEMGR->updateProbeTexture(mProbeInfo); + } } void ReflectionProbe::processBakedCubemap() @@ -818,10 +895,12 @@ String ReflectionProbe::getIrradianceMapPath() void ReflectionProbe::bake() { - if (mReflectionModeType != BakedCubemap) + bool writeFile = mReflectionModeType == BakedCubemap ? true : false; + + if (mReflectionModeType == StaticCubemap) return; - PROBEMGR->bakeProbe(this); + PROBEMGR->bakeProbe(this, writeFile); setMaskBits(-1); } @@ -864,8 +943,10 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state) if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS)) { - bake(); + //bake(); mDynamicLastBakeMS = Platform::getRealMilliseconds(); + + processDynamicCubemap(); } //Submit our probe to actually do the probe action diff --git a/Engine/source/T3D/lighting/reflectionProbe.h b/Engine/source/T3D/lighting/reflectionProbe.h index 4c40f5e2b..91ca35b5d 100644 --- a/Engine/source/T3D/lighting/reflectionProbe.h +++ b/Engine/source/T3D/lighting/reflectionProbe.h @@ -116,6 +116,7 @@ protected: String cubeDescName; U32 cubeDescId; + CubeReflector mCubeReflector; ReflectorDesc *reflectorDesc; //Utilized in dynamic reflections diff --git a/Engine/source/T3D/lighting/skylight.cpp b/Engine/source/T3D/lighting/skylight.cpp index 0a89c0bab..6f816e976 100644 --- a/Engine/source/T3D/lighting/skylight.cpp +++ b/Engine/source/T3D/lighting/skylight.cpp @@ -161,6 +161,14 @@ void Skylight::prepRenderImage(SceneRenderState *state) mProbeInfo->setPosition(camPos); + if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS)) + { + //bake(); + mDynamicLastBakeMS = Platform::getRealMilliseconds(); + + processDynamicCubemap(); + } + //Submit our probe to actually do the probe action // Get a handy pointer to our RenderPassmanager //RenderPassManager *renderPass = state->getRenderPass(); diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp index 00e5795cc..2fcd6ecfb 100644 --- a/Engine/source/renderInstance/renderProbeMgr.cpp +++ b/Engine/source/renderInstance/renderProbeMgr.cpp @@ -853,7 +853,7 @@ void RenderProbeMgr::render( SceneRenderState *state ) //PROFILE_END(); } -void RenderProbeMgr::bakeProbe(ReflectionProbe *probe) +void RenderProbeMgr::bakeProbe(ReflectionProbe *probe, bool writeFiles) { GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE); @@ -865,7 +865,12 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe *probe) U32 prefilterMipLevels = mLog2(F32(resolution)); bool renderWithProbes = Con::getIntVariable("$pref::ReflectionProbes::RenderWithProbes", false); - ReflectionProbe *clientProbe = static_cast(probe->getClientObject()); + ReflectionProbe* clientProbe = nullptr; + + if (probe->isClientObject()) + clientProbe = probe; + else + clientProbe = static_cast(probe->getClientObject()); if (clientProbe == nullptr) return; @@ -960,10 +965,14 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe *probe) U32 endMSTime = Platform::getRealMilliseconds(); F32 diffTime = F32(endMSTime - startMSTime); Con::warnf("RenderProbeMgr::bake() - Finished Capture! Took %g milliseconds", diffTime); - Con::warnf("RenderProbeMgr::bake() - Beginning save now!"); - IBLUtilities::SaveCubeMap(clientProbe->getIrradianceMapPath(), clientProbe->mIrridianceMap->mCubemap); - IBLUtilities::SaveCubeMap(clientProbe->getPrefilterMapPath(), clientProbe->mPrefilterMap->mCubemap); + if (writeFiles) + { + Con::warnf("RenderProbeMgr::bake() - Beginning save now!"); + + IBLUtilities::SaveCubeMap(clientProbe->getIrradianceMapPath(), clientProbe->mIrridianceMap->mCubemap); + IBLUtilities::SaveCubeMap(clientProbe->getPrefilterMapPath(), clientProbe->mPrefilterMap->mCubemap); + } } else { diff --git a/Engine/source/renderInstance/renderProbeMgr.h b/Engine/source/renderInstance/renderProbeMgr.h index 24faccb65..281a5d87e 100644 --- a/Engine/source/renderInstance/renderProbeMgr.h +++ b/Engine/source/renderInstance/renderProbeMgr.h @@ -223,6 +223,7 @@ class RenderProbeMgr : public RenderBinManager bool mProbesDirty; +public: //maximum number of allowed probes static const U32 PROBE_MAX_COUNT = 250; //maximum number of rendered probes per frame adjust as needed @@ -235,6 +236,7 @@ class RenderProbeMgr : public RenderBinManager static const GFXFormat PROBE_FORMAT = GFXFormatR16G16B16A16F;// GFXFormatR8G8B8A8;// when hdr fixed GFXFormatR16G16B16A16F; look into bc6h compression static const U32 INVALID_CUBE_SLOT = U32_MAX; +private: //Array rendering U32 mEffectiveProbeCount; S32 mMipCount; @@ -344,7 +346,7 @@ public: /// Debug rendering static bool smRenderReflectionProbes; - void bakeProbe(ReflectionProbe *probeInfo); + void bakeProbe(ReflectionProbe *probeInfo, bool writeFile = true); void bakeProbes(); void getProbeTextureData(ProbeTextureArrayData* probeTextureSet);