浏览代码

Probe Array WIP

Areloch 6 年之前
父节点
当前提交
f110158654

+ 100 - 1
Engine/source/lighting/probeManager.cpp

@@ -129,7 +129,8 @@ ProbeShaderConstants::ProbeShaderConstants()
    mProbeBoxMaxSC(NULL),
    mProbeIsSphereSC(NULL),
    mProbeLocalPosSC(NULL),
-   mProbeCubemapSC(NULL)
+   mProbeCubemapSC(NULL),
+   mProbeCountSC(NULL)
 {
 }
 
@@ -163,6 +164,7 @@ void ProbeShaderConstants::init(GFXShader* shader)
    mProbeIsSphereSC = shader->getShaderConstHandle(ShaderGenVars::probeIsSphere);
    mProbeLocalPosSC = shader->getShaderConstHandle(ShaderGenVars::probeLocalPos);
    mProbeCubemapSC = shader->getShaderConstHandle(ShaderGenVars::probeCubemap);
+   mProbeCountSC = shader->getShaderConstHandle(ShaderGenVars::probeCount);
 
    mInit = true;
 }
@@ -182,6 +184,7 @@ ProbeManager::ProbeManager()
 
    mSkylightMaterial = nullptr;
    mReflectProbeMaterial = nullptr;
+   mReflectProbeArrayMaterial = nullptr;
 }
 
 ProbeManager::~ProbeManager() 
@@ -624,6 +627,22 @@ ProbeManager::ReflectProbeMaterialInfo* ProbeManager::getReflectProbeMaterial()
 	return mReflectProbeMaterial;
 }
 
+ProbeManager::ReflectionProbeArrayMaterialInfo* ProbeManager::getReflectProbeArrayMaterial()
+{
+   PROFILE_SCOPE(AdvancedLightBinManager_getReflectProbeArrayMaterial);
+
+   //ReflectProbeMaterialInfo *info = NULL;
+
+   if (!mReflectProbeArrayMaterial)
+   {
+      // Now create the material info object.
+      mReflectProbeArrayMaterial = new ReflectionProbeArrayMaterialInfo("ReflectionProbeArrayMaterial",
+         getGFXVertexFormat<GFXVertexPC>());
+   }
+
+   return mReflectProbeArrayMaterial;
+}
+
 void ProbeManager::setupSkylightProbe(ProbeRenderInst *probeInfo)
 {
 	probeInfo->vertBuffer = getSphereMesh(probeInfo->numPrims, probeInfo->primBuffer);
@@ -756,11 +775,19 @@ GFXVertexBufferHandle<GFXVertexPC> ProbeManager::getSphereMesh(U32 &outNumPrimit
 //
 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;
 }
 
@@ -814,6 +841,41 @@ bool SkylightMatInstance::setupPass(SceneRenderState *state, const SceneData &sg
 
 	return true;
 }
+
+bool ReflectProbeArrayMatInstance::init(const FeatureSet &features, const GFXVertexFormat *vertexFormat)
+{
+   bool success = Parent::init(features, vertexFormat);
+
+   // If the initialization failed don't continue.
+   if (!success || !mProcessedMaterial || mProcessedMaterial->getNumPasses() == 0)
+      return false;
+   return true;
+}
+
+bool ReflectProbeArrayMatInstance::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;
+}
 //
 //
 ProbeManager::ReflectProbeMaterialInfo::ReflectProbeMaterialInfo(const String &matName,
@@ -861,6 +923,8 @@ ProbeManager::ReflectProbeMaterialInfo::ReflectProbeMaterialInfo(const String &m
 
 	useSphereMode = matInstance->getMaterialParameterHandle("$useSphereMode");
 
+   probeCount = matInstance->getMaterialParameterHandle("$numProbes");
+
 	for (U32 i = 0; i < 9; i++)
 		shTerms[i] = matInstance->getMaterialParameterHandle(String::ToString("$SHTerms%d", i));
 
@@ -1010,6 +1074,41 @@ ProbeManager::SkylightMaterialInfo::~SkylightMaterialInfo()
 	SAFE_DELETE(matInstance);
 }
 
+//
+//
+ProbeManager::ReflectionProbeArrayMaterialInfo::ReflectionProbeArrayMaterialInfo(const String &matName,
+   const GFXVertexFormat *vertexFormat)
+   : ReflectProbeMaterialInfo(matName, vertexFormat)
+{
+   Material *mat = MATMGR->getMaterialDefinitionByName(matName);
+   if (!mat)
+      return;
+
+   matInstance = new ReflectProbeArrayMatInstance(*mat);
+
+   const Vector<GFXShaderMacro> &macros = Vector<GFXShaderMacro>();
+
+   for (U32 i = 0; i < macros.size(); i++)
+      matInstance->addShaderMacro(macros[i].name, macros[i].value);
+
+   matInstance->init(MATMGR->getDefaultFeatures(), vertexFormat);
+
+   farPlane = matInstance->getMaterialParameterHandle("$farPlane");
+   vsFarPlane = matInstance->getMaterialParameterHandle("$vsFarPlane");
+   negFarPlaneDotEye = matInstance->getMaterialParameterHandle("$negFarPlaneDotEye");
+   zNearFarInvNearFar = matInstance->getMaterialParameterHandle("$zNearFarInvNearFar");
+
+   useCubemap = matInstance->getMaterialParameterHandle("$useCubemap");
+   cubemap = matInstance->getMaterialParameterHandle("$cubeMap");
+
+   eyePosWorld = matInstance->getMaterialParameterHandle("$eyePosWorld");
+}
+
+ProbeManager::ReflectionProbeArrayMaterialInfo::~ReflectionProbeArrayMaterialInfo()
+{
+   SAFE_DELETE(matInstance);
+}
+
 /*bool ProbeManager::lightScene( const char* callback, const char* param )
 {
    BitSet32 flags = 0;

+ 37 - 0
Engine/source/lighting/probeManager.h

@@ -56,6 +56,8 @@
 
 #include "core/util/SystemInterfaceList.h"
 
+#include "materials/processedShaderMaterial.h"
+
 class SimObject;
 class ProbeManager;
 class Material;
@@ -177,6 +179,7 @@ struct ProbeShaderConstants
    GFXShaderConstHandle *mProbeIsSphereSC;
    GFXShaderConstHandle *mProbeLocalPosSC;
    GFXShaderConstHandle *mProbeCubemapSC;
+   GFXShaderConstHandle *mProbeCountSC;
 
    ProbeShaderConstants();
    ~ProbeShaderConstants();
@@ -197,11 +200,15 @@ protected:
 
 	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; }
 };
 
 class SkylightMatInstance : public ReflectProbeMatInstance
@@ -216,6 +223,22 @@ public:
 	virtual bool setupPass(SceneRenderState *state, const SceneData &sgData);
 };
 
+class ReflectProbeArrayMatInstance : public MatInstance
+{
+   typedef MatInstance Parent;
+protected:
+   MaterialParameterHandle * mProbeParamsSC;
+   bool mInternalPass;
+
+   GFXStateBlockRef mProjectionState;
+
+public:
+   ReflectProbeArrayMatInstance(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);
+};
+
 class ProbeManager
 {
 public:
@@ -254,6 +277,8 @@ public:
 		MaterialParameterHandle *shTerms[9];
 		MaterialParameterHandle *shConsts[5];
 
+      MaterialParameterHandle *probeCount;
+
 		ReflectProbeMaterialInfo(const String &matName, const GFXVertexFormat *vertexFormat);
 
 		virtual ~ReflectProbeMaterialInfo();
@@ -275,6 +300,15 @@ public:
 		virtual ~SkylightMaterialInfo();
 	};
 
+   struct ReflectionProbeArrayMaterialInfo : public ReflectProbeMaterialInfo
+   {
+      ReflectionProbeArrayMaterialInfo(const String &matName, const GFXVertexFormat *vertexFormat);
+
+      ReflectProbeArrayMatInstance *matInstance;
+
+      virtual ~ReflectionProbeArrayMaterialInfo();
+   };
+
    enum SpecialProbeTypesEnum
    {
       SkylightProbeType,
@@ -353,6 +387,7 @@ public:
 
    ReflectProbeMaterialInfo* getReflectProbeMaterial();
    SkylightMaterialInfo* getSkylightMaterial();
+   ReflectionProbeArrayMaterialInfo* getReflectProbeArrayMaterial();
 
 protected:
 
@@ -415,6 +450,8 @@ protected:
 
    SkylightMaterialInfo* mSkylightMaterial;
 
+   ReflectionProbeArrayMaterialInfo* mReflectProbeArrayMaterial;
+
    GFXVertexBufferHandle<GFXVertexPC> getSphereMesh(U32 &outNumPrimitives, GFXPrimitiveBufferHandle &outPrimitives);;
 };
 

+ 2 - 0
Engine/source/materials/processedShaderMaterial.h

@@ -266,9 +266,11 @@ protected:
    void _setPrimaryLightConst(const LightInfo* light, const MatrixF& objTrans, const U32 stageNum);
 
    /// This is here to deal with the differences between ProcessedCustomMaterials and ProcessedShaderMaterials.
+public:
    virtual GFXShaderConstBuffer* _getShaderConstBuffer(const U32 pass);
    virtual ShaderConstHandles* _getShaderConstHandles(const U32 pass);
 
+protected:
    ///
    virtual void _initMaterialParameters();
 

+ 170 - 47
Engine/source/renderInstance/renderProbeMgr.cpp

@@ -33,6 +33,8 @@
 
 #include "gfx/gfxDebugEvent.h"
 
+#include "materials/shaderData.h"
+
 IMPLEMENT_CONOBJECT(RenderProbeMgr);
 
 ConsoleDocClass( RenderProbeMgr, 
@@ -116,34 +118,43 @@ void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
 
    // Now build the quad for drawing full-screen vector light
    // passes.... this is a volatile VB and updates every frame.
-   FarFrustumQuadVert verts[4];
+   GFXVertexPC verts[4];
    {
       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);
+      //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);
+     // 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);
+      //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);
+     // invCam.mulP(wsFrustumPoints[Frustum::FarBottomRight], &verts[3].normal);
+    //  verts[3].texCoord.set(1.0, -1.0);
+    //  verts[3].tangent.set(wsFrustumPoints[Frustum::FarBottomRight] - cameraOffsetPos);
    }
+
+   Point3F norms[4];
+   {
+      invCam.mulP(wsFrustumPoints[Frustum::FarTopLeft], &norms[0]);
+      invCam.mulP(wsFrustumPoints[Frustum::FarTopRight], &norms[1]);
+      invCam.mulP(wsFrustumPoints[Frustum::FarBottomLeft], &norms[2]);
+      invCam.mulP(wsFrustumPoints[Frustum::FarBottomRight], &norms[3]);
+   }
+
    mFarFrustumQuadVerts.set(GFX, 4);
    dMemcpy(mFarFrustumQuadVerts.lock(), verts, sizeof(verts));
    mFarFrustumQuadVerts.unlock();
 
    PlaneF farPlane(wsFrustumPoints[Frustum::FarBottomLeft], wsFrustumPoints[Frustum::FarTopLeft], wsFrustumPoints[Frustum::FarTopRight]);
-   PlaneF vsFarPlane(verts[0].normal, verts[1].normal, verts[2].normal);
+   PlaneF vsFarPlane(norms[0], norms[1], norms[2]);
 
 
    // Parameters calculated, assign them to the materials
@@ -168,6 +179,17 @@ void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
          farPlane,
          vsFarPlane);
    }
+
+   ProbeManager::ReflectionProbeArrayMaterialInfo* reflProbeArrayMat = PROBEMGR->getReflectProbeArrayMaterial();
+
+   if (reflProbeArrayMat != nullptr && reflProbeArrayMat->matInstance != nullptr)
+   {
+      reflProbeArrayMat->setViewParameters(frustum.getNearDist(),
+         frustum.getFarDist(),
+         frustum.getPosition(),
+         farPlane,
+         vsFarPlane);
+   }
 }
 
 //-----------------------------------------------------------------------------
@@ -230,7 +252,7 @@ void RenderProbeMgr::render( SceneRenderState *state )
    ProbeManager::SkylightMaterialInfo* skylightMat = PROBEMGR->getSkylightMaterial();
    ProbeManager::ReflectProbeMaterialInfo* reflProbeMat = PROBEMGR->getReflectProbeMaterial();
 
-   for (U32 i = 0; i < ProbeRenderInst::all.size(); i++)
+   /*for (U32 i = 0; i < ProbeRenderInst::all.size(); i++)
    {
 	   ProbeRenderInst* curEntry = ProbeRenderInst::all[i];
 
@@ -268,54 +290,155 @@ void RenderProbeMgr::render( SceneRenderState *state )
 			   GFX->drawPrimitive(GFXTriangleList, 0, curEntry->numPrims);
 		   }
 	   }
-   }
+   }*/
 
-   for (U32 i = 0; i < ProbeRenderInst::all.size(); i++)
+   //Array rendering
+   static U32 MAXPROBECOUNT = 50;
+
+   U32 probeCount = PROBEMGR->mRegisteredProbes.size();
+
+   if (probeCount != 0)
    {
-	   ProbeRenderInst* curEntry = ProbeRenderInst::all[i];
+      AlignedArray<Point3F> probePositions(MAXPROBECOUNT, sizeof(Point3F));
+      dMemset(probePositions.getBuffer(), 0, probePositions.getBufferSize());
 
-	   if (!curEntry->mIsEnabled)
-		   continue;
+      if (reflProbeMat && reflProbeMat->matInstance)
+      {
+         MaterialParameters *matParams = reflProbeMat->matInstance->getMaterialParameters();
 
-	   if (curEntry->numPrims == 0)
-		   continue;
+         MaterialParameterHandle *numProbesSC = reflProbeMat->matInstance->getMaterialParameterHandle("$numProbes");
+         matParams->setSafe(numProbesSC, (float)probeCount);
 
-	   if (curEntry->mIsSkylight && (!skylightMat || !skylightMat->matInstance))
-		   continue;
+         //ProcessedShaderMaterial* processedMat = reflProbeMat->matInstance->getProcessedShaderMaterial();
+         //GFXShaderConstBuffer* shaderConsts = processedMat->_getShaderConstBuffer(0);
 
-	   if (!curEntry->mIsSkylight && (!reflProbeMat || !reflProbeMat->matInstance))
-		   break;
+         //ProbeShaderConstants *psc = PROBEMGR->getProbeShaderConstants(shaderConsts);
 
-	   //Setup
-	   MatrixF probeTrans = curEntry->getTransform();
-	   
-	   if (!curEntry->mIsSkylight)
-	   {
-		   if (curEntry->mProbeShapeType == ProbeRenderInst::Sphere)
-			   probeTrans.scale(curEntry->mRadius * 1.01f);
+         MaterialParameterHandle *probePositionSC = reflProbeMat->matInstance->getMaterialParameterHandle("$inProbePosArray");
 
-		   sgData.objTrans = &probeTrans;
+         U32 effectiveProbeCount = 0;
 
-		   reflProbeMat->setProbeParameters(curEntry, state, worldToCameraXfm);
+         for (U32 i = 0; i < probeCount; i++)
+         {
+            if (effectiveProbeCount >= MAXPROBECOUNT)
+               break;
 
-		   // Set geometry
-		   GFX->setVertexBuffer(curEntry->vertBuffer);
-		   GFX->setPrimitiveBuffer(curEntry->primBuffer);
-		   while (reflProbeMat->matInstance->setupPass(state, sgData))
-		   {
-			   // Set transforms
-			   matrixSet.setWorld(*sgData.objTrans);
-			   reflProbeMat->matInstance->setTransforms(matrixSet, state);
-			   reflProbeMat->matInstance->setSceneInfo(state, sgData);
+            ProbeRenderInst* curEntry = ProbeRenderInst::all[PROBEMGR->mRegisteredProbes[i]];
 
-			   GFX->drawPrimitive(GFXTriangleList, 0, curEntry->numPrims);
-		   }
-	   }
+            /*if (!curEntry->mIsEnabled)
+               continue;
+
+            if (curEntry->numPrims == 0)
+               continue;
+
+            if (curEntry->mIsSkylight && (!skylightMat || !skylightMat->matInstance))
+               continue;
+
+            if (!curEntry->mIsSkylight && (!reflProbeMat || !reflProbeMat->matInstance))
+               break;*/
+
+               //Setup
+            const Point3F &probePos = curEntry->getPosition();
+            probePositions[i].x = probePos.x;
+            probePositions[i].y = probePos.y;
+            probePositions[i].z = probePos.z;
+
+            Point3F test = probePositions[i];
+
+            MatrixF probeTrans = curEntry->getTransform();
+
+            if (!curEntry->mIsSkylight)
+            {
+               //if (curEntry->mProbeShapeType == ProbeRenderInst::Sphere)
+              //    probeTrans.scale(curEntry->mRadius * 1.01f);
+
+               sgData.objTrans = &probeTrans;
+
+               reflProbeMat->setProbeParameters(curEntry, state, worldToCameraXfm);
+            }
+
+            effectiveProbeCount++;
+         }
+
+         if (effectiveProbeCount != 0)
+         {
+            Con::printf("Probe aligned position count: %i", probeCount);
+
+            for (U32 p = 0; p < probeCount; p++)
+            {
+               Point3F prb = probePositions[p];
+
+               Con::printf("Probe %i aligned position is: %g %g %g", p, prb.x, prb.y, prb.z);
+
+               bool tasadfh = true;
+            }
+
+            matParams->set(probePositionSC, probePositions);
+
+            // 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);
+            }
+         }
+      }
    }
+   //
+   //
+   /*ProbeManager::ReflectionProbeArrayMaterialInfo* reflProbeArrayMat = PROBEMGR->getReflectProbeArrayMaterial();
+
+   for (U32 i = 0; i < ProbeRenderInst::all.size(); i++)
+   {
+      if (i > 0)
+         return;
+
+      ProbeRenderInst* curEntry = ProbeRenderInst::all[i];
+
+      if (!reflProbeArrayMat || !reflProbeArrayMat->matInstance)
+         break;
+
+      //Setup
+      //MatrixF probeTrans = curEntry->getTransform();
+
+      //if (!curEntry->mIsSkylight)
+      {
+         //if (curEntry->mProbeShapeType == ProbeRenderInst::Sphere)
+         //   probeTrans.scale(curEntry->mRadius * 1.01f);
+
+         //sgData.objTrans = &state-;
+
+         reflProbeArrayMat->setProbeParameters(curEntry, state, worldToCameraXfm);
+
+         // Set geometry
+         GFX->setVertexBuffer(mFarFrustumQuadVerts);
+         GFX->setPrimitiveBuffer(NULL);
+         while (reflProbeArrayMat->matInstance->setupPass(state, sgData))
+         {
+            // Set transforms
+            //matrixSet.setWorld(*sgData.objTrans);
+            reflProbeArrayMat->matInstance->setTransforms(matrixSet, state);
+            reflProbeArrayMat->matInstance->setSceneInfo(state, sgData);
+
+            GFX->drawPrimitive(GFXTriangleStrip, 0, 2);
+         }
+      }
+   }*/
+   //
+   //
 
    GFX->popActiveRenderTarget();
 
    //PROBEMGR->unregisterAllProbes();
+   PROBEMGR->mRegisteredProbes.clear();
+
    PROFILE_END();
 
    GFX->setVertexBuffer(NULL);

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

@@ -38,18 +38,18 @@
 #include "gfx/gfxVertexBuffer.h"
 #endif
 
+#include "postFx/postEffectCommon.h"
+
 //**************************************************************************
 // RenderObjectMgr
 //**************************************************************************
 class RenderProbeMgr : public RenderBinManager
 {
    typedef RenderBinManager Parent;
-public:
-   typedef GFXVertexPNTT FarFrustumQuadVert;
 
 protected:
 
-   GFXVertexBufferHandle<FarFrustumQuadVert> mFarFrustumQuadVerts;
+   GFXVertexBufferHandle<GFXVertexPC> mFarFrustumQuadVerts;
 
 public:
    RenderProbeMgr();

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

@@ -77,6 +77,7 @@ const String ShaderGenVars::probeBoxMax("$inProbeBoxMax");
 const String ShaderGenVars::probeLocalPos("$inProbeLocalPos");
 const String ShaderGenVars::probeIsSphere("$inProbeIsSphere");
 const String ShaderGenVars::probeCubemap("$inProbeCubemap");
+const String ShaderGenVars::probeCount("$numProbes");
 
 // These are ignored by the D3D layers.
 const String ShaderGenVars::fogMap("$fogMap");

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

@@ -90,6 +90,7 @@ struct ShaderGenVars
    const static String probeLocalPos;
    const static String probeIsSphere;
    const static String probeCubemap;
+   const static String probeCount;
    
    // Textures
    const static String fogMap;

+ 29 - 0
Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs

@@ -405,5 +405,34 @@ new CustomMaterial( SkyLightMaterial )
    sampler["matInfoBuffer"] = "#matinfo";
    sampler["colorBuffer"] = "#color";
    
+   pixVersion = 3.0;
+};
+
+new ShaderData( ReflectionProbeArrayShader )
+{
+   DXVertexShaderFile = "shaders/common/lighting/advanced/convexGeometryV.hlsl";
+   DXPixelShaderFile  = "shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl";
+
+   OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/convexGeometryV.glsl";
+   OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/reflectionProbeArrayP.glsl";
+
+   samplerNames[0] = "$deferredBuffer";
+   samplerNames[1] = "$colorBuffer";
+   samplerNames[2] = "$matInfoBuffer";
+   samplerNames[3] = "$cubeMap";
+   samplerNames[4] = "$irradianceCubemap";
+   samplerNames[5] = "$BRDFTexture";
+   
+   pixVersion = 3.0;
+};
+
+new CustomMaterial( ReflectionProbeArrayMaterial )
+{
+   shader = ReflectionProbeArrayShader;
+   stateBlock = AL_ProbeState;
+   
+   sampler["deferredBuffer"] = "#deferred";
+   sampler["matInfoBuffer"] = "#matinfo";
+   
    pixVersion = 3.0;
 };

+ 63 - 0
Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeArrayP.glsl

@@ -0,0 +1,63 @@
+//-----------------------------------------------------------------------------
+// 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 "../../torque.hlsl"
+
+struct ConnectData
+{
+    float4 hpos    : TORQUE_POSITION;
+    float2 uv      : TEXCOORD;
+};
+
+uniform int face;
+
+TORQUE_UNIFORM_SAMPLERCUBE(environmentMap, 0);
+
+float4 main(ConnectData IN) : TORQUE_TARGET0
+{
+    float3 N = getCubeDir(face,IN.uv);
+    float3 irradiance = 0;
+    
+    // tangent space calculation from origin point
+    float3 up    = float3(0.0, 0.0, 1.0);
+    float3 right = cross(up, N);
+    up           = cross(N, right);
+       
+    float sampleDelta = 0.025;
+    int nrSamples = 0;
+    for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta)
+    {
+        for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta)
+        {
+            // spherical to cartesian (in tangent space)
+            float3 tangentSample = float3(sin(theta) * cos(phi),  sin(theta) * sin(phi), cos(theta));
+            // tangent space to world
+            float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; 
+
+            irradiance += TORQUE_TEXCUBE(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
+            nrSamples++;
+        }
+    }
+    irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples));
+    
+    return float4(irradiance, 1.0);
+}

+ 152 - 0
Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl

@@ -0,0 +1,152 @@
+#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;
+
+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 = float3(1,1,1);//TORQUE_TEXCUBELOD(radianceCube, float4(cubeR, lod)).xyz * (brdf.x + brdf.y);
+    
+   return radiance;
+}
+
+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;
+
+    [unroll]
+    for(float i=0; i < 10; i++)
+    {
+        float3 probeWSPos = float3(i * 1.1, 0, 2);
+        float3 L = probeWSPos - surface.P;
+		blendVal = 1.0-length(L)/radius;
+		clip(blendVal);		
+    }
+
+    //render into the bound space defined above
+	float3 surfToEye = normalize(surface.P - eyePosWorld);
+	float3 irradiance = float3(1,0,0);//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, blendVal);
+
+    /*float3 N = getCubeDir(face,IN.uv);
+    float3 irradiance = 0;
+    
+    // tangent space calculation from origin point
+    float3 up    = float3(0.0, 0.0, 1.0);
+    float3 right = cross(up, N);
+    up           = cross(N, right);
+       
+    float sampleDelta = 0.025;
+    int nrSamples = 0;
+    for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta)
+    {
+        for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta)
+        {
+            // spherical to cartesian (in tangent space)
+            float3 tangentSample = float3(sin(theta) * cos(phi),  sin(theta) * sin(phi), cos(theta));
+            // tangent space to world
+            float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; 
+
+            irradiance += TORQUE_TEXCUBE(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
+            nrSamples++;
+        }
+    }
+    irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples));
+    
+    return float4(irradiance, 1.0);*/
+
+    //return float4(1,0,0,1);
+
+    //float4 texCoord = float4( 1,0,0, 1 );    
+
+    //return texCoord;
+}

+ 28 - 5
Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl

@@ -38,6 +38,11 @@ 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/
@@ -112,7 +117,7 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
    Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
                                     uvScene, eyePosWorld, wsEyeRay, cameraToWorld);		  
 	float blendVal = 1.0;
-	if(useSphereMode)
+	/*if(useSphereMode)
 	{
 		float3 L = probeWSPos - surface.P;
 		blendVal = 1.0-length(L)/radius;
@@ -125,11 +130,29 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
 		clip(blendVal);
 		float compression = 0.05;
 		blendVal=(1.0-compression)+blendVal*compression;
-	}
-	//render into the bound space defined above
-	float3 surfToEye = normalize(surface.P - eyePosWorld);
-	float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).xyz;
+	}*/
+
+    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;
+    for(i=0; i < numProbes; i++)
+    {
+        float3 probeWS = inProbePosArray[i];
+
+        float3 L = probeWS - surface.P;
+		blendVal = 1.0-length(L)/radius;
+		//clip(blendVal);	
+
+        irradiance = float3(blendVal,blendVal,blendVal);
+        specular = irradiance;
+    }
+
+	//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