Procházet zdrojové kódy

Merge branch 'PBR_ProbeArrayWIP' of https://github.com/Areloch/Torque3D into PBR_ProbeArrayWIP

# Conflicts:
#	Engine/source/renderInstance/renderProbeMgr.cpp
Azaezel před 6 roky
rodič
revize
de50110827

+ 232 - 0
Engine/source/T3D/lighting/boxEnvironmentProbe.cpp

@@ -0,0 +1,232 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "T3D/lighting/boxEnvironmentProbe.h"
+#include "math/mathIO.h"
+#include "scene/sceneRenderState.h"
+#include "console/consoleTypes.h"
+#include "core/stream/bitStream.h"
+#include "materials/baseMatInstance.h"
+#include "console/engineAPI.h"
+#include "gfx/gfxDrawUtil.h"
+#include "gfx/gfxDebugEvent.h"
+#include "gfx/gfxTransformSaver.h"
+#include "math/mathUtils.h"
+#include "gfx/bitmap/gBitmap.h"
+#include "core/stream/fileStream.h"
+#include "core/fileObject.h"
+#include "core/resourceManager.h"
+#include "console/simPersistId.h"
+#include "T3D/gameFunctions.h"
+#include "postFx/postEffect.h"
+#include "renderInstance/renderProbeMgr.h"
+#include "renderInstance/renderProbeMgr.h"
+
+#include "math/util/sphereMesh.h"
+#include "materials/materialManager.h"
+#include "math/util/matrixSet.h"
+#include "gfx/bitmap/cubemapSaver.h"
+
+#include "materials/materialFeatureTypes.h"
+
+#include "materials/shaderData.h"
+#include "gfx/gfxTextureManager.h"
+
+#include "gfx/bitmap/imageUtils.h"
+
+#include "T3D/lighting/IBLUtilities.h"
+
+extern bool gEditingMission;
+extern ColorI gCanvasClearColor;
+
+IMPLEMENT_CO_NETOBJECT_V1(BoxEnvironmentProbe);
+
+ConsoleDocClass(BoxEnvironmentProbe,
+   "@brief An example scene object which renders a mesh.\n\n"
+   "This class implements a basic SceneObject that can exist in the world at a "
+   "3D position and render itself. There are several valid ways to render an "
+   "object in Torque. This class implements the preferred rendering method which "
+   "is to submit a MeshRenderInst along with a Material, vertex buffer, "
+   "primitive buffer, and transform and allow the RenderMeshMgr handle the "
+   "actual setup and rendering for you.\n\n"
+   "See the C++ code for implementation details.\n\n"
+   "@ingroup Examples\n");
+
+//-----------------------------------------------------------------------------
+// Object setup and teardown
+//-----------------------------------------------------------------------------
+BoxEnvironmentProbe::BoxEnvironmentProbe() : ReflectionProbe()
+{
+   mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK;
+}
+
+BoxEnvironmentProbe::~BoxEnvironmentProbe()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Object Editing
+//-----------------------------------------------------------------------------
+void BoxEnvironmentProbe::initPersistFields()
+{
+   // SceneObject already handles exposing the transform
+   Parent::initPersistFields();
+}
+
+void BoxEnvironmentProbe::inspectPostApply()
+{
+   Parent::inspectPostApply();
+
+   mDirty = true;
+
+   // Flag the network mask to send the updates
+   // to the client object
+   setMaskBits(-1);
+}
+
+bool BoxEnvironmentProbe::onAdd()
+{
+   if (!Parent::onAdd())
+      return false;
+
+   return true;
+}
+
+void BoxEnvironmentProbe::onRemove()
+{
+   Parent::onRemove();
+}
+
+void BoxEnvironmentProbe::setTransform(const MatrixF & mat)
+{
+   // Let SceneObject handle all of the matrix manipulation
+   Parent::setTransform(mat);
+
+   mDirty = true;
+
+   // Dirty our network mask so that the new transform gets
+   // transmitted to the client object
+   setMaskBits(TransformMask);
+}
+
+U32 BoxEnvironmentProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
+{
+   // Allow the Parent to get a crack at writing its info
+   U32 retMask = Parent::packUpdate(conn, mask, stream);
+
+   return retMask;
+}
+
+void BoxEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
+{
+   // Let the Parent read any info it sent
+   Parent::unpackUpdate(conn, stream);
+}
+
+//-----------------------------------------------------------------------------
+// Object Rendering
+//-----------------------------------------------------------------------------
+
+void BoxEnvironmentProbe::updateProbeParams()
+{
+   Parent::updateProbeParams();
+
+   mProbeInfo->mProbeShapeType = ProbeRenderInst::Box;
+}
+
+void BoxEnvironmentProbe::prepRenderImage(SceneRenderState *state)
+{
+   if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
+      return;
+
+   //special hook-in for BoxEnvironmentProbes
+   Point3F camPos = state->getCameraPosition();
+   mProbeInfo->mBounds.setCenter(camPos);
+
+   mProbeInfo->setPosition(camPos);
+
+   if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
+   {
+      GFXTransformSaver saver;
+
+      // Calculate the distance of this object from the camera
+      Point3F cameraOffset;
+      getRenderTransform().getColumn(3, &cameraOffset);
+      cameraOffset -= state->getDiffuseCameraPosition();
+      F32 dist = cameraOffset.len();
+      if (dist < 0.01f)
+         dist = 0.01f;
+
+      // Set up the LOD for the shape
+      F32 invScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
+
+      mEditorShapeInst->setDetailFromDistance(state, dist * invScale);
+
+      // Make sure we have a valid level of detail
+      if (mEditorShapeInst->getCurrentDetail() < 0)
+         return;
+
+      BaseMatInstance* probePrevMat = mEditorShapeInst->getMaterialList()->getMaterialInst(0);
+
+      setPreviewMatParameters(state, probePrevMat);
+
+      // GFXTransformSaver is a handy helper class that restores
+      // the current GFX matrices to their original values when
+      // it goes out of scope at the end of the function
+
+      // Set up our TS render state      
+      TSRenderState rdata;
+      rdata.setSceneState(state);
+      rdata.setFadeOverride(1.0f);
+
+      // We might have some forward lit materials
+      // so pass down a query to gather lights.
+      LightQuery query;
+      query.init(getWorldSphere());
+      rdata.setLightQuery(&query);
+
+      // Set the world matrix to the objects render transform
+      MatrixF mat = getRenderTransform();
+      mat.scale(Point3F(1, 1, 1));
+      GFX->setWorldMatrix(mat);
+
+      // Animate the the shape
+      mEditorShapeInst->animate();
+
+      // Allow the shape to submit the RenderInst(s) for itself
+      mEditorShapeInst->render(rdata);
+
+      saver.restore();
+   }
+
+   // If the light is selected or light visualization
+   // is enabled then register the callback.
+   const bool isSelectedInEditor = (gEditingMission && isSelected());
+   if (isSelectedInEditor)
+   {
+   }
+}
+
+void BoxEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
+{
+   Parent::setPreviewMatParameters(renderState, mat);
+}

+ 116 - 0
Engine/source/T3D/lighting/boxEnvironmentProbe.h

@@ -0,0 +1,116 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef BOX_ENVIRONMENT_PROBE_H
+#define BOX_ENVIRONMENT_PROBE_H
+
+#ifndef REFLECTIONPROBE_H
+#include "T3D/lighting/reflectionProbe.h"
+#endif
+#ifndef _GFXVERTEXBUFFER_H_
+#include "gfx/gfxVertexBuffer.h"
+#endif
+#ifndef _GFXPRIMITIVEBUFFER_H_
+#include "gfx/gfxPrimitiveBuffer.h"
+#endif
+#ifndef _TSSHAPEINSTANCE_H_
+#include "ts/tsShapeInstance.h"
+#endif
+#include "lighting/lightInfo.h"
+
+#ifndef _RENDERPASSMANAGER_H_
+#include "renderInstance/renderPassManager.h"
+#endif
+
+class BaseMatInstance;
+
+
+//-----------------------------------------------------------------------------
+// This class implements a basic SceneObject that can exist in the world at a
+// 3D position and render itself. There are several valid ways to render an
+// object in Torque. This class implements the preferred rendering method which
+// is to submit a MeshRenderInst along with a Material, vertex buffer,
+// primitive buffer, and transform and allow the RenderMeshMgr handle the
+// actual setup and rendering for you.
+//-----------------------------------------------------------------------------
+
+class BoxEnvironmentProbe : public ReflectionProbe
+{
+   typedef ReflectionProbe Parent;
+
+private:
+
+    //Debug rendering
+   static bool smRenderPreviewProbes;
+
+public:
+   BoxEnvironmentProbe();
+   virtual ~BoxEnvironmentProbe();
+
+   // Declare this object as a ConsoleObject so that we can
+   // instantiate it into the world and network it
+   DECLARE_CONOBJECT(BoxEnvironmentProbe);
+
+   //--------------------------------------------------------------------------
+   // Object Editing
+   // Since there is always a server and a client object in Torque and we
+   // actually edit the server object we need to implement some basic
+   // networking functions
+   //--------------------------------------------------------------------------
+   // Set up any fields that we want to be editable (like position)
+   static void initPersistFields();
+
+   // Allows the object to update its editable settings
+   // from the server object to the client
+   virtual void inspectPostApply();
+
+   // Handle when we are added to the scene and removed from the scene
+   bool onAdd();
+   void onRemove();
+
+   // Override this so that we can dirty the network flag when it is called
+   void setTransform(const MatrixF &mat);
+
+   // This function handles sending the relevant data from the server
+   // object to the client object
+   U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
+   // This function handles receiving relevant data from the server
+   // object and applying it to the client object
+   void unpackUpdate(NetConnection *conn, BitStream *stream);
+
+   //--------------------------------------------------------------------------
+   // Object Rendering
+   // Torque utilizes a "batch" rendering system. This means that it builds a
+   // list of objects that need to render (via RenderInst's) and then renders
+   // them all in one batch. This allows it to optimized on things like
+   // minimizing texture, state, and shader switching by grouping objects that
+   // use the same Materials.
+   //--------------------------------------------------------------------------
+   virtual void updateProbeParams();
+
+   // This is the function that allows this object to submit itself for rendering
+   void prepRenderImage(SceneRenderState *state);
+
+   void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
+};
+
+#endif // BOX_ENVIRONMENT_PROBE_H

+ 27 - 256
Engine/source/T3D/lighting/reflectionProbe.cpp

@@ -51,6 +51,8 @@
 #include "gfx/gfxTextureManager.h"
 #include "T3D/lighting/IBLUtilities.h"
 
+#include "scene/reflector.h"
+
 extern bool gEditingMission;
 extern ColorI gCanvasClearColor;
 bool ReflectionProbe::smRenderPreviewProbes = true;
@@ -75,14 +77,6 @@ ImplementEnumType(ReflectProbeType,
 { ProbeRenderInst::Box, "Box", "Box shape" }
 EndImplementEnumType;
 
-ImplementEnumType(IndrectLightingModeEnum,
-   "Type of mesh data available in a shape.\n"
-   "@ingroup gameObjects")
-{ ReflectionProbe::NoIndirect, "No Lighting", "This probe does not provide any local indirect lighting data" },
-{ ReflectionProbe::AmbientColor, "Ambient Color", "Adds a flat color to act as the local indirect lighting" },
-{ ReflectionProbe::SphericalHarmonics, "Spherical Harmonics", "Creates spherical harmonics data based off the reflection data" },
-   EndImplementEnumType;
-
 ImplementEnumType(ReflectionModeEnum,
    "Type of mesh data available in a shape.\n"
    "@ingroup gameObjects")
@@ -105,8 +99,6 @@ ReflectionProbe::ReflectionProbe()
 
    mProbeShapeType = ProbeRenderInst::Box;
 
-   mIndrectLightingModeType = NoIndirect;
-
    mReflectionModeType = BakedCubemap;
 
    mEnabled = true;
@@ -119,7 +111,6 @@ ReflectionProbe::ReflectionProbe()
    mUseHDRCaptures = true;
 
    mStaticCubemap = NULL;
-   mReflectionPath = "";
    mProbeUniqueID = "";
 
    mEditorShapeInst = NULL;
@@ -168,9 +159,7 @@ void ReflectionProbe::initPersistFields()
       addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
          &_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid");
 
-      addField("ProbeShape", TypeReflectProbeType, Offset(mProbeShapeType, ReflectionProbe),
-         "The type of mesh data to use for collision queries.");
-      addField("radius", TypeF32, Offset(mRadius, ReflectionProbe), "The name of the material used to render the mesh.");
+     addField("radius", TypeF32, Offset(mRadius, ReflectionProbe), "The name of the material used to render the mesh.");
 	  addField("posOffset", TypePoint3F, Offset(mProbePosOffset, ReflectionProbe), "");
 
      //addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
@@ -181,9 +170,6 @@ void ReflectionProbe::initPersistFields()
       addField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe),
          "The type of mesh data to use for collision queries.");
 
-      addField("reflectionPath", TypeImageFilename, Offset(mReflectionPath, ReflectionProbe),
-         "The type of mesh data to use for collision queries.");
-
       addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "Cubemap used instead of reflection texture if fullReflect is off.");
 
       addProtectedField("Bake", TypeBool, Offset(mBake, ReflectionProbe),
@@ -236,7 +222,7 @@ bool ReflectionProbe::_doBake(void *object, const char *index, const char *data)
 
    if (clientProbe)
    {
-      clientProbe->bake(clientProbe->mReflectionPath, 64);
+      clientProbe->bake();
    }
 
    return false;
@@ -361,7 +347,6 @@ U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream
 
    if (stream->writeFlag(mask & BakeInfoMask))
    {
-      stream->write(mReflectionPath);
       stream->write(mProbeUniqueID);
    }
 
@@ -372,7 +357,6 @@ U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream
 
    if (stream->writeFlag(mask & ModeMask))
    {
-      stream->write((U32)mIndrectLightingModeType);
       stream->write((U32)mReflectionModeType);
    }
 
@@ -416,7 +400,6 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
 
    if (stream->readFlag())  // BakeInfoMask
    {
-      stream->read(&mReflectionPath);
       stream->read(&mProbeUniqueID);
    }
 
@@ -429,10 +412,6 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
 
    if (stream->readFlag())  // ModeMask
    {
-      U32 indirectModeType = AmbientColor;
-      stream->read(&indirectModeType);
-      mIndrectLightingModeType = (IndrectLightingModeType)indirectModeType;
-
       U32 reflectModeType = BakedCubemap;
       stream->read(&reflectModeType);
       mReflectionModeType = (ReflectionModeType)reflectModeType;
@@ -461,6 +440,8 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
    {
       updateMaterial();
    }
+
+   //PROBEMGR->updateProbes();
 }
 
 void ReflectionProbe::createGeometry()
@@ -484,7 +465,6 @@ void ReflectionProbe::createGeometry()
 //-----------------------------------------------------------------------------
 // Object Rendering
 //-----------------------------------------------------------------------------
-
 void ReflectionProbe::updateProbeParams()
 {
    if (mProbeInfo == nullptr)
@@ -496,19 +476,11 @@ void ReflectionProbe::updateProbeParams()
 
    updateMaterial();
 
-   mProbeInfo->mAmbient = LinearColorF(0, 0, 0, 0);
-
    mProbeInfo->mProbeShapeType = mProbeShapeType;
 
    mProbeInfo->mTransform = getWorldTransform();
-   mProbeInfo->mTransform.inverse();
-   mProbeInfo->setPosition(getPosition());
 
-   //Point3F pos = mProbeInfo->mTransform.getPosition();
-
-   //Update the bounds
-   //mObjBox.minExtents.set(-1, -1, -1);
-   //mObjBox.maxExtents.set(1, 1, 1);
+   mProbeInfo->mPosition = getPosition();
 
    mObjScale.set(mRadius, mRadius, mRadius);
 
@@ -584,6 +556,8 @@ void ReflectionProbe::updateMaterial()
 
    if (mReflectionModeType != DynamicCubemap)
    {
+      mProbeInfo->mCubeReflector.unregisterReflector();
+
       if ((mReflectionModeType == BakedCubemap) && !mProbeUniqueID.isEmpty())
       {
          if (mPrefilterMap != nullptr && mPrefilterMap->mCubemap.isValid())
@@ -609,6 +583,8 @@ void ReflectionProbe::updateMaterial()
       if (mReflectionModeType == DynamicCubemap && !mDynamicCubemap.isNull())
       {
          mProbeInfo->mCubemap = mDynamicCubemap;
+
+         mProbeInfo->mCubeReflector.registerReflector(this, reflectorDesc); //need to decide how we wanna do the reflectorDesc. static name or a field
       }
       else
       {
@@ -616,11 +592,6 @@ void ReflectionProbe::updateMaterial()
       }
    }
 
-   if (mBrdfTexture.isValid())
-   {
-      mProbeInfo->mBRDFTexture = &mBrdfTexture;
-   }
-
    //Make us ready to render
    if (mEnabled)
       mProbeInfo->mIsEnabled = true;
@@ -668,15 +639,6 @@ bool ReflectionProbe::createClientResources()
    if (mPrefilterMap->mCubemap.isNull())
       Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str());
 
-   //brdf lookup texture   
-   String brdfPath = Con::getVariable("$Core::BRDFTexture", "core/art/pbr/brdfTexture.dds");
-   mBrdfTexture = TEXMGR->createTexture(brdfPath, &GFXTexturePersistentProfile);
-
-   if (!mBrdfTexture)
-   {
-      return false;
-   }
-
    mResourcesCreated = true;
 
    return true;
@@ -703,7 +665,7 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
 
    if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS))
    {
-      bake("", 32);
+      bake();
       mDynamicLastBakeMS = Platform::getRealMilliseconds();
    }
 
@@ -870,244 +832,53 @@ DefineEngineMethod(ReflectionProbe, postApply, void, (), ,
 
 String ReflectionProbe::getPrefilterMapPath()
 {
-   if (mReflectionPath.isEmpty() || mProbeUniqueID.isEmpty())
+   if (mProbeUniqueID.isEmpty())
    {
       Con::errorf("ReflectionProbe::getPrefilterMapPath() - We don't have a set output path or persistant id, so no valid path can be provided!");
       return "";
    }
 
+   String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
+
    char fileName[256];
-   dSprintf(fileName, 256, "%s%s_Prefilter.dds", mReflectionPath.c_str(), mProbeUniqueID.c_str());
+   dSprintf(fileName, 256, "%s%s_Prefilter.dds", path.c_str(), mProbeUniqueID.c_str());
 
    return fileName;
 }
 
 String ReflectionProbe::getIrradianceMapPath()
 {
-   if (mReflectionPath.isEmpty() || mProbeUniqueID.isEmpty())
+   if (mProbeUniqueID.isEmpty())
    {
       Con::errorf("ReflectionProbe::getIrradianceMapPath() - We don't have a set output path or persistant id, so no valid path can be provided!");
       return "";
    }
 
+   String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
+
    char fileName[256];
-   dSprintf(fileName, 256, "%s%s_Irradiance.dds", mReflectionPath.c_str(), mProbeUniqueID.c_str());
+   dSprintf(fileName, 256, "%s%s_Irradiance.dds", path.c_str(), mProbeUniqueID.c_str());
 
    return fileName;
 }
 
-void ReflectionProbe::bake(String outputPath, S32 resolution, bool renderWithProbes)
+void ReflectionProbe::bake()
 {
-   GFXDEBUGEVENT_SCOPE(ReflectionProbe_Bake, ColorI::WHITE);
-
-   Con::warnf("ReflectionProbe::bake() - Beginning bake!");
-
-   U32 startMSTime = Platform::getRealMilliseconds();
-
-   /*PostEffect *preCapture = dynamic_cast<PostEffect*>(Sim::findObject("AL_PreCapture"));
-   PostEffect *deferredShading = dynamic_cast<PostEffect*>(Sim::findObject("AL_DeferredShading"));
-   if (preCapture)
-   {
-	   preCapture->setShaderConst("$radius",String::ToString(mRadius));
-	   preCapture->setShaderConst("$captureRez", String::ToString(F32(resolution)));
-	   preCapture->enable();
-   }
-   if (deferredShading)
-      deferredShading->disable();*/
-
-   GFXCubemapHandle sceneCaptureCubemap;
-
-   if (mReflectionModeType == DynamicCubemap && mDynamicCubemap.isNull())
-   {
-      //mCubemap->createMap();
-      mDynamicCubemap = GFX->createCubemap();
-
-      if(mUseHDRCaptures)
-         mDynamicCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
-      else
-         mDynamicCubemap->initDynamic(resolution, GFXFormatB8G8R8A8);
-
-      sceneCaptureCubemap = mDynamicCubemap;
-   }
-   else if (mReflectionModeType != DynamicCubemap)
-   {
-      //Prep our bake path
-      if (mReflectionPath.isEmpty())
-      {
-         Con::errorf("ReflectionProbe::bake() - Unable to bake our captures because probe doesn't have a path set");
-         return;
-      }
-
-      if (mProbeUniqueID.isEmpty())
-      {
-         Con::errorf("ReflectionProbe::bake() - Unable to bake our captures because probe doesn't have a unique ID set");
-         return;
-      }
-
-      sceneCaptureCubemap = GFX->createCubemap();
-
-      if (mUseHDRCaptures)
-         sceneCaptureCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
-      else
-         sceneCaptureCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
-   }
-
-   bool validCubemap = true;
-
-   // Save the current transforms so we can restore
-   // it for child control rendering below.
-   GFXTransformSaver saver;
-
-   //bool saveEditingMission = gEditingMission;
-   //gEditingMission = false;
-
-   //Set this to true to use the prior method where it goes through the SPT_Reflect path for the bake
-
-   bool probeRenderState = RenderProbeMgr::smRenderReflectionProbes;
-
-   if (!renderWithProbes)
-      RenderProbeMgr::smRenderReflectionProbes = false;
-
-   for (U32 i = 0; i < 6; ++i)
-   {
-      GFXTexHandle blendTex;
-      blendTex.set(resolution, resolution, GFXFormatR16G16B16A16F, &GFXRenderTargetProfile, "");
-
-      GFXTextureTargetRef baseTarget = GFX->allocRenderToTextureTarget();
-
-      GFX->clearTextureStateImmediate(0);
-      
-      baseTarget->attachTexture(GFXTextureTarget::Color0, sceneCaptureCubemap, i);
-
-      // Standard view that will be overridden below.
-      VectorF vLookatPt(0.0f, 0.0f, 0.0f), vUpVec(0.0f, 0.0f, 0.0f), vRight(0.0f, 0.0f, 0.0f);
-
-      switch (i)
-      {
-         case 0: // D3DCUBEMAP_FACE_POSITIVE_X:
-            vLookatPt = VectorF(1.0f, 0.0f, 0.0f);
-            vUpVec = VectorF(0.0f, 1.0f, 0.0f);
-            break;
-         case 1: // D3DCUBEMAP_FACE_NEGATIVE_X:
-            vLookatPt = VectorF(-1.0f, 0.0f, 0.0f);
-            vUpVec = VectorF(0.0f, 1.0f, 0.0f);
-            break;
-         case 2: // D3DCUBEMAP_FACE_POSITIVE_Y:
-            vLookatPt = VectorF(0.0f, 1.0f, 0.0f);
-            vUpVec = VectorF(0.0f, 0.0f, -1.0f);
-            break;
-         case 3: // D3DCUBEMAP_FACE_NEGATIVE_Y:
-            vLookatPt = VectorF(0.0f, -1.0f, 0.0f);
-            vUpVec = VectorF(0.0f, 0.0f, 1.0f);
-            break;
-         case 4: // D3DCUBEMAP_FACE_POSITIVE_Z:
-            vLookatPt = VectorF(0.0f, 0.0f, 1.0f);
-            vUpVec = VectorF(0.0f, 1.0f, 0.0f);
-            break;
-         case 5: // D3DCUBEMAP_FACE_NEGATIVE_Z:
-            vLookatPt = VectorF(0.0f, 0.0f, -1.0f);
-            vUpVec = VectorF(0.0f, 1.0f, 0.0f);
-            break;
-      }
-
-      // create camera matrix
-      VectorF cross = mCross(vUpVec, vLookatPt);
-      cross.normalizeSafe();
-
-      MatrixF matView(true);
-      matView.setColumn(0, cross);
-      matView.setColumn(1, vLookatPt);
-      matView.setColumn(2, vUpVec);
-      matView.setPosition(getPosition()+mProbePosOffset);
-      matView.inverse();
-
-      // set projection to 90 degrees vertical and horizontal
-      F32 left, right, top, bottom;
-      F32 nearPlane = 0.01f;
-      F32 farDist = 1000.f;
-
-      MathUtils::makeFrustum(&left, &right, &top, &bottom, M_HALFPI_F, 1.0f, nearPlane);
-      Frustum frustum(false, left, right, top, bottom, nearPlane, farDist);
-
-      F32 detailAdjustBackup = TSShapeInstance::smDetailAdjust;
-      TSShapeInstance::smDetailAdjust *= getNextPow2(resolution);
-      renderFrame(&baseTarget, matView, frustum, mCaptureMask & EDITOR_RENDER_TYPEMASK, gCanvasClearColor);
-      TSShapeInstance::smDetailAdjust = detailAdjustBackup;
-
-      baseTarget->resolve();
-   }
-
-   if (sceneCaptureCubemap.isValid())
-   {
-      validCubemap = true;
-      mDirty = false;
-   }
-   else
-   {
-      validCubemap = false;
-   }
-
-   //Now, save out the maps
-   //create irridiance cubemap
-   if (validCubemap)
-   {
-      bool se = isServerObject();
-
-      //Just to ensure we're prepped for the generation
-      createClientResources();
-
-      //Prep it with whatever resolution we've dictated for our bake
-      if (mUseHDRCaptures)
-      {
-         mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
-         mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
-      }
-      else
-      {
-         mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
-         mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
-      }
-
-      //IBLUtilities::GenerateAndSaveIrradianceMap(getIrradianceMapPath(), resolution, sceneCaptureCubemap, mIrridianceMap->mCubemap);
-      //IBLUtilities::GenerateAndSavePrefilterMap(getPrefilterMapPath(), resolution, sceneCaptureCubemap, mPrefilterMipLevels, mPrefilterMap->mCubemap);
-
-      GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
-
-      IBLUtilities::GenerateIrradianceMap(renderTarget, sceneCaptureCubemap, mIrridianceMap->mCubemap);
-      IBLUtilities::GeneratePrefilterMap(renderTarget, sceneCaptureCubemap, mPrefilterMipLevels, mPrefilterMap->mCubemap);
-
-      IBLUtilities::SaveCubeMap(getIrradianceMapPath(), mIrridianceMap->mCubemap);
-      IBLUtilities::SaveCubeMap(getPrefilterMapPath(), mPrefilterMap->mCubemap);
-   }
-   else
-   {
-      Con::errorf("ReflectionProbe::bake() - Didn't generate a valid scene capture cubemap, unable to generate prefilter and irradiance maps!");
-   }
-
-   if(!renderWithProbes)
-      RenderProbeMgr::smRenderReflectionProbes = probeRenderState;
-
-   setMaskBits(-1);
-
-   /*if (preCapture)
-      preCapture->disable();
-   if (deferredShading)
-      deferredShading->enable();*/
+   if (mReflectionModeType == DynamicCubemap)
+      return;
 
-   U32 endMSTime = Platform::getRealMilliseconds();
-   F32 diffTime = F32(endMSTime - startMSTime);
+   PROBEMGR->bakeProbe(this);
 
-   Con::warnf("ReflectionProbe::bake() - Finished bake! Took %g milliseconds", diffTime);
+   setMaskBits(CubemapMask);
 }
 
-DefineEngineMethod(ReflectionProbe, Bake, void, (String outputPath, S32 resolution, bool renderWithProbes), ("", 64, false),
+DefineEngineMethod(ReflectionProbe, Bake, void, (), ,
    "@brief returns true if control object is inside the fog\n\n.")
 {
    ReflectionProbe *clientProbe = (ReflectionProbe*)object->getClientObject();
 
    if (clientProbe)
    {
-      clientProbe->bake(outputPath, resolution, renderWithProbes);
+      clientProbe->bake();
    }
-   //object->bake(outputPath, resolution);
 }

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

@@ -47,7 +47,6 @@
 
 class BaseMatInstance;
 
-
 //-----------------------------------------------------------------------------
 // This class implements a basic SceneObject that can exist in the world at a
 // 3D position and render itself. There are several valid ways to render an
@@ -60,16 +59,10 @@ class BaseMatInstance;
 class ReflectionProbe : public SceneObject
 {
    typedef SceneObject Parent;
+   friend class RenderProbeMgr;
 
 public:
 
-   enum IndrectLightingModeType
-   {
-      NoIndirect = 0,            
-      AmbientColor = 1, 
-      SphericalHarmonics = 2
-   };
-
    enum ReflectionModeType
    {
       NoReflection = 0,
@@ -114,9 +107,6 @@ protected:
    ProbeRenderInst* mProbeInfo;
    U32 mProbeInfoIdx;
 
-   //Indirect Lighting Contribution stuff
-   IndrectLightingModeType mIndrectLightingModeType;
-
    //Reflection Contribution stuff
    ReflectionModeType mReflectionModeType;
 
@@ -129,6 +119,10 @@ protected:
    GFXCubemapHandle  mDynamicCubemap;
    bool mUseCubemap;
 
+   String cubeDescName;
+   U32 cubeDescId;
+   ReflectorDesc *reflectorDesc;
+
    ///Prevents us from saving out the cubemaps(for now) but allows us the full HDR range on the in-memory cubemap captures
    bool mUseHDRCaptures;
 
@@ -140,10 +134,6 @@ protected:
    U32 mPrefilterMipLevels;
    U32 mPrefilterSize;
 
-   //brdflookup resources - shares the texture target with the prefilter
-   GFXTexHandle mBrdfTexture;
-
-   String mReflectionPath;
    String mProbeUniqueID;
 
    // Define our vertex format here so we don't have to
@@ -246,7 +236,7 @@ public:
    //Baking
    String getPrefilterMapPath();
    String getIrradianceMapPath();
-   void bake(String outputPath, S32 resolution, bool renderWithProbes = false);
+   void bake();
 
    const U32 getProbeInfoIndex() { return mProbeInfoIdx; }
 };
@@ -254,9 +244,6 @@ public:
 typedef ProbeRenderInst::ProbeShapeType ReflectProbeType;
 DefineEnumType(ReflectProbeType);
 
-typedef ReflectionProbe::IndrectLightingModeType IndrectLightingModeEnum;
-DefineEnumType(IndrectLightingModeEnum);
-
 typedef ReflectionProbe::ReflectionModeType ReflectionModeEnum;
 DefineEnumType(ReflectionModeEnum);
 

+ 0 - 2
Engine/source/T3D/lighting/skylight.cpp

@@ -171,8 +171,6 @@ void Skylight::updateProbeParams()
 
    setGlobalBounds();
 
-   mProbeInfo->mAmbient = LinearColorF(1, 1, 1, 1);
-
    mProbeInfo->mIsSkylight = true; 
    mProbeInfo->mScore = -1.0f; //sky comes first
 }

+ 232 - 0
Engine/source/T3D/lighting/sphereEnvironmentProbe.cpp

@@ -0,0 +1,232 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "T3D/lighting/sphereEnvironmentProbe.h"
+#include "math/mathIO.h"
+#include "scene/sceneRenderState.h"
+#include "console/consoleTypes.h"
+#include "core/stream/bitStream.h"
+#include "materials/baseMatInstance.h"
+#include "console/engineAPI.h"
+#include "gfx/gfxDrawUtil.h"
+#include "gfx/gfxDebugEvent.h"
+#include "gfx/gfxTransformSaver.h"
+#include "math/mathUtils.h"
+#include "gfx/bitmap/gBitmap.h"
+#include "core/stream/fileStream.h"
+#include "core/fileObject.h"
+#include "core/resourceManager.h"
+#include "console/simPersistId.h"
+#include "T3D/gameFunctions.h"
+#include "postFx/postEffect.h"
+#include "renderInstance/renderProbeMgr.h"
+#include "renderInstance/renderProbeMgr.h"
+
+#include "math/util/sphereMesh.h"
+#include "materials/materialManager.h"
+#include "math/util/matrixSet.h"
+#include "gfx/bitmap/cubemapSaver.h"
+
+#include "materials/materialFeatureTypes.h"
+
+#include "materials/shaderData.h"
+#include "gfx/gfxTextureManager.h"
+
+#include "gfx/bitmap/imageUtils.h"
+
+#include "T3D/lighting/IBLUtilities.h"
+
+extern bool gEditingMission;
+extern ColorI gCanvasClearColor;
+
+IMPLEMENT_CO_NETOBJECT_V1(SphereEnvironmentProbe);
+
+ConsoleDocClass(SphereEnvironmentProbe,
+   "@brief An example scene object which renders a mesh.\n\n"
+   "This class implements a basic SceneObject that can exist in the world at a "
+   "3D position and render itself. There are several valid ways to render an "
+   "object in Torque. This class implements the preferred rendering method which "
+   "is to submit a MeshRenderInst along with a Material, vertex buffer, "
+   "primitive buffer, and transform and allow the RenderMeshMgr handle the "
+   "actual setup and rendering for you.\n\n"
+   "See the C++ code for implementation details.\n\n"
+   "@ingroup Examples\n");
+
+//-----------------------------------------------------------------------------
+// Object setup and teardown
+//-----------------------------------------------------------------------------
+SphereEnvironmentProbe::SphereEnvironmentProbe() : ReflectionProbe()
+{
+   mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK;
+}
+
+SphereEnvironmentProbe::~SphereEnvironmentProbe()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Object Editing
+//-----------------------------------------------------------------------------
+void SphereEnvironmentProbe::initPersistFields()
+{
+   // SceneObject already handles exposing the transform
+   Parent::initPersistFields();
+}
+
+void SphereEnvironmentProbe::inspectPostApply()
+{
+   Parent::inspectPostApply();
+
+   mDirty = true;
+
+   // Flag the network mask to send the updates
+   // to the client object
+   setMaskBits(-1);
+}
+
+bool SphereEnvironmentProbe::onAdd()
+{
+   if (!Parent::onAdd())
+      return false;
+
+   return true;
+}
+
+void SphereEnvironmentProbe::onRemove()
+{
+   Parent::onRemove();
+}
+
+void SphereEnvironmentProbe::setTransform(const MatrixF & mat)
+{
+   // Let SceneObject handle all of the matrix manipulation
+   Parent::setTransform(mat);
+
+   mDirty = true;
+
+   // Dirty our network mask so that the new transform gets
+   // transmitted to the client object
+   setMaskBits(TransformMask);
+}
+
+U32 SphereEnvironmentProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
+{
+   // Allow the Parent to get a crack at writing its info
+   U32 retMask = Parent::packUpdate(conn, mask, stream);
+
+   return retMask;
+}
+
+void SphereEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
+{
+   // Let the Parent read any info it sent
+   Parent::unpackUpdate(conn, stream);
+}
+
+//-----------------------------------------------------------------------------
+// Object Rendering
+//-----------------------------------------------------------------------------
+
+void SphereEnvironmentProbe::updateProbeParams()
+{
+   Parent::updateProbeParams();
+
+   mProbeInfo->mProbeShapeType = ProbeRenderInst::Sphere;
+}
+
+void SphereEnvironmentProbe::prepRenderImage(SceneRenderState *state)
+{
+   if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
+      return;
+
+   //special hook-in for SphereEnvironmentProbes
+   Point3F camPos = state->getCameraPosition();
+   mProbeInfo->mBounds.setCenter(camPos);
+
+   mProbeInfo->setPosition(camPos);
+
+   if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
+   {
+      GFXTransformSaver saver;
+
+      // Calculate the distance of this object from the camera
+      Point3F cameraOffset;
+      getRenderTransform().getColumn(3, &cameraOffset);
+      cameraOffset -= state->getDiffuseCameraPosition();
+      F32 dist = cameraOffset.len();
+      if (dist < 0.01f)
+         dist = 0.01f;
+
+      // Set up the LOD for the shape
+      F32 invScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
+
+      mEditorShapeInst->setDetailFromDistance(state, dist * invScale);
+
+      // Make sure we have a valid level of detail
+      if (mEditorShapeInst->getCurrentDetail() < 0)
+         return;
+
+      BaseMatInstance* probePrevMat = mEditorShapeInst->getMaterialList()->getMaterialInst(0);
+
+      setPreviewMatParameters(state, probePrevMat);
+
+      // GFXTransformSaver is a handy helper class that restores
+      // the current GFX matrices to their original values when
+      // it goes out of scope at the end of the function
+
+      // Set up our TS render state      
+      TSRenderState rdata;
+      rdata.setSceneState(state);
+      rdata.setFadeOverride(1.0f);
+
+      // We might have some forward lit materials
+      // so pass down a query to gather lights.
+      LightQuery query;
+      query.init(getWorldSphere());
+      rdata.setLightQuery(&query);
+
+      // Set the world matrix to the objects render transform
+      MatrixF mat = getRenderTransform();
+      mat.scale(Point3F(1, 1, 1));
+      GFX->setWorldMatrix(mat);
+
+      // Animate the the shape
+      mEditorShapeInst->animate();
+
+      // Allow the shape to submit the RenderInst(s) for itself
+      mEditorShapeInst->render(rdata);
+
+      saver.restore();
+   }
+
+   // If the light is selected or light visualization
+   // is enabled then register the callback.
+   const bool isSelectedInEditor = (gEditingMission && isSelected());
+   if (isSelectedInEditor)
+   {
+   }
+}
+
+void SphereEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
+{
+   Parent::setPreviewMatParameters(renderState, mat);
+}

+ 111 - 0
Engine/source/T3D/lighting/sphereEnvironmentProbe.h

@@ -0,0 +1,111 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef SPHERE_ENVIRONMENT_PROBE_H
+#define SPHERE_ENVIRONMENT_PROBE_H
+
+#ifndef REFLECTIONPROBE_H
+#include "T3D/lighting/reflectionProbe.h"
+#endif
+#ifndef _GFXVERTEXBUFFER_H_
+#include "gfx/gfxVertexBuffer.h"
+#endif
+#ifndef _GFXPRIMITIVEBUFFER_H_
+#include "gfx/gfxPrimitiveBuffer.h"
+#endif
+#ifndef _TSSHAPEINSTANCE_H_
+#include "ts/tsShapeInstance.h"
+#endif
+#include "lighting/lightInfo.h"
+
+#ifndef _RENDERPASSMANAGER_H_
+#include "renderInstance/renderPassManager.h"
+#endif
+
+class BaseMatInstance;
+
+
+//-----------------------------------------------------------------------------
+// This class implements a basic SceneObject that can exist in the world at a
+// 3D position and render itself. There are several valid ways to render an
+// object in Torque. This class implements the preferred rendering method which
+// is to submit a MeshRenderInst along with a Material, vertex buffer,
+// primitive buffer, and transform and allow the RenderMeshMgr handle the
+// actual setup and rendering for you.
+//-----------------------------------------------------------------------------
+
+class SphereEnvironmentProbe : public ReflectionProbe
+{
+   typedef ReflectionProbe Parent;
+
+public:
+   SphereEnvironmentProbe();
+   virtual ~SphereEnvironmentProbe();
+
+   // Declare this object as a ConsoleObject so that we can
+   // instantiate it into the world and network it
+   DECLARE_CONOBJECT(SphereEnvironmentProbe);
+
+   //--------------------------------------------------------------------------
+   // Object Editing
+   // Since there is always a server and a client object in Torque and we
+   // actually edit the server object we need to implement some basic
+   // networking functions
+   //--------------------------------------------------------------------------
+   // Set up any fields that we want to be editable (like position)
+   static void initPersistFields();
+
+   // Allows the object to update its editable settings
+   // from the server object to the client
+   virtual void inspectPostApply();
+
+   // Handle when we are added to the scene and removed from the scene
+   bool onAdd();
+   void onRemove();
+
+   // Override this so that we can dirty the network flag when it is called
+   void setTransform(const MatrixF &mat);
+
+   // This function handles sending the relevant data from the server
+   // object to the client object
+   U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
+   // This function handles receiving relevant data from the server
+   // object and applying it to the client object
+   void unpackUpdate(NetConnection *conn, BitStream *stream);
+
+   //--------------------------------------------------------------------------
+   // Object Rendering
+   // Torque utilizes a "batch" rendering system. This means that it builds a
+   // list of objects that need to render (via RenderInst's) and then renders
+   // them all in one batch. This allows it to optimized on things like
+   // minimizing texture, state, and shader switching by grouping objects that
+   // use the same Materials.
+   //--------------------------------------------------------------------------
+   virtual void updateProbeParams();
+
+   // This is the function that allows this object to submit itself for rendering
+   void prepRenderImage(SceneRenderState *state);
+
+   void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
+};
+
+#endif // SPHERE_ENVIRONMENT_PROBE_H

+ 365 - 56
Engine/source/postFx/postEffect.cpp

@@ -170,6 +170,57 @@ void PostEffect::EffectConst::set( const String &newVal )
 
    mStringVal = newVal;
    mDirty = true;
+   mValueType = StringType;
+}
+
+void PostEffect::EffectConst::set(const F32 &newVal)
+{
+   if (mFloatVal == newVal)
+      return;
+
+   mFloatVal = newVal;
+   mDirty = true;
+   mValueType = FloatType;
+}
+
+void PostEffect::EffectConst::set(const Point4F &newVal)
+{
+   if (mPointVal == newVal)
+      return;
+
+   mPointVal = newVal;
+   mDirty = true;
+   mValueType = PointType;
+}
+
+void PostEffect::EffectConst::set(const MatrixF &newVal)
+{
+   if (mMatrixVal == newVal)
+      return;
+
+   mMatrixVal = newVal;
+   mDirty = true;
+   mValueType = MatrixType;
+}
+
+void PostEffect::EffectConst::set(const Vector<Point4F> &newVal)
+{
+   //if (mPointArrayVal == newVal)
+   //   return;
+
+   mPointArrayVal = newVal;
+   mDirty = true;
+   mValueType = PointArrayType;
+}
+
+void PostEffect::EffectConst::set(const Vector<MatrixF> &newVal)
+{
+   //if (mMatrixArrayVal == newVal)
+   //   return;
+
+   mMatrixArrayVal = newVal;
+   mDirty = true;
+   mValueType = MatrixArrayType;
 }
 
 void PostEffect::EffectConst::setToBuffer( GFXShaderConstBufferRef buff )
@@ -194,71 +245,179 @@ void PostEffect::EffectConst::setToBuffer( GFXShaderConstBufferRef buff )
    // Expand to other types as necessary.
    U32 arraySize = mHandle->getArraySize();
 
-   const char *strVal = mStringVal.c_str();
-
-   if ( type == GFXSCT_Int )
+   if (mValueType == StringType)
    {
-      S32 val;
-      Con::setData( TypeS32, &val, 0, 1, &strVal );
-      buff->set( mHandle, val );
+      const char *strVal = mStringVal.c_str();
+
+      if (type == GFXSCT_Int)
+      {
+         S32 val;
+         Con::setData(TypeS32, &val, 0, 1, &strVal);
+         buff->set(mHandle, val);
+      }
+      else if (type == GFXSCT_Float)
+      {
+         F32 val;
+         Con::setData(TypeF32, &val, 0, 1, &strVal);
+         buff->set(mHandle, val);
+      }
+      else if (type == GFXSCT_Float2)
+      {
+         Point2F val;
+         Con::setData(TypePoint2F, &val, 0, 1, &strVal);
+         buff->set(mHandle, val);
+      }
+      else if (type == GFXSCT_Float3)
+      {
+         Point3F val;
+         Con::setData(TypePoint3F, &val, 0, 1, &strVal);
+         buff->set(mHandle, val);
+      }
+      else if (type == GFXSCT_Float4)
+      {
+         Point4F val;
+
+         if (arraySize > 1)
+         {
+            // Do array setup!
+            //U32 unitCount = StringUnit::getUnitCount( strVal, "\t" );
+            //AssertFatal( unitCount == arraySize, "" );
+
+            String tmpString;
+            Vector<Point4F> valArray;
+
+            for (U32 i = 0; i < arraySize; i++)
+            {
+               tmpString = StringUnit::getUnit(strVal, i, "\t");
+               valArray.increment();
+               const char *tmpCStr = tmpString.c_str();
+
+               Con::setData(TypePoint4F, &valArray.last(), 0, 1, &tmpCStr);
+            }
+
+            AlignedArray<Point4F> rectData(valArray.size(), sizeof(Point4F), (U8*)valArray.address(), false);
+            buff->set(mHandle, rectData);
+         }
+         else
+         {
+            // Do regular setup.
+            Con::setData(TypePoint4F, &val, 0, 1, &strVal);
+            buff->set(mHandle, val);
+         }
+      }
+      else
+      {
+#if TORQUE_DEBUG
+         const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str());
+         Con::errorf(err);
+         GFXAssertFatal(0, err);
+#endif
+      }
    }
-   else if ( type == GFXSCT_Float )
+   else if (mValueType == FloatType)
    {
-      F32 val;
-      Con::setData( TypeF32, &val, 0, 1, &strVal );
-      buff->set( mHandle, val );
+      if (type == GFXSCT_Float)
+      {
+         buff->set(mHandle, mFloatVal);
+      }
+      else
+      {
+#if TORQUE_DEBUG
+         const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str());
+         Con::errorf(err);
+         GFXAssertFatal(0, err);
+#endif
+      }
    }
-   else if ( type == GFXSCT_Float2 )
+   else if (mValueType == PointType)
    {
-      Point2F val;
-      Con::setData( TypePoint2F, &val, 0, 1, &strVal );
-      buff->set( mHandle, val );
+      if (type == GFXSCT_Float2)
+      {
+         buff->set(mHandle, Point2F(mPointVal.x, mPointVal.y));
+      }
+      else if (type == GFXSCT_Float3)
+      {
+         buff->set(mHandle, Point3F(mPointVal.x, mPointVal.y, mPointVal.z));
+      }
+      else if (type == GFXSCT_Float4)
+      {
+         buff->set(mHandle, mPointVal);
+      }
+      else
+      {
+#if TORQUE_DEBUG
+         const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str());
+         Con::errorf(err);
+         GFXAssertFatal(0, err);
+#endif
+      }
    }
-   else if ( type == GFXSCT_Float3 )
+   else if (mValueType == MatrixType)
    {
-      Point3F val;
-      Con::setData( TypePoint3F, &val, 0, 1, &strVal );
-      buff->set( mHandle, val );
+      if (type == GFXSCT_Float4x4)
+      {
+         buff->set(mHandle, mMatrixVal);
+      }
+      else
+      {
+   #if TORQUE_DEBUG
+         const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str());
+         Con::errorf(err);
+         GFXAssertFatal(0, err);
+   #endif
+      }
    }
-   else if ( type == GFXSCT_Float4 )
+   else if (mValueType == PointArrayType)
    {
-      Point4F val;
-
-      if ( arraySize > 1 )
+      if (type == GFXSCT_Float4)
       {
-         // Do array setup!
-         //U32 unitCount = StringUnit::getUnitCount( strVal, "\t" );
-         //AssertFatal( unitCount == arraySize, "" );
-
-         String tmpString;
-         Vector<Point4F> valArray;
-
-         for ( U32 i = 0; i < arraySize; i++ )
+         if (arraySize != mPointArrayVal.size())
          {
-            tmpString = StringUnit::getUnit( strVal, i, "\t" );
-            valArray.increment();
-            const char *tmpCStr = tmpString.c_str();
-
-            Con::setData( TypePoint4F, &valArray.last(), 0, 1, &tmpCStr );
+         #if TORQUE_DEBUG
+            const char* err = avar("PostEffect::EffectConst::setToBuffer PointArrayType, attempted to feed an array that does not match the uniform array's size!");
+            Con::errorf(err);
+            GFXAssertFatal(0, err);
+         #endif
+            return;
          }
 
-         AlignedArray<Point4F> rectData( valArray.size(), sizeof( Point4F ), (U8*)valArray.address(), false );
-         buff->set( mHandle, rectData );
+         AlignedArray<Point4F> alignedVal = AlignedArray<Point4F>(arraySize, sizeof(Point4F), (U8*)mPointArrayVal.address(), false);
+
+         buff->set(mHandle, alignedVal);
       }
       else
       {
-         // Do regular setup.
-         Con::setData( TypePoint4F, &val, 0, 1, &strVal );
-         buff->set( mHandle, val );
+   #if TORQUE_DEBUG
+         const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str());
+         Con::errorf(err);
+         GFXAssertFatal(0, err);
+   #endif
       }
    }
-   else
+   else if (mValueType == MatrixArrayType)
    {
-#if TORQUE_DEBUG
-      const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str());
-      Con::errorf(err);
-      GFXAssertFatal(0,err);
-#endif
+      if (type == GFXSCT_Float4x4)
+      {
+         if (arraySize != mMatrixArrayVal.size())
+         {
+   #if TORQUE_DEBUG
+            const char* err = avar("PostEffect::EffectConst::setToBuffer MatrixArrayType, attempted to feed an array that does not match the uniform array's size!");
+            Con::errorf(err);
+            GFXAssertFatal(0, err);
+   #endif
+            return;
+         }
+
+         buff->set(mHandle, mMatrixArrayVal.address(), arraySize);
+      }
+      else
+      {
+   #if TORQUE_DEBUG
+         const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str());
+         Con::errorf(err);
+         GFXAssertFatal(0, err);
+   #endif
+      }
    }
 }
 
@@ -413,6 +572,8 @@ bool PostEffect::onAdd()
    // Find additional textures
    for( S32 i = 0; i < NumTextures; i++ )
    {
+      mTextureType[i] = NormalTextureType;
+
       String texFilename = mTexFilename[i];
 
       // Skip empty stages or ones with variable or target names.
@@ -915,6 +1076,11 @@ void PostEffect::_setupConstants( const SceneRenderState *state )
       setShaderConsts_callback();
    }   
 
+   if (mShaderName == String("PFX_ReflectionProbeArray") || getName() == StringTable->insert("reflectionProbeArrayPostFX"))
+   {
+      bool derp = true;
+   }
+
    EffectConstTable::Iterator iter = mEffectConsts.begin();
    for ( ; iter != mEffectConsts.end(); iter++ )
       iter->value->setToBuffer( mShaderConsts );
@@ -972,6 +1138,30 @@ void PostEffect::_setupTexture( U32 stage, GFXTexHandle &inputTex, const RectI *
       GFX->setTexture( stage, theTex );
 }
 
+void PostEffect::_setupCubemapTexture(U32 stage, GFXCubemapHandle &inputTex)
+{
+   RectI viewport = GFX->getViewport();
+
+   mActiveTextures[stage] = nullptr;
+   mActiveNamedTarget[stage] = nullptr;
+   mActiveTextureViewport[stage] = viewport;
+
+   if (inputTex.isValid())
+      GFX->setCubeTexture(stage, inputTex);
+}
+
+void PostEffect::_setupCubemapArrayTexture(U32 stage, GFXCubemapArrayHandle &inputTex)
+{
+   RectI viewport = GFX->getViewport();
+
+   mActiveTextures[stage] = nullptr;
+   mActiveNamedTarget[stage] = nullptr;
+   mActiveTextureViewport[stage] = viewport;
+
+   if (inputTex.isValid())
+      GFX->setCubeArrayTexture(stage, inputTex);
+}
+
 void PostEffect::_setupTransforms()
 {
    // Set everything to identity.
@@ -1188,8 +1378,15 @@ void PostEffect::process(  const SceneRenderState *state,
    GFXTransformSaver saver;
 
    // Set the textures.
-   for ( U32 i = 0; i < NumTextures; i++ )
-      _setupTexture( i, inOutTex, inTexViewport );
+   for (U32 i = 0; i < NumTextures; i++)
+   {
+      if (mTextureType[i] == NormalTextureType)
+         _setupTexture(i, inOutTex, inTexViewport);
+      else if (mTextureType[i] == CubemapType)
+         _setupCubemapTexture(i, mCubemapTextures[i]);
+      else if (mTextureType[i] == CubemapArrayType)
+         _setupCubemapArrayTexture(i, mCubemapArrayTextures[i]);
+   }
 
    _setupStateBlock( state ) ;
    _setupTransforms();
@@ -1406,6 +1603,38 @@ void PostEffect::setTexture( U32 index, const String &texFilePath )
 
     // Try to load the texture.
     mTextures[index].set( texFilePath, &PostFxTextureProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) );
+
+    mTextureType[index] = NormalTextureType;
+}
+
+void PostEffect::setCubemapTexture(U32 index, const GFXCubemapHandle &cubemapHandle)
+{
+   // Set the new texture name.
+   mCubemapTextures[index].free();
+
+   // Skip empty stages or ones with variable or target names.
+   if (cubemapHandle.isNull())
+      return;
+
+   // Try to load the texture.
+   mCubemapTextures[index] = cubemapHandle;
+
+   mTextureType[index] = CubemapType;
+}
+
+void PostEffect::setCubemapArrayTexture(U32 index, const GFXCubemapArrayHandle &cubemapArrayHandle)
+{
+   // Set the new texture name.
+   mCubemapArrayTextures[index].free();
+
+   // Skip empty stages or ones with variable or target names.
+   if (cubemapArrayHandle.isNull())
+      return;
+
+   // Try to load the texture.
+   mCubemapArrayTextures[index] = cubemapArrayHandle;
+
+   mTextureType[index] = CubemapArrayType;
 }
 
 void PostEffect::setShaderConst( const String &name, const String &val )
@@ -1422,6 +1651,76 @@ void PostEffect::setShaderConst( const String &name, const String &val )
    iter->value->set( val );
 }
 
+void PostEffect::setShaderConst(const String &name, const F32 &val)
+{
+   PROFILE_SCOPE(PostEffect_SetShaderConst_Float);
+
+   EffectConstTable::Iterator iter = mEffectConsts.find(name);
+   if (iter == mEffectConsts.end())
+   {
+      EffectConst *newConst = new EffectConst(name, val);
+      iter = mEffectConsts.insertUnique(name, newConst);
+   }
+
+   iter->value->set(val);
+}
+
+void PostEffect::setShaderConst(const String &name, const Point4F &val)
+{
+   PROFILE_SCOPE(PostEffect_SetShaderConst_Point);
+
+   EffectConstTable::Iterator iter = mEffectConsts.find(name);
+   if (iter == mEffectConsts.end())
+   {
+      EffectConst *newConst = new EffectConst(name, val);
+      iter = mEffectConsts.insertUnique(name, newConst);
+   }
+
+   iter->value->set(val);
+}
+
+void PostEffect::setShaderConst(const String &name, const MatrixF &val)
+{
+   PROFILE_SCOPE(PostEffect_SetShaderConst_Matrix);
+
+   EffectConstTable::Iterator iter = mEffectConsts.find(name);
+   if (iter == mEffectConsts.end())
+   {
+      EffectConst *newConst = new EffectConst(name, val);
+      iter = mEffectConsts.insertUnique(name, newConst);
+   }
+
+   iter->value->set(val);
+}
+
+void PostEffect::setShaderConst(const String &name, const Vector<Point4F> &val)
+{
+   PROFILE_SCOPE(PostEffect_SetShaderConst_PointArray);
+
+   EffectConstTable::Iterator iter = mEffectConsts.find(name);
+   if (iter == mEffectConsts.end())
+   {
+      EffectConst *newConst = new EffectConst(name, val);
+      iter = mEffectConsts.insertUnique(name, newConst);
+   }
+
+   iter->value->set(val);
+}
+
+void PostEffect::setShaderConst(const String &name, const Vector<MatrixF> &val)
+{
+   PROFILE_SCOPE(PostEffect_SetShaderConst_MatrixArray);
+
+   EffectConstTable::Iterator iter = mEffectConsts.find(name);
+   if (iter == mEffectConsts.end())
+   {
+      EffectConst *newConst = new EffectConst(name, val);
+      iter = mEffectConsts.insertUnique(name, newConst);
+   }
+
+   iter->value->set(val);
+}
+
 F32 PostEffect::getAspectRatio() const
 {
    const Point2I &rtSize = GFX->getActiveRenderTarget()->getSize();
@@ -1434,6 +1733,11 @@ void PostEffect::_checkRequirements()
    // properly, we can find all the input textures,
    // and its formats are supported.
 
+   if (mShaderName == String("PFX_ReflectionProbeArray") || getName() == StringTable->insert("reflectionProbeArrayPostFX"))
+   {
+      bool derp = true;
+   }
+
    mIsValid = false;
    mUpdateShader = false;
    mShader = NULL;
@@ -1468,16 +1772,21 @@ void PostEffect::_checkRequirements()
    // they exist... else we're invalid.
    for ( U32 i=0; i < NumTextures; i++ )
    {
-      const String &texFilename = mTexFilename[i];
-
-      if ( texFilename.isNotEmpty() && texFilename[0] == '#' )
+      if (mTextureType[i] == NormalTextureType)
       {
-         NamedTexTarget *namedTarget = NamedTexTarget::find( texFilename.c_str() + 1 );
-         if ( !namedTarget )
-            return;
+         const String &texFilename = mTexFilename[i];
 
-         // Grab the macros for shader initialization.
-         namedTarget->getShaderMacros( &macros );
+         if (texFilename.isNotEmpty() && texFilename[0] == '#')
+         {
+            NamedTexTarget *namedTarget = NamedTexTarget::find(texFilename.c_str() + 1);
+            if (!namedTarget)
+            {
+               return;
+            }
+
+            // Grab the macros for shader initialization.
+            namedTarget->getShaderMacros(&macros);
+         }
       }
    }
 

+ 88 - 0
Engine/source/postFx/postEffect.h

@@ -41,6 +41,9 @@
 #ifndef _GFXTEXTUREHANDLE_H_
 #include "gfx/gfxTextureHandle.h"
 #endif
+#ifndef _GFXCUBEMAP_H_
+#include "gfx/gfxCubemap.h"
+#endif
 #ifndef _GFXTARGET_H_
 #include "gfx/gfxTarget.h"
 #endif
@@ -88,7 +91,16 @@ protected:
    FileName mTexFilename[NumTextures];
    bool mTexSRGB[NumTextures];
 
+   enum
+   {
+      NormalTextureType = 0,
+      CubemapType,
+      CubemapArrayType,
+   } mTextureType[NumTextures];
+
    GFXTexHandle mTextures[NumTextures];
+   GFXCubemapHandle mCubemapTextures[NumTextures];
+   GFXCubemapArrayHandle mCubemapArrayTextures[NumTextures];
 
    NamedTexTarget mNamedTarget;
    NamedTexTarget mNamedTargetDepthStencil; 
@@ -210,7 +222,52 @@ protected:
          set( val );
       }
 
+      EffectConst(const String &name, const F32 &val)
+         : mName(name),
+         mHandle(NULL),
+         mDirty(true)
+      {
+         set(val);
+      }
+
+      EffectConst(const String &name, const Point4F &val)
+         : mName(name),
+         mHandle(NULL),
+         mDirty(true)
+      {
+         set(val);
+      }
+
+      EffectConst(const String &name, const MatrixF &val)
+         : mName(name),
+         mHandle(NULL),
+         mDirty(true)
+      {
+         set(val);
+      }
+
+      EffectConst(const String &name, const Vector<Point4F> &val)
+         : mName(name),
+         mHandle(NULL),
+         mDirty(true)
+      {
+         set(val);
+      }
+
+      EffectConst(const String &name, const Vector<MatrixF> &val)
+         : mName(name),
+         mHandle(NULL),
+         mDirty(true)
+      {
+         set(val);
+      }
+
       void set( const String &newVal );
+      void set(const F32 &newVal);
+      void set(const Point4F &newVal);
+      void set(const MatrixF &newVal);
+      void set(const Vector<Point4F> &newVal);
+      void set(const Vector<MatrixF> &newVal);
 
       void setToBuffer( GFXShaderConstBufferRef buff );
 
@@ -220,6 +277,23 @@ protected:
 
       String mStringVal;
 
+      F32     mFloatVal;
+      Point4F mPointVal;
+      MatrixF mMatrixVal;
+
+      Vector<Point4F> mPointArrayVal;
+      Vector<MatrixF> mMatrixArrayVal;
+
+      enum
+      {
+         StringType,
+         FloatType,
+         PointType,
+         MatrixType,
+         PointArrayType,
+         MatrixArrayType
+      } mValueType;
+
       bool mDirty;
    };
 
@@ -245,6 +319,9 @@ protected:
 
    ///
    virtual void _setupTexture( U32 slot, GFXTexHandle &inputTex, const RectI *inTexViewport );
+   virtual void _setupCubemapTexture(U32 stage, GFXCubemapHandle &inputTex);
+   virtual void _setupCubemapArrayTexture(U32 slot, GFXCubemapArrayHandle &inputTex);
+
 
    /// Protected set method for toggling the enabled state.
    static bool _setIsEnabled( void *object, const char *index, const char *data );
@@ -339,6 +416,8 @@ public:
    F32 getPriority() const { return mRenderPriority; }
 
    void setTexture( U32 index, const String &filePath );
+   void setCubemapTexture(U32 index, const GFXCubemapHandle &cubemapHandle);
+   void setCubemapArrayTexture(U32 index, const GFXCubemapArrayHandle &cubemapArrayHandle);
 
    void setShaderMacro( const String &name, const String &value = String::EmptyString );
    bool removeShaderMacro( const String &name );
@@ -346,6 +425,11 @@ public:
 
    ///
    void setShaderConst( const String &name, const String &val );   
+   void setShaderConst(const String &name, const F32 &val);
+   void setShaderConst(const String &name, const Point4F &val);
+   void setShaderConst(const String &name, const MatrixF &val);
+   void setShaderConst(const String &name, const Vector<Point4F> &val);
+   void setShaderConst(const String &name, const Vector<MatrixF> &val);
 
    void setOnThisFrame( bool enabled ) { mOnThisFrame = enabled; }
    bool isOnThisFrame() { return mOnThisFrame; }
@@ -353,6 +437,10 @@ public:
    bool isOneFrameOnly() { return mOneFrameOnly; }   
 
    F32 getAspectRatio() const;
+
+   GFXShaderRef getShader() { return mShader; }
+   Vector<GFXShaderMacro>* getShaderMacros() { return &mShaderMacros; }
+   GFXShaderConstBufferRef getShaderConstBuffer() { return mShaderConsts; }
    
 
    enum PostEffectRequirements

+ 281 - 486
Engine/source/renderInstance/renderProbeMgr.cpp

@@ -36,6 +36,14 @@
 #include "materials/shaderData.h"
 
 #include "gfx/gfxTextureManager.h"
+
+#include "postFx/postEffect.h"
+#include "T3D/lighting/reflectionProbe.h"
+#include "T3D/lighting/IBLUtilities.h"
+
+//For our cameraQuery setup
+#include "T3D/gameTSCtrl.h"
+
 IMPLEMENT_CONOBJECT(RenderProbeMgr);
 
 ConsoleDocClass( RenderProbeMgr, 
@@ -66,22 +74,13 @@ S32 QSORT_CALLBACK AscendingReflectProbeInfluence(const void* a, const void* b)
 ProbeRenderInst::ProbeRenderInst() : SystemInterface(),
    mTransform(true),
    mDirty(false),
-   mAmbient(0.0f, 0.0f, 0.0f, 1.0f),
    mPriority(1.0f),
    mScore(0.0f),
-   mDebugRender(false),
    mCubemap(NULL),
    mIrradianceCubemap(NULL),
-   mBRDFTexture(NULL),
    mRadius(1.0f),
-   mIntensity(1.0f),
-   mProbePosOffset(0, 0, 0),
-   numPrims(0)
+   mProbePosOffset(0, 0, 0)
 {
-   for (U32 i = 0; i < 5; ++i)
-   {
-      mSHConstants[i] = 0;
-   }
 }
 
 ProbeRenderInst::~ProbeRenderInst()
@@ -94,46 +93,22 @@ ProbeRenderInst::~ProbeRenderInst()
    {
       mIrradianceCubemap.free();
    }
-   if (mBRDFTexture && mBRDFTexture->isValid())
-   {
-      mBRDFTexture->free();
-   }
 }
 
 void ProbeRenderInst::set(const ProbeRenderInst *probeInfo)
 {
    mTransform = probeInfo->mTransform;
-   mAmbient = probeInfo->mAmbient;
    mCubemap = probeInfo->mCubemap;
    mIrradianceCubemap = probeInfo->mIrradianceCubemap;
-   mBRDFTexture = probeInfo->mBRDFTexture;
    mRadius = probeInfo->mRadius;
-   mIntensity = probeInfo->mIntensity;
    mProbeShapeType = probeInfo->mProbeShapeType;
-   numPrims = probeInfo->numPrims;
-   numVerts = probeInfo->numVerts;
-   numIndicesForPoly = probeInfo->numIndicesForPoly;
    mBounds = probeInfo->mBounds;
    mIsSkylight = probeInfo->mIsSkylight;
    mScore = probeInfo->mScore;
-
-   for (U32 i = 0; i < 9; i++)
-   {
-      mSHTerms[i] = probeInfo->mSHTerms[i];
-   }
-
-   for (U32 i = 0; i < 5; i++)
-   {
-      mSHConstants[i] = probeInfo->mSHConstants[i];
-   }
-}
-
-void ProbeRenderInst::getWorldToLightProj(MatrixF *outMatrix) const
-{
-   *outMatrix = getTransform();
-   outMatrix->inverse();
 }
 
+//
+//
 ProbeShaderConstants::ProbeShaderConstants()
    : mInit(false),
    mShader(NULL),
@@ -190,83 +165,19 @@ void ProbeShaderConstants::_onShaderReload()
       init(mShader);
 }
 
-//
-//
-bool ReflectProbeMatInstance::init(const FeatureSet &features, const GFXVertexFormat *vertexFormat)
-{
-   mShaderMat = nullptr;
-
-   bool success = Parent::init(features, vertexFormat);
-
-   // If the initialization failed don't continue.
-   if (!success || !mProcessedMaterial || mProcessedMaterial->getNumPasses() == 0)
-      return false;
-
-   mShaderMat = static_cast<ProcessedShaderMaterial*>(getShaderMaterial());
-   mShaderMat->init(features, vertexFormat, mFeaturesDelegate);
-
-   //mShaderMat->setMaterialParameters(mDefaultParameters, 0);
-
-   return true;
-}
-
-bool ReflectProbeMatInstance::setupPass(SceneRenderState *state, const SceneData &sgData)
-{
-   if (!Parent::setupPass(state, sgData))
-      return false;
-
-   AssertFatal(mProcessedMaterial->getNumPasses() > 0, "No passes created! Ohnoes");
-   const RenderPassData *rpd = mProcessedMaterial->getPass(0);
-   AssertFatal(rpd, "No render pass data!");
-   AssertFatal(rpd->mRenderStates[0], "No render state 0!");
-
-   if (!mProjectionState)
-   {
-      GFXStateBlockDesc desc;
-      desc.setZReadWrite(false);
-      desc.zWriteEnable = false;
-      desc.setCullMode(GFXCullNone);
-      desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvDestAlpha, GFXBlendOpAdd);
-      mProjectionState = GFX->createStateBlock(desc);
-   }
-   // Now override stateblock with our own
-   GFX->setStateBlock(mProjectionState);
-
-   return true;
-}
-
 //
 //
 RenderProbeMgr::RenderProbeMgr()
 : RenderBinManager(RenderPassManager::RIT_Probes, 1.0f, 1.0f),
-   mReflectProbeMaterial(nullptr),
-   mSceneManager(nullptr),
    mLastShader(nullptr),
    mLastConstants(nullptr)
 {
-   String brdfPath = Con::getVariable("$Core::BRDFTexture", "core/art/pbr/brdfTexture.dds");
-   mBrdfTexture = TEXMGR->createTexture(brdfPath, &GFXTexturePersistentProfile);
-
-   probePositions.setSize(MAXPROBECOUNT);
-   probePositions.fill(Point3F::Zero);
+   mEffectiveProbeCount = 0;
+   mMipCount = 0;
 
-   probeWorldToObj.setSize(MAXPROBECOUNT);
-   probeWorldToObj.fill(MatrixF::Identity);
+   mProbeArrayEffect = nullptr;
 
-   probeBBMin.setSize(MAXPROBECOUNT);
-   probeBBMin.fill(Point3F::Zero);
-
-   probeBBMax.setSize(MAXPROBECOUNT);
-   probeBBMax.fill(Point3F::Zero);
-
-   probeUseSphereMode.setSize(MAXPROBECOUNT);
-   probeUseSphereMode.fill(0.0f);
-
-   probeRadius.setSize(MAXPROBECOUNT);
-   probeRadius.fill(0.0f);
-
-   probeAttenuation.setSize(MAXPROBECOUNT);
-   probeAttenuation.fill(0.0f);
+   smProbeManager = this;
 }
 
 RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
@@ -274,6 +185,12 @@ RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 proce
 {  
 }
 
+void RenderProbeMgr::onRemove()
+{
+   SAFE_DELETE(mLastConstants);
+
+   Parent::onRemove();
+}
 void RenderProbeMgr::initPersistFields()
 {
    Parent::initPersistFields();
@@ -311,6 +228,35 @@ void RenderProbeMgr::registerProbe(U32 probeIdx)
       return;
 
    mRegisteredProbes.push_back_unique(probeIdx);
+
+   //rebuild our probe data
+   //_setupStaticParameters();
+}
+
+void RenderProbeMgr::unregisterProbe(U32 probeIdx)
+{
+   //Mostly for consolidation, but also lets us sanity check or prep any other data we need for rendering this in one place at time of flagging for render
+   if (probeIdx >= ProbeRenderInst::all.size())
+      return;
+
+   mRegisteredProbes.remove(probeIdx);
+
+   //rebuild our probe data
+   //_setupStaticParameters();
+}
+
+//
+//
+PostEffect* RenderProbeMgr::getProbeArrayEffect()
+{
+   if (!mProbeArrayEffect)
+   {
+      mProbeArrayEffect = dynamic_cast<PostEffect*>(Sim::findObject("reflectionProbeArrayPostFX"));
+
+      if (!mProbeArrayEffect)
+         return nullptr;
+   }
+   return mProbeArrayEffect;
 }
 
 //remove
@@ -318,78 +264,97 @@ void RenderProbeMgr::registerProbe(U32 probeIdx)
 //Con::setIntVariable("lightMetrics::culledReflectProbes", 0/*mNumLightsCulled*/);
 //
 
-void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
+void RenderProbeMgr::updateProbes()
 {
-   PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
-   const Frustum &frustum = state->getCameraFrustum();
-
-   MatrixF invCam(frustum.getTransform());
-   invCam.inverse();
+	_setupStaticParameters();
+}
 
-   const Point3F *wsFrustumPoints = frustum.getPoints();
-   const Point3F& cameraPos = frustum.getPosition();
+void RenderProbeMgr::_setupStaticParameters()
+{
+   //Array rendering
+   U32 probeCount = ProbeRenderInst::all.size();
 
-   // Perform a camera offset.  We need to manually perform this offset on the sun (or vector) light's
-   // polygon, which is at the far plane.
-   Point3F cameraOffsetPos = cameraPos;
+   mEffectiveProbeCount = 0;
+   mMipCount = 0;
 
-   // Now build the quad for drawing full-screen vector light
-   // passes.... this is a volatile VB and updates every frame.
-   FarFrustumQuadVert verts[4];
+   if (probePositionsData.size() != MAXPROBECOUNT)
    {
-      verts[0].point.set(wsFrustumPoints[Frustum::FarTopLeft] - cameraPos);
-      invCam.mulP(wsFrustumPoints[Frustum::FarTopLeft], &verts[0].normal);
-      verts[0].texCoord.set(-1.0, 1.0);
-      verts[0].tangent.set(wsFrustumPoints[Frustum::FarTopLeft] - cameraOffsetPos);
-
-      verts[1].point.set(wsFrustumPoints[Frustum::FarTopRight] - cameraPos);
-      invCam.mulP(wsFrustumPoints[Frustum::FarTopRight], &verts[1].normal);
-      verts[1].texCoord.set(1.0, 1.0);
-      verts[1].tangent.set(wsFrustumPoints[Frustum::FarTopRight] - cameraOffsetPos);
-
-      verts[2].point.set(wsFrustumPoints[Frustum::FarBottomLeft] - cameraPos);
-      invCam.mulP(wsFrustumPoints[Frustum::FarBottomLeft], &verts[2].normal);
-      verts[2].texCoord.set(-1.0, -1.0);
-      verts[2].tangent.set(wsFrustumPoints[Frustum::FarBottomLeft] - cameraOffsetPos);
-
-      verts[3].point.set(wsFrustumPoints[Frustum::FarBottomRight] - cameraPos);
-      invCam.mulP(wsFrustumPoints[Frustum::FarBottomRight], &verts[3].normal);
-      verts[3].texCoord.set(1.0, -1.0);
-      verts[3].tangent.set(wsFrustumPoints[Frustum::FarBottomRight] - cameraOffsetPos);
+      probePositionsData.setSize(MAXPROBECOUNT);
+      probeWorldToObjData.setSize(MAXPROBECOUNT);
+      probeBBMinData.setSize(MAXPROBECOUNT);
+      probeBBMaxData.setSize(MAXPROBECOUNT);
+      probeUseSphereModeData.setSize(MAXPROBECOUNT);
+      probeRadiusData.setSize(MAXPROBECOUNT);
+      probeAttenuationData.setSize(MAXPROBECOUNT);
    }
 
-   mFarFrustumQuadVerts.set(GFX, 4);
-   dMemcpy(mFarFrustumQuadVerts.lock(), verts, sizeof(verts));
-   mFarFrustumQuadVerts.unlock();
+   probePositionsData.fill(Point4F::Zero);
+   probeWorldToObjData.fill(MatrixF::Identity);
+   probeBBMinData.fill(Point4F::Zero);
+   probeBBMaxData.fill(Point4F::Zero);
+   probeUseSphereModeData.fill(Point4F::Zero);
+   probeRadiusData.fill(Point4F::Zero);
+   probeAttenuationData.fill(Point4F::Zero);
 
-   PlaneF farPlane(wsFrustumPoints[Frustum::FarBottomLeft], wsFrustumPoints[Frustum::FarTopLeft], wsFrustumPoints[Frustum::FarTopRight]);
-   PlaneF vsFarPlane(verts[0].normal, verts[1].normal, verts[2].normal);
+   cubeMaps.clear();
+   irradMaps.clear();
 
-   ReflectProbeMaterialInfo* reflProbeMat = getReflectProbeMaterial();
-
-   if (reflProbeMat != nullptr && reflProbeMat->matInstance != nullptr)
+   for (U32 i = 0; i < probeCount; i++)
    {
-      reflProbeMat->setViewParameters(frustum.getNearDist(),
-         frustum.getFarDist(),
-         frustum.getPosition(),
-         farPlane,
-         vsFarPlane);
-   }
-}
+      if (mEffectiveProbeCount >= MAXPROBECOUNT)
+         break;
 
-RenderProbeMgr::ReflectProbeMaterialInfo* RenderProbeMgr::getReflectProbeMaterial()
-{
-   PROFILE_SCOPE(AdvancedLightBinManager_getReflectProbeMaterial);
+      const ProbeRenderInst& curEntry = *ProbeRenderInst::all[i];
+      if (!curEntry.mIsEnabled)
+         continue;
+
+      if (curEntry.mCubemap.isNull() || curEntry.mIrradianceCubemap.isNull())
+         continue;
+
+      if (!curEntry.mCubemap->isInitialised())
+         continue;
+
+      if (!curEntry.mIrradianceCubemap->isInitialised())
+         continue;
+
+      if (curEntry.mIsSkylight)
+         continue;
+
+	  mMipCount = curEntry.mCubemap.getPointer()->getMipMapLevels();
+
+      //Setup
+      Point3F probePos = curEntry.getPosition() + curEntry.mProbePosOffset;
+      probePositionsData[mEffectiveProbeCount] = Point4F(probePos.x, probePos.y, probePos.z,0);
+
+      probeWorldToObjData[mEffectiveProbeCount] = curEntry.getTransform();
 
-   //ReflectProbeMaterialInfo *info = NULL;
+      probeBBMinData[mEffectiveProbeCount] = Point4F(curEntry.mBounds.minExtents.x, curEntry.mBounds.minExtents.y, curEntry.mBounds.minExtents.z, 0);
+      probeBBMaxData[mEffectiveProbeCount] = Point4F(curEntry.mBounds.maxExtents.x, curEntry.mBounds.maxExtents.y, curEntry.mBounds.maxExtents.z, 0);
 
-   if (!mReflectProbeMaterial)
+      probeUseSphereModeData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType == ProbeRenderInst::Sphere ? 1 : 0, 0,0,0);
 
-      // Now create the material info object.
-      mReflectProbeMaterial = new ReflectProbeMaterialInfo("ReflectionProbeMaterial",
-         getGFXVertexFormat<GFXVertexPC>());
+      probeRadiusData[mEffectiveProbeCount] = Point4F(curEntry.mRadius,0,0,0);
+      probeAttenuationData[mEffectiveProbeCount] = Point4F(1, 0, 0, 0);
 
-   return mReflectProbeMaterial;
+      cubeMaps.push_back(curEntry.mCubemap);
+      irradMaps.push_back(curEntry.mIrradianceCubemap);
+
+      mEffectiveProbeCount++;
+   }
+
+   if (mEffectiveProbeCount != 0)
+   {
+      mCubemapArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
+      mIrradArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
+
+      mCubemapArray->initStatic(cubeMaps.address(), cubeMaps.size());
+      mIrradArray->initStatic(irradMaps.address(), irradMaps.size());
+   }
+}
+
+void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
+{
+   PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
 }
 
 ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuffer* buffer)
@@ -422,10 +387,8 @@ ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuff
       mLastShader = shader;
    }
 
-   mLastConstants = new ProbeShaderConstants();
-
    // Make sure that our current lighting constants are initialized
-   if (!mLastConstants->mInit)
+   if (mLastConstants && !mLastConstants->mInit)
       mLastConstants->init(shader);
 
    return mLastConstants;
@@ -449,7 +412,7 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
       probeRadiusSC->isValid() ||
       probeBoxMinSC->isValid() ||
       probeBoxMaxSC->isValid() ||
-      probeCubemapSC->isValid() && (!ProbeRenderInst::all.empty()))
+      probeCubemapSC->isValid()/* && (!ProbeRenderInst::all.empty())*/)
    {
       PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
 
@@ -477,7 +440,7 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
       const MatrixF &worldToCameraXfm = matSet.getWorldToCamera();
 
       // Gather the data for the first 4 probes.
-      const ProbeRenderInst *probe;
+      /*const ProbeRenderInst *probe;
       for (U32 i = 0; i < 4; i++)
       {
          if (i >= ProbeRenderInst::all.size())
@@ -526,6 +489,33 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
             if (samplerReg != -1)
                GFX->setCubeTexture(samplerReg + i, probe->mCubemap.getPointer());
          }
+      }*/
+
+      for (U32 i = 0; i < 4; i++)
+      {
+         probePositions[i].x = 0;
+         probePositions[i].y = 0;
+         probePositions[i].z = 0;
+
+         probeRadius[i] = 0;
+
+         probeBoxMins[i].x = 0;
+         probeBoxMins[i].y = 0;
+         probeBoxMins[i].z = 0;
+
+         probeBoxMaxs[i].x = 0;
+         probeBoxMaxs[i].y = 0;
+         probeBoxMaxs[i].z = 0;
+
+         probeIsSphere[i] = 0;
+
+         probeLocalPositions[i].x = 0;
+         probeLocalPositions[i].y = 0;
+         probeLocalPositions[i].z = 0;
+
+         S32 samplerReg = probeCubemapSC->getSamplerRegister();
+
+         GFX->setCubeTexture(samplerReg + i, nullptr);
       }
 
       shaderConsts->setSafe(probePositionSC, probePositions);
@@ -534,18 +524,9 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
       shaderConsts->setSafe(probeBoxMaxSC, probeBoxMaxs);
       shaderConsts->setSafe(probeLocalPosSC, probeLocalPositions);
       shaderConsts->setSafe(probeIsSphereSC, probeIsSphere);
-
-      //
-
-      //shaderConsts->setSafe(lightSpotAngleSC, lightSpotAngle);
-      //shaderConsts->setSafe(lightSpotFalloffSC, lightSpotFalloff);
    }
    else
    {
-      /*if (probe->mCubemap && !probe->mCubemap.isNull())
-      {
-         GFX->setCubeTexture(1, probe->mCubemap.getPointer());
-      }*/
       if (probeCubemapSC->isValid())
       {
          for (U32 i = 0; i < 4; ++i)
@@ -573,9 +554,6 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
 
    ProbeShaderConstants *psc = getProbeShaderConstants(shaderConsts);
 
-   //ProbeInfo *probe;
-   //probe = mRegisteredProbes[0];
-
    // NOTE: If you encounter a crash from this point forward
    // while setting a shader constant its probably because the
    // mConstantLookup has bad shaders/constants in it.
@@ -584,7 +562,6 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
    // are reloaded and the light manager is not reset.
    //
    // We should look to fix this by clearing the table.
-
    MatrixSet matSet = state->getRenderPass()->getMatrixSet();
 
    // Update the forward shading light constants.
@@ -605,364 +582,182 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
 //-----------------------------------------------------------------------------
 void RenderProbeMgr::render( SceneRenderState *state )
 {
-   PROFILE_SCOPE(RenderProbeMgr_render);
-
-   // Early out if nothing to draw.
-   if (!ProbeRenderInst::all.size())
+   //PROFILE_SCOPE(RenderProbeMgr_render);
+   if (getProbeArrayEffect() == nullptr)
       return;
 
-   if (!RenderProbeMgr::smRenderReflectionProbes)
-      return;
+   updateProbes();
+
+   // Early out if nothing to draw.
+   if (!ProbeRenderInst::all.size() || !RenderProbeMgr::smRenderReflectionProbes || mEffectiveProbeCount == 0
+	   || !state->isDiffusePass() || cubeMaps.empty() || irradMaps.empty())
+   {
+	   getProbeArrayEffect()->setSkip(true);
+	   return;
+   }
 
    GFXTransformSaver saver;
 
    GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE);
 
-   NamedTexTargetRef sceneColorTargetRef = NamedTexTarget::find("AL_FormatToken");
-   if (sceneColorTargetRef.isNull())
-      return;
-
-   GFXTextureTargetRef probeLightingTargetRef = GFX->allocRenderToTextureTarget();
-
-   if (probeLightingTargetRef.isNull())
-      return;
-
-   //Do a quick pass to update our probes if they're dirty
-   //PROBEMGR->updateDirtyProbes();
-
-   probeLightingTargetRef->attachTexture(GFXTextureTarget::Color0, sceneColorTargetRef->getTexture(0));
-
-   GFX->pushActiveRenderTarget();
-   GFX->setActiveRenderTarget(probeLightingTargetRef);
-
-   GFX->setViewport(sceneColorTargetRef->getViewport());
-    
-   // Restore transforms
-   MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
-   matrixSet.restoreSceneViewProjection();
-
-   const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
-
-   // Set up the SG Data
-   SceneData sgData;
-   sgData.init(state);
-
    // Initialize and set the per-frame parameters after getting
    // the vector light material as we use lazy creation.
-   _setupPerFrameParameters(state);
-
-   //Order the probes by size, biggest to smallest
-   //dQsort(ProbeRenderInst::all.address(), ProbeRenderInst::all.size(), sizeof(const ProbeRenderInst*), AscendingReflectProbeInfluence);
+   //_setupPerFrameParameters(state);
+   
+   //Array rendering
+   U32 probeCount = ProbeRenderInst::all.size();
 
-   //Specular
-   PROFILE_START(RenderProbeManager_ReflectProbeRender);
+   if (mEffectiveProbeCount != 0)
+   {
+      mProbeArrayEffect->setCubemapArrayTexture(4, mCubemapArray);
+      mProbeArrayEffect->setCubemapArrayTexture(5, mIrradArray);
+
+      mProbeArrayEffect->setShaderConst("$cubeMips", (float)mMipCount);
+      
+      mProbeArrayEffect->setShaderConst("$numProbes", (float)mEffectiveProbeCount);
+      mProbeArrayEffect->setShaderConst("$inProbePosArray", probePositionsData);
+      mProbeArrayEffect->setShaderConst("$worldToObjArray", probeWorldToObjData);
+      mProbeArrayEffect->setShaderConst("$bbMinArray", probeBBMinData);
+      mProbeArrayEffect->setShaderConst("$bbMaxArray", probeBBMaxData);
+      mProbeArrayEffect->setShaderConst("$useSphereMode", probeUseSphereModeData);
+      mProbeArrayEffect->setShaderConst("$radius", probeRadiusData);
+      mProbeArrayEffect->setShaderConst("$attenuation", probeAttenuationData);
+   }
 
-   ReflectProbeMaterialInfo* reflProbeMat = getReflectProbeMaterial();
+   // Make sure the effect is gonna render.
+   getProbeArrayEffect()->setSkip(false);
 
-   if (reflProbeMat == nullptr || reflProbeMat->matInstance == nullptr)
-      return;
+   //PROFILE_END();
+}
 
-   MaterialParameters *matParams = reflProbeMat->matInstance->getMaterialParameters();
+void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
+{
+   GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
 
-   MaterialParameterHandle *numProbesSC = reflProbeMat->matInstance->getMaterialParameterHandle("$numProbes");
+   Con::warnf("RenderProbeMgr::bakeProbe() - Beginning bake!");
+   U32 startMSTime = Platform::getRealMilliseconds();
 
-   MaterialParameterHandle *probePositionSC = reflProbeMat->matInstance->getMaterialParameterHandle("$inProbePosArray");
-   MaterialParameterHandle *probeWorldToObjSC = reflProbeMat->matInstance->getMaterialParameterHandle("$worldToObjArray");
-   MaterialParameterHandle *probeBBMinSC = reflProbeMat->matInstance->getMaterialParameterHandle("$bbMinArray");
-   MaterialParameterHandle *probeBBMaxSC = reflProbeMat->matInstance->getMaterialParameterHandle("$bbMaxArray");
-   MaterialParameterHandle *probeUseSphereModeSC = reflProbeMat->matInstance->getMaterialParameterHandle("$useSphereMode");
-   MaterialParameterHandle *probeRadiusSC = reflProbeMat->matInstance->getMaterialParameterHandle("$radius");
-   MaterialParameterHandle *probeAttenuationSC = reflProbeMat->matInstance->getMaterialParameterHandle("$attenuation");
+   String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
+   U32 resolution = Con::getIntVariable("$pref::ReflectionProbes::BakeResolution", 64);
+   U32 prefilterMipLevels = mLog2(F32(resolution));
+   bool renderWithProbes = Con::getIntVariable("$pref::ReflectionProbes::RenderWithProbes", false);
 
-   //Array rendering
-   U32 probeCount = ProbeRenderInst::all.size();
+   ReflectionProbe *clientProbe = static_cast<ReflectionProbe*>(probe->getClientObject());
 
-   if (probeCount == 0)
-      return;
-   MatrixF trans = MatrixF::Identity;
-   sgData.objTrans = &trans;
-   
-   U32 effectiveProbeCount = 0;
+   String probePrefilterPath = clientProbe->getPrefilterMapPath();
+   String probeIrradPath = clientProbe->getIrradianceMapPath();
 
-   for (U32 i = 0; i < probeCount; i++)
+   if (clientProbe->mReflectionModeType != ReflectionProbe::DynamicCubemap)
    {
-      if (effectiveProbeCount >= MAXPROBECOUNT)
-         break;
+      //Prep our bake path
+      if (probePrefilterPath.isEmpty() || probeIrradPath.isEmpty())
+      {
+         Con::errorf("RenderProbeMgr::bake() - Unable to bake our captures because probe doesn't have a path set");
+         return;
+      }
+   }
 
-      ProbeRenderInst* curEntry = ProbeRenderInst::all[i];
-      if (!curEntry->mIsEnabled)
-         continue;
+   // Save the current transforms so we can restore
+   // it for child control rendering below.
+   GFXTransformSaver saver;
 
-      if (curEntry->mCubemap.isNull() || curEntry->mIrradianceCubemap.isNull())
-         continue;
+   bool probeRenderState = RenderProbeMgr::smRenderReflectionProbes;
 
-      if (!curEntry->mCubemap->isInitialised())
-         continue;
+   F32 farPlane = 1000.0f;
 
-      if (!curEntry->mIrradianceCubemap->isInitialised())
-         continue;
+   ReflectorDesc reflDesc;
+   reflDesc.texSize = resolution;
+   reflDesc.farDist = farPlane;
+   reflDesc.detailAdjust = 1;
+   reflDesc.objectTypeMask = -1;
 
-      if (curEntry->mIsSkylight)
-         continue;
+   CubeReflector cubeRefl;
+   cubeRefl.registerReflector(probe, &reflDesc);
 
-      //Setup
-      const Point3F &probePos = curEntry->getPosition();
-      probePositions[i] = probePos + curEntry->mProbePosOffset;
+   ReflectParams reflParams;
 
-      MatrixF trans = curEntry->getTransform();
-      trans.inverse();
+   //need to get the query somehow. Likely do some sort of get function to fetch from the guiTSControl that's active
+   CameraQuery query; //need to get the last cameraQuery
+   query.fov = 90; //90 degree slices for each of the 6 sides
+   query.nearPlane = 0.1f;
+   query.farPlane = farPlane;
+   query.headMatrix = MatrixF();
+   query.cameraMatrix = clientProbe->getTransform();
 
-      probeWorldToObj[i]=trans;
+   Frustum culler;
+   culler.set(false,
+      query.fov,
+      (F32)resolution / (F32)resolution,
+      query.nearPlane,
+      query.farPlane,
+      query.cameraMatrix);
 
-      probeBBMin[i] = curEntry->mBounds.minExtents;
-      probeBBMax[i] = curEntry->mBounds.maxExtents;
+   S32 stereoTarget = GFX->getCurrentStereoTarget();
 
-      probeUseSphereMode[i] = curEntry->mProbeShapeType == ProbeRenderInst::Sphere ? 1 : 0;
+   Point2I maxRes(2048, 2048); //basically a boundary so we don't go over this and break stuff
 
-      probeRadius[i] = curEntry->mRadius;
-      probeAttenuation[i] = 1;
+   reflParams.culler = culler;
+   reflParams.eyeId = stereoTarget;
+   reflParams.query = &query;
+   reflParams.startOfUpdateMs = startMSTime;
+   reflParams.viewportExtent = maxRes;
 
-      cubeMaps.push_back(curEntry->mCubemap);
-      irradMaps.push_back(curEntry->mIrradianceCubemap);
+   if (!renderWithProbes)
+      RenderProbeMgr::smRenderReflectionProbes = false;
 
-      effectiveProbeCount++;
-   }
+   cubeRefl.updateReflection(reflParams);
 
-   if (effectiveProbeCount != 0)
+   //Now, save out the maps
+   //create irridiance cubemap
+   if (cubeRefl.getCubemap())
    {
-      matParams->setSafe(numProbesSC, (float)effectiveProbeCount);
-
-      mCubemapArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
-      mIrradArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
-
-      mCubemapArray->initStatic(cubeMaps.address(), cubeMaps.size());
-      mIrradArray->initStatic(irradMaps.address(), irradMaps.size());
-
-      NamedTexTarget *deferredTarget = NamedTexTarget::find(RenderDeferredMgr::BufferName);
-      if (deferredTarget)
-         GFX->setTexture(0, deferredTarget->getTexture());
-      else
-         GFX->setTexture(0, NULL);
-
-      NamedTexTarget *colorTarget = NamedTexTarget::find(RenderDeferredMgr::ColorBufferName);
-      if (colorTarget)
-         GFX->setTexture(1, colorTarget->getTexture());
-      else
-         GFX->setTexture(1, NULL);
+      //Just to ensure we're prepped for the generation
+      clientProbe->createClientResources();
 
-      NamedTexTarget *matinfoTarget = NamedTexTarget::find(RenderDeferredMgr::MatInfoBufferName);
-      if (matinfoTarget)
-         GFX->setTexture(2, matinfoTarget->getTexture());
-      else
-         GFX->setTexture(2, NULL);
-
-      if (mBrdfTexture)
+      //Prep it with whatever resolution we've dictated for our bake
+      if (clientProbe->mUseHDRCaptures)
       {
-         GFX->setTexture(3, mBrdfTexture);
+         clientProbe->mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
+         clientProbe->mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
       }
       else
-         GFX->setTexture(3, NULL);
-
-
-      GFX->setCubeArrayTexture(4, mCubemapArray);
-      GFX->setCubeArrayTexture(5, mIrradArray);
-      //Final packing
-      AlignedArray<Point4F> _probePositions(MAXPROBECOUNT, sizeof(Point4F), (U8*)probePositions.address(), false);
-      AlignedArray<Point4F> _probeBBMin(MAXPROBECOUNT, sizeof(Point4F), (U8*)probeBBMin.address(), false);
-      AlignedArray<Point4F> _probeBBMax(MAXPROBECOUNT, sizeof(Point4F), (U8*)probeBBMax.address(), false);
-      AlignedArray<float> _probeUseSphereMode(MAXPROBECOUNT, sizeof(float), (U8*)probeUseSphereMode.address(), false);
-      AlignedArray<float> _probeRadius(MAXPROBECOUNT, sizeof(float), (U8*)probeRadius.address(), false);
-      AlignedArray<float> _probeAttenuation(MAXPROBECOUNT, sizeof(float), (U8*)probeAttenuation.address(), false);
-
-      matParams->set(probePositionSC, _probePositions);
-      matParams->set(probeWorldToObjSC, probeWorldToObj.address(), MAXPROBECOUNT);
-      matParams->set(probeBBMinSC, _probeBBMin);
-      matParams->set(probeBBMaxSC, _probeBBMax);
-      matParams->set(probeUseSphereModeSC, _probeUseSphereMode);
-      matParams->set(probeRadiusSC, _probeRadius);
-      matParams->set(probeAttenuationSC, _probeAttenuation);
-
-      // Set geometry
-      GFX->setVertexBuffer(mFarFrustumQuadVerts);
-      GFX->setPrimitiveBuffer(NULL);
-
-      while (reflProbeMat->matInstance->setupPass(state, sgData))
       {
-         // Set transforms
-         matrixSet.setWorld(*sgData.objTrans);
-         reflProbeMat->matInstance->setTransforms(matrixSet, state);
-         reflProbeMat->matInstance->setSceneInfo(state, sgData);
-
-          GFX->drawPrimitive(GFXTriangleStrip, 0, 2);
+         clientProbe->mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
+         clientProbe->mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
       }
-   }
-
-   GFX->popActiveRenderTarget();
-
-   //PROBEMGR->unregisterAllProbes();
-   //PROBEMGR->mRegisteredProbes.clear();
-
-   PROFILE_END();
-
-   GFX->setVertexBuffer(NULL);
-   GFX->setPrimitiveBuffer(NULL);
-
-   // Fire off a signal to let others know that light-bin rendering is ending now
-   //getRenderSignal().trigger(state, this);
-}
-
-//
-//
-RenderProbeMgr::ReflectProbeMaterialInfo::ReflectProbeMaterialInfo(const String &matName,
-   const GFXVertexFormat *vertexFormat)
-   : matInstance(NULL),
-   zNearFarInvNearFar(NULL),
-   farPlane(NULL),
-   vsFarPlane(NULL),
-   negFarPlaneDotEye(NULL),
-   probeWSPos(NULL),
-   attenuation(NULL),
-   radius(NULL),
-   cubeMips(NULL)
-{
-   Material *mat = MATMGR->getMaterialDefinitionByName(matName);
-   if (!mat)
-      return;
 
-   matInstance = new ReflectProbeMatInstance(*mat);
+      GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
 
-   const Vector<GFXShaderMacro> &macros = Vector<GFXShaderMacro>();
+      IBLUtilities::GenerateIrradianceMap(renderTarget, cubeRefl.getCubemap(), clientProbe->mIrridianceMap->mCubemap);
+      IBLUtilities::GeneratePrefilterMap(renderTarget, cubeRefl.getCubemap(), prefilterMipLevels, clientProbe->mPrefilterMap->mCubemap);
 
-   for (U32 i = 0; i < macros.size(); i++)
-      matInstance->addShaderMacro(macros[i].name, macros[i].value);
-
-   matInstance->init(MATMGR->getDefaultFeatures(), vertexFormat);
-
-   attenuation = matInstance->getMaterialParameterHandle("$attenuation");
-   radius = matInstance->getMaterialParameterHandle("$radius");
-   probeLSPos = matInstance->getMaterialParameterHandle("$probeLSPos");
-   probeWSPos = matInstance->getMaterialParameterHandle("$probeWSPos");
-   farPlane = matInstance->getMaterialParameterHandle("$farPlane");
-   vsFarPlane = matInstance->getMaterialParameterHandle("$vsFarPlane");
-   negFarPlaneDotEye = matInstance->getMaterialParameterHandle("$negFarPlaneDotEye");
-   zNearFarInvNearFar = matInstance->getMaterialParameterHandle("$zNearFarInvNearFar");
-
-   useCubemap = matInstance->getMaterialParameterHandle("$useCubemap");
-
-   cubemap = matInstance->getMaterialParameterHandle("$cubeMap");
-   cubeMips = matInstance->getMaterialParameterHandle("$cubeMips");
-
-   eyePosWorld = matInstance->getMaterialParameterHandle("$eyePosWorld");
-   bbMin = matInstance->getMaterialParameterHandle("$bbMin");
-   bbMax = matInstance->getMaterialParameterHandle("$bbMax");
+      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!");
+   }
 
-   useSphereMode = matInstance->getMaterialParameterHandle("$useSphereMode");
+   if (!renderWithProbes)
+      RenderProbeMgr::smRenderReflectionProbes = probeRenderState;
 
-   probeCount = matInstance->getMaterialParameterHandle("$numProbes");
+   cubeRefl.unregisterReflector();
 
-   for (U32 i = 0; i < 9; i++)
-      shTerms[i] = matInstance->getMaterialParameterHandle(String::ToString("$SHTerms%d", i));
+   U32 endMSTime = Platform::getRealMilliseconds();
+   F32 diffTime = F32(endMSTime - startMSTime);
 
-   for (U32 i = 0; i < 5; i++)
-      shConsts[i] = matInstance->getMaterialParameterHandle(String::ToString("$SHConsts%d", i));
+   Con::warnf("RenderProbeMgr::bake() - Finished bake! Took %g milliseconds", diffTime);
 }
 
-RenderProbeMgr::ReflectProbeMaterialInfo::~ReflectProbeMaterialInfo()
+void RenderProbeMgr::bakeProbes()
 {
-   SAFE_DELETE(matInstance);
+   //TODO: make this just find every probe in the current missionGroup and run the bake on it automagically
 }
 
-void RenderProbeMgr::ReflectProbeMaterialInfo::setViewParameters(const F32 _zNear,
-   const F32 _zFar,
-   const Point3F &_eyePos,
-   const PlaneF &_farPlane,
-   const PlaneF &_vsFarPlane)
+DefineEngineMethod(RenderProbeMgr, bakeProbe, void, (ReflectionProbe* probe), (nullAsType< ReflectionProbe*>()),
+   "@brief returns true if control object is inside the fog\n\n.")
 {
-   MaterialParameters *matParams = matInstance->getMaterialParameters();
-
-   matParams->setSafe(farPlane, *((const Point4F *)&_farPlane));
-
-   matParams->setSafe(vsFarPlane, *((const Point4F *)&_vsFarPlane));
-
-   if (negFarPlaneDotEye->isValid())
-   {
-      // -dot( farPlane, eyePos )
-      const F32 negFarPlaneDotEyeVal = -(mDot(*((const Point3F *)&_farPlane), _eyePos) + _farPlane.d);
-      matParams->set(negFarPlaneDotEye, negFarPlaneDotEyeVal);
-   }
-
-   matParams->setSafe(zNearFarInvNearFar, Point4F(_zNear, _zFar, 1.0f / _zNear, 1.0f / _zFar));
-
-   Point4F frPlane = *((const Point4F *)&_farPlane);
-   Point4F vsFrPlane = *((const Point4F *)&_vsFarPlane);
-   Point4F nearFarInvNearFar = Point4F(_zNear, _zFar, 1.0f / _zNear, 1.0f / _zFar);
-   const F32 negFarPlaneDotEyeVal = -(mDot(*((const Point3F *)&_farPlane), _eyePos) + _farPlane.d);
-}
-
-void RenderProbeMgr::ReflectProbeMaterialInfo::setProbeParameters(const ProbeRenderInst *probeInfo, const SceneRenderState* renderState, const MatrixF &worldViewOnly)
-{
-   //Set up the params
-   MaterialParameters *matParams = matInstance->getMaterialParameters();
-
-   matParams->setSafe(radius, probeInfo->mRadius);
-
-   Point3F probePos = probeInfo->getPosition() + probeInfo->mProbePosOffset;
-   //worldViewOnly.mulP(probeInfo->getPosition(), &probePos);
-   matParams->setSafe(probeWSPos, probePos);
-
-   worldViewOnly.mulP(probeInfo->getPosition(), &probePos);
-   matParams->setSafe(probeLSPos, probePos);
-
-   // Get the attenuation falloff ratio and normalize it.
-   Point3F attenRatio = Point3F(0.0f, 1.0f, 1.0f);
-   F32 total = attenRatio.x + attenRatio.y + attenRatio.z;
-   if (total > 0.0f)
-      attenRatio /= total;
-
-   F32 probeRadius = probeInfo->mRadius;
-
-   Point2F attenParams((1.0f / probeRadius) * attenRatio.y,
-      (1.0f / (probeRadius * probeRadius)) * attenRatio.z);
-
-   matParams->setSafe(attenuation, attenParams);
-
-   NamedTexTarget* deferredTexTarget = NamedTexTarget::find("deferred");
-   NamedTexTarget* matInfoTexTarget = NamedTexTarget::find("matinfo");
-   NamedTexTarget* colorTexTarget = NamedTexTarget::find("color");
-
-   if (!deferredTexTarget || !matInfoTexTarget || !colorTexTarget)
-   {
-      Con::errorf("ProbeManager::ReflectProbeMaterialInfo::setProbeParameters: Could not retrieve gbuffer");
-      return;
-   }
-
-   //set textures
-   GFX->setTexture(0, deferredTexTarget->getTexture());
-   GFX->setTexture(1, colorTexTarget->getTexture());
-   GFX->setTexture(2, matInfoTexTarget->getTexture());
-
-   //Add some safety catches in the event the cubemaps aren't fully initialized yet
-   if (probeInfo->mCubemap == nullptr || probeInfo->mCubemap.isNull())
-   {
-      GFX->setCubeTexture(3, nullptr);
-      matParams->setSafe(cubeMips, 2.0f);
-   }
-   else
-   {
-      GFX->setCubeTexture(3, probeInfo->mCubemap.getPointer());
-      matParams->setSafe(cubeMips, mPow(probeInfo->mCubemap.getPointer()->getMipMapLevels(), 2.0f));
-   }
-
-   if (probeInfo->mIrradianceCubemap == nullptr || probeInfo->mIrradianceCubemap.isNull())
-      GFX->setCubeTexture(4, nullptr);
-   else
-      GFX->setCubeTexture(4, probeInfo->mIrradianceCubemap.getPointer());
-
-   GFX->setTexture(5, probeInfo->mBRDFTexture->getPointer());
-
-   //set material params
-   matParams->setSafe(eyePosWorld, renderState->getCameraPosition());
-   matParams->setSafe(bbMin, probeInfo->mBounds.minExtents);
-   matParams->setSafe(bbMax, probeInfo->mBounds.maxExtents);
-   matParams->setSafe(useSphereMode, probeInfo->mProbeShapeType == ProbeRenderInst::Sphere ? 1.0f : 0.0f);
+   if(probe != nullptr)
+      object->bakeProbe(probe);
 }

+ 66 - 162
Engine/source/renderInstance/renderProbeMgr.h

@@ -48,27 +48,32 @@
 #include "postFx/postEffectCommon.h"
 #endif
 
+#ifndef _REFLECTOR_H_
+#include "scene/reflector.h"
+#endif
+
 static U32 MAXPROBECOUNT = 50;
 
+class PostEffect;
+class ReflectionProbe;
+
 struct ProbeRenderInst : public SystemInterface<ProbeRenderInst>
 {
-   LinearColorF mAmbient;
-
    MatrixF mTransform;
 
    F32 mRadius;
-   F32 mIntensity;
 
    bool mDirty;
 
    Box3F mBounds;
+   Point3F mPosition;
    Point3F mProbePosOffset;
 
    GFXCubemapHandle mCubemap;
-
    GFXCubemapHandle mIrradianceCubemap;
 
-   GFXTexHandle *mBRDFTexture;
+   //Utilized in dynamic reflections
+   CubeReflector mCubeReflector;
 
    /// The priority of this light used for
    /// light and shadow scoring.
@@ -80,16 +85,6 @@ struct ProbeRenderInst : public SystemInterface<ProbeRenderInst>
 
    bool mIsSkylight;
 
-   /// Whether to render debugging visualizations
-   /// for this light.
-   bool mDebugRender;
-
-   GFXPrimitiveBufferHandle primBuffer;
-   GFXVertexBufferHandle<GFXVertexPC> vertBuffer;
-   U32 numPrims;
-   U32 numVerts;
-   Vector< U32 > numIndicesForPoly;
-
    enum ProbeShapeType
    {
       Sphere = 0,            ///< Sphere shaped
@@ -98,10 +93,6 @@ struct ProbeRenderInst : public SystemInterface<ProbeRenderInst>
 
    ProbeShapeType mProbeShapeType;
 
-   //Spherical Harmonics data
-   LinearColorF mSHTerms[9];
-   F32 mSHConstants[5];
-
 public:
 
    ProbeRenderInst();
@@ -114,28 +105,18 @@ public:
    const MatrixF& getTransform() const { return mTransform; }
    void setTransform(const MatrixF &xfm) { mTransform = xfm; }
 
-   Point3F getPosition() const { return mTransform.getPosition(); }
-   void setPosition(const Point3F &pos) { mTransform.setPosition(pos); }
+   Point3F getPosition() const { return mPosition; }
+   void setPosition(const Point3F &pos) { mPosition = pos; }
 
    VectorF getDirection() const { return mTransform.getForwardVector(); }
    void setDirection(const VectorF &val);
 
-   const LinearColorF& getAmbient() const { return mAmbient; }
-   void setAmbient(const LinearColorF &val) { mAmbient = val; }
-
    void setPriority(F32 priority) { mPriority = priority; }
    F32 getPriority() const { return mPriority; }
 
    void setScore(F32 score) { mScore = score; }
    F32 getScore() const { return mScore; }
 
-   bool isDebugRenderingEnabled() const { return mDebugRender; }
-   void enableDebugRendering(bool value) { mDebugRender = value; }
-
-   // Builds the world to light view projection used for
-   // shadow texture and cookie lookups.
-   void getWorldToLightProj(MatrixF *outMatrix) const;
-
    void clear();
 };
 
@@ -167,26 +148,6 @@ struct ProbeShaderConstants
 
 typedef Map<GFXShader*, ProbeShaderConstants*> ProbeConstantMap;
 
-class ReflectProbeMatInstance : public MatInstance
-{
-   typedef MatInstance Parent;
-protected:
-   MaterialParameterHandle * mProbeParamsSC;
-   bool mInternalPass;
-
-   GFXStateBlockRef mProjectionState;
-
-   ProcessedShaderMaterial* mShaderMat;
-
-public:
-   ReflectProbeMatInstance(Material &mat) : Parent(mat), mProbeParamsSC(NULL), mInternalPass(false), mProjectionState(NULL) {}
-
-   virtual bool init(const FeatureSet &features, const GFXVertexFormat *vertexFormat);
-   virtual bool setupPass(SceneRenderState *state, const SceneData &sgData);
-
-   ProcessedShaderMaterial* getProcessedShaderMaterial() { return mShaderMat; }
-};
-
 //**************************************************************************
 // RenderObjectMgr
 //**************************************************************************
@@ -194,82 +155,53 @@ class RenderProbeMgr : public RenderBinManager
 {
    typedef RenderBinManager Parent;
 
-   struct ReflectProbeMaterialInfo
-   {
-      ReflectProbeMatInstance *matInstance;
-
-      // { zNear, zFar, 1/zNear, 1/zFar }
-      MaterialParameterHandle *zNearFarInvNearFar;
-
-      // Far frustum plane (World Space)
-      MaterialParameterHandle *farPlane;
-
-      // Far frustum plane (View Space)
-      MaterialParameterHandle *vsFarPlane;
-
-      // -dot( farPlane, eyePos )
-      MaterialParameterHandle *negFarPlaneDotEye;
-
-      // Light Parameters
-      MaterialParameterHandle *probeLSPos;
-      MaterialParameterHandle *probeWSPos;
-      MaterialParameterHandle *attenuation;
-      MaterialParameterHandle *radius;
-
-      MaterialParameterHandle *useCubemap;
-      MaterialParameterHandle *cubemap;
-      MaterialParameterHandle *cubeMips;
-
-      MaterialParameterHandle *eyePosWorld;
-      MaterialParameterHandle *bbMin;
-      MaterialParameterHandle *bbMax;
-
-      MaterialParameterHandle *useSphereMode;
-
-      MaterialParameterHandle *shTerms[9];
-      MaterialParameterHandle *shConsts[5];
-
-      MaterialParameterHandle *probeCount;
-
-      ReflectProbeMaterialInfo(const String &matName, const GFXVertexFormat *vertexFormat);
-
-      virtual ~ReflectProbeMaterialInfo();
-
-
-      void setViewParameters(const F32 zNear,
-         const F32 zFar,
-         const Point3F &eyePos,
-         const PlaneF &farPlane,
-         const PlaneF &_vsFarPlane);
-
-      void setProbeParameters(const ProbeRenderInst *probe, const SceneRenderState* renderState, const MatrixF &worldViewOnly);
-   };
-
-   enum SpecialProbeTypesEnum
-   {
-      SkylightProbeType,
-      SpecialProbeTypesCount
-   };
-
    Vector<U32> mRegisteredProbes;
 
-   ReflectProbeMaterialInfo* mReflectProbeMaterial;
-
-   /// The scene graph the light manager is associated with.
-   SceneManager *mSceneManager;
-
+   //Array rendering
+   U32 mEffectiveProbeCount;
+   S32 mMipCount;
+   Vector<Point4F> probePositionsData;
+   Vector<MatrixF> probeWorldToObjData;
+   Vector<Point4F> probeBBMinData;
+   Vector<Point4F> probeBBMaxData;
+   Vector<Point4F> probeUseSphereModeData;
+   Vector<Point4F> probeRadiusData;
+   Vector<Point4F> probeAttenuationData;
+   Vector<GFXCubemapHandle> cubeMaps;
+   Vector<GFXCubemapHandle> irradMaps;
+
+   AlignedArray<Point4F> mProbePositions;
+   AlignedArray<Point4F> mProbeBBMin;
+   AlignedArray<Point4F> mProbeBBMax;
+   AlignedArray<float> mProbeUseSphereMode;
+   AlignedArray<float> mProbeRadius;
+   AlignedArray<float> mProbeAttenuation;
+
+   GFXCubemapArrayHandle mCubemapArray;
+   GFXCubemapArrayHandle mIrradArray;
+
+   //Utilized in forward rendering
    ProbeConstantMap mConstantLookup;
    GFXShaderRef mLastShader;
    ProbeShaderConstants* mLastConstants;
 
-protected:
+   //
+   SimObjectPtr<PostEffect> mProbeArrayEffect;
 
+public:
+   RenderProbeMgr();
+   RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder);
+
+   virtual void onRemove();
+
+   // ConsoleObject
+   static void initPersistFields();
+   DECLARE_CONOBJECT(RenderProbeMgr);
+
+protected:
    /// The current active light manager.
    static RenderProbeMgr *smProbeManager;
 
-   typedef GFXVertexPNTT FarFrustumQuadVert;
-   GFXVertexBufferHandle<FarFrustumQuadVert> mFarFrustumQuadVerts;
-
    /// This helper function sets the shader constansts
    /// for the stock 4 light forward lighting code.
    void _update4ProbeConsts(const SceneData &sgData,
@@ -283,57 +215,37 @@ protected:
       GFXShaderConstHandle *probeLocalPosSC,
       GFXShaderConstBuffer *shaderConsts);
 
-      GFXTextureObject * mBrdfTexture;
-
-      //Array rendering
-
-      Vector<Point3F> probePositions;
-      Vector<MatrixF> probeWorldToObj;
-      Vector<Point3F> probeBBMin;
-      Vector<Point3F> probeBBMax;
-      Vector<float> probeUseSphereMode;
-      Vector<float> probeRadius;
-      Vector<float> probeAttenuation;
-      Vector<GFXCubemapHandle> cubeMaps;
-      Vector<GFXCubemapHandle> irradMaps;
-
-      GFXCubemapArrayHandle mCubemapArray;
-      GFXCubemapArrayHandle mIrradArray;
-public:
-   RenderProbeMgr();
-   RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder);
-
-   // RenderBinMgr
+   void _setupStaticParameters();
    void _setupPerFrameParameters(const SceneRenderState *state);
    virtual void addElement(RenderInst *inst);
    virtual void render(SceneRenderState * state);
 
-   virtual void setProbeInfo(ProcessedMaterial *pmat,
-      const Material *mat,
-      const SceneData &sgData,
-      const SceneRenderState *state,
-      U32 pass,
-      GFXShaderConstBuffer *shaderConsts);
    ProbeShaderConstants* getProbeShaderConstants(GFXShaderConstBuffer* buffer);
 
-   // ConsoleObject
-   static void initPersistFields();
-   DECLARE_CONOBJECT(RenderProbeMgr);
+   PostEffect* getProbeArrayEffect();
+
+public:
+   // RenderBinMgr
+   void updateProbes();
 
    /// Returns the active LM.
    static inline RenderProbeMgr* getProbeManager();
 
-   ReflectProbeMaterialInfo* getReflectProbeMaterial();
-
    void registerProbe(U32 probeIdx);
+   void unregisterProbe(U32 probeIdx);
 
-   // Returns the scene manager passed at activation.
-   SceneManager* getSceneManager() { return mSceneManager; }
-
-   void setSceneManager(SceneManager* sceneManager) { mSceneManager = sceneManager; }
+   virtual void setProbeInfo(ProcessedMaterial *pmat,
+	   const Material *mat,
+	   const SceneData &sgData,
+	   const SceneRenderState *state,
+	   U32 pass,
+	   GFXShaderConstBuffer *shaderConsts);
 
    /// Debug rendering
    static bool smRenderReflectionProbes;
+
+   void bakeProbe(ReflectionProbe *probeInfo);
+   void bakeProbes();
 };
 
 RenderProbeMgr* RenderProbeMgr::getProbeManager()
@@ -342,15 +254,7 @@ RenderProbeMgr* RenderProbeMgr::getProbeManager()
    {
       RenderProbeMgr* probeManager = new RenderProbeMgr();
 
-      if (gClientSceneGraph != nullptr)
-      {
-         probeManager->setSceneManager(gClientSceneGraph);
-         smProbeManager = probeManager;
-      }
-      else
-      {
-         delete probeManager;
-      }
+      smProbeManager = probeManager;
    }
 
    return smProbeManager;

+ 33 - 134
Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs

@@ -277,94 +277,7 @@ new CustomMaterial( AL_ParticlePointLightMaterial )
    pixVersion = 3.0;
 };
 
-//Reflection probe Specular
-new ShaderData( ReflectionProbeShader )
-{
-   /*DXVertexShaderFile = "shaders/common/lighting/advanced/convexGeometryV.hlsl";
-   DXPixelShaderFile  = "shaders/common/lighting/advanced/reflectionProbeP.hlsl";
-
-   OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/convexGeometryV.glsl";
-   OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/reflectionProbeP.glsl";
-
-   samplerNames[0] = "$deferredBuffer";
-   samplerNames[1] = "$colorBuffer";
-   samplerNames[2] = "$matInfoBuffer";
-   samplerNames[3] = "$cubeMap";
-   samplerNames[4] = "$irradianceCubemap";
-   samplerNames[5] = "$BRDFTexture";*/
-   
-   DXVertexShaderFile = "shaders/common/lighting/advanced/farFrustumQuadV.hlsl";
-   DXPixelShaderFile  = "shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl";
-
-   OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl";
-   OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/reflectionProbeArrayP.glsl";
-
-   samplerNames[0] = "$deferredBuffer";
-   samplerNames[1] = "$colorBuffer";
-   samplerNames[2] = "$matInfoBuffer";
-   samplerNames[3] = "$BRDFTexture";
-   samplerNames[4] = "$cubeMap";
-   samplerNames[5] = "$irradianceCubemap";
-   
-   pixVersion = 3.0;
-};
-
-// Convex-geometry light states
-new GFXStateBlockData( AL_ProbeState )
-{
-   blendDefined = true;
-   blendEnable = true;
-   blendSrc = GFXBlendSrcAlpha; //TODO change this to GFXBlendOne once probes are done in one pass!
-   blendDest = GFXBlendOne;
-   blendOp = GFXBlendOpAdd;
-   
-   colorWriteDefined = true;
-   colorWriteRed = true;
-   colorWriteBlue = true;
-   colorWriteGreen = true;
-   colorWriteAlpha = true;
-   
-   zDefined = true;
-   zEnable = true;
-   zWriteEnable = false;
-   zFunc = GFXCmpGreaterEqual;
-
-   samplersDefined = true;
-   samplerStates[0] = SamplerClampPoint;  // G-buffer
-   mSamplerNames[0] = "deferredBuffer";
-   samplerStates[1] = SamplerClampLinear;
-   mSamplerNames[1] = "colorBuffer";   
-   samplerStates[2] = SamplerClampLinear;
-   mSamplerNames[2] = "matInfoBuffer";   
-
-   mSamplerNames[3] = "BRDFTexture";
-   mSamplerNames[4] = "cubeMap";
-   mSamplerNames[5] = "irradianceCubemap";
-   
-   cullDefined = true;
-   cullMode = GFXCullCW;
-   
-   stencilDefined = true;
-   stencilEnable = true;
-   stencilFailOp = GFXStencilOpKeep;
-   stencilZFailOp = GFXStencilOpKeep;
-   stencilPassOp = GFXStencilOpKeep;
-   stencilFunc = GFXCmpLess;
-   stencilRef = 0;
-};
-
-new CustomMaterial( ReflectionProbeMaterial )
-{
-   shader = ReflectionProbeShader;
-   stateBlock = AL_ProbeState;
-   
-   sampler["deferredBuffer"] = "#deferred";
-   sampler["matInfoBuffer"] = "#matinfo";
-   
-   pixVersion = 3.0;
-};
-
-//Skylight
+//Probe Processing
 new ShaderData( IrradianceShader )
 {
    DXVertexShaderFile = "shaders/common/lighting/advanced/cubemapV.hlsl";
@@ -391,63 +304,49 @@ new ShaderData( PrefiterCubemapShader )
    pixVersion = 3.0;
 };
 
-new ShaderData( SkyLightShader )
+//
+singleton ShaderData( PFX_ReflectionProbeArray )
 {
-   DXVertexShaderFile = "shaders/common/lighting/advanced/convexGeometryV.hlsl";
-   DXPixelShaderFile  = "shaders/common/lighting/advanced/skylightP.hlsl";
+   DXVertexShaderFile   = "shaders/common/postFx/postFxV.hlsl";
+   DXPixelShaderFile    = "shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl";
 
-   OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/convexGeometryV.glsl";
-   OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/skylightP.glsl";
-
-   samplerNames[0] = "$deferredBuffer";
-   samplerNames[1] = "$matInfoBuffer";
-   samplerNames[2] = "$colorBuffer";
-   samplerNames[3] = "$cubeMap";
-   samplerNames[4] = "$irradianceCubemap";
-   samplerNames[5] = "$BRDFTexture";
-   
-   pixVersion = 3.0;
-};
-
-new CustomMaterial( SkyLightMaterial )
-{
-   shader = SkyLightShader;
-   stateBlock = AL_ProbeState;
+   //OGLVertexShaderFile  = "shaders/common/postFx/gl//postFxV.glsl";
+   //OGLPixelShaderFile   = "shaders/common/postFx/gl/passthruP.glsl";
    
-   sampler["deferredBuffer"] = "#deferred";
-   sampler["matInfoBuffer"] = "#matinfo";
-   sampler["colorBuffer"] = "#color";
-   
-   pixVersion = 3.0;
-};
-
-new ShaderData( ReflectionProbeArrayShader )
-{
-   DXVertexShaderFile = "shaders/common/lighting/advanced/reflectionProbeArrayV.hlsl";
-   DXPixelShaderFile  = "shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl";
-
-   OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/reflectionProbeArrayV.glsl";
-   OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/reflectionProbeArrayP.glsl";
-
    samplerNames[0] = "$deferredBuffer";
    samplerNames[1] = "$colorBuffer";
    samplerNames[2] = "$matInfoBuffer";
    samplerNames[3] = "$BRDFTexture";
    samplerNames[4] = "$cubeMap";
    samplerNames[5] = "$irradianceCubemap";
-   
-   pixVersion = 3.0;
+
+   pixVersion = 2.0;
+};  
+
+singleton GFXStateBlockData( PFX_ReflectionProbeArrayStateBlock )
+{  
+   samplersDefined = true;
+   samplerStates[0] = SamplerClampLinear;
 };
 
-new CustomMaterial( ReflectionProbeArrayMaterial )
+singleton PostEffect( reflectionProbeArrayPostFX )
 {
-   shader = ReflectionProbeArrayShader;
-   stateBlock = AL_ProbeState;
-   
-   sampler["deferredBuffer"] = "#deferred";
-   sampler["colorBuffer"] = "#color";
-   sampler["matInfoBuffer"] = "#matinfo";
-   sampler["BRDFTexture"] = "core/art/pbr/brdfTexture.dds";
+   // Do not allow the selection effect to work in reflection 
+   // passes by default so we don't do the extra drawing.
+   //allowReflectPass = false;
+                  
+   renderTime = "PFXAfterBin";
+   renderBin = "ProbeBin";
+   renderPriority = 9999;
+   isEnabled = true;
+
+   shader = PFX_ReflectionProbeArray;
+   stateBlock = PFX_ReflectionProbeArrayStateBlock;
+
+   texture[0] = "#deferred";
+   texture[1] = "#color";
+   texture[2] = "#matinfo";
+   texture[3] = "core/art/pbr/brdfTexture.dds";
    
-   pixVersion = 3.0;
+   target = "AL_FormatToken";
 };

+ 1 - 0
Templates/Full/game/core/scripts/client/missionDownload.cs

@@ -89,6 +89,7 @@ function clientCmdMissionStartPhase3(%seq,%missionName)
    echo ("*** Phase 3: Mission Lighting");
    $MSeq = %seq;
    $Client::MissionFile = %missionName;
+   $pref::ReflectionProbes::CurrentLevelPath = filePath($Client::MissionFile) @ "/" @ fileBase($Client::MissionFile) @ "/probes/";
 
    // Need to light the mission before we are ready.
    // The sceneLightingComplete function will complete the handshake 

+ 70 - 73
Templates/Full/game/levels/AProbeTest.mis

@@ -39,11 +39,9 @@ new SimGroup(MissionGroup) {
    };
    new Skylight() {
       enabled = "0";
-      ProbeShape = "Box";
       radius = "10";
       posOffset = "0 0 0";
       ReflectionMode = "Static Cubemap";
-      reflectionPath = "levels/AProbeTest/probes/";
       StaticCubemap = "sky_day_hdr_cubemap";
       Bake = "0";
       position = "0 0 0";
@@ -52,6 +50,8 @@ new SimGroup(MissionGroup) {
       canSave = "1";
       canSaveDynamicFields = "1";
       persistentId = "e4c73467-4089-11e8-b478-cd227cd60b8b";
+         ProbeShape = "Box";
+         reflectionPath = "levels/AProbeTest/probes/";
    };
    new SimGroup(PlayerDropPoints) {
       canSave = "1";
@@ -126,15 +126,13 @@ new SimGroup(MissionGroup) {
       canSaveDynamicFields = "1";
          direction = "1 1 -1";
    };
-   new ReflectionProbe() {
+   new BoxEnvironmentProbe() {
       enabled = "1";
-      ProbeShape = "Box";
       radius = "5";
       posOffset = "0 0 0";
       ReflectionMode = "Baked Cubemap";
-      reflectionPath = "levels/probeTest/probes/";
       Bake = "0";
-      position = "0 0.0825528 2.18272";
+      position = "0 0 4";
       rotation = "1 0 0 0";
       scale = "5 5 5";
       canSave = "1";
@@ -144,6 +142,65 @@ new SimGroup(MissionGroup) {
          IndirectLight = "1 1 1 1";
          IndirectLightMode = "Spherical Harmonics";
          Intensity = "1";
+         ProbeShape = "Box";
+         reflectionPath = "levels/probeTest/probes/";
+         SkyColor = "0.5 0.5 1 1";
+   };
+   new BoxEnvironmentProbe() {
+      enabled = "1";
+      radius = "5";
+      posOffset = "0 0 0";
+      ReflectionMode = "Baked Cubemap";
+      Bake = "0";
+      position = "-10 8 4";
+      rotation = "1 0 0 0";
+      scale = "5 5 5";
+      canSave = "1";
+      canSaveDynamicFields = "1";
+      persistentId = "f281a5ff-1ae9-11e9-9c9a-df9135416cc7";
+         GroundColor = "0.8 0.7 0.5 1";
+         IndirectLight = "1 1 1 1";
+         IndirectLightMode = "Spherical Harmonics";
+         Intensity = "1";
+         reflectionPath = "levels/probeTest/probes/";
+         SkyColor = "0.5 0.5 1 1";
+   };
+   new BoxEnvironmentProbe() {
+      enabled = "1";
+      radius = "5";
+      posOffset = "0 0 0";
+      ReflectionMode = "Baked Cubemap";
+      Bake = "0";
+      position = "-10 0 4";
+      rotation = "1 0 0 0";
+      scale = "5 5 5";
+      canSave = "1";
+      canSaveDynamicFields = "1";
+      persistentId = "e9c2eed2-1ae9-11e9-9c9a-df9135416cc7";
+         GroundColor = "0.8 0.7 0.5 1";
+         IndirectLight = "1 1 1 1";
+         IndirectLightMode = "Spherical Harmonics";
+         Intensity = "1";
+         reflectionPath = "levels/probeTest/probes/";
+         SkyColor = "0.5 0.5 1 1";
+   };
+   new BoxEnvironmentProbe() {
+      enabled = "1";
+      radius = "5";
+      posOffset = "0 0 0";
+      ReflectionMode = "Baked Cubemap";
+      Bake = "0";
+      position = "-10 -8 4";
+      rotation = "1 0 0 0";
+      scale = "5 5 5";
+      canSave = "1";
+      canSaveDynamicFields = "1";
+      persistentId = "f4db4dde-1ae9-11e9-9c9a-df9135416cc7";
+         GroundColor = "0.8 0.7 0.5 1";
+         IndirectLight = "1 1 1 1";
+         IndirectLightMode = "Spherical Harmonics";
+         Intensity = "1";
+         reflectionPath = "levels/probeTest/probes/";
          SkyColor = "0.5 0.5 1 1";
    };
    new ConvexShape() {
@@ -156,7 +213,7 @@ new SimGroup(MissionGroup) {
 
       surface = "0 0 0 1 0 0 0.5";
       surface = "0 1 0 0 0 0 -0.5";
-      surface = "0.707107 0 0 0.707106 0 0.5 0";
+      surface = "0.707107 0 0 0.707107 0 0.5 0";
       surface = "0 0.707107 -0.707107 0 0 -0.5 -2.84217e-14";
       surface = "0.5 0.5 -0.5 0.5 -0.5 0 -9.93411e-08";
       surface = "0.5 -0.5 0.5 0.5 0.5 0 -9.93411e-08";
@@ -171,7 +228,7 @@ new SimGroup(MissionGroup) {
 
       surface = "0 0 0 1 0 0 0.5";
       surface = "0 1 0 0 0 0 -0.5";
-      surface = "0.707107 0 0 0.707106 0 0.5 0";
+      surface = "0.707107 0 0 0.707107 0 0.5 0";
       surface = "0 0.707107 -0.707107 0 0 -0.5 -2.84217e-14";
       surface = "0.5 0.5 -0.5 0.5 -0.5 0 -9.93411e-08";
       surface = "0.5 -0.5 0.5 0.5 0.5 0 -9.93411e-08";
@@ -186,7 +243,7 @@ new SimGroup(MissionGroup) {
 
       surface = "0 0 0 1 0 0 0.5";
       surface = "0 1 0 0 0 0 -0.5";
-      surface = "0.707107 0 0 0.707107 0 0.5 0";
+      surface = "0.707107 0 0 0.707106 0 0.5 0";
       surface = "0 0.707107 -0.707107 0 0 -0.5 -2.84217e-14";
       surface = "0.5 0.5 -0.5 0.5 -0.5 0 -9.93411e-08";
       surface = "0.5 -0.5 0.5 0.5 0.5 0 -9.93411e-08";
@@ -201,7 +258,7 @@ new SimGroup(MissionGroup) {
 
       surface = "0 0 0 1 0 0 0.5";
       surface = "0 1 0 0 0 0 -0.5";
-      surface = "0.707107 0 0 0.707107 0 0.5 0";
+      surface = "0.707107 0 0 0.707106 0 0.5 0";
       surface = "0 0.707107 -0.707107 0 0 -0.5 -2.84217e-14";
       surface = "0.5 0.5 -0.5 0.5 -0.5 0 -9.93411e-08";
       surface = "0.5 -0.5 0.5 0.5 0.5 0 -9.93411e-08";
@@ -216,7 +273,7 @@ new SimGroup(MissionGroup) {
 
       surface = "0 0 0 1 0 0 0.5";
       surface = "0 1 0 0 0 0 -0.5";
-      surface = "0.707107 0 0 0.707107 0 0.5 0";
+      surface = "0.707107 0 0 0.707106 0 0.5 0";
       surface = "0 0.707107 -0.707107 0 0 -0.5 -2.84217e-14";
       surface = "0.5 0.5 -0.5 0.5 -0.5 0 -9.93411e-08";
       surface = "0.5 -0.5 0.5 0.5 0.5 0 -9.93411e-08";
@@ -231,7 +288,7 @@ new SimGroup(MissionGroup) {
 
       surface = "0 0 0 1 0 0 0.5";
       surface = "0 1 0 0 0 0 -0.5";
-      surface = "0.707107 0 0 0.707106 0 0.5 0";
+      surface = "0.707107 0 0 0.707107 0 0.5 0";
       surface = "0 0.707107 -0.707107 0 0 -0.5 -2.84217e-14";
       surface = "0.5 0.5 -0.5 0.5 -0.5 0 -9.93411e-08";
       surface = "0.5 -0.5 0.5 0.5 0.5 0 -9.93411e-08";
@@ -246,7 +303,7 @@ new SimGroup(MissionGroup) {
 
       surface = "0 0 0 1 0 0 0.5";
       surface = "0 1 0 0 0 0 -0.5";
-      surface = "0.707107 0 0 0.707107 0 0.5 0";
+      surface = "0.707107 0 0 0.707106 0 0.5 0";
       surface = "0 0.707107 -0.707107 0 0 -0.5 -2.84217e-14";
       surface = "0.5 0.5 -0.5 0.5 -0.5 0 -9.93411e-08";
       surface = "0.5 -0.5 0.5 0.5 0.5 0 -9.93411e-08";
@@ -313,65 +370,5 @@ new SimGroup(MissionGroup) {
       canSave = "1";
       canSaveDynamicFields = "1";
    };
-   new ReflectionProbe() {
-      enabled = "1";
-      ProbeShape = "Box";
-      radius = "5";
-      posOffset = "0 0 0";
-      ReflectionMode = "Baked Cubemap";
-      reflectionPath = "levels/probeTest/probes/";
-      Bake = "0";
-      position = "-8.24487 0.0825528 2.5031";
-      rotation = "1 0 0 0";
-      scale = "5 5 5";
-      canSave = "1";
-      canSaveDynamicFields = "1";
-      persistentId = "e9c2eed2-1ae9-11e9-9c9a-df9135416cc7";
-         GroundColor = "0.8 0.7 0.5 1";
-         IndirectLight = "1 1 1 1";
-         IndirectLightMode = "Spherical Harmonics";
-         Intensity = "1";
-         SkyColor = "0.5 0.5 1 1";
-   };
-   new ReflectionProbe() {
-      enabled = "1";
-      ProbeShape = "Box";
-      radius = "5";
-      posOffset = "0 0 0";
-      ReflectionMode = "Baked Cubemap";
-      reflectionPath = "levels/probeTest/probes/";
-      Bake = "0";
-      position = "-8.24487 3.18253 2.18272";
-      rotation = "1 0 0 0";
-      scale = "5 5 5";
-      canSave = "1";
-      canSaveDynamicFields = "1";
-      persistentId = "f281a5ff-1ae9-11e9-9c9a-df9135416cc7";
-         GroundColor = "0.8 0.7 0.5 1";
-         IndirectLight = "1 1 1 1";
-         IndirectLightMode = "Spherical Harmonics";
-         Intensity = "1";
-         SkyColor = "0.5 0.5 1 1";
-   };
-   new ReflectionProbe() {
-      enabled = "1";
-      ProbeShape = "Box";
-      radius = "5";
-      posOffset = "0 0 0";
-      ReflectionMode = "Baked Cubemap";
-      reflectionPath = "levels/probeTest/probes/";
-      Bake = "0";
-      position = "-8.24487 -3.37372 2.18272";
-      rotation = "1 0 0 0";
-      scale = "5 5 5";
-      canSave = "1";
-      canSaveDynamicFields = "1";
-      persistentId = "f4db4dde-1ae9-11e9-9c9a-df9135416cc7";
-         GroundColor = "0.8 0.7 0.5 1";
-         IndirectLight = "1 1 1 1";
-         IndirectLightMode = "Spherical Harmonics";
-         Intensity = "1";
-         SkyColor = "0.5 0.5 1 1";
-   };
 };
 //--- OBJECT WRITE END ---

+ 31 - 18
Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl

@@ -1,8 +1,7 @@
+#include "../../postFx/postFx.hlsl"
+#include "../../shaderModel.hlsl"
 #include "../../shaderModelAutoGen.hlsl"
-
-#include "farFrustumQuad.hlsl"
 #include "../../lighting.hlsl"
-#include "../../torque.hlsl"
 
 TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
 TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 1);
@@ -21,13 +20,15 @@ uniform float cubeMips;
 uniform float numProbes;
 TORQUE_UNIFORM_SAMPLERCUBEARRAY(cubeMapAR, 4);
 TORQUE_UNIFORM_SAMPLERCUBEARRAY(irradianceCubemapAR, 5);
+//TORQUE_UNIFORM_SAMPLERCUBE(cubeMapAR, 4);
+//TORQUE_UNIFORM_SAMPLERCUBE(irradianceCubemapAR, 5);
 uniform float4    inProbePosArray[MAX_PROBES];
 uniform float4x4  worldToObjArray[MAX_PROBES];
 uniform float4    bbMinArray[MAX_PROBES];
 uniform float4    bbMaxArray[MAX_PROBES];
-uniform float     useSphereMode[MAX_PROBES];
-uniform float     radius[MAX_PROBES];
-uniform float2    attenuation[MAX_PROBES];
+uniform float4     useSphereMode[MAX_PROBES];
+uniform float4     radius[MAX_PROBES];
+uniform float4    attenuation[MAX_PROBES];
 
 // Box Projected IBL Lighting
 // Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
@@ -51,6 +52,7 @@ float3 iblBoxDiffuse( Surface surface, int id)
    float3 cubeN = boxProject(surface.P, surface.N, inProbePosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz);
    cubeN.z *=-1;
    return TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR,cubeN,id,0).xyz;
+   //return TORQUE_TEXCUBELOD(irradianceCubemapAR,float4(cubeN,0)).xyz;
 }
 
 float3 iblBoxSpecular(Surface surface, float3 surfToEye, TORQUE_SAMPLER2D(brdfTexture), int id)
@@ -67,6 +69,7 @@ float3 iblBoxSpecular(Surface surface, float3 surfToEye, TORQUE_SAMPLER2D(brdfTe
    cubeR = boxProject(surface.P, surface.N, inProbePosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz);
 	
    float3 radiance = TORQUE_TEXCUBEARRAYLOD(cubeMapAR,cubeR,id,lod).xyz * (brdf.x + brdf.y);
+   //float3 radiance = TORQUE_TEXCUBELOD(cubeMapAR,float4(cubeR,lod)).xyz * (brdf.x + brdf.y);
     
    return radiance;
 }
@@ -76,8 +79,8 @@ float defineBoxSpaceInfluence(Surface surface, int id)
     float tempAttenVal = 3.5; //replace with per probe atten
     float3 surfPosLS = mul( worldToObjArray[id], float4(surface.P,1.0)).xyz;
 
-    float3 boxMinLS = inProbePosArray[id].xyz-(float3(1,1,1)*radius[0]);
-    float3 boxMaxLS = inProbePosArray[id].xyz+(float3(1,1,1)*radius[0]);
+    float3 boxMinLS = inProbePosArray[id].xyz-(float3(1,1,1)*radius[0].x);
+    float3 boxMaxLS = inProbePosArray[id].xyz+(float3(1,1,1)*radius[0].x);
 
     float boxOuterRange = length(boxMaxLS - boxMinLS);
     float boxInnerRange = boxOuterRange / tempAttenVal;
@@ -88,11 +91,11 @@ float defineBoxSpaceInfluence(Surface surface, int id)
     return max(localDir.x, max(localDir.y, localDir.z)) * -1;
 }
 
-float4 main( FarFrustumQuadConnectP IN ) : SV_TARGET
+float4 main( PFXVertToPix IN ) : SV_TARGET
 {
    //unpack normal and linear depth 
    float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, IN.uv0.xy);
-   
+
    //create surface
    Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
                                     IN.uv0.xy, eyePosWorld, IN.wsEyeRay, cameraToWorld);
@@ -102,29 +105,30 @@ float4 main( FarFrustumQuadConnectP IN ) : SV_TARGET
    {   
       discard;
    }                                    
-	float blendVal[MAX_PROBES];
+	
+   float blendVal[MAX_PROBES];
    float3 surfToEye = normalize(surface.P - eyePosWorld);
 
    int i = 0;
-	float blendSum = 0;
-	float invBlendSum = 0;
+   float blendSum = 0;
+   float invBlendSum = 0;
       
    for(i=0; i < numProbes; i++)
    {
         float3 probeWS = inProbePosArray[i].xyz;
         float3 L = probeWS - surface.P;
       
-        if(useSphereMode[i])
+        /*if(useSphereMode[i])
         {
             float3 L = inProbePosArray[i].xyz - surface.P;
             blendVal[i] = 1.0-length(L)/radius[i];
             blendVal[i] = max(0,blendVal[i]);
         }
         else
-        {
+        {*/
             blendVal[i] = defineBoxSpaceInfluence(surface, i);
             blendVal[i] = max(0,blendVal[i]);		
-        }
+        //}
 		blendSum += blendVal[i];
         invBlendSum +=(1.0f - blendVal[i]);
    }
@@ -141,6 +145,13 @@ float4 main( FarFrustumQuadConnectP IN ) : SV_TARGET
       blendSum += blendVal[i];
    }
 
+   float finalSum = blendSum;
+
+    //return TORQUE_TEX2D(colorBuffer, IN.uv0.xy);
+    //return float4(surface.N,1);
+   //return float4(1,1,1, 1);
+   //return float4(finalSum,finalSum,finalSum, 1);
+
     // Normalize blendVal
    if (blendSum == 0.0f) // Possible with custom weight
    {
@@ -162,11 +173,13 @@ float4 main( FarFrustumQuadConnectP IN ) : SV_TARGET
    kD *= 1.0 - surface.metalness;
    for (i = 0; i < numProbes; ++i)
    {
-      irradiance += blendVal[i]*iblBoxDiffuse(surface,i);
+      irradiance += float3(blendVal[i],blendVal[i],blendVal[i])/*blendVal[i]*iblBoxDiffuse(surface,i)*/;
       
       specular += blendVal[i]*F*iblBoxSpecular(surface, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture),i);
    }
    //final diffuse color
    float3 diffuse = kD * irradiance * surface.baseColor.rgb;
-	return float4(diffuse + specular * surface.ao, blendSum);
+	float4 finalColor = float4(diffuse + specular * surface.ao, 1);
+
+    return finalColor;
 }

+ 0 - 52
Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayV.hlsl

@@ -1,52 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "../../hlslStructs.hlsl"
-#include "../../shaderModel.hlsl"
-#include "../../torque.hlsl"
-
-struct GFXVertexPT
-{
-   float3 pos : POSITION;
-   float4 uv : TEXCOORD1;
-};
-
-struct ConnectData
-{
-   float4 hpos : TORQUE_POSITION;
-   float4 uv0 : TEXCOORD1;
-   float4 vsEyeDir : TEXCOORD2;
-};
-
-uniform float4 rtParams0;
-uniform float4x4 worldViewOnly;
-
-ConnectData main( GFXVertexPT IN )
-{
-   ConnectData OUT;
-   
-   OUT.hpos = float4(IN.pos,1.0);
-   OUT.uv0 = float4(viewportCoordToRenderTarget( IN.uv, rtParams0 ),0,0); 
-   OUT.vsEyeDir = mul(worldViewOnly, float4(IN.pos, 1.0));
-   
-   return OUT;
-}

+ 0 - 171
Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl

@@ -1,171 +0,0 @@
-#include "../../shaderModelAutoGen.hlsl"
-
-#include "farFrustumQuad.hlsl"
-#include "../../lighting.hlsl"
-#include "../../torque.hlsl"
-
-struct ConvexConnectP
-{
-   float4 pos : TORQUE_POSITION;
-   float4 wsEyeDir : TEXCOORD0;
-   float4 ssPos : TEXCOORD1;
-   float4 vsEyeDir : TEXCOORD2;
-};
-
-TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
-TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 1);
-TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 2);
-TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 3);
-TORQUE_UNIFORM_SAMPLERCUBE(irradianceCubemap, 4);
-TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 5);
-uniform float cubeMips;
-
-uniform float4 rtParams0;
-
-uniform float3 probeWSPos;
-uniform float3 probeLSPos;
-uniform float4 vsFarPlane;
-
-uniform float  radius;
-uniform float2 attenuation;
-
-uniform float4x4 worldToObj;
-uniform float4x4 cameraToWorld;
-
-uniform float3 eyePosWorld;
-uniform float3 bbMin;
-uniform float3 bbMax;
-
-uniform float useSphereMode;
-
-#define MAX_PROBES 50
-
-uniform float numProbes;
-uniform float3 inProbePosArray[MAX_PROBES];
-
-// 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 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
-{ 
-   float3 nrdir = reflectDir;
-	float3 offset = wsPosition;
-   float3 plane1vec = (boxMax - offset) / nrdir;
-   float3 plane2vec = (boxMin - offset) / nrdir;
-	
-	float3 furthestPlane = max(plane1vec, plane2vec);
-	float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
-   float3 posonbox = offset + nrdir * dist;
-
-   return posonbox - boxWSPos;
-}
-
-float3 iblBoxSpecular(float3 normal, float3 wsPos, float roughness, float3 surfToEye,
-                     TORQUE_SAMPLER2D(brdfTexture), 
-                    TORQUE_SAMPLERCUBE(radianceCube),
-                    float3 boxPos,
-                    float3 boxMin,
-                    float3 boxMax)
-{
-   float ndotv = clamp(dot(normal, surfToEye), 0.0, 1.0);
-
-    // BRDF
-   float2 brdf = TORQUE_TEX2DLOD(brdfTexture, float4(roughness, ndotv,0.0,0.0)).xy;
-
-    // Radiance (Specular)
-	float maxmip = pow(cubeMips+1,2);
-   float lod = roughness*maxmip;
-   float3 r = reflect(surfToEye, normal);
-   float3 cubeR = normalize(r);
-   cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax);
-	
-   float3 radiance = TORQUE_TEXCUBELOD(radianceCube, float4(cubeR, lod)).xyz * (brdf.x + brdf.y);
-    
-   return radiance;
-}
-
-float defineBoxSpaceInfluence(float3 surfPosWS, float3 probePos, float radius, float atten)
-{
-    float3 surfPosLS = mul( worldToObj, float4(surfPosWS,1.0)).xyz;
-
-    float3 boxMinLS = probePos-(float3(1,1,1)*radius);
-    float3 boxMaxLS = probePos+(float3(1,1,1)*radius);
-
-    float boxOuterRange = length(boxMaxLS - boxMinLS);
-    float boxInnerRange = boxOuterRange / atten;
-
-    float3 localDir = float3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z));
-    localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange);
-
-    return max(localDir.x, max(localDir.y, localDir.z)) * -1;
-}
-
-float4 main( ConvexConnectP IN ) : SV_TARGET
-{ 
-   // Compute scene UV
-   float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; 
-   float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-
-   //eye ray WS/LS
-   float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
-   float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz;
-   
-   //unpack normal and linear depth 
-   float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene);
-   
-   //create surface
-   Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
-                                    uvScene, eyePosWorld, wsEyeRay, cameraToWorld);		  
-	float blendVal = 1.0;
-	/*if(useSphereMode)
-	{
-		float3 L = probeWSPos - surface.P;
-		blendVal = 1.0-length(L)/radius;
-		clip(blendVal);		
-	}
-	else
-	{
-		float tempAttenVal = 3.5;
-		blendVal = defineBoxSpaceInfluence(surface.P, probeWSPos, radius, tempAttenVal);
-		clip(blendVal);
-		float compression = 0.05;
-		blendVal=(1.0-compression)+blendVal*compression;
-	}*/
-
-    float3 surfToEye = normalize(surface.P - eyePosWorld);
-    float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).xyz;
-	float3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), TORQUE_SAMPLERCUBE_MAKEARG(cubeMap), probeWSPos, bbMin, bbMax);
-
-    int i;
-	irradiance = float3(0,0,0);
-	float blendSum = 0.00001;
-    for(i=0; i < numProbes; i++)
-    {
-        float3 probeWS = inProbePosArray[i];
-
-        float3 L = probeWS - surface.P;
-		blendVal = 1.0-length(L)/radius;
-		blendVal = max(0,blendVal);
-
-        irradiance += float3(blendVal,blendVal,blendVal);
-        specular = irradiance;
-		blendSum += blendVal;
-    }
-	//irradiance /= blendSum;
-	//specular /= blendSum;
-	blendSum /= numProbes;
-	
-	//render into the bound space defined above
-	//
-	//float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).xyz;
-	//float3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), TORQUE_SAMPLERCUBE_MAKEARG(cubeMap), probeWSPos, bbMin, bbMax);
-   float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
-   specular *= F;
-   //energy conservation
-	float3 kD = 1.0.xxx - F;
-	kD *= 1.0 - surface.metalness;
-   //final diffuse color
-   float3 diffuse = kD * irradiance * surface.baseColor.rgb;
-
-   return float4(diffuse + specular * surface.ao, blendSum);
-}

+ 0 - 62
Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl

@@ -1,62 +0,0 @@
-#include "../../shaderModelAutoGen.hlsl"
-
-#include "farFrustumQuad.hlsl"
-#include "../../lighting.hlsl"
-#include "../../torque.hlsl"
-
-struct ConvexConnectP
-{
-   float4 pos : TORQUE_POSITION;
-   float4 wsEyeDir : TEXCOORD0;
-   float4 ssPos : TEXCOORD1;
-   float4 vsEyeDir : TEXCOORD2;
-};
-
-TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
-TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 1);
-TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 2);
-TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 3);
-TORQUE_UNIFORM_SAMPLERCUBE(irradianceCubemap, 4);
-TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 5);
-
-uniform float4 rtParams0;
-uniform float4 vsFarPlane;
-uniform float4x4 cameraToWorld;
-uniform float3 eyePosWorld;
-
-float3 iblSpecular(in Surface surface, float3 F)
-{
-	const float MAX_REFLECTION_LOD = 4.0;
-	float3 prefilteredColor = TORQUE_TEXCUBELOD(cubeMap, float4(surface.R, surface.roughness * MAX_REFLECTION_LOD)).rgb;
-	float2 envBRDF  = TORQUE_TEX2D(BRDFTexture, float2(surface.NdotV, surface.roughness)).rg;
-	return prefilteredColor * (F * envBRDF.x + envBRDF.y);
-}
-
-float4 main( ConvexConnectP IN ) : SV_TARGET
-{ 
-   // Compute scene UV
-   float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; 
-   float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-
-   //eye ray WS/LS
-   float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
-   float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz;
-   
-   //unpack normal and linear depth 
-   float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene);
-   
-   //create surface
-   Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
-                                    uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
-
-   float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
-   float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).rgb;
-   float3 specular = iblSpecular(surface, F);
-   //energy conservation
-	float3 kD = 1.0.xxx - F;
-	kD *= 1.0 - surface.metalness;
-   //final diffuse color
-   float3 diffuse = kD * irradiance * surface.baseColor.rgb;
-
-   return float4(diffuse + specular * surface.ao, 0);
-}

+ 2 - 1
Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs

@@ -56,7 +56,8 @@ function EWCreatorWindow::init( %this )
       %this.registerMissionObject( "PointLight",          "Point Light" );
       %this.registerMissionObject( "SpotLight",           "Spot Light" );
       
-      %this.registerMissionObject( "ReflectionProbe",       "Reflection Probe" );
+      %this.registerMissionObject( "BoxEnvironmentProbe",       "Box Environment Probe" );
+      %this.registerMissionObject( "SphereEnvironmentProbe",    "Sphere Environment Probe" );
       %this.registerMissionObject( "Skylight",       "Skylight" );
       
       %this.registerMissionObject( "GroundCover",         "Ground Cover" );

+ 1 - 14
Templates/Full/game/tools/worldEditor/scripts/lighting.ed.cs

@@ -64,18 +64,5 @@ function EditorLightingMenu::onMenuSelect( %this )
 
 function updateReflectionProbes()
 {
-   /*%probeIds = parseMissionGroupForIds("ReflectionProbe", "");
-   %probeCount = getWordCount(%probeIds);
-   
-   for(%i=0; %i < %probeCount; %i++)
-   {
-      %probe = getWord(%probeIds, %i);
-      
-      %path = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
-      %probe.bake(%path, 64);
-   }
-   
-   EWorldEditor.isDirty = true;*/
-   
-   Canvas.pushDialog(ProbeBakeDlg);
+  Canvas.pushDialog(ProbeBakeDlg);
 }

+ 8 - 6
Templates/Full/game/tools/worldEditor/scripts/probeBake.ed.cs

@@ -16,14 +16,16 @@ function ProbeBakeDlg::onWake(%this)
 
 function ProbeBakeDlg_RunBake::onClick(%this)
 {
-   %probeIds = parseMissionGroupForIds("ReflectionProbe", "");
+   %boxProbeIds = parseMissionGroupForIds("BoxEnvironmentProbe", "");
+   %sphereProbeIds = parseMissionGroupForIds("SphereEnvironmentProbe", "");
    %skylightIds = parseMissionGroupForIds("Skylight", "");
    
+   %probeIds = rtrim(ltrim(%boxProbeIds SPC %sphereProbeIds));
    %probeIds = rtrim(ltrim(%probeIds SPC %skylightIds));
    %probeCount = getWordCount(%probeIds);
    
    %numIter = ProbeBakeDlg_NumIterTxt.getText();
-   %resolution = ProbeBakeDlg_ProbeResList.getText();
+   $pref::ReflectionProbes::BakeResolution = ProbeBakeDlg_ProbeResList.getText();
    %progressStep = 100 / (%numIter * %probeCount);
    %currentProgressValue = 0;
    
@@ -32,17 +34,17 @@ function ProbeBakeDlg_RunBake::onClick(%this)
    
    for(%iter=0; %iter < %numIter; %iter++)
    {
-      %renderWithProbes = false;
+      $pref::ReflectionProbes::RenderWithProbes = false;
       
       if(%iter != 0)
-         %renderWithProbes = true;
+         $pref::ReflectionProbes::RenderWithProbes = true;
          
       for(%i=0; %i < %probeCount; %i++)
       {
          %probe = getWord(%probeIds, %i);
          
-         %path = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
-         %probe.bake(%path, %resolution, %renderWithProbes);
+         $pref::ReflectionProbes::CurrentLevelPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
+         ProbeBin.bakeProbe(%probe);
          
          %currentProgressValue += %progressStep;
          ProbeBakeDlg_Progress.setValue(%currentProgressValue);