Просмотр исходного кода

Merge pull request #311 from Areloch/DynamicReflProbes

Re-implements the dynamic cubemap mode option for reflection probes
Brian Roberts 5 лет назад
Родитель
Сommit
d785927074

+ 89 - 8
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

+ 1 - 0
Engine/source/T3D/lighting/reflectionProbe.h

@@ -116,6 +116,7 @@ protected:
 
    String cubeDescName;
    U32 cubeDescId;
+   CubeReflector mCubeReflector;
    ReflectorDesc *reflectorDesc;
 
    //Utilized in dynamic reflections

+ 8 - 0
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();

+ 14 - 5
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<ReflectionProbe*>(probe->getClientObject());
+   ReflectionProbe* clientProbe = nullptr;
+
+   if (probe->isClientObject())
+      clientProbe = probe;
+   else
+      clientProbe = static_cast<ReflectionProbe*>(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
    {

+ 3 - 1
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);