Cleaned and repacked work to update the probe bin and reflection probe behavior to clean and standardize it.

This commit is contained in:
JeffR 2022-02-12 15:53:40 -06:00
parent 68ae0ca96d
commit 79eebdd5f3
24 changed files with 1113 additions and 1012 deletions

View file

@ -77,7 +77,7 @@ ConsoleDocClass(BoxEnvironmentProbe,
BoxEnvironmentProbe::BoxEnvironmentProbe() : ReflectionProbe() BoxEnvironmentProbe::BoxEnvironmentProbe() : ReflectionProbe()
{ {
mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK; mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK;
mProbeShapeType = ProbeRenderInst::Box; mProbeShapeType = ProbeInfo::Box;
mAtten = 0.0; mAtten = 0.0;
} }
@ -158,7 +158,7 @@ void BoxEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
void BoxEnvironmentProbe::updateProbeParams() void BoxEnvironmentProbe::updateProbeParams()
{ {
mProbeShapeType = ProbeRenderInst::Box; mProbeShapeType = ProbeInfo::Box;
mProbeInfo.mAtten = mAtten; mProbeInfo.mAtten = mAtten;
Parent::updateProbeParams(); Parent::updateProbeParams();

View file

@ -73,8 +73,8 @@ ConsoleDocClass(ReflectionProbe,
ImplementEnumType(ReflectProbeType, ImplementEnumType(ReflectProbeType,
"Type of mesh data available in a shape.\n" "Type of mesh data available in a shape.\n"
"@ingroup gameObjects") "@ingroup gameObjects")
{ ProbeRenderInst::Sphere, "Sphere", "Sphere shaped" }, { ReflectionProbe::ProbeInfo::Sphere, "Sphere", "Sphere shaped" },
{ ProbeRenderInst::Box, "Box", "Box shape" } { ReflectionProbe::ProbeInfo::Box, "Box", "Box shape" }
EndImplementEnumType; EndImplementEnumType;
ImplementEnumType(ReflectionModeEnum, ImplementEnumType(ReflectionModeEnum,
@ -97,7 +97,7 @@ ReflectionProbe::ReflectionProbe()
mTypeMask = LightObjectType | MarkerObjectType; mTypeMask = LightObjectType | MarkerObjectType;
mProbeShapeType = ProbeRenderInst::Box; mProbeShapeType = ProbeInfo::Box;
mReflectionModeType = BakedCubemap; mReflectionModeType = BakedCubemap;
@ -121,8 +121,6 @@ ReflectionProbe::ReflectionProbe()
mRefreshRateMS = 200; mRefreshRateMS = 200;
mDynamicLastBakeMS = 0; mDynamicLastBakeMS = 0;
mMaxDrawDistance = 75;
mResourcesCreated = false; mResourcesCreated = false;
mPrefilterSize = 64; mPrefilterSize = 64;
mPrefilterMipLevels = mLog2(F32(mPrefilterSize)); mPrefilterMipLevels = mLog2(F32(mPrefilterSize));
@ -239,7 +237,7 @@ bool ReflectionProbe::_setRadius(void *object, const char *index, const char *da
{ {
ReflectionProbe* probe = reinterpret_cast<ReflectionProbe*>(object); ReflectionProbe* probe = reinterpret_cast<ReflectionProbe*>(object);
if (probe->mProbeShapeType != ProbeRenderInst::Sphere) if (probe->mProbeShapeType != ProbeInfo::Sphere)
return false; return false;
probe->mObjScale = Point3F(probe->mRadius, probe->mRadius, probe->mRadius); probe->mObjScale = Point3F(probe->mRadius, probe->mRadius, probe->mRadius);
@ -291,7 +289,7 @@ bool ReflectionProbe::onAdd()
if (!mPersistentId) if (!mPersistentId)
mPersistentId = getOrCreatePersistentId(); mPersistentId = getOrCreatePersistentId();
mProbeUniqueID = String::ToString(mPersistentId->getUUID().getHash()); mProbeUniqueID = mPersistentId->getUUID().toString();
} }
// Refresh this object's material (if any) // Refresh this object's material (if any)
@ -312,7 +310,7 @@ void ReflectionProbe::onRemove()
{ {
if (isClientObject()) if (isClientObject())
{ {
PROBEMGR->unregisterProbe(mProbeInfo.mProbeIdx); PROBEMGR->unregisterProbe(&mProbeInfo);
} }
// Remove this object from the scene // Remove this object from the scene
@ -461,10 +459,10 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
if (stream->readFlag()) // StaticDataMask if (stream->readFlag()) // StaticDataMask
{ {
U32 shapeType = ProbeRenderInst::Sphere; U32 shapeType = ProbeInfo::Sphere;
stream->read(&shapeType); stream->read(&shapeType);
mProbeShapeType = (ProbeRenderInst::ProbeShapeType)shapeType; mProbeShapeType = (ProbeInfo::ProbeShapeType)shapeType;
stream->read(&mRadius); stream->read(&mRadius);
@ -497,6 +495,8 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ReflectionProbe::updateProbeParams() void ReflectionProbe::updateProbeParams()
{ {
mProbeInfo.mObject = this;
if (!mResourcesCreated) if (!mResourcesCreated)
{ {
if (!createClientResources()) if (!createClientResources())
@ -507,12 +507,12 @@ void ReflectionProbe::updateProbeParams()
mProbeInfo.mProbeShapeType = mProbeShapeType; mProbeInfo.mProbeShapeType = mProbeShapeType;
if (mProbeShapeType == ProbeRenderInst::Sphere) if (mProbeShapeType == ProbeInfo::Sphere)
mObjScale.set(mRadius, mRadius, mRadius); mObjScale.set(mRadius, mRadius, mRadius);
Box3F bounds; Box3F bounds;
if (mProbeShapeType == ProbeRenderInst::Skylight) if (mProbeShapeType == ProbeInfo::Skylight)
{ {
mProbeInfo.mPosition = Point3F::Zero; mProbeInfo.mPosition = Point3F::Zero;
mProbeInfo.mTransform = MatrixF::Identity; mProbeInfo.mTransform = MatrixF::Identity;
@ -564,8 +564,6 @@ void ReflectionProbe::updateProbeParams()
else else
processDynamicCubemap(); processDynamicCubemap();
} }
PROBEMGR->updateProbes();
} }
void ReflectionProbe::processDynamicCubemap() void ReflectionProbe::processDynamicCubemap()
@ -575,7 +573,7 @@ void ReflectionProbe::processDynamicCubemap()
void ReflectionProbe::processBakedCubemap() void ReflectionProbe::processBakedCubemap()
{ {
mProbeInfo.mIsEnabled = false; //mProbeInfo.mIsEnabled = false;
if ((mReflectionModeType != BakedCubemap) || mProbeUniqueID.isEmpty()) if ((mReflectionModeType != BakedCubemap) || mProbeUniqueID.isEmpty())
return; return;
@ -611,7 +609,7 @@ void ReflectionProbe::processBakedCubemap()
if (mEnabled && mProbeInfo.mPrefilterCubemap->isInitialized() && mProbeInfo.mIrradianceCubemap->isInitialized()) if (mEnabled && mProbeInfo.mPrefilterCubemap->isInitialized() && mProbeInfo.mIrradianceCubemap->isInitialized())
{ {
mProbeInfo.mIsEnabled = true; //mProbeInfo.mIsEnabled = true;
mCubemapDirty = false; mCubemapDirty = false;
@ -622,6 +620,11 @@ void ReflectionProbe::processBakedCubemap()
mProbeInfo.mPrefilterCubemap.free(); mProbeInfo.mPrefilterCubemap.free();
mProbeInfo.mIrradianceCubemap.free(); mProbeInfo.mIrradianceCubemap.free();
} }
else
{
//if we failed, disable
mProbeInfo.mIsEnabled = false;
}
} }
void ReflectionProbe::processStaticCubemap() void ReflectionProbe::processStaticCubemap()
@ -811,16 +814,16 @@ void ReflectionProbe::createEditorResources()
void ReflectionProbe::prepRenderImage(SceneRenderState *state) void ReflectionProbe::prepRenderImage(SceneRenderState *state)
{ {
if (!mEnabled || !RenderProbeMgr::smRenderReflectionProbes) if (!mEnabled || (!RenderProbeMgr::smRenderReflectionProbes && Con::getVariable("$Probes::Capturing", "0") == "0"))
return; return;
Point3F distVec = getRenderPosition() - state->getCameraPosition(); Point3F distVec = getRenderPosition() - state->getCameraPosition();
F32 dist = distVec.len(); F32 dist = distVec.len();
//Culling distance. Can be adjusted for performance options considerations via the scalar //Culling distance. Can be adjusted for performance options considerations via the scalar
if (dist > mMaxDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0)) if (dist > RenderProbeMgr::smMaxProbeDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0))
{ {
mProbeInfo.mScore = mMaxDrawDistance; mProbeInfo.mScore = RenderProbeMgr::smMaxProbeDrawDistance;
return; return;
} }
@ -842,7 +845,7 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
//mProbeInfo.mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f); //mProbeInfo.mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f);
PROBEMGR->submitProbe(mProbeInfo); PROBEMGR->submitProbe(&mProbeInfo);
#ifdef TORQUE_TOOLS #ifdef TORQUE_TOOLS
if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mPrefilterMap != nullptr) if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mPrefilterMap != nullptr)
@ -938,7 +941,7 @@ void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
ColorI color = ColorI(255, 0, 255, 63); ColorI color = ColorI(255, 0, 255, 63);
const MatrixF worldToObjectXfm = mObjToWorld; const MatrixF worldToObjectXfm = mObjToWorld;
if (mProbeShapeType == ProbeRenderInst::Sphere) if (mProbeShapeType == ProbeInfo::Sphere)
{ {
draw->drawSphere(desc, mRadius, getPosition(), color); draw->drawSphere(desc, mRadius, getPosition(), color);
} }

View file

@ -41,10 +41,6 @@
#include "renderInstance/renderPassManager.h" #include "renderInstance/renderPassManager.h"
#endif #endif
#ifndef RENDER_PROBE_MGR_H
#include "renderInstance/renderProbeMgr.h"
#endif
class BaseMatInstance; class BaseMatInstance;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -74,6 +70,67 @@ public:
DynamicCubemap = 5, DynamicCubemap = 5,
}; };
/// <summary>
/// This contains all the important data the Probe uses for rendering.
/// </summary>
struct ProbeInfo
{
bool mIsEnabled;
MatrixF mTransform;
ReflectionProbe* mObject;
F32 mRadius;
bool mDirty;
Box3F mBounds;
Point3F mExtents;
Point3F mPosition;
Point3F mProbeRefOffset;
Point3F mProbeRefScale;
F32 mAtten;
F32 mScore;
GFXCubemapHandle mPrefilterCubemap;
GFXCubemapHandle mIrradianceCubemap;
/// The priority of this light used for
/// light and shadow scoring.
F32 mPriority;
enum ProbeShapeType
{
Box = 0,
Sphere = 1,
Skylight = 2
};
ProbeShapeType mProbeShapeType;
public:
ProbeInfo() : mScore(0) {}
~ProbeInfo() {}
// Copies data passed in from light
void set(const ProbeInfo* probeInfo);
// Accessors
const MatrixF& getTransform() const { return mTransform; }
void setTransform(const MatrixF& xfm) { mTransform = xfm; }
Point3F getPosition() const { return mPosition; }
void setPosition(const Point3F& pos) { mPosition = pos; }
void setPriority(F32 priority) { mPriority = priority; }
F32 getPriority() const { return mPriority; }
void clear();
};
protected: protected:
// Networking masks // Networking masks
@ -124,7 +181,7 @@ protected:
/// <summary> /// <summary>
/// The shape of the probe /// The shape of the probe
/// </summary> /// </summary>
ProbeRenderInst::ProbeShapeType mProbeShapeType; ProbeInfo::ProbeShapeType mProbeShapeType;
/// <summary> /// <summary>
/// This is effectively a packed cache of the probe data actually utilized for rendering. /// This is effectively a packed cache of the probe data actually utilized for rendering.
@ -132,7 +189,7 @@ protected:
/// When the manager goes to render it has the compacted data to read over more efficiently for setting up what probes should /// When the manager goes to render it has the compacted data to read over more efficiently for setting up what probes should
/// Actually render in that frame /// Actually render in that frame
/// </summary> /// </summary>
ProbeRenderInst mProbeInfo; ProbeInfo mProbeInfo;
/// <summary> /// <summary>
/// Used to dictate what sort of cubemap the probes use when using IBL /// Used to dictate what sort of cubemap the probes use when using IBL
@ -166,14 +223,13 @@ protected:
CubemapData *mStaticCubemap; CubemapData *mStaticCubemap;
GFXCubemapHandle mDynamicCubemap; GFXCubemapHandle mDynamicCubemap;
String cubeDescName; //String cubeDescName;
U32 cubeDescId; //U32 cubeDescId;
ReflectorDesc *reflectorDesc; //ReflectorDesc *reflectorDesc;
//Utilized in dynamic reflections //Utilized in dynamic reflections
//CubeReflector mCubeReflector; //CubeReflector mCubeReflector;
///Prevents us from saving out the cubemaps(for now) but allows us the full HDR range on the in-memory cubemap captures
bool mUseHDRCaptures; bool mUseHDRCaptures;
//irridiance resources //irridiance resources
@ -196,7 +252,6 @@ protected:
U32 mDynamicLastBakeMS; U32 mDynamicLastBakeMS;
U32 mRefreshRateMS; U32 mRefreshRateMS;
F32 mMaxDrawDistance;
bool mResourcesCreated; bool mResourcesCreated;
U32 mCaptureMask; U32 mCaptureMask;
@ -313,7 +368,7 @@ public:
void bake(); void bake();
}; };
typedef ProbeRenderInst::ProbeShapeType ReflectProbeType; typedef ReflectionProbe::ProbeInfo::ProbeShapeType ReflectProbeType;
DefineEnumType(ReflectProbeType); DefineEnumType(ReflectProbeType);
typedef ReflectionProbe::ReflectionModeType ReflectionModeEnum; typedef ReflectionProbe::ReflectionModeType ReflectionModeEnum;

View file

@ -148,7 +148,7 @@ void Skylight::unpackUpdate(NetConnection *conn, BitStream *stream)
void Skylight::updateProbeParams() void Skylight::updateProbeParams()
{ {
mProbeShapeType = ProbeRenderInst::Skylight; mProbeShapeType = ProbeInfo::Skylight;
Parent::updateProbeParams(); Parent::updateProbeParams();
} }
@ -167,7 +167,7 @@ void Skylight::prepRenderImage(SceneRenderState *state)
// Get a handy pointer to our RenderPassmanager // Get a handy pointer to our RenderPassmanager
//RenderPassManager *renderPass = state->getRenderPass(); //RenderPassManager *renderPass = state->getRenderPass();
PROBEMGR->submitProbe(mProbeInfo); PROBEMGR->submitProbe(&mProbeInfo);
#ifdef TORQUE_TOOLS #ifdef TORQUE_TOOLS
if (Skylight::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr) if (Skylight::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)

View file

@ -77,7 +77,7 @@ ConsoleDocClass(SphereEnvironmentProbe,
SphereEnvironmentProbe::SphereEnvironmentProbe() : ReflectionProbe() SphereEnvironmentProbe::SphereEnvironmentProbe() : ReflectionProbe()
{ {
mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK; mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK;
mProbeShapeType = ProbeRenderInst::Sphere; mProbeShapeType = ProbeInfo::Sphere;
} }
SphereEnvironmentProbe::~SphereEnvironmentProbe() SphereEnvironmentProbe::~SphereEnvironmentProbe()
@ -144,83 +144,10 @@ void SphereEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream
void SphereEnvironmentProbe::updateProbeParams() void SphereEnvironmentProbe::updateProbeParams()
{ {
mProbeShapeType = ProbeRenderInst::Sphere; mProbeShapeType = ProbeInfo::Sphere;
Parent::updateProbeParams(); Parent::updateProbeParams();
} }
void SphereEnvironmentProbe::prepRenderImage(SceneRenderState *state)
{
if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
return;
#ifdef TORQUE_TOOLS
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)
{
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
ri->renderDelegate.bind(this, &ReflectionProbe::_onRenderViz);
ri->type = RenderPassManager::RIT_Editor;
state->getRenderPass()->addInst(ri);
}
#endif
}
void SphereEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat) void SphereEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
{ {
Parent::setPreviewMatParameters(renderState, mat); Parent::setPreviewMatParameters(renderState, mat);

View file

@ -98,10 +98,6 @@ public:
// use the same Materials. // use the same Materials.
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
virtual void updateProbeParams(); 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); void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
}; };

View file

@ -970,14 +970,6 @@ void ScatterSky::_render( ObjectRenderInst *ri, SceneRenderState *state, BaseMat
xform *= GFX->getViewMatrix(); xform *= GFX->getViewMatrix();
xform *= GFX->getWorldMatrix(); xform *= GFX->getWorldMatrix();
if(state->isReflectPass())
{
static MatrixF rotMat(EulerF(0.0, 0.0, M_PI_F));
xform.mul(rotMat);
rotMat.set(EulerF(M_PI_F, 0.0, 0.0));
xform.mul(rotMat);
}
mShaderConsts->setSafe( mModelViewProjSC, xform ); mShaderConsts->setSafe( mModelViewProjSC, xform );
mShaderConsts->setSafe( mMiscSC, miscParams ); mShaderConsts->setSafe( mMiscSC, miscParams );
mShaderConsts->setSafe( mSphereRadiiSC, sphereRadii ); mShaderConsts->setSafe( mSphereRadiiSC, sphereRadii );

File diff suppressed because it is too large Load diff

View file

@ -39,7 +39,7 @@
#include "gfx/gfxVertexBuffer.h" #include "gfx/gfxVertexBuffer.h"
#endif #endif
#include "core/util/systemInterfaceList.h" //#include "core/util/systemInterfaceList.h"
#ifndef _MATERIALS_PROCESSEDSHADERMATERIAL_H_ #ifndef _MATERIALS_PROCESSEDSHADERMATERIAL_H_
#include "materials/processedShaderMaterial.h" #include "materials/processedShaderMaterial.h"
@ -52,52 +52,23 @@
#include "scene/reflector.h" #include "scene/reflector.h"
#endif #endif
static U32 MAXPROBECOUNT = 50; #ifndef REFLECTIONPROBE_H
#include "T3D/lighting/reflectionProbe.h"
#endif
class PostEffect; class PostEffect;
class ReflectionProbe; class ReflectionProbe;
/// <summary>
/// A simple container for a ReflectionProbe's ProbeInfo and index for it's associated
/// cubemaps in the cubemap array pair
/// </summary>
struct ProbeRenderInst struct ProbeRenderInst
{ {
bool mIsEnabled; ReflectionProbe::ProbeInfo* mProbeInfo;
MatrixF mTransform;
F32 mRadius;
bool mDirty;
Box3F mBounds;
Point3F mExtents;
Point3F mPosition;
Point3F mProbeRefOffset;
Point3F mProbeRefScale;
F32 mAtten;
GFXCubemapHandle mPrefilterCubemap;
GFXCubemapHandle mIrradianceCubemap;
/// The priority of this light used for
/// light and shadow scoring.
F32 mPriority;
/// A temporary which holds the score used
/// when prioritizing lights for rendering.
F32 mScore;
enum ProbeShapeType
{
Box = 0, ///< Sphere shaped
Sphere = 1, ///< Box-based shape
Skylight = 2
};
ProbeShapeType mProbeShapeType;
U32 mCubemapIndex; U32 mCubemapIndex;
U32 mProbeIdx;
public: public:
ProbeRenderInst(); ProbeRenderInst();
@ -105,28 +76,11 @@ public:
// Copies data passed in from light // Copies data passed in from light
void set(const ProbeRenderInst *probeInfo); void set(const ProbeRenderInst *probeInfo);
// Accessors
const MatrixF& getTransform() const { return mTransform; }
void setTransform(const MatrixF &xfm) { mTransform = xfm; }
Point3F getPosition() const { return mPosition; }
void setPosition(const Point3F &pos) { mPosition = pos; }
void setPriority(F32 priority) { mPriority = priority; }
F32 getPriority() const { return mPriority; }
void setScore(F32 score) { mScore = score; }
F32 getScore() const { return mScore; }
void clear();
inline bool operator ==(const ProbeRenderInst& b) const
{
return mProbeIdx == b.mProbeIdx;
}
}; };
/// <summary>
/// A container for all the shader consts needed for rendering probes in forward mode
/// </summary>
struct ProbeShaderConstants struct ProbeShaderConstants
{ {
bool mInit; bool mInit;
@ -134,19 +88,21 @@ struct ProbeShaderConstants
GFXShaderRef mShader; GFXShaderRef mShader;
//Reflection Probes //Reflection Probes
GFXShaderConstHandle *mProbePositionSC; GFXShaderConstHandle *mProbePositionArraySC;
GFXShaderConstHandle *mProbeRefPosSC; GFXShaderConstHandle *mProbeRefPosArraySC;
GFXShaderConstHandle *mRefScaleSC; GFXShaderConstHandle *mRefScaleArraySC;
GFXShaderConstHandle *mWorldToObjArraySC; GFXShaderConstHandle *mWorldToObjArraySC;
GFXShaderConstHandle *mProbeConfigDataSC; GFXShaderConstHandle *mProbeConfigDataArraySC;
GFXShaderConstHandle *mProbeSpecularCubemapSC; GFXShaderConstHandle *mProbeSpecularCubemapArraySC;
GFXShaderConstHandle *mProbeIrradianceCubemapSC; GFXShaderConstHandle *mProbeIrradianceCubemapArraySC;
GFXShaderConstHandle *mProbeCountSC; GFXShaderConstHandle *mProbeCountSC;
GFXShaderConstHandle *mBRDFTextureMap; GFXShaderConstHandle *mBRDFTextureMap;
GFXShaderConstHandle *mSkylightCubemapIdxSC; GFXShaderConstHandle *mSkylightCubemapIdxSC;
GFXShaderConstHandle* mMaxProbeDrawDistanceSC;
ProbeShaderConstants(); ProbeShaderConstants();
~ProbeShaderConstants(); ~ProbeShaderConstants();
@ -159,6 +115,10 @@ struct ProbeShaderConstants
typedef Map<GFXShader*, ProbeShaderConstants*> ProbeConstantMap; typedef Map<GFXShader*, ProbeShaderConstants*> ProbeConstantMap;
/// <summary>
/// A container for processed and packed probe data. This is made when we get the frame's
/// best probes, and is passed to the shader for actual rendering.
/// </summary>
struct ProbeDataSet struct ProbeDataSet
{ {
Vector<Point4F> probePositionArray; Vector<Point4F> probePositionArray;
@ -198,18 +158,10 @@ struct ProbeDataSet
probeWorldToObjArray.setSize(maxProbeCount); probeWorldToObjArray.setSize(maxProbeCount);
skyLightIdx = -1;
effectiveProbeCount = 0; effectiveProbeCount = 0;
} }
}; };
struct ProbeTextureArrayData
{
GFXTexHandle BRDFTexture;
GFXCubemapArrayHandle prefilterArray;
GFXCubemapArrayHandle irradianceArray;
};
//************************************************************************** //**************************************************************************
// RenderObjectMgr // RenderObjectMgr
//************************************************************************** //**************************************************************************
@ -217,11 +169,6 @@ class RenderProbeMgr : public RenderBinManager
{ {
typedef RenderBinManager Parent; typedef RenderBinManager Parent;
Vector<ProbeRenderInst*> mRegisteredProbes;
bool mProbesDirty;
Vector<ProbeRenderInst> mActiveProbes;
public: public:
//maximum number of allowed probes //maximum number of allowed probes
static const U32 PROBE_MAX_COUNT = 250; static const U32 PROBE_MAX_COUNT = 250;
@ -230,51 +177,161 @@ public:
//number of slots to allocate at once in the cubemap array //number of slots to allocate at once in the cubemap array
static const U32 PROBE_ARRAY_SLOT_BUFFER_SIZE = 10; static const U32 PROBE_ARRAY_SLOT_BUFFER_SIZE = 10;
static const U32 PROBE_IRRAD_SIZE = 64; //These dictate the default resolution size for the probe arrays
static const U32 PROBE_PREFILTER_SIZE = 64;
static const GFXFormat PROBE_FORMAT = GFXFormatR16G16B16A16F;// GFXFormatR8G8B8A8;// when hdr fixed GFXFormatR16G16B16A16F; look into bc6h compression static const GFXFormat PROBE_FORMAT = GFXFormatR16G16B16A16F;// GFXFormatR8G8B8A8;// when hdr fixed GFXFormatR16G16B16A16F; look into bc6h compression
static const U32 INVALID_CUBE_SLOT = U32_MAX; static const U32 INVALID_CUBE_SLOT = U32_MAX;
static F32 smMaxProbeDrawDistance; static F32 smMaxProbeDrawDistance;
static S32 smMaxProbesPerFrame; static S32 smMaxProbesPerFrame;
static S32 smProbeBakeResolution;
SceneRenderState *mState;
private: private:
//Array rendering /// <summary>
U32 mEffectiveProbeCount; /// List of registered probes. These are not necessarily rendered in a given frame
S32 mMipCount; /// but the Probe Manager is aware of them and they have cubemap array slots allocated
/// </summary>
Vector<ProbeRenderInst> mRegisteredProbes;
/// <summary>
/// List of active probes. These are ones that are not only registered, but submitted by the probe itself as
/// ready to be rendered. Likely to be rendered in the current frame, settings-dependent.
/// </summary>
Vector<ProbeRenderInst> mActiveProbes;
/// <summary>
/// The PostEffect used to actually rendered the probes into the frame when in deferred mode
/// </summary>
SimObjectPtr<PostEffect> mProbeArrayEffect;
/// <summary>
/// Do we have a active skylight probe
/// </summary>
bool mHasSkylight; bool mHasSkylight;
/// <summary>
/// If we have a skylight, what's the array pair index for it?
/// </summary>
S32 mSkylightCubemapIdx; S32 mSkylightCubemapIdx;
//number of cubemaps /// <summary>
/// The 'effective' probe count. This tracks the number of probes that are actually going to be rendered
/// </summary>
U32 mEffectiveProbeCount;
//
//Array rendering
/// <summary>
/// The number of mips the cubemap array has. Mips are used in the PBR calcs for handling roughness
/// </summary>
S32 mMipCount;
/// <summary>
/// The number of cubemaps registered in our array pair
/// </summary>
U32 mCubeMapCount; U32 mCubeMapCount;
//number of cubemap slots allocated
/// <summary>
/// The number of allocated slots for the array pair. Rather than adding slots one at a time to the arrays
/// We allocate in chunks so we don't have to resize/rebuild the arrays as often
/// </summary>
U32 mCubeSlotCount; U32 mCubeSlotCount;
//array of cubemap slots, due to the editor these may be mixed around as probes are added and deleted
/// <summary>
/// List indicating if a given allocated slot is actually in use.
/// Due to the editor these may be mixed around as probes are added and deleted
/// </summary>
/// <returns></returns>
bool mCubeMapSlots[PROBE_MAX_COUNT]; bool mCubeMapSlots[PROBE_MAX_COUNT];
/// <summary>
/// The prefilter cubemap array
/// </summary>
GFXCubemapArrayHandle mPrefilterArray; GFXCubemapArrayHandle mPrefilterArray;
/// <summary>
/// The irradiance cubemap array
/// </summary>
GFXCubemapArrayHandle mIrradianceArray; GFXCubemapArrayHandle mIrradianceArray;
//Utilized in forward rendering //Utilized in forward rendering
/// <summary>
/// This is used to look up already-made ProbeShaderConsts for a given shader
/// This allows us to avoid having to rebuild the consts each frame if it's a shader
/// we've already handled before.
/// </summary>
ProbeConstantMap mConstantLookup; ProbeConstantMap mConstantLookup;
/// <summary>
/// The last shader we rendered(in forward mode). With this, we can shortcut the constant
/// lookup if the shader being processed and the last one are the same.
/// </summary>
GFXShaderRef mLastShader; GFXShaderRef mLastShader;
/// <summary>
/// THe previous shader constants. When used in conjunction with the mLastShader, we can skip
/// having to do a lookup to find an existing ProbeShaderConstants, saving overhead on batched
/// rendering
/// </summary>
ProbeShaderConstants* mLastConstants; ProbeShaderConstants* mLastConstants;
// /// <summary>
SimObjectPtr<PostEffect> mProbeArrayEffect; /// The BRDF texture used in PBR math calculations
/// </summary>
//Default skylight, used for shape editors, etc
ProbeRenderInst* mDefaultSkyLight;
GFXTexHandle mBRDFTexture; GFXTexHandle mBRDFTexture;
/// <summary>
/// Processed best probe selection list of the current frame when rendering in deferred mode.
/// </summary>
ProbeDataSet mProbeData; ProbeDataSet mProbeData;
///Prevents us from saving out the cubemaps(for now) but allows us the full HDR range on the in-memory cubemap captures
/// <summary>
/// Allows us the full HDR range on the in-memory cubemap captures
/// </summary>
bool mUseHDRCaptures; bool mUseHDRCaptures;
U32 mPrefilterMipLevels; protected:
U32 mPrefilterSize; /// The current active light manager.
static RenderProbeMgr* smProbeManager;
//=============================================================================
// Internal Management/Utility Functions
//=============================================================================
/// <summary>
/// Simple utility function that finds the next free cubemap slot for the cubemap array
/// </summary>
/// <returns>U32 index of next available slot</returns>
U32 _findNextEmptyCubeSlot()
{
for (U32 i = 0; i < PROBE_MAX_COUNT; i++)
{
if (!mCubeMapSlots[i])
return i;
}
return INVALID_CUBE_SLOT;
}
/// <summary>
/// Utility function to quickly find a ProbeRenderInst in association to a
/// ReflectionProbe's ProbeInfo
/// </summary>
/// <param name="probeInfo"></param>
/// <returns>Associated ProbeRederInst to param's probeInfo. Null if no matches found</returns>
ProbeRenderInst* findProbeInst(ReflectionProbe::ProbeInfo* probeInfo)
{
for (U32 i = 0; i < mRegisteredProbes.size(); i++)
{
auto asd = mRegisteredProbes[i];
if (mRegisteredProbes[i].mProbeInfo == probeInfo)
{
return &mRegisteredProbes[i];
}
}
return nullptr;
}
public: public:
RenderProbeMgr(); RenderProbeMgr();
RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder); RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder);
@ -286,75 +343,139 @@ public:
static void initPersistFields(); static void initPersistFields();
static void consoleInit(); static void consoleInit();
virtual void addElement(RenderInst* inst) {};
DECLARE_CONOBJECT(RenderProbeMgr); DECLARE_CONOBJECT(RenderProbeMgr);
protected: /// <summary>
/// The current active light manager. /// Static flag used to indicate if probes should be rendered at all. Used for debugging
static RenderProbeMgr *smProbeManager; /// </summary>
/// This helper function sets the shader constansts
/// for the stock 4 light forward lighting code.
void _update4ProbeConsts(const SceneData &sgData,
MatrixSet &matSet,
ProbeShaderConstants *probeShaderConsts,
GFXShaderConstBuffer *shaderConsts);
void _setupStaticParameters();
void _setupPerFrameParameters(const SceneRenderState *state);
virtual void addElement(RenderInst* inst) {};
virtual void render(SceneRenderState * state);
ProbeShaderConstants* getProbeShaderConstants(GFXShaderConstBuffer* buffer);
PostEffect* getProbeArrayEffect();
U32 _findNextEmptyCubeSlot()
{
for (U32 i = 0; i < PROBE_MAX_COUNT; i++)
{
if (!mCubeMapSlots[i])
return i;
}
return INVALID_CUBE_SLOT;
}
public:
// RenderBinMgr
void updateProbes();
/// Returns the active LM.
static inline RenderProbeMgr* getProbeManager();
void registerProbe(ProbeRenderInst* newProbe);
void unregisterProbe(U32 probeIdx);
void submitProbe(const ProbeRenderInst& newProbe);
static S32 QSORT_CALLBACK _probeScoreCmp(const ProbeRenderInst* a, const ProbeRenderInst* b);
virtual void setProbeInfo(ProcessedMaterial *pmat,
const Material *mat,
const SceneData &sgData,
const SceneRenderState *state,
U32 pass,
GFXShaderConstBuffer *shaderConsts);
void setupSGData(SceneData& data, const SceneRenderState* state, LightInfo* light);
void updateProbeTexture(ProbeRenderInst* probeInfo);
void reloadTextures();
/// Debug rendering
static bool smRenderReflectionProbes; static bool smRenderReflectionProbes;
void bakeProbe(ReflectionProbe *probeInfo); //=============================================================================
// Utility functions for processing and setting up the probes for rendering
//=============================================================================
/// <summary>
/// Sorts probes based on their score values. These scores are calculated by the probes themselves based on size, distance from camera, etc
/// </summary>
static S32 QSORT_CALLBACK _probeScoreCmp(const ProbeRenderInst* a, const ProbeRenderInst* b);
/// <summary>
/// Builds a dataset of the best probes to be rendered this frame.
/// </summary>
/// <param name="objPosition"></param>
/// <param name="probeDataSet"></param>
void getBestProbes(const Point3F& objPosition, ProbeDataSet* probeDataSet);
/// <summary>
/// This function adds a ReflectionProbe to the registered list and also allocates
/// a slot in the cubemap array pair for its use
/// </summary>
/// <param name="probeInfo">The probe info to be registered to the bin</param>
void registerProbe(ReflectionProbe::ProbeInfo* probeInfo);
/// <summary>
/// This function removes the ReflectionProbe from the registered list, and marks it's cubemap
/// array slots as unused, allowing them to be freed.
/// </summary>
/// <param name="probeInfo">The probe info to be un-registered to the bin</param>
void unregisterProbe(ReflectionProbe::ProbeInfo* probeInfo);
/// <summary>
/// This function is for registering a ReflectionProbe's probe info
/// as being rendered in the current frame. This is distinct from
/// registered probes in that registered probes are any 'real' probe
/// in the scene, but they may not necessarily render
/// Active(submmitted) probes are intended to actual be rendered this frame
/// </summary>
/// <param name="probe">The ProbeInfo being submitted to be rendered</param>
void submitProbe(ReflectionProbe::ProbeInfo* probe);
/// <summary>
/// Gets the PostEffect used by the bin for rendering the probe array in deferred
/// </summary>
/// <returns>the PostEffect object</returns>
PostEffect* getProbeArrayEffect();
/// <summary>
/// Finds the associated cubemap array slot for the incoming ProbeInfo and updates the array's texture(s) from it
/// </summary>
/// <param name="probeInfo"></param>
void updateProbeTexture(ReflectionProbe::ProbeInfo* probeInfo);
/// <summary>
/// Forces an update for all registered probes' cubemaps
/// </summary>
void reloadTextures();
/// <summary>
/// Takes a reflection probe and runs the cubemap bake process on it, outputting the resulting files to disk
/// </summary>
void bakeProbe(ReflectionProbe* probe);
/// <summary>
/// Runs the cubemap bake on all probes in the current scene
/// </summary>
void bakeProbes(); void bakeProbes();
void getProbeTextureData(ProbeTextureArrayData* probeTextureSet); /// <summary>
S32 getSkylightIndex() { return mSkylightCubemapIdx; } /// Returns the active Probe Manager.
//accumulates the best fit of probes given the object position /// </summary>
void getBestProbes(const Point3F& objPosition, ProbeDataSet* probeDataSet); static inline RenderProbeMgr* getProbeManager();
//=============================================================================
// Forward Rendering functions
//=============================================================================
/// <summary>
/// This function returns or builds a ProbeShaderConsts containing needed data for
/// rendering probes in forward mode
/// </summary>
/// <param name="buffer">The GFXShaderConstBuffer used to build or fetch the Probe Consts</param>
ProbeShaderConstants* getProbeShaderConstants(GFXShaderConstBuffer* buffer);
/// <summary>
/// Sets up the probe data required for doing a render in forward mode.
/// </summary>
virtual void setProbeInfo(ProcessedMaterial* pmat,
const Material* mat,
const SceneData& sgData,
const SceneRenderState* state,
U32 pass,
GFXShaderConstBuffer* shaderConsts);
/// <summary>
/// Invoked as part of the setup in preperation to render an object in forward mode. Used to ensure the probes are
/// sorted ahead of render.
/// </summary>
/// <param name="state"></param>
void setupSGData(SceneData& data, const SceneRenderState* state, LightInfo* light);
/// <summary>
/// Sets up and binds all the shader const data required for rendering probes/IBL for a forward-rendered material.
/// </summary>
/// <returns></returns>
void _update4ProbeConsts(const SceneData& sgData,
MatrixSet& matSet,
ProbeShaderConstants* probeShaderConsts,
GFXShaderConstBuffer* shaderConsts);
//=============================================================================
// Deferred Rendering Functions
//=============================================================================
/// <summary>
/// Ensures the probes are properly sorted before we render them in deferred mode
/// </summary>
void _setupPerFrameParameters(const SceneRenderState *state);
/// <summary>
/// Renders the sorted probes list via a PostEffect to draw them into the buffer data in deferred mode.
/// </summary>
virtual void render(SceneRenderState * state);
virtual void clear() { mActiveProbes.clear(); Parent::clear(); }
}; };
RenderProbeMgr* RenderProbeMgr::getProbeManager() RenderProbeMgr* RenderProbeMgr::getProbeManager()

View file

@ -758,7 +758,7 @@ Var* ShaderFeatureGLSL::getWsView( Var *wsPosition, MultiLine *meta )
eyePos->constSortPos = cspPass; eyePos->constSortPos = cspPass;
} }
meta->addStatement( new GenOp( " @ = normalize( @ - @ );\r\n", meta->addStatement( new GenOp( " @ = @ - @;\r\n",
new DecOp( wsView ), eyePos, wsPosition ) ); new DecOp( wsView ), eyePos, wsPosition ) );
} }
@ -838,79 +838,66 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector<ShaderComponent*> &compon
Var* ShaderFeatureGLSL::getSurface(Vector<ShaderComponent*>& componentList, MultiLine* meta, const MaterialFeatureData& fd) Var* ShaderFeatureGLSL::getSurface(Vector<ShaderComponent*>& componentList, MultiLine* meta, const MaterialFeatureData& fd)
{ {
ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]); Var *surface = (Var *)LangElement::find("surface");
Var* diffuseColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
Var* ormConfig = (Var*)LangElement::find("ORMConfig");
if (!ormConfig)
{
Var* metalness = (Var*)LangElement::find("metalness");
if (!metalness)
{
metalness = new Var("metalness", "float");
metalness->uniform = true;
metalness->constSortPos = cspPotentialPrimitive;
}
Var* roughness = (Var*)LangElement::find("roughness");
if (!roughness)
{
roughness = new Var("roughness", "float");
roughness->uniform = true;
roughness->constSortPos = cspPotentialPrimitive;
}
ormConfig = new Var("ORMConfig", "vec4");
LangElement* colorDecl = new DecOp(ormConfig);
meta->addStatement(new GenOp(" @ = vec4(0.0,1.0,@,@);\r\n", colorDecl, roughness, metalness)); //reconstruct ormConfig, no ao darkening
}
Var* normal = (Var*)LangElement::find("normal");
if (!normal)
{
normal = new Var("normal", "vec3");
meta->addStatement(new GenOp(" @;\r\n\n", new DecOp(normal)));
Var* wsNormal = (Var*)LangElement::find("wsNormal");
if (!fd.features[MFT_NormalMap])
{
if (!wsNormal)
wsNormal = getInWorldNormal(componentList);
meta->addStatement(new GenOp(" @ = normalize( @ );\r\n\n", normal, wsNormal));
}
else
{
meta->addStatement(new GenOp(" @ = normalize( @ );\r\n", normal, wsNormal));
}
}
Var* wsEyePos = (Var*)LangElement::find("eyePosWorld");
if (!wsEyePos)
{
wsEyePos = new Var("eyePosWorld", "vec3");
wsEyePos->uniform = true;
wsEyePos->constSortPos = cspPass;
}
Var* wsPosition = getInWsPosition(componentList);
Var* wsView = getWsView(wsPosition, meta);
Var* surface = (Var*)LangElement::find("surface");
if (!surface) if (!surface)
{ {
Var* diffuseColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
Var* ormConfig = (Var*)LangElement::find("ORMConfig");
if (!ormConfig)
{
Var* metalness = (Var*)LangElement::find("metalness");
if (!metalness)
{
metalness = new Var("metalness", "float");
metalness->uniform = true;
metalness->constSortPos = cspPotentialPrimitive;
}
Var* roughness = (Var*)LangElement::find("roughness");
if (!roughness)
{
roughness = new Var("roughness", "float");
roughness->uniform = true;
roughness->constSortPos = cspPotentialPrimitive;
}
ormConfig = new Var("ORMConfig", "vec4");
LangElement* colorDecl = new DecOp(ormConfig);
meta->addStatement(new GenOp(" @ = vec4(0.0,1.0,@,@);\r\n", colorDecl, roughness, metalness)); //reconstruct ormConfig, no ao darkening
}
Var* normal = (Var*)LangElement::find("normal");
if (!normal)
{
normal = new Var("normal", "vec3");
meta->addStatement(new GenOp(" @;\r\n\n", new DecOp(normal)));
Var *wsNormal = (Var *)LangElement::find("wsNormal");
if (!wsNormal)
wsNormal = getInWorldNormal(componentList);
meta->addStatement(new GenOp(" @ = normalize( @ );\r\n", normal, wsNormal));
}
Var* wsEyePos = (Var*)LangElement::find("eyePosWorld");
if (!wsEyePos)
{
wsEyePos = new Var("eyePosWorld", "vec3");
wsEyePos->uniform = true;
wsEyePos->constSortPos = cspPass;
}
Var* wsPosition = getInWsPosition(componentList);
Var* wsView = getWsView(wsPosition, meta);
surface = new Var("surface", "Surface"); surface = new Var("surface", "Surface");
meta->addStatement(new GenOp(" @ = createForwardSurface(@,@,@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, normal, ormConfig, meta->addStatement(new GenOp(" @ = createForwardSurface(@,normalize(@),@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, normal, ormConfig,
wsPosition, wsEyePos, wsView)); wsPosition, wsEyePos, wsView));
} }
/*Var* surface = (Var*)LangElement::find("surface");
if (!surface)
{
surface = new Var("surface", "float");
}*/
return surface; return surface;
} }
//**************************************************************************** //****************************************************************************
@ -3003,12 +2990,12 @@ void ReflectionProbeFeatGLSL::processPix(Vector<ShaderComponent*>& componentList
inRefPosArray->uniform = true; inRefPosArray->uniform = true;
inRefPosArray->constSortPos = cspPotentialPrimitive; inRefPosArray->constSortPos = cspPotentialPrimitive;
Var * refScaleArray = new Var("inRefScale", "vec4"); Var * refScaleArray = new Var("inRefScaleArray", "vec4");
refScaleArray->arraySize = MAX_FORWARD_PROBES; refScaleArray->arraySize = MAX_FORWARD_PROBES;
refScaleArray->uniform = true; refScaleArray->uniform = true;
refScaleArray->constSortPos = cspPotentialPrimitive; refScaleArray->constSortPos = cspPotentialPrimitive;
Var * probeConfigData = new Var("inProbeConfigData", "vec4"); Var * probeConfigData = new Var("inProbeConfigDataArray", "vec4");
probeConfigData->arraySize = MAX_FORWARD_PROBES; probeConfigData->arraySize = MAX_FORWARD_PROBES;
probeConfigData->uniform = true; probeConfigData->uniform = true;
probeConfigData->constSortPos = cspPotentialPrimitive; probeConfigData->constSortPos = cspPotentialPrimitive;
@ -3026,12 +3013,12 @@ void ReflectionProbeFeatGLSL::processPix(Vector<ShaderComponent*>& componentList
BRDFTexture->sampler = true; BRDFTexture->sampler = true;
BRDFTexture->constNum = Var::getTexUnitNum(); // used as texture unit num here BRDFTexture->constNum = Var::getTexUnitNum(); // used as texture unit num here
Var * specularCubemapAR = new Var("inSpecularCubemapAR", "samplerCubeArray"); Var * specularCubemapAR = new Var("SpecularCubemapAR", "samplerCubeArray");
specularCubemapAR->uniform = true; specularCubemapAR->uniform = true;
specularCubemapAR->sampler = true; specularCubemapAR->sampler = true;
specularCubemapAR->constNum = Var::getTexUnitNum(); specularCubemapAR->constNum = Var::getTexUnitNum();
Var * irradianceCubemapAR = new Var("inIrradianceCubemapAR", "samplerCubeArray"); Var * irradianceCubemapAR = new Var("IrradianceCubemapAR", "samplerCubeArray");
irradianceCubemapAR->uniform = true; irradianceCubemapAR->uniform = true;
irradianceCubemapAR->sampler = true; irradianceCubemapAR->sampler = true;
irradianceCubemapAR->constNum = Var::getTexUnitNum(); irradianceCubemapAR->constNum = Var::getTexUnitNum();
@ -3044,14 +3031,24 @@ void ReflectionProbeFeatGLSL::processPix(Vector<ShaderComponent*>& componentList
return; return;
} }
Var* eyePos = (Var*)LangElement::find("eyePosWorld");
if (!eyePos)
{
eyePos = new Var;
eyePos->setType("vec3");
eyePos->setName("eyePosWorld");
eyePos->uniform = true;
eyePos->constSortPos = cspPotentialPrimitive;
}
Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
//Reflection vec //Reflection vec
String computeForwardProbes = String(" @.rgb = computeForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t"); String computeForwardProbes = String(" @.rgb = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
computeForwardProbes += String("@,@,\r\n\t\t"); computeForwardProbes += String("@,@,\r\n\t\t");
computeForwardProbes += String("@,@).rgb; \r\n"); computeForwardProbes += String("@,@).rgb; \r\n");
meta->addStatement(new GenOp(computeForwardProbes.c_str(), curColor, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray, meta->addStatement(new GenOp(computeForwardProbes.c_str(), curColor, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray, eyePos,
skylightCubemapIdx, BRDFTexture, skylightCubemapIdx, BRDFTexture,
irradianceCubemapAR, specularCubemapAR)); irradianceCubemapAR, specularCubemapAR));
@ -3078,9 +3075,9 @@ void ReflectionProbeFeatGLSL::setTexData(Material::StageData& stageDat,
passData.mSamplerNames[texIndex] = "BRDFTexture"; passData.mSamplerNames[texIndex] = "BRDFTexture";
passData.mTexType[texIndex++] = Material::Standard; passData.mTexType[texIndex++] = Material::Standard;
// assuming here that it is a scenegraph cubemap // assuming here that it is a scenegraph cubemap
passData.mSamplerNames[texIndex] = "inSpecularCubemapAR"; passData.mSamplerNames[texIndex] = "SpecularCubemapAR";
passData.mTexType[texIndex++] = Material::SGCube; passData.mTexType[texIndex++] = Material::SGCube;
passData.mSamplerNames[texIndex] = "inIrradianceCubemapAR"; passData.mSamplerNames[texIndex] = "IrradianceCubemapAR";
passData.mTexType[texIndex++] = Material::SGCube; passData.mTexType[texIndex++] = Material::SGCube;
} }
} }

View file

@ -764,7 +764,7 @@ Var* ShaderFeatureHLSL::getWsView( Var *wsPosition, MultiLine *meta )
eyePos->constSortPos = cspPass; eyePos->constSortPos = cspPass;
} }
meta->addStatement( new GenOp( " @ = normalize( @ - @ );\r\n", meta->addStatement( new GenOp( " @ = @ - @;\r\n",
new DecOp( wsView ), eyePos, wsPosition ) ); new DecOp( wsView ), eyePos, wsPosition ) );
} }
@ -844,14 +844,16 @@ Var* ShaderFeatureHLSL::addOutDetailTexCoord( Vector<ShaderComponent*> &compon
Var* ShaderFeatureHLSL::getSurface(Vector<ShaderComponent*>& componentList, MultiLine* meta, const MaterialFeatureData& fd) Var* ShaderFeatureHLSL::getSurface(Vector<ShaderComponent*>& componentList, MultiLine* meta, const MaterialFeatureData& fd)
{ {
ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]); Var *surface = (Var *)LangElement::find("surface");
Var* diffuseColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); if (!surface)
{
Var *diffuseColor = (Var *)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
Var* ormConfig = (Var*)LangElement::find("ORMConfig"); Var *ormConfig = (Var *)LangElement::find("ORMConfig");
if (!ormConfig) if (!ormConfig)
{ {
Var* metalness = (Var*)LangElement::find("metalness"); Var *metalness = (Var *)LangElement::find("metalness");
if (!metalness) if (!metalness)
{ {
metalness = new Var("metalness", "float"); metalness = new Var("metalness", "float");
@ -859,7 +861,7 @@ Var* ShaderFeatureHLSL::getSurface(Vector<ShaderComponent*>& componentList, Mult
metalness->constSortPos = cspPotentialPrimitive; metalness->constSortPos = cspPotentialPrimitive;
} }
Var* roughness = (Var*)LangElement::find("roughness"); Var *roughness = (Var *)LangElement::find("roughness");
if (!roughness) if (!roughness)
{ {
roughness = new Var("roughness", "float"); roughness = new Var("roughness", "float");
@ -868,30 +870,24 @@ Var* ShaderFeatureHLSL::getSurface(Vector<ShaderComponent*>& componentList, Mult
} }
ormConfig = new Var("ORMConfig", "float4"); ormConfig = new Var("ORMConfig", "float4");
LangElement* colorDecl = new DecOp(ormConfig); LangElement *colorDecl = new DecOp(ormConfig);
meta->addStatement(new GenOp(" @ = float4(0.0,1.0,@,@);\r\n", colorDecl, roughness, metalness)); //reconstruct matinfo, no ao darkening meta->addStatement(new GenOp(" @ = float4(0.0,1.0,@,@);\r\n", colorDecl, roughness, metalness)); //reconstruct matinfo, no ao darkening
} }
Var* normal = (Var*)LangElement::find("normal"); Var *normal = (Var *)LangElement::find("normal");
if (!normal) if (!normal)
{ {
normal = new Var("normal", "float3"); normal = new Var("normal", "float3");
meta->addStatement(new GenOp(" @;\r\n\n", new DecOp(normal))); meta->addStatement(new GenOp(" @;\r\n\n", new DecOp(normal)));
Var* wsNormal = (Var*)LangElement::find("wsNormal"); Var *wsNormal = (Var *)LangElement::find("wsNormal");
if (!fd.features[MFT_NormalMap])
{
if (!wsNormal) if (!wsNormal)
wsNormal = getInWorldNormal(componentList); wsNormal = getInWorldNormal(componentList);
meta->addStatement(new GenOp(" @ = normalize( @ );\r\n\n", normal, wsNormal));
}
else
{
meta->addStatement(new GenOp(" @ = normalize( @ );\r\n", normal, wsNormal)); meta->addStatement(new GenOp(" @ = normalize( @ );\r\n", normal, wsNormal));
} }
}
Var* wsEyePos = (Var*)LangElement::find("eyePosWorld"); Var *wsEyePos = (Var *)LangElement::find("eyePosWorld");
if (!wsEyePos) if (!wsEyePos)
{ {
@ -900,15 +896,11 @@ Var* ShaderFeatureHLSL::getSurface(Vector<ShaderComponent*>& componentList, Mult
wsEyePos->constSortPos = cspPass; wsEyePos->constSortPos = cspPass;
} }
Var* wsPosition = getInWsPosition(componentList); Var *wsPosition = getInWsPosition(componentList);
Var* wsView = getWsView(wsPosition, meta); Var *wsView = getWsView(wsPosition, meta);
Var* surface = (Var*)LangElement::find("surface");
if (!surface)
{
surface = new Var("surface", "Surface"); surface = new Var("surface", "Surface");
meta->addStatement(new GenOp(" @ = createForwardSurface(@,@,@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, normal, ormConfig, meta->addStatement(new GenOp(" @ = createForwardSurface(@,normalize(@),@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, normal, ormConfig,
wsPosition, wsEyePos, wsView)); wsPosition, wsEyePos, wsView));
} }
@ -3076,12 +3068,12 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
inRefPosArray->uniform = true; inRefPosArray->uniform = true;
inRefPosArray->constSortPos = cspPotentialPrimitive; inRefPosArray->constSortPos = cspPotentialPrimitive;
Var * refScaleArray = new Var("inRefScale", "float4"); Var * refScaleArray = new Var("inRefScaleArray", "float4");
refScaleArray->arraySize = MAX_FORWARD_PROBES; refScaleArray->arraySize = MAX_FORWARD_PROBES;
refScaleArray->uniform = true; refScaleArray->uniform = true;
refScaleArray->constSortPos = cspPotentialPrimitive; refScaleArray->constSortPos = cspPotentialPrimitive;
Var *probeConfigData = new Var("inProbeConfigData", "float4"); Var *probeConfigData = new Var("inProbeConfigDataArray", "float4");
probeConfigData->arraySize = MAX_FORWARD_PROBES; probeConfigData->arraySize = MAX_FORWARD_PROBES;
probeConfigData->uniform = true; probeConfigData->uniform = true;
probeConfigData->constSortPos = cspPotentialPrimitive; probeConfigData->constSortPos = cspPotentialPrimitive;
@ -3101,22 +3093,22 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
BRDFTextureTex->texture = true; BRDFTextureTex->texture = true;
BRDFTextureTex->constNum = BRDFTexture->constNum; BRDFTextureTex->constNum = BRDFTexture->constNum;
Var *specularCubemapAR = new Var("inSpecularCubemapAR", "SamplerState"); Var *specularCubemapAR = new Var("SpecularCubemapAR", "SamplerState");
specularCubemapAR->uniform = true; specularCubemapAR->uniform = true;
specularCubemapAR->sampler = true; specularCubemapAR->sampler = true;
specularCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here specularCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here
Var *specularCubemapARTex = new Var("texture_inSpecularCubemapAR", "TextureCubeArray"); Var *specularCubemapARTex = new Var("texture_SpecularCubemapAR", "TextureCubeArray");
specularCubemapARTex->uniform = true; specularCubemapARTex->uniform = true;
specularCubemapARTex->texture = true; specularCubemapARTex->texture = true;
specularCubemapARTex->constNum = specularCubemapAR->constNum; specularCubemapARTex->constNum = specularCubemapAR->constNum;
Var *irradianceCubemapAR = new Var("inIrradianceCubemapAR", "SamplerState"); Var *irradianceCubemapAR = new Var("IrradianceCubemapAR", "SamplerState");
irradianceCubemapAR->uniform = true; irradianceCubemapAR->uniform = true;
irradianceCubemapAR->sampler = true; irradianceCubemapAR->sampler = true;
irradianceCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here irradianceCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here
Var *irradianceCubemapARTex = new Var("texture_inIrradianceCubemapAR", "TextureCubeArray"); Var *irradianceCubemapARTex = new Var("texture_IrradianceCubemapAR", "TextureCubeArray");
irradianceCubemapARTex->uniform = true; irradianceCubemapARTex->uniform = true;
irradianceCubemapARTex->texture = true; irradianceCubemapARTex->texture = true;
irradianceCubemapARTex->constNum = irradianceCubemapAR->constNum; irradianceCubemapARTex->constNum = irradianceCubemapAR->constNum;
@ -3138,11 +3130,21 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
ibl = new Var("ibl", "float3"); ibl = new Var("ibl", "float3");
} }
String computeForwardProbes = String(" @ = computeForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t"); Var* eyePos = (Var*)LangElement::find("eyePosWorld");
if (!eyePos)
{
eyePos = new Var;
eyePos->setType("float3");
eyePos->setName("eyePosWorld");
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
String computeForwardProbes = String(" @ = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
computeForwardProbes += String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t"); computeForwardProbes += String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t");
computeForwardProbes += String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n"); computeForwardProbes += String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n");
meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray, meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray, eyePos,
skylightCubemapIdx, BRDFTexture, skylightCubemapIdx, BRDFTexture,
irradianceCubemapAR, specularCubemapAR)); irradianceCubemapAR, specularCubemapAR));
@ -3171,9 +3173,9 @@ void ReflectionProbeFeatHLSL::setTexData(Material::StageData &stageDat,
passData.mSamplerNames[texIndex] = "BRDFTexture"; passData.mSamplerNames[texIndex] = "BRDFTexture";
passData.mTexType[texIndex++] = Material::Standard; passData.mTexType[texIndex++] = Material::Standard;
// assuming here that it is a scenegraph cubemap // assuming here that it is a scenegraph cubemap
passData.mSamplerNames[texIndex] = "inSpecularCubemapAR"; passData.mSamplerNames[texIndex] = "SpecularCubemapAR";
passData.mTexType[texIndex++] = Material::SGCube; passData.mTexType[texIndex++] = Material::SGCube;
passData.mSamplerNames[texIndex] = "inIrradianceCubemapAR"; passData.mSamplerNames[texIndex] = "IrradianceCubemapAR";
passData.mTexType[texIndex++] = Material::SGCube; passData.mTexType[texIndex++] = Material::SGCube;
} }
} }

View file

@ -80,17 +80,19 @@ const String ShaderGenVars::glowMul("$glowMul");
//Reflection Probes - Forward lit. not to be confused with the deferred handwritten vars //Reflection Probes - Forward lit. not to be confused with the deferred handwritten vars
//change to parity once we've got the same arrays used for both routes //change to parity once we've got the same arrays used for both routes
const String ShaderGenVars::probePosition("$inProbePosArray"); const String ShaderGenVars::probePositionArray("$inProbePosArray");
const String ShaderGenVars::probeRefPos("$inRefPosArray"); const String ShaderGenVars::probeRefPosArray("$inRefPosArray");
const String ShaderGenVars::refScale("$inRefScale"); const String ShaderGenVars::refScaleArray("$inRefScaleArray");
const String ShaderGenVars::worldToObjArray("$inWorldToObjArray"); const String ShaderGenVars::worldToObjArray("$inWorldToObjArray");
const String ShaderGenVars::probeConfigData("$inProbeConfigData"); const String ShaderGenVars::probeConfigDataArray("$inProbeConfigDataArray");
const String ShaderGenVars::specularCubemapAR("$inSpecularCubemapAR"); const String ShaderGenVars::specularCubemapAR("$SpecularCubemapAR");
const String ShaderGenVars::irradianceCubemapAR("$inIrradianceCubemapAR"); const String ShaderGenVars::irradianceCubemapAR("$IrradianceCubemapAR");
const String ShaderGenVars::probeCount("$inNumProbes"); const String ShaderGenVars::probeCount("$inNumProbes");
const String ShaderGenVars::BRDFTextureMap("$BRDFTexture"); const String ShaderGenVars::BRDFTextureMap("$BRDFTexture");
const String ShaderGenVars::maxProbeDrawDistance("$maxProbeDrawDistance");
//Skylight //Skylight
const String ShaderGenVars::skylightCubemapIdx("$inSkylightCubemapIdx"); const String ShaderGenVars::skylightCubemapIdx("$inSkylightCubemapIdx");

View file

@ -91,17 +91,19 @@ struct ShaderGenVars
const static String glowMul; const static String glowMul;
//Reflection Probes //Reflection Probes
const static String probePosition; const static String probePositionArray;
const static String probeRefPos; const static String probeRefPosArray;
const static String refScale; const static String refScaleArray;
const static String worldToObjArray; const static String worldToObjArray;
const static String probeConfigData; const static String probeConfigDataArray;
const static String specularCubemapAR; const static String specularCubemapAR;
const static String irradianceCubemapAR; const static String irradianceCubemapAR;
const static String probeCount; const static String probeCount;
const static String BRDFTextureMap; const static String BRDFTextureMap;
const static String maxProbeDrawDistance;
//Skylight //Skylight
const static String skylightCubemapIdx; const static String skylightCubemapIdx;

View file

@ -15,4 +15,6 @@ singleton PostEffect( reflectionProbeArrayPostFX )
texture[0] = "#deferred"; texture[0] = "#deferred";
texture[1] = "#color"; texture[1] = "#color";
texture[2] = "#matinfo"; texture[2] = "#matinfo";
allowReflectPass = true;
}; };

View file

@ -23,6 +23,8 @@
#include "./torque.glsl" #include "./torque.glsl"
#include "./brdf.glsl" #include "./brdf.glsl"
uniform float maxProbeDrawDistance;
#ifndef TORQUE_SHADERGEN #ifndef TORQUE_SHADERGEN
#line 27 #line 27
// These are the uniforms used by most lighting shaders. // These are the uniforms used by most lighting shaders.
@ -330,7 +332,7 @@ float defineSphereSpaceInfluence(vec3 wsPosition, vec3 wsProbePosition, float ra
{ {
vec3 L = wsProbePosition.xyz - wsPosition; vec3 L = wsProbePosition.xyz - wsPosition;
float contribution = 1.0 - length(L) / radius; float contribution = 1.0 - length(L) / radius;
return contribution; return saturate(contribution);
} }
float getDistBoxToPoint(vec3 pt, vec3 extents) float getDistBoxToPoint(vec3 pt, vec3 extents)
@ -342,10 +344,9 @@ float getDistBoxToPoint(vec3 pt, vec3 extents)
float defineBoxSpaceInfluence(vec3 wsPosition, mat4 worldToObj, float attenuation) float defineBoxSpaceInfluence(vec3 wsPosition, mat4 worldToObj, float attenuation)
{ {
vec3 surfPosLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz; vec3 surfPosLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz;
float atten = 1.0 - attenuation;
float baseVal = 0.25; float baseVal = 0.25;
float dist = getDistBoxToPoint(surfPosLS, vec3(baseVal, baseVal, baseVal)); float dist = getDistBoxToPoint(surfPosLS, vec3(baseVal, baseVal, baseVal));
return saturate(smoothstep(baseVal + 0.0001, atten*baseVal, dist)); return saturate(smoothstep(baseVal, (baseVal-attenuation/2), dist));
} }
// Box Projected IBL Lighting // Box Projected IBL Lighting
@ -367,9 +368,9 @@ vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 refSca
} }
vec4 computeForwardProbes(Surface surface, vec4 computeForwardProbes(Surface surface,
float cubeMips, int numProbes, mat4x4 worldToObjArray[MAX_FORWARD_PROBES], vec4 probeConfigData[MAX_FORWARD_PROBES], float cubeMips, int numProbes, mat4x4 inWorldToObjArray[MAX_FORWARD_PROBES], vec4 inProbeConfigData[MAX_FORWARD_PROBES],
vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refScaleArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES], vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 inRefScaleArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
float skylightCubemapIdx, sampler2D BRDFTexture, vec3 wsEyePos, float skylightCubemapIdx, sampler2D BRDFTexture,
samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR) samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR)
{ {
int i = 0; int i = 0;
@ -384,47 +385,37 @@ vec4 computeForwardProbes(Surface surface,
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
contribution[i] = 0; contribution[i] = 0;
float atten = 1.0-(length(wsEyePos-inProbePosArray[i].xyz)/maxProbeDrawDistance);
if (probeConfigData[i].r == 0) //box if (inProbeConfigData[i].r == 0) //box
{ {
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b); contribution[i] = defineBoxSpaceInfluence(surface.P, inWorldToObjArray[i], inProbeConfigData[i].b)*atten;
if (contribution[i] > 0.0)
probehits++;
} }
else if (probeConfigData[i].r == 1) //sphere else if (inProbeConfigData[i].r == 1) //sphere
{ {
contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g); contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, inProbeConfigData[i].g)*atten;
if (contribution[i] > 0.0)
probehits++;
} }
contribution[i] = max(contribution[i], 0); if (contribution[i]>0.0)
probehits++;
else
contribution[i] = 0.0;
blendSum += contribution[i]; blendSum += contribution[i];
invBlendSum += (1.0f - contribution[i]);
} }
if (probehits > 1.0) if (probehits > 1.0)//if we overlap
{ {
invBlendSum = (probehits - blendSum)/(probehits-1); //grab the remainder
for (i = 0; i < numProbes; i++) for (i = 0; i < numProbes; i++)
{ {
blendFactor[i] = ((contribution[i] / blendSum)) / probehits; blendFactor[i] = contribution[i]/blendSum; //what % total is this instance
blendFactor[i] *= ((contribution[i]) / invBlendSum); blendFactor[i] *= blendFactor[i] / invBlendSum; //what should we add to sum to 1
blendFactor[i] = saturate(blendFactor[i]); blendFacSum += blendFactor[i]; //running tally of results
blendFacSum += blendFactor[i];
} }
// Normalize blendVal
if (blendFacSum == 0.0f) // Possible with custom weight
{
blendFacSum = 1.0f;
}
float invBlendSumWeighted = 1.0f / blendFacSum;
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
blendFactor[i] *= invBlendSumWeighted; contribution[i] *= blendFactor[i]/blendFacSum; //normalize
contribution[i] *= blendFactor[i];
} }
} }
@ -471,8 +462,8 @@ vec4 computeForwardProbes(Surface surface,
float contrib = contribution[i]; float contrib = contribution[i];
if (contrib > 0.0f) if (contrib > 0.0f)
{ {
float cubemapIdx = int(probeConfigData[i].a); float cubemapIdx = int(inProbeConfigData[i].a);
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz); vec3 dir = boxProject(surface.P, surface.R, inWorldToObjArray[i], inRefScaleArray[i].xyz, inRefPosArray[i].xyz);
irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib; irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib; specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;
@ -491,8 +482,8 @@ vec4 computeForwardProbes(Surface surface,
vec3 kD = 1.0f - F; vec3 kD = 1.0f - F;
kD *= 1.0f - surface.metalness; kD *= 1.0f - surface.metalness;
float dfgNdotV = max( surface.NdotV , 0.0009765625f ); //0.5f/512.0f (512 is size of dfg/brdf lookup tex) //float dfgNdotV = max( surface.NdotV , 0.0009765625f ); //0.5f/512.0f (512 is size of dfg/brdf lookup tex)
vec2 envBRDF = textureLod(BRDFTexture, vec2(dfgNdotV, surface.roughness),0).rg; vec2 envBRDF = textureLod(BRDFTexture, vec2(surface.NdotV, surface.roughness),0).rg;
specular *= F * envBRDF.x + surface.f90 * envBRDF.y; specular *= F * envBRDF.x + surface.f90 * envBRDF.y;
irradiance *= kD * surface.baseColor.rgb; irradiance *= kD * surface.baseColor.rgb;
@ -504,13 +495,16 @@ vec4 computeForwardProbes(Surface surface,
float horizonOcclusion = 1.3; float horizonOcclusion = 1.3;
float horizon = saturate( 1 + horizonOcclusion * dot(surface.R, surface.N)); float horizon = saturate( 1 + horizonOcclusion * dot(surface.R, surface.N));
horizon *= horizon; horizon *= horizon;
#if CAPTURING == 1
return vec4(mix(surface.baseColor.rgb,(irradiance + specular) * horizon,surface.metalness/2),0);
#else
return vec4((irradiance + specular) * horizon, 0);//alpha writes disabled return vec4((irradiance + specular) * horizon, 0);//alpha writes disabled
#endif
} }
vec4 debugVizForwardProbes(Surface surface, vec4 debugVizForwardProbes(Surface surface,
float cubeMips, int numProbes, mat4 worldToObjArray[MAX_FORWARD_PROBES], vec4 probeConfigData[MAX_FORWARD_PROBES], float cubeMips, int numProbes, mat4 inWorldToObjArray[MAX_FORWARD_PROBES], vec4 inProbeConfigData[MAX_FORWARD_PROBES],
vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refScaleArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES], vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 inRefScaleArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
float skylightCubemapIdx, sampler2D BRDFTexture, float skylightCubemapIdx, sampler2D BRDFTexture,
samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR, int showAtten, int showContrib, int showSpec, int showDiff) samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR, int showAtten, int showContrib, int showSpec, int showDiff)
{ {
@ -527,15 +521,15 @@ vec4 debugVizForwardProbes(Surface surface,
{ {
contribution[i] = 0; contribution[i] = 0;
if (probeConfigData[i].r == 0) //box if (inProbeConfigData[i].r == 0) //box
{ {
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b); contribution[i] = defineBoxSpaceInfluence(surface.P, inWorldToObjArray[i], inProbeConfigData[i].b);
if (contribution[i] > 0.0) if (contribution[i] > 0.0)
probehits++; probehits++;
} }
else if (probeConfigData[i].r == 1) //sphere else if (inProbeConfigData[i].r == 1) //sphere
{ {
contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g); contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, inProbeConfigData[i].g);
if (contribution[i] > 0.0) if (contribution[i] > 0.0)
probehits++; probehits++;
} }
@ -620,8 +614,8 @@ vec4 debugVizForwardProbes(Surface surface,
float contrib = contribution[i]; float contrib = contribution[i];
if (contrib > 0.0f) if (contrib > 0.0f)
{ {
float cubemapIdx = probeConfigData[i].a; float cubemapIdx = inProbeConfigData[i].a;
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz); vec3 dir = boxProject(surface.P, surface.R, inWorldToObjArray[i], inRefScaleArray[i].xyz, inRefPosArray[i].xyz);
irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib; irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib; specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;

View file

@ -24,6 +24,9 @@
#include "./brdf.hlsl" #include "./brdf.hlsl"
#include "./shaderModelAutoGen.hlsl" #include "./shaderModelAutoGen.hlsl"
//globals
uniform float3 eyePosWorld;
uniform float maxProbeDrawDistance;
#ifndef TORQUE_SHADERGEN #ifndef TORQUE_SHADERGEN
// These are the uniforms used by most lighting shaders. // These are the uniforms used by most lighting shaders.
@ -333,7 +336,7 @@ float defineSphereSpaceInfluence(float3 wsPosition, float3 wsProbePosition, floa
{ {
float3 L = wsProbePosition.xyz - wsPosition; float3 L = wsProbePosition.xyz - wsPosition;
float contribution = 1.0 - length(L) / radius; float contribution = 1.0 - length(L) / radius;
return contribution; return saturate(contribution);
} }
float getDistBoxToPoint(float3 pt, float3 extents) float getDistBoxToPoint(float3 pt, float3 extents)
@ -345,10 +348,9 @@ float getDistBoxToPoint(float3 pt, float3 extents)
float defineBoxSpaceInfluence(float3 wsPosition, float4x4 worldToObj, float attenuation) float defineBoxSpaceInfluence(float3 wsPosition, float4x4 worldToObj, float attenuation)
{ {
float3 surfPosLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz; float3 surfPosLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
float atten = 1.0 - attenuation;
float baseVal = 0.25; float baseVal = 0.25;
float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal)); float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal));
return saturate(smoothstep(baseVal + 0.0001, atten*baseVal, dist)); return saturate(smoothstep(baseVal, (baseVal-attenuation/2), dist));
} }
// Box Projected IBL Lighting // Box Projected IBL Lighting
@ -370,9 +372,9 @@ float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, f
} }
float4 computeForwardProbes(Surface surface, float4 computeForwardProbes(Surface surface,
float cubeMips, int numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES], float cubeMips, int numProbes, float4x4 inWorldToObjArray[MAX_FORWARD_PROBES], float4 inProbeConfigData[MAX_FORWARD_PROBES],
float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refScaleArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES], float4 inProbePosArray[MAX_FORWARD_PROBES], float4 inRefScaleArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture), float3 wsEyePos, float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture),
TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR)) TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR))
{ {
int i = 0; int i = 0;
@ -384,50 +386,41 @@ float4 computeForwardProbes(Surface surface,
float probehits = 0; float probehits = 0;
//Set up our struct data //Set up our struct data
float contribution[MAX_FORWARD_PROBES]; float contribution[MAX_FORWARD_PROBES];
//Process prooooobes
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
contribution[i] = 0; contribution[i] = 0.0;
float atten = 1.0-(length(wsEyePos-inProbePosArray[i].xyz)/maxProbeDrawDistance);
if (probeConfigData[i].r == 0) //box if (inProbeConfigData[i].r == 0) //box
{ {
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b); contribution[i] = defineBoxSpaceInfluence(surface.P, inWorldToObjArray[i], inProbeConfigData[i].b)*atten;
if (contribution[i] > 0.0)
probehits++;
} }
else if (probeConfigData[i].r == 1) //sphere else if (inProbeConfigData[i].r == 1) //sphere
{ {
contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g); contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, inProbeConfigData[i].g)*atten;
if (contribution[i] > 0.0)
probehits++;
} }
contribution[i] = max(contribution[i], 0); if (contribution[i]>0.0)
probehits++;
else
contribution[i] = 0.0;
blendSum += contribution[i]; blendSum += contribution[i];
invBlendSum += (1.0f - contribution[i]);
} }
if (probehits > 1.0) if (probehits > 1.0)//if we overlap
{ {
invBlendSum = (probehits - blendSum)/(probehits-1); //grab the remainder
for (i = 0; i < numProbes; i++) for (i = 0; i < numProbes; i++)
{ {
blendFactor[i] = ((contribution[i] / blendSum)) / probehits; blendFactor[i] = contribution[i]/blendSum; //what % total is this instance
blendFactor[i] *= ((contribution[i]) / invBlendSum); blendFactor[i] *= blendFactor[i] / invBlendSum; //what should we add to sum to 1
blendFactor[i] = saturate(blendFactor[i]); blendFacSum += blendFactor[i]; //running tally of results
blendFacSum += blendFactor[i];
} }
// Normalize blendVal
if (blendFacSum == 0.0f) // Possible with custom weight
{
blendFacSum = 1.0f;
}
float invBlendSumWeighted = 1.0f / blendFacSum;
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
blendFactor[i] *= invBlendSumWeighted; contribution[i] *= blendFactor[i]/blendFacSum; //normalize
contribution[i] *= blendFactor[i];
} }
} }
@ -474,8 +467,8 @@ float4 computeForwardProbes(Surface surface,
float contrib = contribution[i]; float contrib = contribution[i];
if (contrib > 0.0f) if (contrib > 0.0f)
{ {
int cubemapIdx = probeConfigData[i].a; int cubemapIdx = inProbeConfigData[i].a;
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz); float3 dir = boxProject(surface.P, surface.R, inWorldToObjArray[i], inRefScaleArray[i].xyz, inRefPosArray[i].xyz);
irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib; irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib; specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;
@ -494,8 +487,8 @@ float4 computeForwardProbes(Surface surface,
float3 kD = 1.0f - F; float3 kD = 1.0f - F;
kD *= 1.0f - surface.metalness; kD *= 1.0f - surface.metalness;
float dfgNdotV = max( surface.NdotV , 0.0009765625f ); //0.5f/512.0f (512 is size of dfg/brdf lookup tex) //float dfgNdotV = max( surface.NdotV , 0.0009765625f ); //0.5f/512.0f (512 is size of dfg/brdf lookup tex)
float2 envBRDF = TORQUE_TEX2DLOD(BRDFTexture, float4(dfgNdotV, surface.roughness,0,0)).rg; float2 envBRDF = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.NdotV, surface.roughness,0,0)).rg;
specular *= F * envBRDF.x + surface.f90 * envBRDF.y; specular *= F * envBRDF.x + surface.f90 * envBRDF.y;
irradiance *= kD * surface.baseColor.rgb; irradiance *= kD * surface.baseColor.rgb;
@ -507,13 +500,16 @@ float4 computeForwardProbes(Surface surface,
float horizonOcclusion = 1.3; float horizonOcclusion = 1.3;
float horizon = saturate( 1 + horizonOcclusion * dot(surface.R, surface.N)); float horizon = saturate( 1 + horizonOcclusion * dot(surface.R, surface.N));
horizon *= horizon; horizon *= horizon;
#if CAPTURING == 1
return float4(lerp(surface.baseColor.rgb,(irradiance + specular) * horizon,surface.metalness/2),0);
#else
return float4((irradiance + specular) * horizon, 0);//alpha writes disabled return float4((irradiance + specular) * horizon, 0);//alpha writes disabled
#endif
} }
float4 debugVizForwardProbes(Surface surface, float4 debugVizForwardProbes(Surface surface,
float cubeMips, int numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES], float cubeMips, int numProbes, float4x4 inWorldToObjArray[MAX_FORWARD_PROBES], float4 inProbeConfigData[MAX_FORWARD_PROBES],
float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refScaleArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES], float4 inProbePosArray[MAX_FORWARD_PROBES], float4 inRefScaleArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture), float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture),
TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR), int showAtten, int showContrib, int showSpec, int showDiff) TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR), int showAtten, int showContrib, int showSpec, int showDiff)
{ {
@ -530,15 +526,15 @@ float4 debugVizForwardProbes(Surface surface,
{ {
contribution[i] = 0; contribution[i] = 0;
if (probeConfigData[i].r == 0) //box if (inProbeConfigData[i].r == 0) //box
{ {
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b); contribution[i] = defineBoxSpaceInfluence(surface.P, inWorldToObjArray[i], inProbeConfigData[i].b);
if (contribution[i] > 0.0) if (contribution[i] > 0.0)
probehits++; probehits++;
} }
else if (probeConfigData[i].r == 1) //sphere else if (inProbeConfigData[i].r == 1) //sphere
{ {
contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g); contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, inProbeConfigData[i].g);
if (contribution[i] > 0.0) if (contribution[i] > 0.0)
probehits++; probehits++;
} }
@ -623,8 +619,8 @@ float4 debugVizForwardProbes(Surface surface,
float contrib = contribution[i]; float contrib = contribution[i];
if (contrib > 0.0f) if (contrib > 0.0f)
{ {
int cubemapIdx = probeConfigData[i].a; int cubemapIdx = inProbeConfigData[i].a;
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz); float3 dir = boxProject(surface.P, surface.R, inWorldToObjArray[i], inRefScaleArray[i].xyz, inRefPosArray[i].xyz);
irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib; irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib; specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;

View file

@ -196,6 +196,38 @@ void main()
lightCol *= max(cookie.r, max(cookie.g, cookie.b)); lightCol *= max(cookie.r, max(cookie.g, cookie.b));
#endif #endif
#ifdef DIFFUSE_LIGHT_VIZ
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
vec3 diffuse = BRDF_GetDebugDiffuse(surface,surfaceToLight) * factor;
vec3 final = max(0.0f, diffuse);
OUT_col = vec4(final, 0);
return
#endif
#ifdef SPECULAR_LIGHT_VIZ
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
vec3 diffuse = BRDF_GetDebugSpecular(surface,surfaceToLight) * factor;
vec3 final = max(0.0f, diffuse);
OUT_col = vec4(final, 0);
return
#endif
#ifdef DETAIL_LIGHTING_VIZ
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
vec3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
vec3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
vec3 final = max(vec3(0.0f), diffuse + spec * surface.F);
OUT_col = vec4(final, 0);
return
#endif
//get punctual light contribution //get punctual light contribution
lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed); lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
} }

View file

@ -84,78 +84,57 @@ void main()
{ {
contribution[i] = 0; contribution[i] = 0;
float atten =1.0-(length(eyePosWorld-probePosArray[i].xyz)/maxProbeDrawDistance);
if (probeConfigData[i].r == 0) //box if (probeConfigData[i].r == 0) //box
{ {
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b); contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b)*atten;
if (contribution[i]>0.0)
probehits++;
} }
else if (probeConfigData[i].r == 1) //sphere else if (probeConfigData[i].r == 1) //sphere
{ {
contribution[i] = defineSphereSpaceInfluence(surface.P, probePosArray[i].xyz, probeConfigData[i].g); contribution[i] = defineSphereSpaceInfluence(surface.P, probePosArray[i].xyz, probeConfigData[i].g)*atten;
}
if (contribution[i]>0.0) if (contribution[i]>0.0)
probehits++; probehits++;
} else
contribution[i] = 0;
contribution[i] = max(contribution[i],0);
blendSum += contribution[i]; blendSum += contribution[i];
invBlendSum += (1.0f - contribution[i]);
} }
// Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
// And as we invert, we need to divide by Num-1 to stay normalized (else sum is > 1).
// respect constraint B.
// Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary
// and respect constraint A.
if (probehits > 1.0) if (probehits > 1.0)//if we overlap
{ {
invBlendSum = (probehits - blendSum)/(probehits-1); //grab the remainder
for (i = 0; i < numProbes; i++) for (i = 0; i < numProbes; i++)
{ {
blendFactor[i] = ((contribution[i] / blendSum)) / probehits; blendFactor[i] = contribution[i]/blendSum; //what % total is this instance
blendFactor[i] *= ((contribution[i]) / invBlendSum); blendFactor[i] *= blendFactor[i] / invBlendSum; //what should we add to sum to 1
blendFactor[i] = saturate(blendFactor[i]); blendFacSum += blendFactor[i]; //running tally of results
blendFacSum += blendFactor[i];
} }
// Normalize blendVal
if (blendFacSum == 0.0f) // Possible with custom weight
{
blendFacSum = 1.0f;
}
float invBlendSumWeighted = 1.0f / blendFacSum;
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
blendFactor[i] *= invBlendSumWeighted; contribution[i] *= blendFactor[i]/blendFacSum; //normalize
contribution[i] *= blendFactor[i];
} }
} }
#if DEBUGVIZ_ATTENUATION == 1 #if DEBUGVIZ_ATTENUATION == 1
float contribAlpha = 1; float contribAlpha = 0;
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
contribAlpha -= contribution[i]; contribAlpha += contribution[i];
} }
OUT_col = vec4(1 - contribAlpha, 1 - contribAlpha, 1 - contribAlpha, 1); OUT_col = vec4(contribAlpha,contribAlpha,contribAlpha, 1);
return; return;
#endif #endif
#if DEBUGVIZ_CONTRIB == 1 #if DEBUGVIZ_CONTRIB == 1
vec3 finalContribColor = vec3(0, 0, 0); vec3 finalContribColor = vec3(0, 0, 0);
float contribAlpha = 1;
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
finalContribColor += contribution[i] *probeContribColors[i].rgb; finalContribColor += contribution[i] * vec3(fmod(i+1,2),fmod(i+1,3),fmod(i+1,4));
contribAlpha -= contribution[i];
} }
//Skylight coloration for anything not covered by probes above
if(skylightCubemapIdx != -1)
finalContribColor += vec3(0, 1, 0) * contribAlpha;
OUT_col = vec4(finalContribColor, 1); OUT_col = vec4(finalContribColor, 1);
return; return;
#endif #endif
@ -188,7 +167,7 @@ void main()
} }
#endif #endif
if (skylightCubemapIdx != -1 && alpha > 0.001) if (skylightCubemapIdx != -1 && alpha >= 0.001)
{ {
irradiance = lerp(irradiance,textureLod(irradianceCubemapAR, vec4(surface.R, skylightCubemapIdx), 0).xyz,alpha); irradiance = lerp(irradiance,textureLod(irradianceCubemapAR, vec4(surface.R, skylightCubemapIdx), 0).xyz,alpha);
specular = lerp(specular,textureLod(specularCubemapAR, vec4(surface.R, skylightCubemapIdx), lod).xyz,alpha); specular = lerp(specular,textureLod(specularCubemapAR, vec4(surface.R, skylightCubemapIdx), lod).xyz,alpha);
@ -220,6 +199,9 @@ void main()
float horizonOcclusion = 1.3; float horizonOcclusion = 1.3;
float horizon = saturate( 1 + horizonOcclusion * dot(surface.R, surface.N)); float horizon = saturate( 1 + horizonOcclusion * dot(surface.R, surface.N));
horizon *= horizon; horizon *= horizon;
#if CAPTURING == 1
OUT_col = vec4(irradiance + specular, 0);//alpha writes disabled OUT_col = vec4(mix(surface.baseColor.rgb,(irradiance + specular) * horizon,surface.metalness/2),0);
#else
OUT_col = vec4((irradiance + specular) * horizon, 0);//alpha writes disabled
#endif
} }

View file

@ -122,6 +122,41 @@ void main()
lightCol *= max(cookie.r, max(cookie.g, cookie.b)); lightCol *= max(cookie.r, max(cookie.g, cookie.b));
#endif #endif
#ifdef DIFFUSE_LIGHT_VIZ
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
vec3 diffuse = BRDF_GetDebugDiffuse(surface,surfaceToLight) * factor;
vec3 final = max(0.0f, diffuse) * getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams );
OUT_col = vec4(final, 0);
return;
#endif
#ifdef SPECULAR_LIGHT_VIZ
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
vec3 diffuse = BRDF_GetDebugSpecular(surface,surfaceToLight) * factor;
vec3 final = max(0.0f, diffuse) * getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams );
OUT_col = vec4(final, 0);
return;
#endif
#ifdef DETAIL_LIGHTING_VIZ
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
vec3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
vec3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
vec3 final = max(vec3(0.0f), diffuse + spec * surface.F) * getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams );
OUT_col = vec4(final, 0);
return;
#endif
//get Punctual light contribution //get Punctual light contribution
lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed); lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
//get spot angle attenuation //get spot angle attenuation

View file

@ -216,7 +216,7 @@ void main()
lightingColor = shadowed_colors.rgb; lightingColor = shadowed_colors.rgb;
#endif #endif
shadow = lerp( shadow, 1.0, saturate( fadeOutAmt ) ); shadow = mix( shadow, 1.0, saturate( fadeOutAmt ) );
#ifdef PSSM_DEBUG_RENDER #ifdef PSSM_DEBUG_RENDER
if ( fadeOutAmt > 1.0 ) if ( fadeOutAmt > 1.0 )
@ -225,6 +225,37 @@ void main()
#endif //NO_SHADOW #endif //NO_SHADOW
#ifdef DIFFUSE_LIGHT_VIZ
vec3 factor = lightingColor.rgb * max(surfaceToLight.NdotL, 0) * shadow * lightBrightness;
vec3 diffuse = BRDF_GetDebugDiffuse(surface,surfaceToLight) * factor;
vec3 final = max(0.0f, diffuse);
OUT_col = vec4(final, 0);
return;
#endif
#ifdef SPECULAR_LIGHT_VIZ
vec3 factor = lightingColor.rgb * max(surfaceToLight.NdotL, 0) * shadow * lightBrightness;
vec3 spec = BRDF_GetDebugSpecular(surface, surfaceToLight) * factor;
vec3 final = max(0.0f, factor);
OUT_col = vec4(final, 0);
return;
#endif
#ifdef DETAIL_LIGHTING_VIZ
vec3 factor = lightingColor.rgb * max(surfaceToLight.NdotL, 0) * shadow * lightBrightness;
vec3 diffuse = BRDF_GetDebugDiffuse(surface,surfaceToLight) * factor;
vec3 spec = BRDF_GetDebugSpecular(surface,surfaceToLight) * factor;
vec3 final = max(0.0f, diffuse + spec);
OUT_col = vec4(final, 0);
return;
#endif
//get directional light contribution //get directional light contribution
vec3 lighting = getDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow); vec3 lighting = getDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow);

View file

@ -134,7 +134,6 @@ uniform float shadowSoftness;
uniform float4x4 worldToCamera; uniform float4x4 worldToCamera;
uniform float3x3 worldToLightProj; uniform float3x3 worldToLightProj;
uniform float3 eyePosWorld;
uniform float4x4 cameraToWorld; uniform float4x4 cameraToWorld;
float4 main( ConvexConnectP IN ) : SV_TARGET float4 main( ConvexConnectP IN ) : SV_TARGET
@ -218,12 +217,12 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
#ifdef DETAIL_LIGHTING_VIZ #ifdef DETAIL_LIGHTING_VIZ
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius); float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation; float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
vec3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor; float3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
vec3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor; float3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
vec3 final = max(vec3(0.0f), diffuse + spec * surface.F); float3 final = max(float3(0.0f), diffuse + spec * surface.F);
return final; return final;
#endif #endif

View file

@ -12,7 +12,6 @@ TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 3);
uniform float4 rtParams0; uniform float4 rtParams0;
uniform float4 vsFarPlane; uniform float4 vsFarPlane;
uniform float4x4 cameraToWorld; uniform float4x4 cameraToWorld;
uniform float3 eyePosWorld;
//cubemap arrays require all the same size. so shared mips# value //cubemap arrays require all the same size. so shared mips# value
uniform float cubeMips; uniform float cubeMips;
@ -76,79 +75,58 @@ float4 main(PFXVertToPix IN) : SV_TARGET
//Process prooooobes //Process prooooobes
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
contribution[i] = 0; contribution[i] = 0.0;
float atten =1.0-(length(eyePosWorld-probePosArray[i].xyz)/maxProbeDrawDistance);
if (probeConfigData[i].r == 0) //box if (probeConfigData[i].r == 0) //box
{ {
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b); contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b)*atten;
if (contribution[i]>0.0)
probehits++;
} }
else if (probeConfigData[i].r == 1) //sphere else if (probeConfigData[i].r == 1) //sphere
{ {
contribution[i] = defineSphereSpaceInfluence(surface.P, probePosArray[i].xyz, probeConfigData[i].g); contribution[i] = defineSphereSpaceInfluence(surface.P, probePosArray[i].xyz, probeConfigData[i].g)*atten;
}
if (contribution[i]>0.0) if (contribution[i]>0.0)
probehits++; probehits++;
} else
contribution[i] = 0.0;
contribution[i] = max(contribution[i],0);
blendSum += contribution[i]; blendSum += contribution[i];
invBlendSum += (1.0f - contribution[i]);
} }
// Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
// And as we invert, we need to divide by Num-1 to stay normalized (else sum is > 1).
// respect constraint B.
// Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary
// and respect constraint A.
if (probehits > 1.0) if (probehits > 1.0)//if we overlap
{ {
invBlendSum = (probehits - blendSum)/(probehits-1); //grab the remainder
for (i = 0; i < numProbes; i++) for (i = 0; i < numProbes; i++)
{ {
blendFactor[i] = ((contribution[i] / blendSum)) / probehits; blendFactor[i] = contribution[i]/blendSum; //what % total is this instance
blendFactor[i] *= ((contribution[i]) / invBlendSum); blendFactor[i] *= blendFactor[i] / invBlendSum; //what should we add to sum to 1
blendFactor[i] = saturate(blendFactor[i]); blendFacSum += blendFactor[i]; //running tally of results
blendFacSum += blendFactor[i];
} }
// Normalize blendVal
if (blendFacSum == 0.0f) // Possible with custom weight
{
blendFacSum = 1.0f;
}
float invBlendSumWeighted = 1.0f / blendFacSum;
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
blendFactor[i] *= invBlendSumWeighted; contribution[i] *= blendFactor[i]/blendFacSum; //normalize
contribution[i] *= blendFactor[i];
} }
} }
#if DEBUGVIZ_ATTENUATION == 1 #if DEBUGVIZ_ATTENUATION == 1
float contribAlpha = 1; float contribAlpha = 0;
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
contribAlpha -= contribution[i]; contribAlpha += contribution[i];
} }
return float4(1 - contribAlpha, 1 - contribAlpha, 1 - contribAlpha, 1); return float4(contribAlpha,contribAlpha,contribAlpha, 1);
#endif #endif
#if DEBUGVIZ_CONTRIB == 1 #if DEBUGVIZ_CONTRIB == 1
float3 finalContribColor = float3(0, 0, 0); float3 finalContribColor = float3(0, 0, 0);
float contribAlpha = 1;
for (i = 0; i < numProbes; ++i) for (i = 0; i < numProbes; ++i)
{ {
finalContribColor += contribution[i] *probeContribColors[i].rgb; finalContribColor += contribution[i] * float3(fmod(i+1,2),fmod(i+1,3),fmod(i+1,4));
contribAlpha -= contribution[i];
} }
//Skylight coloration for anything not covered by probes above
if(skylightCubemapIdx != -1)
finalContribColor += float3(0, 1, 0) * contribAlpha;
return float4(finalContribColor, 1); return float4(finalContribColor, 1);
#endif #endif
} }
@ -209,6 +187,9 @@ float4 main(PFXVertToPix IN) : SV_TARGET
float horizonOcclusion = 1.3; float horizonOcclusion = 1.3;
float horizon = saturate( 1 + horizonOcclusion * dot(surface.R, surface.N)); float horizon = saturate( 1 + horizonOcclusion * dot(surface.R, surface.N));
horizon *= horizon; horizon *= horizon;
#if CAPTURING == 1
return float4(lerp(surface.baseColor.rgb,(irradiance + specular) * horizon,surface.metalness/2),0);
#else
return float4((irradiance + specular) * horizon, 0);//alpha writes disabled return float4((irradiance + specular) * horizon, 0);//alpha writes disabled
#endif
} }

View file

@ -67,7 +67,6 @@ uniform float4x4 worldToLightProj;
uniform float4 lightParams; uniform float4 lightParams;
uniform float shadowSoftness; uniform float shadowSoftness;
uniform float3 eyePosWorld;
uniform float4x4 cameraToWorld; uniform float4x4 cameraToWorld;
uniform float4x4 worldToCamera; uniform float4x4 worldToCamera;
@ -147,12 +146,12 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
#ifdef DETAIL_LIGHTING_VIZ #ifdef DETAIL_LIGHTING_VIZ
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius); float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation; float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
vec3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor; float3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
vec3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor; float3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
vec3 final = max(vec3(0.0f), diffuse + spec * surface.F) * getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams ); vec3 final = max(float3(0.0f), diffuse + spec * surface.F) * getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams );
return final; return final;
#endif #endif

View file

@ -42,7 +42,6 @@ uniform float4 lightColor;
uniform float4 lightAmbient; uniform float4 lightAmbient;
uniform float shadowSoftness; uniform float shadowSoftness;
uniform float3 eyePosWorld;
uniform float4 atlasXOffset; uniform float4 atlasXOffset;
uniform float4 atlasYOffset; uniform float4 atlasYOffset;