瀏覽代碼

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

# Conflicts:
#	Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl
Azaezel 6 年之前
父節點
當前提交
6a7d046a19

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

@@ -91,6 +91,8 @@ void BoxEnvironmentProbe::initPersistFields()
 {
    // SceneObject already handles exposing the transform
    Parent::initPersistFields();
+
+   removeField("radius");
 }
 
 void BoxEnvironmentProbe::inspectPostApply()
@@ -154,7 +156,7 @@ void BoxEnvironmentProbe::updateProbeParams()
    mProbeInfo->mProbeShapeType = ProbeRenderInst::Box;
 }
 
-void BoxEnvironmentProbe::prepRenderImage(SceneRenderState *state)
+/*void BoxEnvironmentProbe::prepRenderImage(SceneRenderState *state)
 {
    if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
       return;
@@ -223,7 +225,7 @@ void BoxEnvironmentProbe::prepRenderImage(SceneRenderState *state)
       ri->type = RenderPassManager::RIT_Editor;
       state->getRenderPass()->addInst(ri);
    }
-}
+}*/
 
 void BoxEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
 {

+ 1 - 1
Engine/source/T3D/lighting/boxEnvironmentProbe.h

@@ -108,7 +108,7 @@ public:
    virtual void updateProbeParams();
 
    // This is the function that allows this object to submit itself for rendering
-   void prepRenderImage(SceneRenderState *state);
+   //void prepRenderImage(SceneRenderState *state);
 
    void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
 };

+ 105 - 30
Engine/source/T3D/lighting/reflectionProbe.cpp

@@ -106,6 +106,7 @@ ReflectionProbe::ReflectionProbe()
    mDirty = false;
 
    mRadius = 10;
+   mObjScale = Point3F::One * 10;
    mProbeRefScale = Point3F::One*10;
 
    mUseCubemap = false;
@@ -159,17 +160,19 @@ void ReflectionProbe::initPersistFields()
    addGroup("Rendering");
       addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
          &_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid");
-
-     addField("radius", TypeF32, Offset(mRadius, ReflectionProbe), "The name of the material used to render the mesh.");
-
-     //addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
-     //   &_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
    endGroup("Rendering");
 
    addGroup("Reflection");
+      addProtectedField("radius", TypeF32, Offset(mRadius, ReflectionProbe), &_setRadius, &defaultProtectedGetFn, 
+         "The name of the material used to render the mesh.");
+
+      addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
+      &_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
+
 	   addField("refOffset", TypePoint3F, Offset(mProbeRefOffset, ReflectionProbe), "");
       addField("refScale", TypePoint3F, Offset(mProbeRefScale, ReflectionProbe), "");
-      addField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe),
+
+      addProtectedField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe), &_setReflectionMode, &defaultProtectedGetFn,
          "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.");
@@ -217,15 +220,7 @@ bool ReflectionProbe::_doBake(void *object, const char *index, const char *data)
 {
    ReflectionProbe* probe = reinterpret_cast< ReflectionProbe* >(object);
 
-   //if (probe->mDirty)
-   //   probe->bake(probe->mReflectionPath, 256);
-
-   ReflectionProbe *clientProbe = (ReflectionProbe*)probe->getClientObject();
-
-   if (clientProbe)
-   {
-      clientProbe->bake();
-   }
+   probe->bake();
 
    return false;
 }
@@ -236,12 +231,39 @@ bool ReflectionProbe::_toggleEditPosOffset(void *object, const char *index, cons
 
    probe->mEditPosOffset = !probe->mEditPosOffset;
 
-   //if (probe->mDirty)
-   //   probe->bake(probe->mReflectionPath, 256);
-
    return false;
 }
 
+bool ReflectionProbe::_setRadius(void *object, const char *index, const char *data)
+{
+   ReflectionProbe* probe = reinterpret_cast<ReflectionProbe*>(object);
+
+   if (probe->mProbeShapeType != ProbeRenderInst::Sphere)
+      return false;
+
+   probe->mObjScale = Point3F(probe->mRadius, probe->mRadius, probe->mRadius);
+   
+   return true;
+}
+
+bool ReflectionProbe::_setReflectionMode(void *object, const char *index, const char *data)
+{
+   ReflectionProbe* probe = reinterpret_cast<ReflectionProbe*>(object);
+
+   if (data == "Static Cubemap")
+   {
+      probe->mReflectionModeType = StaticCubemap;
+   }
+   else if (data == "Baked Cubemap")
+   {
+      //Clear our cubemap if we changed it to be baked, just for cleanliness
+      probe->mReflectionModeType = BakedCubemap;
+      probe->mCubemapName = "";
+   }
+
+   return true;
+}
+
 bool ReflectionProbe::onAdd()
 {
    if (!Parent::onAdd())
@@ -249,9 +271,8 @@ bool ReflectionProbe::onAdd()
 
    mEditPosOffset = false;
 
-   mObjBox.minExtents.set(-1, -1, -1);
-   mObjBox.maxExtents.set(1, 1, 1);
-   //mObjScale.set(mRadius/2, mRadius/2, mRadius/2);
+   mObjBox.minExtents.set(-0.5, -0.5, -0.5);
+   mObjBox.maxExtents.set(0.5, 0.5, 0.5);
 
    // Skip our transform... it just dirties mask bits.
    Parent::setTransform(mObjToWorld);
@@ -266,7 +287,7 @@ bool ReflectionProbe::onAdd()
       if (!mPersistentId)
          mPersistentId = getOrCreatePersistentId();
 
-      mProbeUniqueID = std::to_string(mPersistentId->getUUID().getHash()).c_str();
+      mProbeUniqueID = String::ToString(mPersistentId->getUUID().getHash());
    }
 
    // Refresh this object's material (if any)
@@ -330,6 +351,49 @@ void ReflectionProbe::setTransform(const MatrixF & mat)
    setMaskBits(TransformMask);
 }
 
+const MatrixF& ReflectionProbe::getTransform() const 
+{ 
+   if (!mEditPosOffset)
+      return mObjToWorld; 
+   else
+   {
+      MatrixF transformMat = MatrixF::Identity;
+      transformMat.setPosition(mProbeRefOffset);
+
+      return transformMat;
+   }
+}
+
+void ReflectionProbe::setScale(const VectorF &scale)
+{
+   if (!mEditPosOffset)
+      Parent::setScale(scale);
+   else
+      mProbeRefScale = scale;
+
+   mDirty = true;
+
+   // Dirty our network mask so that the new transform gets
+   // transmitted to the client object
+   setMaskBits(TransformMask);
+}
+
+const VectorF& ReflectionProbe::getScale() const
+{ 
+   if (!mEditPosOffset)
+      return mObjScale;
+   else
+      return mProbeRefScale;
+}
+
+bool ReflectionProbe::writeField(StringTableEntry fieldname, const char *value)
+{
+   if (fieldname == StringTable->insert("Bake") || fieldname == StringTable->insert("EditPosOffset"))
+      return false;
+
+   return Parent::writeField(fieldname, value);
+}
+
 U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
 {
    // Allow the Parent to get a crack at writing its info
@@ -338,8 +402,9 @@ U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream
    // Write our transform information
    if (stream->writeFlag(mask & TransformMask))
    {
-      mathWrite(*stream, getTransform());
-      mathWrite(*stream, getScale());
+      stream->writeFlag(mEditPosOffset);
+      mathWrite(*stream, mObjToWorld);
+      mathWrite(*stream, mObjScale);
       mathWrite(*stream, mProbeRefOffset);
       mathWrite(*stream, mProbeRefScale);
    }
@@ -385,10 +450,13 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
 
    if (stream->readFlag())  // TransformMask
    {
+      mEditPosOffset = stream->readFlag();
       mathRead(*stream, &mObjToWorld);
       mathRead(*stream, &mObjScale);
 
-      setTransform(mObjToWorld);
+      Parent::setTransform(mObjToWorld);
+
+      resetWorldBox();
 
       mathRead(*stream, &mProbeRefOffset);
       mathRead(*stream, &mProbeRefScale);      
@@ -491,7 +559,9 @@ void ReflectionProbe::updateProbeParams()
    mProbeInfo->mTransform = getWorldTransform();
 
    mProbeInfo->mPosition = getPosition();
-   mObjScale.set(mRadius, mRadius, mRadius);
+
+   if(mProbeShapeType == ProbeRenderInst::Sphere)
+      mObjScale.set(mRadius, mRadius, mRadius);
 
    // Skip our transform... it just dirties mask bits.
    Parent::setTransform(mObjToWorld);
@@ -783,19 +853,24 @@ void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
    // Base the sphere color on the light color.
    ColorI color = ColorI(255, 0, 255, 63);
 
-   const MatrixF worldToObjectXfm = getTransform();
+   const MatrixF worldToObjectXfm = mObjToWorld;
    if (mProbeShapeType == ProbeRenderInst::Sphere)
    {
       draw->drawSphere(desc, mRadius, getPosition(), color);
    }
    else
    {
-      Box3F projCube(-Point3F(mRadius, mRadius, mRadius),Point3F(mRadius, mRadius, mRadius));
+      Point3F tscl = worldToObjectXfm.getScale();
+
+      Box3F projCube(-mObjScale/2, mObjScale / 2);
       projCube.setCenter(getPosition());
       draw->drawCube(desc, projCube, color, &worldToObjectXfm);
    }
-   Box3F refCube = Box3F(-mProbeRefScale/2, mProbeRefScale/2);
-   refCube.setCenter(getPosition()+mProbeRefOffset);
+
+   Point3F renderPos = getRenderTransform().getPosition();
+
+   Box3F refCube = Box3F(-mProbeRefScale / 2, mProbeRefScale / 2);
+   refCube.setCenter(renderPos + mProbeRefOffset);
    color = ColorI(0, 255, 255, 63);
    draw->drawCube(desc, refCube, color, &worldToObjectXfm);
 }

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

@@ -186,6 +186,8 @@ public:
    static bool _setEnabled(void *object, const char *index, const char *data);
    static bool _doBake(void *object, const char *index, const char *data);
    static bool _toggleEditPosOffset(void *object, const char *index, const char *data);
+   static bool _setRadius(void *object, const char *index, const char *data);
+   static bool _setReflectionMode(void *object, const char *index, const char *data);
 
    // Handle when we are added to the scene and removed from the scene
    bool onAdd();
@@ -194,7 +196,12 @@ public:
    virtual void handleDeleteAction();
 
    // Override this so that we can dirty the network flag when it is called
-   void setTransform(const MatrixF &mat);
+   virtual void setTransform(const MatrixF &mat);
+   virtual const MatrixF& getTransform() const;
+   virtual void setScale(const VectorF &scale);
+   virtual const VectorF& getScale() const;
+
+   virtual bool writeField(StringTableEntry fieldname, const char *value);
 
    // This function handles sending the relevant data from the server
    // object to the client object

+ 7 - 1
Engine/source/T3D/lighting/skylight.cpp

@@ -91,6 +91,12 @@ void Skylight::initPersistFields()
 {
    // SceneObject already handles exposing the transform
    Parent::initPersistFields();
+
+   removeField("radius");
+   removeField("scale");
+   removeField("EditPosOffset");
+   removeField("refOffset");
+   removeField("refScale");
 }
 
 void Skylight::inspectPostApply()
@@ -151,7 +157,7 @@ void Skylight::updateProbeParams()
 {
    Parent::updateProbeParams();
 
-   mProbeInfo->mProbeShapeType = ProbeRenderInst::Sphere;
+   mProbeInfo->mProbeShapeType = ProbeRenderInst::Skylight;
 
    mProbeInfo->setPosition(getPosition());
 

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

@@ -43,7 +43,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

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

@@ -91,6 +91,8 @@ void SphereEnvironmentProbe::initPersistFields()
 {
    // SceneObject already handles exposing the transform
    Parent::initPersistFields();
+
+   removeField("scale");
 }
 
 void SphereEnvironmentProbe::inspectPostApply()

+ 8 - 3
Engine/source/renderInstance/renderProbeMgr.cpp

@@ -333,8 +333,8 @@ void RenderProbeMgr::_setupStaticParameters()
       if (!curEntry.mIrradianceCubemap->isInitialised())
          continue;
 
-      if (curEntry.mIsSkylight)
-         continue;
+      //if (curEntry.mIsSkylight)
+      //   continue;
 
 	   mMipCount = curEntry.mCubemap.getPointer()->getMipMapLevels();
 
@@ -350,7 +350,7 @@ void RenderProbeMgr::_setupStaticParameters()
       probeBBMinData[mEffectiveProbeCount] = Point4F(bbMin.x, bbMin.y, bbMin.z, 0);
       probeBBMaxData[mEffectiveProbeCount] = Point4F(bbMax.x, bbMax.y, bbMax.z, 0);
 
-      probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType == ProbeRenderInst::Sphere ? 1 : 0, 
+      probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType, 
          curEntry.mRadius,
          attenuation,
          1);
@@ -690,6 +690,8 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
 {
    GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
 
+   bool serverObj = probe->isServerObject();
+
    Con::warnf("RenderProbeMgr::bakeProbe() - Beginning bake!");
    U32 startMSTime = Platform::getRealMilliseconds();
 
@@ -700,6 +702,9 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
 
    ReflectionProbe *clientProbe = static_cast<ReflectionProbe*>(probe->getClientObject());
 
+   if (clientProbe == nullptr)
+      return;
+
    String probePrefilterPath = clientProbe->getPrefilterMapPath();
    String probeIrradPath = clientProbe->getIrradianceMapPath();
 

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

@@ -88,8 +88,9 @@ struct ProbeRenderInst : public SystemInterface<ProbeRenderInst>
 
    enum ProbeShapeType
    {
-      Sphere = 0,            ///< Sphere shaped
-      Box = 1,               ///< Box-based shape
+      Box = 0,            ///< Sphere shaped
+      Sphere = 1,               ///< Box-based shape
+      Skylight = 2
    };
 
    ProbeShapeType mProbeShapeType;

+ 1 - 1
Engine/source/scene/sceneObject.h

@@ -484,7 +484,7 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
       const MatrixF& getWorldTransform() const { return mWorldToObj; }
 
       /// Returns the scale of the object
-      const VectorF& getScale() const { return mObjScale; }
+      virtual const VectorF& getScale() const { return mObjScale; }
 
       /// Returns the bounding box for this object in local coordinates.
       const Box3F& getObjBox() const { return mObjBox; }

+ 87 - 12
Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl

@@ -32,8 +32,55 @@ uniform float4    probeConfigData[MAX_PROBES];   //r,g,b/mode,radius,atten
 uniform float4    probeContribColors[MAX_PROBES]; 
 #endif
 
-//Probe IBL stuff
-struct ProbeData
+// 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 wsEyeRay, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
+{ 
+   float3 positionLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz;
+   //float3 rayLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz;
+   //float3 reflCameraLS = mul(worldToObjArray[id], float4(reflectDir), 1.0)).xyz;
+
+   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 iblSkylightDiffuse(Surface surface, ProbeData probe)
+{
+   float lod = surface.roughness*cubeMips;
+   float3 color = TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, surface.N, probe.probeIdx, lod).xyz;
+
+   return color;
+}
+
+float3 iblSkylightSpecular(Surface surface, ProbeData probe)
+{
+   // BRDF
+   float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, surface.NdotV, 0.0, 0.0)).xy;
+
+   // Radiance (Specular)
+#if DEBUGVIZ_SPECCUBEMAP == 0
+   float lod = surface.roughness*cubeMips;
+#elif DEBUGVIZ_SPECCUBEMAP == 1
+   float lod = 0;
+#endif
+
+   float3 color = TORQUE_TEXCUBEARRAYLOD(cubeMapAR, surface.N, probe.probeIdx, 0).xyz * (brdf.x + brdf.y);
+   //float3 color = float3(1, 1, 1);
+
+   return color;
+}
+
+
+float3 iblBoxDiffuse( Surface surface, ProbeData probe)
 {
    float3 wsPosition;
    float radius;
@@ -169,14 +216,19 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
       {
          probes[i].defineBoxSpaceInfluence(surface, IN.wsEyeRay);
       }
-      else
+      else if (probes[i].type == 1) //sphere
       {
          probes[i].defineSphereSpaceInfluence(surface,IN.wsEyeRay);
       }
-      if (probes[i].contribution>1||probes[i].contribution<0)
-         probes[i].contribution = 0;
-      blendSum += probes[i].contribution;
-      invBlendSum += (1.0f - probes[i].contribution);
+      else //skylight
+      {
+         //
+         blendVal[i] = 1;
+      }
+
+      blendVal[i] = saturate(blendVal[i]);
+      blendSum += blendVal[i];
+      invBlendSum += (1.0f - blendVal[i]);
    }
 
    // Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
@@ -248,9 +300,18 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
       if (probes[i].contribution == 0)
          continue;
 
-      irradiance += probes[i].iblBoxDiffuse(surface);
-      
-      specular += F*probes[i].iblBoxSpecular(surface);
+      if (probes[i].type == 2) //skylight
+      {
+         irradiance += blendFactor[i] * iblSkylightDiffuse(surface, probes[i]);
+
+         specular += blendFactor[i] * F * iblSkylightSpecular(surface, probes[i]);
+      }
+      else
+      {
+         irradiance += blendFactor[i] * iblBoxDiffuse(surface, probes[i]);
+
+         specular += blendFactor[i] * F*iblBoxSpecular(surface, probes[i]);
+      }
    }
 
    //final diffuse color
@@ -263,7 +324,14 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
    float3 cubeColor = float3(0, 0, 0);
    for (i = 0; i < numProbes; ++i)
    {
-      cubeColor += probes[i].iblBoxSpecular(surface);
+      //if (probes[i].type == 2) //skylight
+      //{
+         cubeColor += blendFactor[i] * iblSkylightSpecular(surface, probes[i]);
+      /*}
+      else
+      {
+         cubeColor += blendFactor[i] * iblBoxSpecular(surface, probes[i]);
+      }*/
    }
 
    return float4(cubeColor, 1);
@@ -271,7 +339,14 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
    float3 cubeColor = float3(0, 0, 0);
    for (i = 0; i < numProbes; ++i)
    {
-      cubeColor += probes[i].iblBoxDiffuse(surface);
+      //if (probes[i].type == 2) //skylight
+      //{
+         cubeColor += blendFactor[i] * iblSkylightDiffuse(surface, probes[i]);
+      /*}
+      else
+      {
+         cubeColor += blendFactor[i] * iblBoxDiffuse(surface, probes[i]);
+      }*/
    }
 
    return float4(cubeColor, 1);