Browse Source

Overhauls the handling of probes to utilize an active probe list to improve performance and allow a greater total number of active probes in a scene.
Also fixes handling of metal materials during bakes to render properly, and fixes a possible double-up return in findObjectByType, which could cause doubling when getting probes in the scene

Areloch 4 years ago
parent
commit
6a3603c737

+ 1 - 4
Engine/source/T3D/lighting/boxEnvironmentProbe.cpp

@@ -158,11 +158,8 @@ void BoxEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
 
 void BoxEnvironmentProbe::updateProbeParams()
 {
-   if (!mProbeInfo)
-      return;
-
    mProbeShapeType = ProbeRenderInst::Box;
-   mProbeInfo->mAtten = mAtten;
+   mProbeInfo.mAtten = mAtten;
 
    Parent::updateProbeParams();
 }

+ 79 - 218
Engine/source/T3D/lighting/reflectionProbe.cpp

@@ -83,17 +83,13 @@ 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;
 
 //-----------------------------------------------------------------------------
 // Object setup and teardown
 //-----------------------------------------------------------------------------
-ReflectionProbe::ReflectionProbe() :
-   cubeDescId(0),
-   reflectorDesc(nullptr),
-   mSphereVertCount(0),
-   mSpherePrimitiveCount(0)
+ReflectionProbe::ReflectionProbe()
 {
    // Flag this object so that it will always
    // be sent across the network to clients
@@ -106,8 +102,7 @@ ReflectionProbe::ReflectionProbe() :
    mReflectionModeType = BakedCubemap;
 
    mEnabled = true;
-   mBake = false;
-   mDirty = false;
+   mBakeReflections = false;
    mCubemapDirty = false;
 
    mRadius = 10;
@@ -122,17 +117,14 @@ ReflectionProbe::ReflectionProbe() :
    mEditorShapeInst = NULL;
    mEditorShape = NULL;
 
-   mRefreshRateMS = 500;
+   mRefreshRateMS = 200;
    mDynamicLastBakeMS = 0;
 
    mMaxDrawDistance = 75;
 
    mResourcesCreated = false;
-
-   mProbeInfo = nullptr;
-
    mPrefilterSize = 64;
-   mPrefilterMipLevels = mLog2(F32(mPrefilterSize))+1;
+   mPrefilterMipLevels = mLog2(F32(mPrefilterSize));
    mPrefilterMap = nullptr;
    mIrridianceMap = nullptr;
 
@@ -158,7 +150,7 @@ void ReflectionProbe::initPersistFields()
 {
    addGroup("Rendering");
       addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
-         &_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid");
+         &_setEnabled, &defaultProtectedGetFn, "Is the probe enabled or not");
    endGroup("Rendering");
 
    addGroup("Reflection");
@@ -168,18 +160,18 @@ void ReflectionProbe::initPersistFields()
       addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
       &_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
 
-	   addField("refOffset", TypePoint3F, Offset(mProbeRefOffset, ReflectionProbe), "");
-      addField("refScale", TypePoint3F, Offset(mProbeRefScale, ReflectionProbe), "");
+	   addField("refOffset", TypePoint3F, Offset(mProbeRefOffset, ReflectionProbe), "The reference positional offset for the probe. This is used for adjusting the perceived center and area of influence.\nHelpful in adjusting parallax issues");
+      addField("refScale", TypePoint3F, Offset(mProbeRefScale, ReflectionProbe), "The reference scale for the probe. This is used for adjusting the perceived center and area of influence.\nHelpful in adjusting parallax issues");
 
       addProtectedField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe), &_setReflectionMode, &defaultProtectedGetFn,
-         "The type of mesh data to use for collision queries.");
+         "Used to dictate what sort of cubemap the probes use when using IBL.");
 
-      addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "Cubemap used instead of reflection texture if fullReflect is off.");
+      addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "This is used when a static cubemap is used. The name of the cubemap is looked up and loaded for the IBL calculations.");
 
-      addField("DynamicReflectionRefreshMS", TypeS32, Offset(mRefreshRateMS, ReflectionProbe), "How often the dynamic cubemap is refreshed in milliseconds. Only works when the ReflectionMode is set to DynamicCubemap.");
+      //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);
+      addProtectedField("Bake", TypeBool, Offset(mBakeReflections, ReflectionProbe),
+         &_doBake, &defaultProtectedGetFn, "Bake Probe Reflections", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
    endGroup("Reflection");
 
    Con::addVariable("$Light::renderReflectionProbes", TypeBool, &RenderProbeMgr::smRenderReflectionProbes,
@@ -319,8 +311,7 @@ void ReflectionProbe::onRemove()
 {
    if (isClientObject())
    {
-      PROBEMGR->unregisterProbe(mProbeInfo->mProbeIdx);
-      mProbeInfo = nullptr;
+      PROBEMGR->unregisterProbe(mProbeInfo.mProbeIdx);
    }
 
    // Remove this object from the scene
@@ -436,7 +427,6 @@ 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))
@@ -463,7 +453,7 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
       resetWorldBox();
 
       mathRead(*stream, &mProbeRefOffset);
-      mathRead(*stream, &mProbeRefScale);      
+      mathRead(*stream, &mProbeRefScale);
 
       mDirty = true;
    }
@@ -490,8 +480,6 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
       if(oldReflectModeType != mReflectionModeType || oldCubemapName != mCubemapName)
          mCubemapDirty = true;
 
-      stream->read(&mRefreshRateMS);
-
       mDirty = true;
    }
 
@@ -501,11 +489,6 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
 
       mDirty = true;
    }
-
-   if (mDirty)
-   {
-      updateProbeParams();
-   }
 }
 
 //-----------------------------------------------------------------------------
@@ -513,12 +496,9 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
 //-----------------------------------------------------------------------------
 void ReflectionProbe::updateProbeParams()
 {
-   if (!mProbeInfo)
-      return;
-
-   mProbeInfo->mIsEnabled = mEnabled;
+   mProbeInfo.mIsEnabled = mEnabled;
 
-   mProbeInfo->mProbeShapeType = mProbeShapeType;
+   mProbeInfo.mProbeShapeType = mProbeShapeType;
 
    if (mProbeShapeType == ProbeRenderInst::Sphere)
       mObjScale.set(mRadius, mRadius, mRadius);
@@ -527,10 +507,8 @@ void ReflectionProbe::updateProbeParams()
 
    if (mProbeShapeType == ProbeRenderInst::Skylight)
    {
-      mProbeInfo->mPosition = Point3F::Zero;
-      mProbeInfo->mTransform = MatrixF::Identity;
-
-      mProbeInfo->mIsSkylight = true;
+      mProbeInfo.mPosition = Point3F::Zero;
+      mProbeInfo.mTransform = MatrixF::Identity;
 
       F32 visDist = gClientSceneGraph->getVisibleDistance();
       Box3F skylightBounds = Box3F(visDist * 2);
@@ -541,21 +519,19 @@ void ReflectionProbe::updateProbeParams()
 
       setGlobalBounds();
 
-      mProbeInfo->mScore = -1.0f;
+      mProbeInfo.mScore = 10000.0f;
    }
    else
    {
       MatrixF transform = getTransform();
-      mProbeInfo->mPosition = getPosition();
+      mProbeInfo.mPosition = getPosition();
 
       transform.scale(getScale());
-      mProbeInfo->mTransform = transform.inverse();
-
-      mProbeInfo->mIsSkylight = false;
+      mProbeInfo.mTransform = transform.inverse();
 
       bounds = mWorldBox;
 
-      mProbeInfo->mScore = mMaxDrawDistance;
+      mProbeInfo.mScore = 1;
    }
 
    // Skip our transform... it just dirties mask bits.
@@ -563,14 +539,14 @@ void ReflectionProbe::updateProbeParams()
 
    resetWorldBox();
 
-   mProbeInfo->mBounds = bounds;
-   mProbeInfo->mExtents = getScale();
-   mProbeInfo->mRadius = mRadius;
+   mProbeInfo.mBounds = bounds;
+   mProbeInfo.mExtents = getScale();
+   mProbeInfo.mRadius = mRadius;
 
-   mProbeInfo->mProbeRefOffset = mProbeRefOffset;
-   mProbeInfo->mProbeRefScale = mProbeRefScale;
+   mProbeInfo.mProbeRefOffset = mProbeRefOffset;
+   mProbeInfo.mProbeRefScale = mProbeRefScale;
 
-   mProbeInfo->mDirty = true;
+   mProbeInfo.mDirty = true;
 
    if (mCubemapDirty)
    {
@@ -587,108 +563,12 @@ void ReflectionProbe::updateProbeParams()
 
 void ReflectionProbe::processDynamicCubemap()
 {
-   /*if (!mProbeInfo)
-      return;
-
-   mEnabled = false;
-
-   if (mReflectionModeType == DynamicCubemap && !mDynamicCubemap.isNull())
-   {
-      mProbeInfo->mPrefilterCubemap = mDynamicCubemap;
-
-      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)
-      mProbeInfo->mIsEnabled = true;
-   else
-      mProbeInfo->mIsEnabled = false;
-
-   mCubemapDirty = false;
-
-   //Update the probe manager with our new texture!
-   //if (!mProbeInfo->mIsSkylight && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized())
-   //   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))+1;
-
-      //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()
 {
-   if (!mProbeInfo)
-      return;
-
-   mProbeInfo->mIsEnabled = false;
+   mProbeInfo.mIsEnabled = false;
 
    if ((mReflectionModeType != BakedCubemap) || mProbeUniqueID.isEmpty())
       return;
@@ -700,7 +580,7 @@ void ReflectionProbe::processBakedCubemap()
       mIrridianceMap->updateFaces();
    }
 
-   if (mIrridianceMap == nullptr || !mIrridianceMap->mCubemap->isInitialized())
+   if (mIrridianceMap == nullptr || mIrridianceMap->mCubemap.isNull())
    {
       Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str());
       return;
@@ -713,32 +593,33 @@ void ReflectionProbe::processBakedCubemap()
       mPrefilterMap->updateFaces();
    }
 
-   if (mPrefilterMap == nullptr || !mPrefilterMap->mCubemap->isInitialized())
+   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;
+   mProbeInfo.mPrefilterCubemap = mPrefilterMap->mCubemap;
+   mProbeInfo.mIrradianceCubemap = mIrridianceMap->mCubemap;
 
-   if (mEnabled && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized())
+   if (mEnabled && mProbeInfo.mPrefilterCubemap->isInitialized() && mProbeInfo.mIrradianceCubemap->isInitialized())
    {
-      mProbeInfo->mIsEnabled = true;
+      mProbeInfo.mIsEnabled = true;
 
       mCubemapDirty = false;
 
       //Update the probe manager with our new texture!
-      PROBEMGR->updateProbeTexture(mProbeInfo);
+      PROBEMGR->updateProbeTexture(&mProbeInfo);
+
+      //now, cleanup
+      mProbeInfo.mPrefilterCubemap.free();
+      mProbeInfo.mIrradianceCubemap.free();
    }
 }
 
 void ReflectionProbe::processStaticCubemap()
 {
-   if (!mProbeInfo)
-      return;
-
-   mProbeInfo->mIsEnabled = false;
+   mProbeInfo.mIsEnabled = false;
 
    String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
 
@@ -747,45 +628,31 @@ void ReflectionProbe::processStaticCubemap()
 
    if (Platform::isFile(irradFileName))
    {
-      if (mIrridianceMap == nullptr)
-      {
-         Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked irradiance map at %s", irradFileName);
-         return;
-      }
-
       mIrridianceMap->setCubemapFile(FileName(irradFileName));
-
-      if (mIrridianceMap->mCubemap.isNull())
-      {
-         Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked irradiance map at %s", irradFileName);
-         return;
-      }
-
       mIrridianceMap->updateFaces();
    }
 
+   if (mIrridianceMap == nullptr || mIrridianceMap->mCubemap.isNull())
+   {
+      Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked irradiance map at %s", irradFileName);
+      return;
+   }
+
    char prefilterFileName[256];
    dSprintf(prefilterFileName, 256, "%s%s_Prefilter.dds", path.c_str(), mCubemapName.c_str());
 
    if (Platform::isFile(prefilterFileName))
    {
-      if (mPrefilterMap == nullptr)
-      {
-         Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked prefilter map at %s", prefilterFileName);
-         return;
-      }
-
       mPrefilterMap->setCubemapFile(FileName(prefilterFileName));
-
-      if (mPrefilterMap->mCubemap.isNull())
-      {
-         Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked prefilter map at %s", prefilterFileName);
-         return;
-      }
-
       mPrefilterMap->updateFaces();
    }
 
+   if (mPrefilterMap == nullptr || mPrefilterMap->mCubemap.isNull())
+   {
+      Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked prefilter map at %s", prefilterFileName);
+      return;
+   }
+
    if (!Platform::isFile(prefilterFileName) || !Platform::isFile(irradFileName))
    {
       //If we are missing either of the files, just re-run the bake
@@ -823,34 +690,29 @@ void ReflectionProbe::processStaticCubemap()
       IBLUtilities::SaveCubeMap(prefilterFileName, mPrefilterMap->mCubemap);
    }
 
-   if ((mIrridianceMap != nullptr && !mIrridianceMap->mCubemap.isNull()) && (mPrefilterMap != nullptr && !mPrefilterMap->mCubemap.isNull()))
+   if ((mIrridianceMap != nullptr || !mIrridianceMap->mCubemap.isNull()) && (mPrefilterMap != nullptr || !mPrefilterMap->mCubemap.isNull()))
    {
-      mProbeInfo->mPrefilterCubemap = mPrefilterMap->mCubemap;
-      mProbeInfo->mIrradianceCubemap = mIrridianceMap->mCubemap;
+      mProbeInfo.mPrefilterCubemap = mPrefilterMap->mCubemap;
+      mProbeInfo.mIrradianceCubemap = mIrridianceMap->mCubemap;
    }
 
-   if (mEnabled && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized())
+   if (mEnabled && mProbeInfo.mPrefilterCubemap->isInitialized() && mProbeInfo.mIrradianceCubemap->isInitialized())
    {
-      mProbeInfo->mIsEnabled = true;
+      mProbeInfo.mIsEnabled = true;
 
       mCubemapDirty = false;
 
       //Update the probe manager with our new texture!
-      PROBEMGR->updateProbeTexture(mProbeInfo);
+      PROBEMGR->updateProbeTexture(&mProbeInfo);
    }
 }
 
 bool ReflectionProbe::createClientResources()
 {
-   if (mProbeInfo == nullptr)
-   {
-      mProbeInfo = PROBEMGR->registerProbe();
-      if (!mProbeInfo)
-         return false;
-
-      mProbeInfo->mIsEnabled = false;
-   }
+   PROBEMGR->registerProbe(&mProbeInfo);
 
+   mProbeInfo.mIsEnabled = false;
+   
    //irridiance resources
    if (!mIrridianceMap)
    {
@@ -909,12 +771,10 @@ String ReflectionProbe::getIrradianceMapPath()
 
 void ReflectionProbe::bake()
 {
-   bool writeFile = mReflectionModeType == BakedCubemap ? true : false;
-
-   if (mReflectionModeType == StaticCubemap)
+   if (mReflectionModeType != BakedCubemap)
       return;
 
-   PROBEMGR->bakeProbe(this, writeFile);
+   PROBEMGR->bakeProbe(this);
 
    setMaskBits(-1);
 }
@@ -922,8 +782,9 @@ void ReflectionProbe::bake()
 //-----------------------------------------------------------------------------
 //Rendering of editing/debug stuff
 //-----------------------------------------------------------------------------
-void ReflectionProbe::createGeometry()
+void ReflectionProbe::createEditorResources()
 {
+#ifdef TORQUE_TOOLS
    // Clean up our previous shape
    if (mEditorShapeInst)
       SAFE_DELETE(mEditorShapeInst);
@@ -938,6 +799,7 @@ void ReflectionProbe::createGeometry()
    {
       mEditorShapeInst = new TSShapeInstance(mEditorShape, isClientObject());
    }
+#endif
 }
 
 void ReflectionProbe::prepRenderImage(SceneRenderState *state)
@@ -951,16 +813,14 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
    //Culling distance. Can be adjusted for performance options considerations via the scalar
    if (dist > mMaxDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0))
    {
-      mProbeInfo->mScore = mMaxDrawDistance;
+      mProbeInfo.mScore = mMaxDrawDistance;
       return;
    }
 
    if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS))
    {
-      //bake();
+      bake();
       mDynamicLastBakeMS = Platform::getRealMilliseconds();
-
-      processDynamicCubemap();
    }
 
    //Submit our probe to actually do the probe action
@@ -968,20 +828,20 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
    //RenderPassManager *renderPass = state->getRenderPass();
 
    //Update our score based on our radius, distance
-   mProbeInfo->mScore = mProbeInfo->mRadius/mMax(dist,1.0f);
+   mProbeInfo.mScore = mMax(dist, 1.0f);
 
    Point3F vect = distVec;
    vect.normalizeSafe();
 
-   mProbeInfo->mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f);
+   //mProbeInfo.mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f);
 
-   //Register
-   //PROBEMGR->registerProbe(mProbeInfoIdx);
+   PROBEMGR->submitProbe(mProbeInfo);
 
+#ifdef TORQUE_TOOLS
    if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mPrefilterMap != nullptr)
    {
       if(!mEditorShapeInst)
-         createGeometry();
+         createEditorResources();
 
       GFXTransformSaver saver;
 
@@ -1039,7 +899,7 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
       saver.restore();
    }
 
-   // If the light is selected or light visualization
+   // If the probe is selected or probe visualization
    // is enabled then register the callback.
    const bool isSelectedInEditor = (gEditingMission && isSelected());
    if (isSelectedInEditor)
@@ -1049,6 +909,7 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
       ri->type = RenderPassManager::RIT_Editor;
       state->getRenderPass()->addInst(ri);
    }
+#endif
 }
 
 void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
@@ -1127,7 +988,7 @@ DefineEngineMethod(ReflectionProbe, postApply, void, (), ,
 }
 
 DefineEngineMethod(ReflectionProbe, Bake, void, (), ,
-   "@brief returns true if control object is inside the fog\n\n.")
+   "@brief Bakes the cubemaps for a reflection probe\n\n.")
 {
    ReflectionProbe *clientProbe = (ReflectionProbe*)object->getClientObject();
 

+ 92 - 19
Engine/source/T3D/lighting/reflectionProbe.h

@@ -63,6 +63,9 @@ class ReflectionProbe : public SceneObject
 
 public:
 
+   /// <summary>
+   /// Used to dictate what sort of cubemap the probes use when using IBL
+   /// </summary>
    enum ReflectionModeType
    {
       NoReflection = 0,
@@ -87,36 +90,84 @@ protected:
       NextFreeMask = Parent::NextFreeMask << 3
    };
 
-   bool mBake;
+   /// <summary>
+   /// Only used for interfacing with the editor's inspector bake button
+   /// </summary>
+   bool mBakeReflections;
+
+   /// <summary>
+   /// Whether this probe is enabled or not
+   /// </summary>
    bool mEnabled;
+   
    bool mDirty;
+
+   /// <summary>
+   /// Whether this probe's cubemap is dirty or not
+   /// </summary>
    bool mCubemapDirty;
 
+#ifdef TORQUE_TOOLS
+   /// <summary>
+   /// Used only when the editor is loaded, this is the shape data used for the probe viewing(aka, a sphere)
+   /// </summary>
    Resource<TSShape> mEditorShape;
+   /// <summary>
+   /// This is the shape instance of the editor shape data
+   /// </summary>
    TSShapeInstance* mEditorShapeInst;
+#endif // TORQUE_TOOLS
 
    //--------------------------------------------------------------------------
    // Rendering variables
    //--------------------------------------------------------------------------
+   /// <summary>
+   /// The shape of the probe
+   /// </summary>
    ProbeRenderInst::ProbeShapeType mProbeShapeType;
 
-   ProbeRenderInst* mProbeInfo;
-
-   //Reflection Contribution stuff
+   /// <summary>
+   /// This is effectively a packed cache of the probe data actually utilized for rendering.
+   /// The RenderProbeManager uses this via the probe calling registerProbe on creation, and unregisterProbe on destruction
+   /// When the manager goes to render it has the compacted data to read over more efficiently for setting up what probes should
+   /// Actually render in that frame
+   /// </summary>
+   ProbeRenderInst mProbeInfo;
+
+   /// <summary>
+   /// Used to dictate what sort of cubemap the probes use when using IBL
+   /// </summary>
    ReflectionModeType mReflectionModeType;
 
+   /// <summary>
+   /// The radius of the probe's influence. Only really relevent in Sphere probes
+   /// </summary>
    F32 mRadius;
+   /// <summary>
+   /// The reference positional offset for the probe. This is used for adjusting the perceived center and area of influence.
+   /// Helpful in adjusting parallax issues
+   /// </summary>
    Point3F mProbeRefOffset;
+   /// <summary>
+   /// The reference scale for the probe. This is used for adjusting the perceived center and area of influence.
+   /// Helpful in adjusting parallax issues
+   /// </summary>
    Point3F mProbeRefScale;
+
+   /// <summary>
+   /// Only used for interfacing with the editor's inspector edit offset button
+   /// </summary>
    bool mEditPosOffset;
 
+   /// <summary>
+   /// This is used when a static cubemap is used. The name of the cubemap is looked up and loaded for the IBL calculations
+   /// </summary>
    String mCubemapName;
    CubemapData *mStaticCubemap;
    GFXCubemapHandle  mDynamicCubemap;
 
    String cubeDescName;
    U32 cubeDescId;
-   CubeReflector mCubeReflector;
    ReflectorDesc *reflectorDesc;
 
    //Utilized in dynamic reflections
@@ -133,19 +184,12 @@ protected:
    U32 mPrefilterMipLevels;
    U32 mPrefilterSize;
 
+   /// <summary>
+   /// This is calculated based on the object's persistantID. Effectively a unique hash ID to set it apart from other probes
+   /// Used to ensure the cubemaps named when baking are unique
+   /// </summary>
    String mProbeUniqueID;
 
-   // Define our vertex format here so we don't have to
-   // change it in multiple spots later
-   typedef GFXVertexPNTTB VertexType;
-
-   // The GFX vertex and primitive buffers
-   GFXVertexBufferHandle< VertexType > mVertexBuffer;
-   GFXPrimitiveBufferHandle            mPrimitiveBuffer;
-
-   U32 mSphereVertCount;
-   U32 mSpherePrimitiveCount;
-
    //Debug rendering
    static bool smRenderPreviewProbes;
 
@@ -188,6 +232,10 @@ public:
    bool onAdd();
    void onRemove();
 
+   /// <summary>
+   /// This is called when the object is deleted. It allows us to do special-case cleanup actions
+   /// In probes' case, it's used to delete baked cubemap files
+   /// </summary>
    virtual void handleDeleteAction();
 
    // Override this so that we can dirty the network flag when it is called
@@ -215,14 +263,26 @@ public:
    //--------------------------------------------------------------------------
 
    // Create the geometry for rendering
-   void createGeometry();
+   void createEditorResources();
 
+   /// <summary>
+   /// Updates the probe rendering data
+   /// </summary>
    virtual void updateProbeParams();
-
+   
    bool createClientResources();
 
+   /// <summary>
+   /// Updates the probe's cubemaps in the array when using dynamic reflections
+   /// </summary>
    void processDynamicCubemap();
+   /// <summary>
+   /// Updates the probe's cubemaps in the array when using baked cubemaps
+   /// </summary>
    void processBakedCubemap();
+   /// <summary>
+   /// Updates the probe's cubemaps in the array when using a static cubemaps
+   /// </summary>
    void processStaticCubemap();
 
    // This is the function that allows this object to submit itself for rendering
@@ -234,9 +294,22 @@ public:
 
    void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
 
-   //Baking
+   /// <summary>
+   /// This gets the filepath to the prefilter cubemap associated to this probe.
+   /// In the event the probe is set to use a static cubemap, it is the prefiltered version of the cubemap's file
+   /// </summary>
+   /// <returns>The filepath to the prefilter cubemap</returns>
    String getPrefilterMapPath();
+   /// <summary>
+   /// This gets the filepath to the irradiance cubemap associated to this probe.
+   /// In the event the probe is set to use a static cubemap, it is the irradiance version of the cubemap's file
+   /// </summary>
+   /// <returns>The filepath to the irradiance cubemap</returns>
    String getIrradianceMapPath();
+
+   /// <summary>
+   /// Invokes a cubemap bake action for this probe
+   /// </summary>
    void bake();
 };
 

+ 10 - 14
Engine/source/T3D/lighting/skylight.cpp

@@ -135,6 +135,11 @@ void Skylight::unpackUpdate(NetConnection *conn, BitStream *stream)
 {
    // Let the Parent read any info it sent
    Parent::unpackUpdate(conn, stream);
+
+   if (mDirty)
+   {
+      updateProbeParams();
+   }
 }
 
 //-----------------------------------------------------------------------------
@@ -143,9 +148,6 @@ void Skylight::unpackUpdate(NetConnection *conn, BitStream *stream)
 
 void Skylight::updateProbeParams()
 {
-   if (!mProbeInfo)
-      return;
-
    mProbeShapeType = ProbeRenderInst::Skylight;
    Parent::updateProbeParams();
 }
@@ -157,24 +159,17 @@ void Skylight::prepRenderImage(SceneRenderState *state)
 
    //special hook-in for skylights
    Point3F camPos = state->getCameraPosition();
-   mProbeInfo->mBounds.setCenter(camPos);
+   mProbeInfo.mBounds.setCenter(camPos);
 
-   mProbeInfo->setPosition(camPos);
-
-   if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS))
-   {
-      //bake();
-      mDynamicLastBakeMS = Platform::getRealMilliseconds();
-
-      processDynamicCubemap();
-   }
+   mProbeInfo.setPosition(camPos);
 
    //Submit our probe to actually do the probe action
    // Get a handy pointer to our RenderPassmanager
    //RenderPassManager *renderPass = state->getRenderPass();
 
-   //PROBEMGR->registerSkylight(mProbeInfo, this);
+   PROBEMGR->submitProbe(mProbeInfo);
 
+#ifdef TORQUE_TOOLS
    if (Skylight::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
    {
       GFXTransformSaver saver;
@@ -235,6 +230,7 @@ void Skylight::prepRenderImage(SceneRenderState *state)
    if (isSelectedInEditor)
    {
    }
+#endif
 }
 
 void Skylight::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)

+ 7 - 3
Engine/source/T3D/lighting/sphereEnvironmentProbe.cpp

@@ -131,6 +131,11 @@ void SphereEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream
 {
    // Let the Parent read any info it sent
    Parent::unpackUpdate(conn, stream);
+
+   if (mDirty)
+   {
+      updateProbeParams();
+   }
 }
 
 //-----------------------------------------------------------------------------
@@ -139,9 +144,6 @@ void SphereEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream
 
 void SphereEnvironmentProbe::updateProbeParams()
 {
-   if (!mProbeInfo)
-      return;
-
    mProbeShapeType = ProbeRenderInst::Sphere;
    Parent::updateProbeParams();
 }
@@ -151,6 +153,7 @@ void SphereEnvironmentProbe::prepRenderImage(SceneRenderState *state)
    if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
       return;
 
+#ifdef TORQUE_TOOLS
    if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
    {
       GFXTransformSaver saver;
@@ -215,6 +218,7 @@ void SphereEnvironmentProbe::prepRenderImage(SceneRenderState *state)
       ri->type = RenderPassManager::RIT_Editor;
       state->getRenderPass()->addInst(ri);
    }
+#endif
 }
 
 void SphereEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)

+ 1 - 1
Engine/source/console/simSet.h

@@ -332,7 +332,7 @@ void SimSet::findObjectByType( Vector<T*> &foundObjects )
       curSet = dynamic_cast<SimSet*>( *itr );
 
       // If child object is a set, call recursively into it.
-      if ( curSet )
+      if ( curSet && curSet->size() != 0)
          curSet->findObjectByType( foundObjects ); 
 
       // Add this child object if appropriate.

+ 173 - 228
Engine/source/renderInstance/renderProbeMgr.cpp

@@ -45,6 +45,8 @@
 //For our cameraQuery setup
 #include "T3D/gameTSCtrl.h"
 
+#include "T3D/Scene.h"
+
 #define TORQUE_GFX_VISUAL_DEBUG //renderdoc debugging
 
 IMPLEMENT_CONOBJECT(RenderProbeMgr);
@@ -59,6 +61,8 @@ ConsoleDocClass( RenderProbeMgr,
 RenderProbeMgr *RenderProbeMgr::smProbeManager = NULL;
 
 bool RenderProbeMgr::smRenderReflectionProbes = true;
+F32 RenderProbeMgr::smMaxProbeDrawDistance = 100;
+S32 RenderProbeMgr::smMaxProbesPerFrame = 8;
 
 S32 QSORT_CALLBACK AscendingReflectProbeInfluence(const void* a, const void* b)
 {
@@ -87,7 +91,6 @@ ProbeRenderInst::ProbeRenderInst() :
    mProbeRefScale(1,1,1),
    mAtten(0.0),
    mCubemapIndex(0),
-   mIsSkylight(false),
    mProbeIdx(0),
    mProbeShapeType(Box)
 {
@@ -113,7 +116,6 @@ void ProbeRenderInst::set(const ProbeRenderInst *probeInfo)
    mRadius = probeInfo->mRadius;
    mProbeShapeType = probeInfo->mProbeShapeType;
    mBounds = probeInfo->mBounds;
-   mIsSkylight = probeInfo->mIsSkylight;
    mScore = probeInfo->mScore;
    mAtten = probeInfo->mAtten;
 }
@@ -125,8 +127,7 @@ ProbeShaderConstants::ProbeShaderConstants()
    mShader(NULL),
    mProbePositionSC(NULL),
    mProbeRefPosSC(NULL),
-   mRefBoxMinSC(NULL),
-   mRefBoxMaxSC(NULL),
+   mRefScaleSC(NULL),
    mProbeConfigDataSC(NULL),
    mProbeSpecularCubemapSC(NULL),
    mProbeIrradianceCubemapSC(NULL),
@@ -160,8 +161,7 @@ void ProbeShaderConstants::init(GFXShader* shader)
    //Reflection Probes
    mProbePositionSC = shader->getShaderConstHandle(ShaderGenVars::probePosition);
    mProbeRefPosSC = shader->getShaderConstHandle(ShaderGenVars::probeRefPos);
-   mRefBoxMinSC = shader->getShaderConstHandle(ShaderGenVars::refBoxMin);
-   mRefBoxMaxSC = shader->getShaderConstHandle(ShaderGenVars::refBoxMax);
+   mRefScaleSC = shader->getShaderConstHandle(ShaderGenVars::refScale);
    mWorldToObjArraySC = shader->getShaderConstHandle(ShaderGenVars::worldToObjArray);
    mProbeConfigDataSC = shader->getShaderConstHandle(ShaderGenVars::probeConfigData);
    mProbeSpecularCubemapSC = shader->getShaderConstHandle(ShaderGenVars::specularCubemapAR);
@@ -179,8 +179,7 @@ bool ProbeShaderConstants::isValid()
 {
    if (mProbePositionSC->isValid() ||
       mProbeConfigDataSC->isValid() ||
-      mRefBoxMinSC->isValid() ||
-      mRefBoxMaxSC->isValid() ||
+      mRefScaleSC->isValid() ||
       mProbeSpecularCubemapSC->isValid() ||
       mProbeIrradianceCubemapSC->isValid())
       return true;
@@ -204,8 +203,7 @@ RenderProbeMgr::RenderProbeMgr()
    mHasSkylight(false),
    mSkylightCubemapIdx(-1),
    mCubeMapCount(0),
-   mDefaultSkyLight(nullptr),
-   mBakeRenderTarget(nullptr)
+   mDefaultSkyLight(nullptr)
 {
    mEffectiveProbeCount = 0;
    mMipCount = 0;
@@ -221,6 +219,9 @@ RenderProbeMgr::RenderProbeMgr()
    {
       mCubeMapSlots[i] = false;
    }
+
+   mPrefilterSize = 64;
+   mPrefilterMipLevels = mLog2(F32(mPrefilterSize)) + 1;
 }
 
 RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
@@ -236,6 +237,10 @@ RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 proce
    mLastConstants = nullptr;
    mMipCount = 0;
    mProbesDirty = false;
+   mUseHDRCaptures = true;
+
+   mPrefilterSize = 64;
+   mPrefilterMipLevels = mLog2(F32(mPrefilterSize)) + 1;
 }
 
 RenderProbeMgr::~RenderProbeMgr()
@@ -303,35 +308,22 @@ void RenderProbeMgr::initPersistFields()
    Parent::initPersistFields();
 }
 
-void RenderProbeMgr::addElement(RenderInst *inst)
+void RenderProbeMgr::consoleInit()
 {
-   // If this instance is translucent handle it in RenderTranslucentMgr
-   //if (inst->translucentSort)
-      return;
+   Parent::consoleInit();
 
-   //AssertFatal(inst->defaultKey != 0, "RenderMeshMgr::addElement() - Got null sort key... did you forget to set it?");
-
-   /*internalAddElement(inst);
-
-   ProbeRenderInst* probeInst = static_cast<ProbeRenderInst*>(inst);
-
-   if (probeInst->mIsSkylight)
-   {
-      addSkylightProbe(probeInst);
-   }
-   else
-   {
-      if (probeInst->mProbeShapeType == ProbeInfo::Sphere)
-         addSphereReflectionProbe(probeInst);
-      else
-         addConvexReflectionProbe(probeInst);
-   }*/
+   // Vars for debug rendering while the RoadEditor is open, only used if smEditorOpen is true.
+   Con::addVariable("$pref::maxProbeDrawDistance", TypeF32, &RenderProbeMgr::smMaxProbeDrawDistance, "Max distance for reflection probes to render.\n");
+   Con::addVariable("$pref::MaxProbesPerFrame", TypeS32, &RenderProbeMgr::smMaxProbesPerFrame, "Max number of Environment Probes that can be rendered per-frame.\n");
 }
 
-ProbeRenderInst* RenderProbeMgr::registerProbe()
+void RenderProbeMgr::registerProbe(ProbeRenderInst* newProbe)
 {
-   mRegisteredProbes.increment();
-   ProbeRenderInst* newProbe = &mRegisteredProbes.last();
+   //Can't have over the probe limit
+   if (mRegisteredProbes.size() + 1 >= PROBE_MAX_COUNT)
+      return;
+
+   mRegisteredProbes.push_back(newProbe);
 
    newProbe->mProbeIdx = mRegisteredProbes.size() - 1;
 
@@ -339,7 +331,7 @@ ProbeRenderInst* RenderProbeMgr::registerProbe()
    if (cubeIndex == INVALID_CUBE_SLOT)
    {
       Con::warnf("RenderProbeMgr::addProbe: Invalid cubemap slot.");
-      return nullptr;
+      return;
    }
 
    //check if we need to resize the cubemap array
@@ -372,8 +364,6 @@ ProbeRenderInst* RenderProbeMgr::registerProbe()
 #endif
 
    mProbesDirty = true;
-
-   return newProbe;
 }
 
 void RenderProbeMgr::unregisterProbe(U32 probeIdx)
@@ -382,11 +372,11 @@ void RenderProbeMgr::unregisterProbe(U32 probeIdx)
    if (probeIdx >= mRegisteredProbes.size())
       return;
 
-   if (mRegisteredProbes[probeIdx].mCubemapIndex == INVALID_CUBE_SLOT)
+   if (mRegisteredProbes[probeIdx]->mCubemapIndex == INVALID_CUBE_SLOT)
       return;
 
    //mark cubemap slot as available now
-   mCubeMapSlots[mRegisteredProbes[probeIdx].mCubemapIndex] = false;
+   mCubeMapSlots[mRegisteredProbes[probeIdx]->mCubemapIndex] = false;
    mCubeMapCount--;
 
    mRegisteredProbes.erase(probeIdx);
@@ -394,13 +384,18 @@ void RenderProbeMgr::unregisterProbe(U32 probeIdx)
    //recalculate all the probe's indicies just to be sure
    for (U32 i = 0; i < mRegisteredProbes.size(); i++)
    {
-      mRegisteredProbes[i].mProbeIdx = i;
+      mRegisteredProbes[i]->mProbeIdx = i;
    }
 
    //rebuild our probe data
    mProbesDirty = true;
 }
 
+void RenderProbeMgr::submitProbe(const ProbeRenderInst& newProbe)
+{
+   mActiveProbes.push_back(newProbe);
+}
+
 //
 //
 PostEffect* RenderProbeMgr::getProbeArrayEffect()
@@ -425,75 +420,6 @@ void RenderProbeMgr::updateProbes()
 	mProbesDirty = true;
 }
 
-void RenderProbeMgr::_setupStaticParameters()
-{
-   //Array rendering
-   U32 probeCount = mRegisteredProbes.size();
-
-   mEffectiveProbeCount = 0;
-   mMipCount = 1;
-
-   mHasSkylight = false;
-   mSkylightCubemapIdx = -1;
-
-   if (probePositionsData.size() != MAXPROBECOUNT)
-   {
-      probePositionsData.setSize(MAXPROBECOUNT);
-      probeRefPositionsData.setSize(MAXPROBECOUNT);
-      probeWorldToObjData.setSize(MAXPROBECOUNT);
-      refBoxMinData.setSize(MAXPROBECOUNT);
-      refBoxMaxData.setSize(MAXPROBECOUNT);
-      probeConfigData.setSize(MAXPROBECOUNT);
-   }
-
-   probePositionsData.fill(Point4F::Zero);
-   probeRefPositionsData.fill(Point4F::Zero);
-   probeWorldToObjData.fill(MatrixF::Identity);
-   refBoxMinData.fill(Point4F::Zero);
-   refBoxMaxData.fill(Point4F::Zero);
-   probeConfigData.fill(Point4F(-1,0,0,0));
-
-   for (U32 i = 0; i < probeCount; i++)
-   {
-      if (mEffectiveProbeCount >= MAXPROBECOUNT)
-         break;
-
-      const ProbeRenderInst& curEntry = mRegisteredProbes[i];
-      if (!curEntry.mIsEnabled)
-         continue;
-
-      U32 mips = mRegisteredProbes[i].mPrefilterCubemap.getPointer()->getMipMapLevels();
-      mMipCount = (mips != 0 && mips >= mMipCount) ? mips : 0;
-
-      if (curEntry.mIsSkylight)
-      {
-         mSkylightCubemapIdx = curEntry.mCubemapIndex;
-         continue;
-      }
-
-      //Setup
-      Point3F probePos = curEntry.getPosition();
-      Point3F refPos = curEntry.getPosition() +curEntry.mProbeRefOffset;
-      probePositionsData[mEffectiveProbeCount] = Point4F(probePos.x, probePos.y, probePos.z,0);
-      probeRefPositionsData[mEffectiveProbeCount] = Point4F(refPos.x, refPos.y, refPos.z, 0);
-
-      probeWorldToObjData[mEffectiveProbeCount] = curEntry.getTransform();
-      Point3F bbMin = refPos - curEntry.mProbeRefScale/2 * curEntry.getTransform().getScale();
-      Point3F bbMax = refPos + curEntry.mProbeRefScale/2 * curEntry.getTransform().getScale();
-      refBoxMinData[mEffectiveProbeCount] = Point4F(bbMin.x, bbMin.y, bbMin.z, 0);
-      refBoxMaxData[mEffectiveProbeCount] = Point4F(bbMax.x, bbMax.y, bbMax.z, 0);
-
-      probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType, 
-         curEntry.mRadius,
-         curEntry.mAtten,
-         curEntry.mCubemapIndex);
-
-      mEffectiveProbeCount++;
-   }
-
-   mProbesDirty = false;
-}
-
 void RenderProbeMgr::updateProbeTexture(ProbeRenderInst* probeInfo)
 {
    if (probeInfo->mIrradianceCubemap.isNull() || !probeInfo->mIrradianceCubemap->isInitialized())
@@ -523,7 +449,7 @@ void RenderProbeMgr::reloadTextures()
    U32 probeCount = mRegisteredProbes.size();
    for (U32 i = 0; i < probeCount; i++)
    {
-      updateProbeTexture(&mRegisteredProbes[i]);
+      updateProbeTexture(mRegisteredProbes[i]);
    }
 
    mProbesDirty = true;
@@ -532,6 +458,10 @@ void RenderProbeMgr::reloadTextures()
 void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
 {
    PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
+
+   mProbeData = ProbeDataSet(smMaxProbesPerFrame);
+
+   getBestProbes(state->getCameraPosition(), &mProbeData);
 }
 
 ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuffer* buffer)
@@ -579,6 +509,12 @@ ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuff
    return mLastConstants;
 }
 
+void RenderProbeMgr::setupSGData(SceneData& data, const SceneRenderState* state, LightInfo* light)
+{
+   //ensure they're sorted for forward rendering
+   mActiveProbes.sort(_probeScoreCmp);
+}
+
 void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
    MatrixSet &matSet,
    ProbeShaderConstants *probeShaderConsts,
@@ -586,10 +522,8 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
 {
    PROFILE_SCOPE(ProbeManager_Update4ProbeConsts);
 
-   return;
-
    // Skip over gathering lights if we don't have to!
-   //if (probeShaderConsts->isValid())
+   if (probeShaderConsts->isValid())
    {
       PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
 
@@ -600,17 +534,29 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
 
       getBestProbes(sgData.objTrans->getPosition(), &probeSet);
 
+      static AlignedArray<Point4F> probePositionAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
+      static AlignedArray<Point4F> refScaleAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
+      static AlignedArray<Point4F> probeRefPositionAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
+      static AlignedArray<Point4F> probeConfigAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
+
+      for (U32 i = 0; i < probeSet.maxProbeCount; i++)
+      {
+         probePositionAlignedArray[i] = probeSet.probePositionArray[i];
+         probeRefPositionAlignedArray[i] = probeSet.probeRefPositionArray[i];
+         refScaleAlignedArray[i] = probeSet.refScaleArray[i];
+         probeConfigAlignedArray[i] = probeSet.probeConfigArray[i];
+      }
+
       shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (S32)probeSet.effectiveProbeCount);
 
-      shaderConsts->setSafe(probeShaderConsts->mProbePositionSC, probeSet.probePositionArray);
-      shaderConsts->setSafe(probeShaderConsts->mProbeRefPosSC, probeSet.probeRefPositionArray);
+      shaderConsts->setSafe(probeShaderConsts->mProbePositionSC, probePositionAlignedArray);
+      shaderConsts->setSafe(probeShaderConsts->mProbeRefPosSC, probeRefPositionAlignedArray);
 
       if(probeShaderConsts->isValid())
          shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeSet.probeWorldToObjArray.address(), probeSet.effectiveProbeCount, GFXSCT_Float4x4);
 
-      shaderConsts->setSafe(probeShaderConsts->mRefBoxMinSC, probeSet.refBoxMinArray);
-      shaderConsts->setSafe(probeShaderConsts->mRefBoxMaxSC, probeSet.refBoxMaxArray);
-      shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataSC, probeSet.probeConfigArray);
+      shaderConsts->setSafe(probeShaderConsts->mRefScaleSC, refScaleAlignedArray);
+      shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataSC, probeConfigAlignedArray);
 
       shaderConsts->setSafe(probeShaderConsts->mSkylightCubemapIdxSC, (float)probeSet.skyLightIdx);
 
@@ -624,80 +570,70 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
    }
 }
 
+S32 QSORT_CALLBACK RenderProbeMgr::_probeScoreCmp(const ProbeRenderInst* a, const  ProbeRenderInst* b)
+{
+   F32 diff = a->getScore() - b->getScore();
+   return diff > 0 ? 1 : diff < 0 ? -1 : 0;
+}
+
 void RenderProbeMgr::getBestProbes(const Point3F& objPosition, ProbeDataSet* probeDataSet)
 {
    PROFILE_SCOPE(ProbeManager_getBestProbes);
 
-   // Skip over gathering lights if we don't have to!
-   //if (probeShaderConsts->isValid())
-   {
-      //Array rendering
-      U32 probeCount = mRegisteredProbes.size();
-
-      Vector<S8> bestPickProbes;
-
-      probeDataSet->effectiveProbeCount = 0;
-      for (U32 i = 0; i < probeCount; i++)
-      {
-         const ProbeRenderInst& curEntry = mRegisteredProbes[i];
-         if (!curEntry.mIsEnabled)
-            continue;
-
-         if (!curEntry.mIsSkylight)
-         {
-            F32 dist = Point3F(objPosition - curEntry.getPosition()).len();
+   //Array rendering
+   U32 probeCount = mActiveProbes.size();
 
-            if (dist > curEntry.mRadius || dist > curEntry.mExtents.len())
-               continue;
+   Vector<S8> bestPickProbes;
+   bestPickProbes.setSize(probeDataSet->maxProbeCount);
+   bestPickProbes.fill(-1);
 
-            S32 bestPickIndex = -1;
-            for (U32 p = 0; p < bestPickProbes.size(); p++)
-            {
-               if (p > probeDataSet->MAX_PROBE_COUNT)
-                  break;
+   probeDataSet->effectiveProbeCount = 0;
+   for (U32 i = 0; i < probeCount; i++)
+   {
+      if (probeDataSet->skyLightIdx != -1 && probeDataSet->effectiveProbeCount >= probeDataSet->maxProbeCount)
+         break;
 
-               if (bestPickProbes[p] == -1 || (Point3F(objPosition - mRegisteredProbes[bestPickProbes[p]].mPosition).len() > dist))
-                  bestPickIndex = p;
-            }
+      const ProbeRenderInst& curEntry = mActiveProbes[i];
+      if (!curEntry.mIsEnabled)
+         continue;
 
-            //Can't have over our max count. Otherwise, if we haven't found a good slot for our best pick, insert it
-            //if we have a best pick slot, update it
-            if (bestPickIndex == -1 || bestPickProbes.size() >= probeDataSet->MAX_PROBE_COUNT)
-               bestPickProbes.push_back(i);
-            else
-               bestPickProbes[bestPickIndex] = i;
-         }
-         else
+      if (curEntry.mProbeShapeType != ProbeRenderInst::Skylight)
+      {
+         if (probeDataSet->effectiveProbeCount < probeDataSet->maxProbeCount)
          {
-            probeDataSet->skyLightIdx = curEntry.mCubemapIndex;
+            bestPickProbes[probeDataSet->effectiveProbeCount] = i;
+            probeDataSet->effectiveProbeCount++;
          }
       }
-
-      //Grab our best probe picks
-      for (U32 i = 0; i < bestPickProbes.size(); i++)
+      else
       {
-         if (bestPickProbes[i] == -1)
-            continue;
+         probeDataSet->skyLightIdx = curEntry.mCubemapIndex;
+      }
+   }
+
+   //Grab our best probe picks
+   for (U32 i = 0; i < bestPickProbes.size(); i++)
+   {
+      if (bestPickProbes[i] == -1)
+         continue;
 
-         const ProbeRenderInst& curEntry = mRegisteredProbes[bestPickProbes[i]];
+      const ProbeRenderInst& curEntry = mActiveProbes[bestPickProbes[i]];
 
-         probeDataSet->probePositionArray[probeDataSet->effectiveProbeCount] = curEntry.getPosition();
-         probeDataSet->probeRefPositionArray[probeDataSet->effectiveProbeCount] = curEntry.mProbeRefOffset;
-         probeDataSet->probeWorldToObjArray[probeDataSet->effectiveProbeCount] = curEntry.getTransform();
+      MatrixF p2A = curEntry.getTransform();
+      p2A.inverse();
+      probeDataSet->refScaleArray[i] = curEntry.mProbeRefScale / p2A.getScale();
 
-         Point3F refPos = curEntry.getPosition() + curEntry.mProbeRefOffset;
-         Point3F refBoxMin = refPos - curEntry.mProbeRefScale * curEntry.getTransform().getScale();
-         Point3F refBoxMax = refPos + curEntry.mProbeRefScale * curEntry.getTransform().getScale();
+      Point3F probePos = curEntry.getPosition();
+      Point3F refPos = probePos + curEntry.mProbeRefOffset * probeDataSet->refScaleArray[i].asPoint3F();
+      probeDataSet->probeWorldToObjArray[i] = curEntry.getTransform();
 
-         probeDataSet->refBoxMinArray[probeDataSet->effectiveProbeCount] = Point4F(refBoxMin.x, refBoxMin.y, refBoxMin.z, 0);
-         probeDataSet->refBoxMaxArray[probeDataSet->effectiveProbeCount] = Point4F(refBoxMax.x, refBoxMax.y, refBoxMax.z, 0);
-         probeDataSet->probeConfigArray[probeDataSet->effectiveProbeCount] = Point4F(curEntry.mProbeShapeType,
-            curEntry.mRadius,
-            curEntry.mAtten,
-            curEntry.mCubemapIndex);
+      probeDataSet->probePositionArray[i] = Point4F(probePos.x, probePos.y, probePos.z, 0);
+      probeDataSet->probeRefPositionArray[i] = Point4F(refPos.x, refPos.y, refPos.z, 0);
 
-         probeDataSet->effectiveProbeCount++;
-      }
+      probeDataSet->probeConfigArray[i] = Point4F(curEntry.mProbeShapeType,
+         curEntry.mRadius,
+         curEntry.mAtten,
+         curEntry.mCubemapIndex);
    }
 }
 
@@ -720,9 +656,6 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
    if (sgData.binType == SceneData::DeferredBin)
       return;
 
-   // if (mRegisteredProbes.empty())
-   //    return;
-
    PROFILE_SCOPE(ProbeManager_setProbeInfo);
 
    ProbeShaderConstants *psc = getProbeShaderConstants(shaderConsts);
@@ -747,26 +680,29 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
 void RenderProbeMgr::render( SceneRenderState *state )
 {
    if (getProbeArrayEffect() == nullptr)
+   {
+      mActiveProbes.clear();
       return;
+   }
+
+   GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE);
+
+   //Sort the active probes
+   mActiveProbes.sort(_probeScoreCmp);
 
-   if (mProbesDirty)
-	   _setupStaticParameters();
+   // Initialize and set the per-frame data
+   _setupPerFrameParameters(state);
 
    // Early out if nothing to draw.
-   if (!RenderProbeMgr::smRenderReflectionProbes || (!state->isDiffusePass() && !state->isReflectPass()) || (mEffectiveProbeCount == 0 && mSkylightCubemapIdx == -1))
+   if (!RenderProbeMgr::smRenderReflectionProbes || (!state->isDiffusePass() && !state->isReflectPass()) || (mProbeData.effectiveProbeCount == 0 && mProbeData.skyLightIdx == -1))
    {
       getProbeArrayEffect()->setSkip(true);
+      mActiveProbes.clear();
       return;
    }
 
    GFXTransformSaver saver;
 
-   GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE);
-
-   // Initialize and set the per-frame parameters after getting
-   // the vector light material as we use lazy creation.
-   //_setupPerFrameParameters(state);
-
    //Visualization
    String useDebugAtten = Con::getVariable("$Probes::showAttenuation", "0");
    mProbeArrayEffect->setShaderMacro("DEBUGVIZ_ATTENUATION", useDebugAtten);
@@ -780,11 +716,14 @@ void RenderProbeMgr::render( SceneRenderState *state )
    String useDebugContrib = Con::getVariable("$Probes::showProbeContrib", "0");
    mProbeArrayEffect->setShaderMacro("DEBUGVIZ_CONTRIB", useDebugContrib);
 
-   if(mSkylightCubemapIdx != -1 && mEffectiveProbeCount == 0)
+   if(mProbeData.skyLightIdx != -1 && mProbeData.effectiveProbeCount == 0)
       mProbeArrayEffect->setShaderMacro("SKYLIGHT_ONLY", "1");
    else
       mProbeArrayEffect->setShaderMacro("SKYLIGHT_ONLY", "0");
 
+   String probePerFrame = Con::getVariable("$pref::MaxProbesPerFrame", "8");
+   mProbeArrayEffect->setShaderMacro("MAX_PROBES", probePerFrame);
+
    //ssao mask
    if (AdvancedLightBinManager::smUseSSAOMask)
    {
@@ -795,7 +734,6 @@ void RenderProbeMgr::render( SceneRenderState *state )
       {
          mProbeArrayEffect->setShaderMacro("USE_SSAO_MASK");
          mProbeArrayEffect->setTexture(6, pTexObj);
-         
       }
    }
    else
@@ -807,24 +745,24 @@ void RenderProbeMgr::render( SceneRenderState *state )
    mProbeArrayEffect->setCubemapArrayTexture(4, mPrefilterArray);
    mProbeArrayEffect->setCubemapArrayTexture(5, mIrradianceArray);
 
-   mProbeArrayEffect->setShaderConst("$numProbes", (S32)mEffectiveProbeCount);
-   mProbeArrayEffect->setShaderConst("$skylightCubemapIdx", (S32)mSkylightCubemapIdx);
+   mProbeArrayEffect->setShaderConst("$numProbes", (S32)mProbeData.effectiveProbeCount);
+   mProbeArrayEffect->setShaderConst("$skylightCubemapIdx", (S32)mProbeData.skyLightIdx);
 
    mProbeArrayEffect->setShaderConst("$cubeMips", (float)mMipCount);
 
    //also set up some colors
    Vector<Point4F> contribColors;
 
-   contribColors.setSize(MAXPROBECOUNT);
+   contribColors.setSize(mProbeData.effectiveProbeCount);
 
-   if (mEffectiveProbeCount != 0)
+   if (mProbeData.effectiveProbeCount != 0)
    {
       if (useDebugContrib == String("1"))
       {
          MRandomLCG RandomGen;
-         RandomGen.setSeed(mEffectiveProbeCount);
+         RandomGen.setSeed(mProbeData.effectiveProbeCount);
 
-         for (U32 i = 0; i < mEffectiveProbeCount; i++)
+         for (U32 i = 0; i < mProbeData.effectiveProbeCount; i++)
          {
             //we're going to cheat here a little for consistent debugging behavior. The first 3 probes will always have R G and then B for their colors, every other will be random
             if (i == 0)
@@ -841,20 +779,19 @@ void RenderProbeMgr::render( SceneRenderState *state )
 
    mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
 
-   mProbeArrayEffect->setShaderConst("$inProbePosArray", probePositionsData);
-   mProbeArrayEffect->setShaderConst("$inRefPosArray", probeRefPositionsData);
-   mProbeArrayEffect->setShaderConst("$worldToObjArray", probeWorldToObjData);
-   mProbeArrayEffect->setShaderConst("$refBoxMinArray", refBoxMinData);
-   mProbeArrayEffect->setShaderConst("$refBoxMaxArray", refBoxMaxData);
-   mProbeArrayEffect->setShaderConst("$probeConfigData", probeConfigData);
+   mProbeArrayEffect->setShaderConst("$inProbePosArray", mProbeData.probePositionArray);
+   mProbeArrayEffect->setShaderConst("$inRefPosArray", mProbeData.probeRefPositionArray);
+   mProbeArrayEffect->setShaderConst("$worldToObjArray", mProbeData.probeWorldToObjArray);
+   mProbeArrayEffect->setShaderConst("$refScaleArray", mProbeData.refScaleArray);
+   mProbeArrayEffect->setShaderConst("$probeConfigData", mProbeData.probeConfigArray);
 
    // Make sure the effect is gonna render.
    getProbeArrayEffect()->setSkip(false);
 
-   //PROFILE_END();
+   mActiveProbes.clear();
 }
 
-void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
+void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
 {
    GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
 
@@ -863,15 +800,15 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
 
    String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
    U32 resolution = Con::getIntVariable("$pref::ReflectionProbes::BakeResolution", 64);
-   U32 prefilterMipLevels = mLog2(F32(resolution))+1;
+   U32 prefilterMipLevels = mLog2(F32(resolution)) + 1;
    bool renderWithProbes = Con::getIntVariable("$pref::ReflectionProbes::RenderWithProbes", false);
 
    ReflectionProbe* clientProbe = nullptr;
 
-   if (probe->isClientObject())
-      clientProbe = probe;
-   else
+   if (probe->isServerObject())
       clientProbe = static_cast<ReflectionProbe*>(probe->getClientObject());
+   else
+      return;
 
    if (clientProbe == nullptr)
       return;
@@ -901,7 +838,7 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
    reflDesc.texSize = resolution;
    reflDesc.farDist = farPlane;
    reflDesc.detailAdjust = 1;
-   reflDesc.objectTypeMask = probe->mCaptureMask;
+   reflDesc.objectTypeMask = probe->mProbeShapeType == ProbeRenderInst::ProbeShapeType::Skylight ? SKYLIGHT_CAPTURE_TYPEMASK : REFLECTION_PROBE_CAPTURE_TYPEMASK;
 
    CubeReflector cubeRefl;
    cubeRefl.registerReflector(probe, &reflDesc);
@@ -939,13 +876,16 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
 
    GFXFormat reflectFormat;
 
-   if (clientProbe->mUseHDRCaptures)
+   if (mUseHDRCaptures)
       reflectFormat = GFXFormatR16G16B16A16F;
    else
       reflectFormat = GFXFormatR8G8B8A8;
    const GFXFormat oldRefFmt = REFLECTMGR->getReflectFormat();
    REFLECTMGR->setReflectFormat(reflectFormat);
-   cubeRefl.updateReflection(reflParams);
+   
+   mProbeArrayEffect->setShaderConst("$CAPTURING", true);
+   cubeRefl.updateReflection(reflParams, clientProbe->getTransform().getPosition()+clientProbe->mProbeRefOffset);
+   mProbeArrayEffect->setShaderConst("$CAPTURING", false);
 
    //Now, save out the maps
    //create irridiance cubemap
@@ -958,34 +898,24 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
       clientProbe->mIrridianceMap->mCubemap->initDynamic(resolution, reflectFormat);
       clientProbe->mPrefilterMap->mCubemap->initDynamic(resolution, reflectFormat);
 
-      if (mBakeRenderTarget == nullptr)
-         mBakeRenderTarget = GFX->allocRenderToTextureTarget(false);
-      else
-         mBakeRenderTarget->resurrect();
+      GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
 
-      IBLUtilities::GenerateIrradianceMap(mBakeRenderTarget, cubeRefl.getCubemap(), clientProbe->mIrridianceMap->mCubemap);
-      IBLUtilities::GeneratePrefilterMap(mBakeRenderTarget, cubeRefl.getCubemap(), prefilterMipLevels, clientProbe->mPrefilterMap->mCubemap);
+      IBLUtilities::GenerateIrradianceMap(renderTarget, cubeRefl.getCubemap(), clientProbe->mIrridianceMap->mCubemap);
+      IBLUtilities::GeneratePrefilterMap(renderTarget, cubeRefl.getCubemap(), prefilterMipLevels, clientProbe->mPrefilterMap->mCubemap);
 
       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!");
 
-      if (writeFiles)
-      {
-         Con::warnf("RenderProbeMgr::bake() - Beginning save now!");
-
-         IBLUtilities::SaveCubeMap(clientProbe->getIrradianceMapPath(), clientProbe->mIrridianceMap->mCubemap);
-         IBLUtilities::SaveCubeMap(clientProbe->getPrefilterMapPath(), clientProbe->mPrefilterMap->mCubemap);
-      }
-
-      mBakeRenderTarget->zombify();
+      IBLUtilities::SaveCubeMap(clientProbe->getIrradianceMapPath(), clientProbe->mIrridianceMap->mCubemap);
+      IBLUtilities::SaveCubeMap(clientProbe->getPrefilterMapPath(), clientProbe->mPrefilterMap->mCubemap);
    }
    else
    {
       Con::errorf("RenderProbeMgr::bake() - Didn't generate a valid scene capture cubemap, unable to generate prefilter and irradiance maps!");
    }
 
-
    if (!renderWithProbes)
       RenderProbeMgr::smRenderReflectionProbes = probeRenderState;
 
@@ -1002,12 +932,27 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
 
 void RenderProbeMgr::bakeProbes()
 {
-   //TODO: make this just find every probe in the current missionGroup and run the bake on it automagically
+   Vector<ReflectionProbe*> probes;
+
+   Scene::getRootScene()->findObjectByType<ReflectionProbe>(probes);
+
+   for (U32 i = 0; i < probes.size(); i++)
+   {
+      if (probes[i]->isClientObject())
+         continue;
+
+      bakeProbe(probes[i]);
+   }
 }
 
 DefineEngineMethod(RenderProbeMgr, bakeProbe, void, (ReflectionProbe* probe), (nullAsType< ReflectionProbe*>()),
-   "@brief returns true if control object is inside the fog\n\n.")
+   "@brief Bakes the cubemaps for a reflection probe\n\n.")
 {
    if(probe != nullptr)
       object->bakeProbe(probe);
 }
+
+DefineEngineMethod(RenderProbeMgr, bakeProbes, void, (),, "@brief Iterates over all reflection probes in the scene and bakes their cubemaps\n\n.")
+{
+   object->bakeProbes();
+}

+ 46 - 46
Engine/source/renderInstance/renderProbeMgr.h

@@ -85,8 +85,6 @@ struct ProbeRenderInst
    /// when prioritizing lights for rendering.
    F32 mScore;
 
-   bool mIsSkylight;
-
    enum ProbeShapeType
    {
       Box = 0,            ///< Sphere shaped
@@ -115,9 +113,6 @@ public:
    Point3F getPosition() const { return mPosition; }
    void setPosition(const Point3F &pos) { mPosition = pos; }
 
-   VectorF getDirection() const { return mTransform.getForwardVector(); }
-   void setDirection(const VectorF &val);
-
    void setPriority(F32 priority) { mPriority = priority; }
    F32 getPriority() const { return mPriority; }
 
@@ -141,8 +136,7 @@ struct ProbeShaderConstants
    //Reflection Probes
    GFXShaderConstHandle *mProbePositionSC;
    GFXShaderConstHandle *mProbeRefPosSC;
-   GFXShaderConstHandle *mRefBoxMinSC;
-   GFXShaderConstHandle *mRefBoxMaxSC;
+   GFXShaderConstHandle *mRefScaleSC;
    GFXShaderConstHandle *mWorldToObjArraySC;
    GFXShaderConstHandle *mProbeConfigDataSC;
    GFXShaderConstHandle *mProbeSpecularCubemapSC;
@@ -167,39 +161,43 @@ typedef Map<GFXShader*, ProbeShaderConstants*> ProbeConstantMap;
 
 struct ProbeDataSet
 {
-   AlignedArray<Point4F> probePositionArray;
-   AlignedArray<Point4F> refBoxMinArray;
-   AlignedArray<Point4F> refBoxMaxArray;
-   AlignedArray<Point4F> probeRefPositionArray;
-   AlignedArray<Point4F> probeConfigArray;
+   Vector<Point4F> probePositionArray;
+   Vector<Point4F> refScaleArray;
+   Vector<Point4F> probeRefPositionArray;
+   Vector<Point4F> probeConfigArray;
 
    Vector<MatrixF> probeWorldToObjArray;
 
    S32 skyLightIdx;
 
    U32 effectiveProbeCount;
+   U32 maxProbeCount;
+
+   ProbeDataSet()
+   {
+      probePositionArray.setSize(0);
+      refScaleArray.setSize(0);
+      probeRefPositionArray.setSize(0);
+      probeConfigArray.setSize(0);
 
-   U32 MAX_PROBE_COUNT;
+      probeWorldToObjArray.setSize(0);
+
+      skyLightIdx = -1;
+      effectiveProbeCount = 0;
+      maxProbeCount = 0;
+   }
 
-   ProbeDataSet(U32 maxProbeCount)
+   ProbeDataSet(U32 _maxProbeCount)
    {
-      MAX_PROBE_COUNT = maxProbeCount;
+      maxProbeCount = _maxProbeCount;
 
-      probePositionArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
-      refBoxMinArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
-      refBoxMaxArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
-      probeRefPositionArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
-      probeConfigArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
+      probePositionArray.setSize(maxProbeCount);
+      refScaleArray.setSize(maxProbeCount);
+      probeRefPositionArray.setSize(maxProbeCount);
+      probeConfigArray.setSize(maxProbeCount);
 
       probeWorldToObjArray.setSize(maxProbeCount);
 
-      // Need to clear the buffers so that we don't leak
-      // lights from previous passes or have NaNs.
-      dMemset(probePositionArray.getBuffer(), 0, probePositionArray.getBufferSize());
-      dMemset(refBoxMinArray.getBuffer(), 0, refBoxMinArray.getBufferSize());
-      dMemset(refBoxMaxArray.getBuffer(), 0, refBoxMaxArray.getBufferSize());
-      dMemset(probeRefPositionArray.getBuffer(), 0, probeRefPositionArray.getBufferSize());
-      dMemset(probeConfigArray.getBuffer(), 0, probeConfigArray.getBufferSize());
       skyLightIdx = -1;
       effectiveProbeCount = 0;
    }
@@ -219,10 +217,11 @@ class RenderProbeMgr : public RenderBinManager
 {
    typedef RenderBinManager Parent;
 
-   Vector<ProbeRenderInst> mRegisteredProbes;
+   Vector<ProbeRenderInst*> mRegisteredProbes;
 
    bool mProbesDirty;
-
+   
+   Vector<ProbeRenderInst>  mActiveProbes;
 public:
    //maximum number of allowed probes
    static const U32 PROBE_MAX_COUNT = 250;
@@ -236,27 +235,17 @@ public:
    static const GFXFormat PROBE_FORMAT = GFXFormatR16G16B16A16F;// GFXFormatR8G8B8A8;// when hdr fixed GFXFormatR16G16B16A16F; look into bc6h compression
    static const U32 INVALID_CUBE_SLOT = U32_MAX;
 
+   static F32 smMaxProbeDrawDistance;
+   static S32 smMaxProbesPerFrame;
+
 private:
    //Array rendering
    U32 mEffectiveProbeCount;
    S32 mMipCount;
-   Vector<Point4F> probePositionsData;
-   Vector<Point4F> probeRefPositionsData;
-   Vector<MatrixF> probeWorldToObjData;
-   Vector<Point4F> refBoxMinData;
-   Vector<Point4F> refBoxMaxData;
-   Vector<Point4F> probeConfigData;
 
    bool            mHasSkylight;
    S32             mSkylightCubemapIdx;
 
-   AlignedArray<Point4F> mProbePositions;
-   AlignedArray<Point4F> mRefBoxMin;
-   AlignedArray<Point4F> mRefBoxMax;
-   AlignedArray<float> mProbeUseSphereMode;
-   AlignedArray<float> mProbeRadius;
-   AlignedArray<float> mProbeAttenuation;
-
    //number of cubemaps
    U32 mCubeMapCount;
    //number of cubemap slots allocated
@@ -280,8 +269,12 @@ private:
 
    GFXTexHandle mBRDFTexture;
 
-   GFXTextureTargetRef mBakeRenderTarget;
+   ProbeDataSet mProbeData;
+   ///Prevents us from saving out the cubemaps(for now) but allows us the full HDR range on the in-memory cubemap captures
+   bool mUseHDRCaptures;
 
+   U32 mPrefilterMipLevels;
+   U32 mPrefilterSize;
 public:
    RenderProbeMgr();
    RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder);
@@ -291,6 +284,8 @@ public:
 
    // ConsoleObject
    static void initPersistFields();
+   static void consoleInit();
+
    DECLARE_CONOBJECT(RenderProbeMgr);
 
 protected:
@@ -306,7 +301,7 @@ protected:
 
    void _setupStaticParameters();
    void _setupPerFrameParameters(const SceneRenderState *state);
-   virtual void addElement(RenderInst *inst);
+   virtual void addElement(RenderInst* inst) {};
    virtual void render(SceneRenderState * state);
 
    ProbeShaderConstants* getProbeShaderConstants(GFXShaderConstBuffer* buffer);
@@ -331,8 +326,11 @@ public:
    /// Returns the active LM.
    static inline RenderProbeMgr* getProbeManager();
 
-   ProbeRenderInst* registerProbe();
+   void registerProbe(ProbeRenderInst* newProbe);
    void unregisterProbe(U32 probeIdx);
+   void submitProbe(const ProbeRenderInst& newProbe);
+
+   static S32 QSORT_CALLBACK _probeScoreCmp(const ProbeRenderInst* a, const  ProbeRenderInst* b);
 
    virtual void setProbeInfo(ProcessedMaterial *pmat,
 	   const Material *mat,
@@ -341,6 +339,8 @@ public:
 	   U32 pass,
 	   GFXShaderConstBuffer *shaderConsts);
 
+   void setupSGData(SceneData& data, const SceneRenderState* state, LightInfo* light);
+   
    void updateProbeTexture(ProbeRenderInst* probeInfo);
 
    void reloadTextures();
@@ -348,7 +348,7 @@ public:
    /// Debug rendering
    static bool smRenderReflectionProbes;
 
-   void bakeProbe(ReflectionProbe *probeInfo, bool writeFile = true);
+   void bakeProbe(ReflectionProbe *probeInfo);
    void bakeProbes();
 
    void getProbeTextureData(ProbeTextureArrayData* probeTextureSet);

+ 12 - 4
Engine/source/scene/reflector.cpp

@@ -295,7 +295,7 @@ void CubeReflector::unregisterReflector()
    mEnabled = false;
 }
 
-void CubeReflector::updateReflection( const ReflectParams &params )
+void CubeReflector::updateReflection( const ReflectParams &params, Point3F explicitPostion)
 {
    GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateReflection, ColorI::WHITE );
 
@@ -336,7 +336,7 @@ void CubeReflector::updateReflection( const ReflectParams &params )
 
 
    for ( U32 i = 0; i < 6; i++ )
-      updateFace( params, i );
+      updateFace( params, i, explicitPostion);
    
 
    GFX->popActiveRenderTarget();
@@ -347,7 +347,7 @@ void CubeReflector::updateReflection( const ReflectParams &params )
    mLastTexSize = texDim;
 }
 
-void CubeReflector::updateFace( const ReflectParams &params, U32 faceidx )
+void CubeReflector::updateFace( const ReflectParams &params, U32 faceidx, Point3F explicitPostion)
 {
    GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateFace, ColorI::WHITE );
 
@@ -402,7 +402,15 @@ void CubeReflector::updateFace( const ReflectParams &params, U32 faceidx )
    matView.setColumn( 0, cross );
    matView.setColumn( 1, vLookatPt );
    matView.setColumn( 2, vUpVec );
-   matView.setPosition( mObject->getPosition() );
+
+   if (explicitPostion == Point3F::Max)
+   {
+      matView.setPosition(mObject->getPosition());
+   }
+   else
+   {
+      matView.setPosition(explicitPostion);
+   }
    matView.inverse();
 
    GFX->setWorldMatrix(matView);

+ 2 - 2
Engine/source/scene/reflector.h

@@ -151,11 +151,11 @@ public:
                            ReflectorDesc *inDesc );
 
    virtual void unregisterReflector();
-   virtual void updateReflection( const ReflectParams &params );   
+   virtual void updateReflection( const ReflectParams &params, Point3F explicitPostion = Point3F::Max);
 
    GFXCubemap* getCubemap() const { return mCubemap; }
 
-   void updateFace( const ReflectParams &params, U32 faceidx );
+   void updateFace( const ReflectParams &params, U32 faceidx, Point3F explicitPostion = Point3F::Max);
    F32 calcFaceScore( const ReflectParams &params, U32 faceidx );
 
 protected:

+ 6 - 11
Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp

@@ -3004,15 +3004,10 @@ void ReflectionProbeFeatGLSL::processPix(Vector<ShaderComponent*>& componentList
    inRefPosArray->uniform = true;
    inRefPosArray->constSortPos = cspPotentialPrimitive;
 
-   Var * refBoxMinArray = new Var("inRefBoxMin", "vec4");
-   refBoxMinArray->arraySize = MAX_FORWARD_PROBES;
-   refBoxMinArray->uniform = true;
-   refBoxMinArray->constSortPos = cspPotentialPrimitive;
-
-   Var * refBoxMaxArray = new Var("inRefBoxMax", "vec4");
-   refBoxMaxArray->arraySize = MAX_FORWARD_PROBES;
-   refBoxMaxArray->uniform = true;
-   refBoxMaxArray->constSortPos = cspPotentialPrimitive;
+   Var * refScaleArray = new Var("inRefScale", "vec4");
+   refScaleArray->arraySize = MAX_FORWARD_PROBES;
+   refScaleArray->uniform = true;
+   refScaleArray->constSortPos = cspPotentialPrimitive;
 
    Var * probeConfigData = new Var("probeConfigData", "vec4");
    probeConfigData->arraySize = MAX_FORWARD_PROBES;
@@ -3053,11 +3048,11 @@ void ReflectionProbeFeatGLSL::processPix(Vector<ShaderComponent*>& componentList
    Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
       
    //Reflection vec
-   String computeForwardProbes = String("   @.rgb = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
+   String computeForwardProbes = String("   @.rgb = computeForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t");
    computeForwardProbes += String("@,@,\r\n\t\t");
    computeForwardProbes += String("@,@).rgb; \r\n");
 
-   meta->addStatement(new GenOp(computeForwardProbes.c_str(), curColor, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refBoxMinArray, refBoxMaxArray, inRefPosArray,
+   meta->addStatement(new GenOp(computeForwardProbes.c_str(), curColor, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
       skylightCubemapIdx, BRDFTexture,
       irradianceCubemapAR, specularCubemapAR));
 

+ 3 - 4
Engine/source/shaderGen/HLSL/debugVizFeatureHLSL.cpp

@@ -140,8 +140,7 @@ void DebugVizHLSL::processPix(Vector<ShaderComponent*>& componentList,
       Var* skylightCubemapIdx = (Var*)LangElement::find("skylightCubemapIdx");
       Var* inProbePosArray = (Var*)LangElement::find("inProbePosArray");
       Var* inRefPosArray = (Var*)LangElement::find("inRefPosArray");
-      Var* refBoxMinArray = (Var*)LangElement::find("inRefBoxMin");
-      Var* refBoxMaxArray = (Var*)LangElement::find("inRefBoxMax");
+      Var* refScaleArray = (Var*)LangElement::find("inRefScale");
 
       Var* probeConfigData = (Var*)LangElement::find("probeConfigData");
       Var* worldToObjArray = (Var*)LangElement::find("worldToObjArray");
@@ -181,11 +180,11 @@ void DebugVizHLSL::processPix(Vector<ShaderComponent*>& componentList,
       dSprintf(buf, sizeof(buf), "   @ = %s;\r\n", showDiff);
       meta->addStatement(new GenOp(buf, new DecOp(showDiffVar)));
 
-      String computeForwardProbes = String::String("   @ = debugVizForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
+      String computeForwardProbes = String::String("   @ = debugVizForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t");
       computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t");
       computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@), @, @, @, @).rgb; \r\n");
 
-      meta->addStatement(new GenOp(computeForwardProbes.c_str(), ibl, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refBoxMinArray, refBoxMaxArray, inRefPosArray,
+      meta->addStatement(new GenOp(computeForwardProbes.c_str(), ibl, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
          skylightCubemapIdx, BRDFTexture,
          irradianceCubemapAR, specularCubemapAR,
          showAttenVar, showContribVar, showSpecVar, showDiffVar));

+ 6 - 11
Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp

@@ -3075,15 +3075,10 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
    inRefPosArray->uniform = true;
    inRefPosArray->constSortPos = cspPotentialPrimitive;
 
-   Var * refBoxMinArray = new Var("inRefBoxMin", "float4");
-   refBoxMinArray->arraySize = MAX_FORWARD_PROBES;
-   refBoxMinArray->uniform = true;
-   refBoxMinArray->constSortPos = cspPotentialPrimitive;
-
-   Var * refBoxMaxArray = new Var("inRefBoxMax", "float4");
-   refBoxMaxArray->arraySize = MAX_FORWARD_PROBES;
-   refBoxMaxArray->uniform = true;
-   refBoxMaxArray->constSortPos = cspPotentialPrimitive;
+   Var * refScaleArray = new Var("inRefScale", "float4");
+   refScaleArray->arraySize = MAX_FORWARD_PROBES;
+   refScaleArray->uniform = true;
+   refScaleArray->constSortPos = cspPotentialPrimitive;
 
    Var *probeConfigData = new Var("probeConfigData", "float4");
    probeConfigData->arraySize = MAX_FORWARD_PROBES;
@@ -3142,11 +3137,11 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
       ibl = new Var("ibl", "float3");
    }
 
-   String computeForwardProbes = String::String("   @ = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
+   String computeForwardProbes = String::String("   @ = computeForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t");
    computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t"); 
    computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n");
       
-   meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refBoxMinArray, refBoxMaxArray, inRefPosArray,
+   meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
       skylightCubemapIdx, BRDFTexture,
       irradianceCubemapAR, specularCubemapAR));
 

+ 1 - 2
Engine/source/shaderGen/shaderGenVars.cpp

@@ -81,8 +81,7 @@ const String ShaderGenVars::glowMul("$glowMul");
 //Reflection Probes
 const String ShaderGenVars::probePosition("$inProbePosArray");
 const String ShaderGenVars::probeRefPos("$inRefPosArray");
-const String ShaderGenVars::refBoxMin("$inRefBoxMin");
-const String ShaderGenVars::refBoxMax("$inRefBoxMax");
+const String ShaderGenVars::refScale("$inRefScale");
 const String ShaderGenVars::worldToObjArray("$worldToObjArray");
 const String ShaderGenVars::probeConfigData("$probeConfigData");
 const String ShaderGenVars::specularCubemapAR("$specularCubemapAR");

+ 1 - 2
Engine/source/shaderGen/shaderGenVars.h

@@ -93,8 +93,7 @@ struct ShaderGenVars
    //Reflection Probes
    const static String probePosition;
    const static String probeRefPos;
-   const static String refBoxMin;
-   const static String refBoxMax;
+   const static String refScale;
    const static String worldToObjArray;
    const static String probeConfigData;
    const static String specularCubemapAR;

+ 17 - 9
Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl

@@ -44,7 +44,10 @@ uniform vec4 albedo;
 
 #endif // !TORQUE_SHADERGEN
 
-#define MAX_PROBES 50
+#ifndef MAX_PROBES
+#define MAX_PROBES 8
+#endif
+
 #define MAX_FORWARD_PROBES 4
 
 #define MAX_FORWARD_LIGHT 4
@@ -216,7 +219,12 @@ vec3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight)
    float D = D_GGX(surfaceToLight.NdotH, surface.linearRoughnessSq);
    vec3 Fr = D * F * Vis;
 
+#if CAPTURING == true
+   return mix(Fd + Fr,surface.f0,surface.metalness);
+#else
    return Fd + Fr;
+#endif
+
 }
 
 vec3 getDirectionalLight(Surface surface, SurfaceToLight surfaceToLight, vec3 lightColor, float lightIntensity, float shadow)
@@ -331,14 +339,14 @@ float defineBoxSpaceInfluence(vec3 wsPosition, mat4 worldToObj, float attenuatio
 // Box Projected IBL Lighting
 // Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
 // and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
-vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 refBoxMin, vec3 refBoxMax, vec3 refPosition)
+vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 refScale, vec3 refPosition)
 {
    vec3 RayLS = tMul(worldToObj, vec4(wsReflectVec, 0.0)).xyz;
    vec3 PositionLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz;
 
-   vec3 unit = refBoxMax.xyz - refBoxMin.xyz;
-   vec3 plane1vec = (unit / 2 - PositionLS) / RayLS;
-   vec3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
+   vec3 unit = refScale;
+   vec3 plane1vec = (unit - PositionLS) / RayLS;
+   vec3 plane2vec = (-unit - PositionLS) / RayLS;
    vec3 furthestPlane = max(plane1vec, plane2vec);
    float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
    vec3 posonbox = wsPosition + wsReflectVec * dist;
@@ -348,7 +356,7 @@ vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 refBox
 
 vec4 computeForwardProbes(Surface surface,
     float cubeMips, int numProbes, mat4x4 worldToObjArray[MAX_FORWARD_PROBES], vec4 probeConfigData[MAX_FORWARD_PROBES], 
-    vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refBoxMinArray[MAX_FORWARD_PROBES], vec4 refBoxMaxArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
+    vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refScaleArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
     float skylightCubemapIdx, sampler2D BRDFTexture, 
 	samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR)
 {
@@ -452,7 +460,7 @@ vec4 computeForwardProbes(Surface surface,
       if (contrib > 0.0f)
       {
          float cubemapIdx = int(probeConfigData[i].a);
-         vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
+         vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
 
          irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
          specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;
@@ -490,7 +498,7 @@ vec4 computeForwardProbes(Surface surface,
 
 vec4 debugVizForwardProbes(Surface surface,
     float cubeMips, int numProbes, mat4 worldToObjArray[MAX_FORWARD_PROBES], vec4 probeConfigData[MAX_FORWARD_PROBES], 
-    vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refBoxMinArray[MAX_FORWARD_PROBES], vec4 refBoxMaxArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
+    vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refScaleArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
     float skylightCubemapIdx, sampler2D BRDFTexture, 
 	 samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR, int showAtten, int showContrib, int showSpec, int showDiff)
 {
@@ -601,7 +609,7 @@ vec4 debugVizForwardProbes(Surface surface,
       if (contrib > 0.0f)
       {
          float cubemapIdx = probeConfigData[i].a;
-         vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
+         vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
 
          irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
          specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;

+ 18 - 10
Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl

@@ -45,7 +45,10 @@ uniform float4 albedo;
 
 #endif // !TORQUE_SHADERGEN
 
-#define MAX_PROBES 50
+#ifndef MAX_PROBES
+#define MAX_PROBES 8
+#endif
+
 #define MAX_FORWARD_PROBES 4
 
 #define MAX_FORWARD_LIGHT 4
@@ -216,8 +219,13 @@ float3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight)
    float Vis = V_SmithGGXCorrelated(surface.NdotV, surfaceToLight.NdotL, surface.linearRoughnessSq);
    float D = D_GGX(surfaceToLight.NdotH, surface.linearRoughnessSq);
    float3 Fr = D * F * Vis;
-
+   
+#if CAPTURING == true
+    return lerp(Fd + Fr,surface.f0,surface.metalness);
+#else
    return Fd + Fr;
+#endif
+
 }
 
 float3 getDirectionalLight(Surface surface, SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float shadow)
@@ -335,14 +343,14 @@ float defineBoxSpaceInfluence(float3 wsPosition, float4x4 worldToObj, float atte
 // Box Projected IBL Lighting
 // Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
 // and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
-float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, float3 refBoxMin, float3 refBoxMax, float3 refPosition)
+float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, float3 refScale, float3 refPosition)
 {
    float3 RayLS = mul(worldToObj, float4(wsReflectVec, 0.0)).xyz;
    float3 PositionLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
 
-   float3 unit = refBoxMax.xyz - refBoxMin.xyz;
-   float3 plane1vec = (unit / 2 - PositionLS) / RayLS;
-   float3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
+   float3 unit = refScale;
+   float3 plane1vec = (unit - PositionLS) / RayLS;
+   float3 plane2vec = (-unit - PositionLS) / RayLS;
    float3 furthestPlane = max(plane1vec, plane2vec);
    float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
    float3 posonbox = wsPosition + wsReflectVec * dist;
@@ -352,7 +360,7 @@ float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, f
 
 float4 computeForwardProbes(Surface surface,
     float cubeMips, int numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES], 
-    float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refBoxMinArray[MAX_FORWARD_PROBES], float4 refBoxMaxArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
+    float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refScaleArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
     float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture), 
 	 TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR))
 {
@@ -456,7 +464,7 @@ float4 computeForwardProbes(Surface surface,
       if (contrib > 0.0f)
       {
          int cubemapIdx = probeConfigData[i].a;
-         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
+         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
 
          irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
          specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;
@@ -494,7 +502,7 @@ float4 computeForwardProbes(Surface surface,
 
 float4 debugVizForwardProbes(Surface surface,
     float cubeMips, int numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES], 
-    float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refBoxMinArray[MAX_FORWARD_PROBES], float4 refBoxMaxArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
+    float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refScaleArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
     float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture), 
 	 TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR), int showAtten, int showContrib, int showSpec, int showDiff)
 {
@@ -605,7 +613,7 @@ float4 debugVizForwardProbes(Surface surface,
       if (contrib > 0.0f)
       {
          int cubemapIdx = probeConfigData[i].a;
-         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
+         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
 
          irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
          specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;

+ 1 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/prefilterP.glsl

@@ -127,4 +127,5 @@ void main()
 {   
 	vec3 N = getCubeDir(face, uv0);
 	OUT_col = prefilterEnvMap(N);
+	OUT_col.a = 1;
 }

+ 2 - 3
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/reflectionProbeArrayP.glsl

@@ -33,8 +33,7 @@ uniform vec4 rtParams6;
 uniform vec4    inProbePosArray[MAX_PROBES];
 uniform vec4    inRefPosArray[MAX_PROBES];
 uniform mat4    worldToObjArray[MAX_PROBES];
-uniform vec4    refBoxMinArray[MAX_PROBES];
-uniform vec4    refBoxMaxArray[MAX_PROBES];
+uniform vec4    refScaleArray[MAX_PROBES];
 uniform vec4    probeConfigData[MAX_PROBES];   //r,g,b/mode,radius,atten
 
 #if DEBUGVIZ_CONTRIB
@@ -180,7 +179,7 @@ void main()
       if (contrib > 0.0f)
       {
          float cubemapIdx = probeConfigData[i].a;
-         vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
+         vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
 
          irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
          specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;

+ 1 - 1
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/prefilterP.hlsl

@@ -126,5 +126,5 @@ float4 prefilterEnvMap(float3 R)
 float4 main(ConnectData IN) : TORQUE_TARGET0
 {
 	float3 N = getCubeDir(face, IN.uv);
-	return prefilterEnvMap(N);
+	return float4(prefilterEnvMap(N).rgb,1.0);
 }

+ 2 - 3
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/reflectionProbeArrayP.hlsl

@@ -30,8 +30,7 @@ uniform float4 rtParams6;
 uniform float4    inProbePosArray[MAX_PROBES];
 uniform float4    inRefPosArray[MAX_PROBES];
 uniform float4x4  worldToObjArray[MAX_PROBES];
-uniform float4    refBoxMinArray[MAX_PROBES];
-uniform float4    refBoxMaxArray[MAX_PROBES];
+uniform float4    refScaleArray[MAX_PROBES];
 uniform float4    probeConfigData[MAX_PROBES];   //r,g,b/mode,radius,atten
 
 #if DEBUGVIZ_CONTRIB
@@ -172,7 +171,7 @@ float4 main(PFXVertToPix IN) : SV_TARGET
       if (contrib > 0.0f)
       {
          int cubemapIdx = probeConfigData[i].a;
-         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
+         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
 
          irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
          specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;

+ 5 - 11
Templates/BaseGame/game/tools/worldEditor/scripts/probeBake.ed.cs

@@ -39,17 +39,11 @@ function ProbeBakeDlg_RunBake::onClick(%this)
       if(%iter != 0)
          $pref::ReflectionProbes::RenderWithProbes = true;
          
-      for(%i=0; %i < %probeCount; %i++)
-      {
-         %probe = getWord(%probeIds, %i);
-         
-         $pref::ReflectionProbes::CurrentLevelPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
-         ProbeBin.bakeProbe(%probe);
-         
-         %currentProgressValue += %progressStep;
-         ProbeBakeDlg_Progress.setValue(%currentProgressValue);
-         Canvas.repaint();
-      }
+      $pref::ReflectionProbes::CurrentLevelPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
+      ProbeBin.bakeProbes();
+      
+      %currentProgressValue += %progressStep;
+      ProbeBakeDlg_Progress.setValue(%currentProgressValue);
    }
    
    EWorldEditor.isDirty = true;