mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-16 09:04:38 +00:00
Overhauls the handling of probes to utilize an active probe list to improve performance and allow a greater total number of active probes in a scene.
Also fixes handling of metal materials during bakes to render properly, and fixes a possible double-up return in findObjectByType, which could cause doubling when getting probes in the scene
This commit is contained in:
parent
072b5ecb19
commit
6a3603c737
22 changed files with 490 additions and 610 deletions
|
|
@ -158,11 +158,8 @@ void BoxEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
|
|
||||||
void BoxEnvironmentProbe::updateProbeParams()
|
void BoxEnvironmentProbe::updateProbeParams()
|
||||||
{
|
{
|
||||||
if (!mProbeInfo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mProbeShapeType = ProbeRenderInst::Box;
|
mProbeShapeType = ProbeRenderInst::Box;
|
||||||
mProbeInfo->mAtten = mAtten;
|
mProbeInfo.mAtten = mAtten;
|
||||||
|
|
||||||
Parent::updateProbeParams();
|
Parent::updateProbeParams();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,17 +83,13 @@ ImplementEnumType(ReflectionModeEnum,
|
||||||
{ ReflectionProbe::NoReflection, "No Reflections", "This probe does not provide any local reflection data"},
|
{ ReflectionProbe::NoReflection, "No Reflections", "This probe does not provide any local reflection data"},
|
||||||
{ ReflectionProbe::StaticCubemap, "Static Cubemap", "Uses a static CubemapData" },
|
{ ReflectionProbe::StaticCubemap, "Static Cubemap", "Uses a static CubemapData" },
|
||||||
{ ReflectionProbe::BakedCubemap, "Baked Cubemap", "Uses a cubemap baked from the probe's current position" },
|
{ ReflectionProbe::BakedCubemap, "Baked Cubemap", "Uses a cubemap baked from the probe's current position" },
|
||||||
{ ReflectionProbe::DynamicCubemap, "Dynamic Cubemap", "Uses a cubemap baked from the probe's current position, updated at a set rate" },
|
//{ ReflectionProbe::DynamicCubemap, "Dynamic Cubemap", "Uses a cubemap baked from the probe's current position, updated at a set rate" },
|
||||||
EndImplementEnumType;
|
EndImplementEnumType;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Object setup and teardown
|
// Object setup and teardown
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
ReflectionProbe::ReflectionProbe() :
|
ReflectionProbe::ReflectionProbe()
|
||||||
cubeDescId(0),
|
|
||||||
reflectorDesc(nullptr),
|
|
||||||
mSphereVertCount(0),
|
|
||||||
mSpherePrimitiveCount(0)
|
|
||||||
{
|
{
|
||||||
// Flag this object so that it will always
|
// Flag this object so that it will always
|
||||||
// be sent across the network to clients
|
// be sent across the network to clients
|
||||||
|
|
@ -106,8 +102,7 @@ ReflectionProbe::ReflectionProbe() :
|
||||||
mReflectionModeType = BakedCubemap;
|
mReflectionModeType = BakedCubemap;
|
||||||
|
|
||||||
mEnabled = true;
|
mEnabled = true;
|
||||||
mBake = false;
|
mBakeReflections = false;
|
||||||
mDirty = false;
|
|
||||||
mCubemapDirty = false;
|
mCubemapDirty = false;
|
||||||
|
|
||||||
mRadius = 10;
|
mRadius = 10;
|
||||||
|
|
@ -122,17 +117,14 @@ ReflectionProbe::ReflectionProbe() :
|
||||||
mEditorShapeInst = NULL;
|
mEditorShapeInst = NULL;
|
||||||
mEditorShape = NULL;
|
mEditorShape = NULL;
|
||||||
|
|
||||||
mRefreshRateMS = 500;
|
mRefreshRateMS = 200;
|
||||||
mDynamicLastBakeMS = 0;
|
mDynamicLastBakeMS = 0;
|
||||||
|
|
||||||
mMaxDrawDistance = 75;
|
mMaxDrawDistance = 75;
|
||||||
|
|
||||||
mResourcesCreated = false;
|
mResourcesCreated = false;
|
||||||
|
|
||||||
mProbeInfo = nullptr;
|
|
||||||
|
|
||||||
mPrefilterSize = 64;
|
mPrefilterSize = 64;
|
||||||
mPrefilterMipLevels = mLog2(F32(mPrefilterSize))+1;
|
mPrefilterMipLevels = mLog2(F32(mPrefilterSize));
|
||||||
mPrefilterMap = nullptr;
|
mPrefilterMap = nullptr;
|
||||||
mIrridianceMap = nullptr;
|
mIrridianceMap = nullptr;
|
||||||
|
|
||||||
|
|
@ -158,7 +150,7 @@ void ReflectionProbe::initPersistFields()
|
||||||
{
|
{
|
||||||
addGroup("Rendering");
|
addGroup("Rendering");
|
||||||
addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
|
addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
|
||||||
&_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid");
|
&_setEnabled, &defaultProtectedGetFn, "Is the probe enabled or not");
|
||||||
endGroup("Rendering");
|
endGroup("Rendering");
|
||||||
|
|
||||||
addGroup("Reflection");
|
addGroup("Reflection");
|
||||||
|
|
@ -168,18 +160,18 @@ void ReflectionProbe::initPersistFields()
|
||||||
addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
|
addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
|
||||||
&_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
|
&_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
|
||||||
|
|
||||||
addField("refOffset", TypePoint3F, Offset(mProbeRefOffset, ReflectionProbe), "");
|
addField("refOffset", TypePoint3F, Offset(mProbeRefOffset, ReflectionProbe), "The reference positional offset for the probe. This is used for adjusting the perceived center and area of influence.\nHelpful in adjusting parallax issues");
|
||||||
addField("refScale", TypePoint3F, Offset(mProbeRefScale, ReflectionProbe), "");
|
addField("refScale", TypePoint3F, Offset(mProbeRefScale, ReflectionProbe), "The reference scale for the probe. This is used for adjusting the perceived center and area of influence.\nHelpful in adjusting parallax issues");
|
||||||
|
|
||||||
addProtectedField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe), &_setReflectionMode, &defaultProtectedGetFn,
|
addProtectedField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe), &_setReflectionMode, &defaultProtectedGetFn,
|
||||||
"The type of mesh data to use for collision queries.");
|
"Used to dictate what sort of cubemap the probes use when using IBL.");
|
||||||
|
|
||||||
addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "Cubemap used instead of reflection texture if fullReflect is off.");
|
addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "This is used when a static cubemap is used. The name of the cubemap is looked up and loaded for the IBL calculations.");
|
||||||
|
|
||||||
addField("DynamicReflectionRefreshMS", TypeS32, Offset(mRefreshRateMS, ReflectionProbe), "How often the dynamic cubemap is refreshed in milliseconds. Only works when the ReflectionMode is set to DynamicCubemap.");
|
//addField("DynamicReflectionRefreshMS", TypeS32, Offset(mRefreshRateMS, ReflectionProbe), "How often the dynamic cubemap is refreshed in milliseconds. Only works when the ReflectionMode is set to DynamicCubemap.");
|
||||||
|
|
||||||
addProtectedField("Bake", TypeBool, Offset(mBake, ReflectionProbe),
|
addProtectedField("Bake", TypeBool, Offset(mBakeReflections, ReflectionProbe),
|
||||||
&_doBake, &defaultProtectedGetFn, "Regenerate Voxel Grid", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
|
&_doBake, &defaultProtectedGetFn, "Bake Probe Reflections", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
|
||||||
endGroup("Reflection");
|
endGroup("Reflection");
|
||||||
|
|
||||||
Con::addVariable("$Light::renderReflectionProbes", TypeBool, &RenderProbeMgr::smRenderReflectionProbes,
|
Con::addVariable("$Light::renderReflectionProbes", TypeBool, &RenderProbeMgr::smRenderReflectionProbes,
|
||||||
|
|
@ -319,8 +311,7 @@ void ReflectionProbe::onRemove()
|
||||||
{
|
{
|
||||||
if (isClientObject())
|
if (isClientObject())
|
||||||
{
|
{
|
||||||
PROBEMGR->unregisterProbe(mProbeInfo->mProbeIdx);
|
PROBEMGR->unregisterProbe(mProbeInfo.mProbeIdx);
|
||||||
mProbeInfo = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove this object from the scene
|
// Remove this object from the scene
|
||||||
|
|
@ -436,7 +427,6 @@ U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream
|
||||||
stream->write(mProbeUniqueID);
|
stream->write(mProbeUniqueID);
|
||||||
stream->write((U32)mReflectionModeType);
|
stream->write((U32)mReflectionModeType);
|
||||||
stream->write(mCubemapName);
|
stream->write(mCubemapName);
|
||||||
stream->write(mRefreshRateMS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->writeFlag(mask & EnabledMask))
|
if (stream->writeFlag(mask & EnabledMask))
|
||||||
|
|
@ -463,7 +453,7 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
|
|
||||||
mathRead(*stream, &mProbeRefOffset);
|
mathRead(*stream, &mProbeRefOffset);
|
||||||
mathRead(*stream, &mProbeRefScale);
|
mathRead(*stream, &mProbeRefScale);
|
||||||
|
|
||||||
mDirty = true;
|
mDirty = true;
|
||||||
}
|
}
|
||||||
|
|
@ -490,8 +480,6 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
if(oldReflectModeType != mReflectionModeType || oldCubemapName != mCubemapName)
|
if(oldReflectModeType != mReflectionModeType || oldCubemapName != mCubemapName)
|
||||||
mCubemapDirty = true;
|
mCubemapDirty = true;
|
||||||
|
|
||||||
stream->read(&mRefreshRateMS);
|
|
||||||
|
|
||||||
mDirty = true;
|
mDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,11 +489,6 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
|
|
||||||
mDirty = true;
|
mDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDirty)
|
|
||||||
{
|
|
||||||
updateProbeParams();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -513,12 +496,9 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ReflectionProbe::updateProbeParams()
|
void ReflectionProbe::updateProbeParams()
|
||||||
{
|
{
|
||||||
if (!mProbeInfo)
|
mProbeInfo.mIsEnabled = mEnabled;
|
||||||
return;
|
|
||||||
|
|
||||||
mProbeInfo->mIsEnabled = mEnabled;
|
mProbeInfo.mProbeShapeType = mProbeShapeType;
|
||||||
|
|
||||||
mProbeInfo->mProbeShapeType = mProbeShapeType;
|
|
||||||
|
|
||||||
if (mProbeShapeType == ProbeRenderInst::Sphere)
|
if (mProbeShapeType == ProbeRenderInst::Sphere)
|
||||||
mObjScale.set(mRadius, mRadius, mRadius);
|
mObjScale.set(mRadius, mRadius, mRadius);
|
||||||
|
|
@ -527,10 +507,8 @@ void ReflectionProbe::updateProbeParams()
|
||||||
|
|
||||||
if (mProbeShapeType == ProbeRenderInst::Skylight)
|
if (mProbeShapeType == ProbeRenderInst::Skylight)
|
||||||
{
|
{
|
||||||
mProbeInfo->mPosition = Point3F::Zero;
|
mProbeInfo.mPosition = Point3F::Zero;
|
||||||
mProbeInfo->mTransform = MatrixF::Identity;
|
mProbeInfo.mTransform = MatrixF::Identity;
|
||||||
|
|
||||||
mProbeInfo->mIsSkylight = true;
|
|
||||||
|
|
||||||
F32 visDist = gClientSceneGraph->getVisibleDistance();
|
F32 visDist = gClientSceneGraph->getVisibleDistance();
|
||||||
Box3F skylightBounds = Box3F(visDist * 2);
|
Box3F skylightBounds = Box3F(visDist * 2);
|
||||||
|
|
@ -541,21 +519,19 @@ void ReflectionProbe::updateProbeParams()
|
||||||
|
|
||||||
setGlobalBounds();
|
setGlobalBounds();
|
||||||
|
|
||||||
mProbeInfo->mScore = -1.0f;
|
mProbeInfo.mScore = 10000.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MatrixF transform = getTransform();
|
MatrixF transform = getTransform();
|
||||||
mProbeInfo->mPosition = getPosition();
|
mProbeInfo.mPosition = getPosition();
|
||||||
|
|
||||||
transform.scale(getScale());
|
transform.scale(getScale());
|
||||||
mProbeInfo->mTransform = transform.inverse();
|
mProbeInfo.mTransform = transform.inverse();
|
||||||
|
|
||||||
mProbeInfo->mIsSkylight = false;
|
|
||||||
|
|
||||||
bounds = mWorldBox;
|
bounds = mWorldBox;
|
||||||
|
|
||||||
mProbeInfo->mScore = mMaxDrawDistance;
|
mProbeInfo.mScore = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip our transform... it just dirties mask bits.
|
// Skip our transform... it just dirties mask bits.
|
||||||
|
|
@ -563,14 +539,14 @@ void ReflectionProbe::updateProbeParams()
|
||||||
|
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
|
|
||||||
mProbeInfo->mBounds = bounds;
|
mProbeInfo.mBounds = bounds;
|
||||||
mProbeInfo->mExtents = getScale();
|
mProbeInfo.mExtents = getScale();
|
||||||
mProbeInfo->mRadius = mRadius;
|
mProbeInfo.mRadius = mRadius;
|
||||||
|
|
||||||
mProbeInfo->mProbeRefOffset = mProbeRefOffset;
|
mProbeInfo.mProbeRefOffset = mProbeRefOffset;
|
||||||
mProbeInfo->mProbeRefScale = mProbeRefScale;
|
mProbeInfo.mProbeRefScale = mProbeRefScale;
|
||||||
|
|
||||||
mProbeInfo->mDirty = true;
|
mProbeInfo.mDirty = true;
|
||||||
|
|
||||||
if (mCubemapDirty)
|
if (mCubemapDirty)
|
||||||
{
|
{
|
||||||
|
|
@ -587,108 +563,12 @@ void ReflectionProbe::updateProbeParams()
|
||||||
|
|
||||||
void ReflectionProbe::processDynamicCubemap()
|
void ReflectionProbe::processDynamicCubemap()
|
||||||
{
|
{
|
||||||
/*if (!mProbeInfo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mEnabled = false;
|
|
||||||
|
|
||||||
if (mReflectionModeType == DynamicCubemap && !mDynamicCubemap.isNull())
|
|
||||||
{
|
|
||||||
mProbeInfo->mPrefilterCubemap = mDynamicCubemap;
|
|
||||||
|
|
||||||
if (reflectorDesc == nullptr)
|
|
||||||
{
|
|
||||||
//find it
|
|
||||||
if (!Sim::findObject("DefaultCubeDesc", reflectorDesc))
|
|
||||||
{
|
|
||||||
mProbeInfo->mIsEnabled = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mCubeReflector.unregisterReflector();
|
|
||||||
mCubeReflector.registerReflector(this, reflectorDesc); //need to decide how we wanna do the reflectorDesc. static name or a field
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mEnabled)
|
|
||||||
mProbeInfo->mIsEnabled = true;
|
|
||||||
else
|
|
||||||
mProbeInfo->mIsEnabled = false;
|
|
||||||
|
|
||||||
mCubemapDirty = false;
|
|
||||||
|
|
||||||
//Update the probe manager with our new texture!
|
|
||||||
//if (!mProbeInfo->mIsSkylight && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized())
|
|
||||||
// PROBEMGR->updateProbeTexture(mProbeInfo->mProbeIdx);*/
|
|
||||||
|
|
||||||
if (!mProbeInfo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mProbeInfo->mIsEnabled = false;
|
|
||||||
|
|
||||||
if (mReflectionModeType != DynamicCubemap)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (reflectorDesc == nullptr)
|
|
||||||
{
|
|
||||||
//find it
|
|
||||||
if (!Sim::findObject("DefaultCubeDesc", reflectorDesc))
|
|
||||||
{
|
|
||||||
mProbeInfo->mIsEnabled = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCubeReflector.unregisterReflector();
|
|
||||||
mCubeReflector.registerReflector(this, reflectorDesc); //need to decide how we wanna do the reflectorDesc. static name or a field
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCubeReflector.getCubemap())
|
|
||||||
{
|
|
||||||
U32 resolution = Con::getIntVariable("$pref::ReflectionProbes::BakeResolution", 64);
|
|
||||||
U32 prefilterMipLevels = mLog2(F32(resolution))+1;
|
|
||||||
|
|
||||||
//Prep it with whatever resolution we've dictated for our bake
|
|
||||||
mIrridianceMap->mCubemap->initDynamic(resolution, PROBEMGR->PROBE_FORMAT);
|
|
||||||
mPrefilterMap->mCubemap->initDynamic(resolution, PROBEMGR->PROBE_FORMAT);
|
|
||||||
|
|
||||||
GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
|
|
||||||
|
|
||||||
IBLUtilities::GenerateIrradianceMap(renderTarget, mCubeReflector.getCubemap(), mIrridianceMap->mCubemap);
|
|
||||||
IBLUtilities::GeneratePrefilterMap(renderTarget, mCubeReflector.getCubemap(), prefilterMipLevels, mPrefilterMap->mCubemap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIrridianceMap == nullptr || mIrridianceMap->mCubemap.isNull())
|
|
||||||
{
|
|
||||||
Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPrefilterMap == nullptr || mPrefilterMap->mCubemap.isNull())
|
|
||||||
{
|
|
||||||
Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mProbeInfo->mPrefilterCubemap = mPrefilterMap->mCubemap;
|
|
||||||
mProbeInfo->mIrradianceCubemap = mIrridianceMap->mCubemap;
|
|
||||||
|
|
||||||
if (mEnabled && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized())
|
|
||||||
{
|
|
||||||
mProbeInfo->mIsEnabled = true;
|
|
||||||
|
|
||||||
mCubemapDirty = false;
|
|
||||||
|
|
||||||
//Update the probe manager with our new texture!
|
|
||||||
PROBEMGR->updateProbeTexture(mProbeInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReflectionProbe::processBakedCubemap()
|
void ReflectionProbe::processBakedCubemap()
|
||||||
{
|
{
|
||||||
if (!mProbeInfo)
|
mProbeInfo.mIsEnabled = false;
|
||||||
return;
|
|
||||||
|
|
||||||
mProbeInfo->mIsEnabled = false;
|
|
||||||
|
|
||||||
if ((mReflectionModeType != BakedCubemap) || mProbeUniqueID.isEmpty())
|
if ((mReflectionModeType != BakedCubemap) || mProbeUniqueID.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
@ -700,7 +580,7 @@ void ReflectionProbe::processBakedCubemap()
|
||||||
mIrridianceMap->updateFaces();
|
mIrridianceMap->updateFaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIrridianceMap == nullptr || !mIrridianceMap->mCubemap->isInitialized())
|
if (mIrridianceMap == nullptr || mIrridianceMap->mCubemap.isNull())
|
||||||
{
|
{
|
||||||
Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str());
|
Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str());
|
||||||
return;
|
return;
|
||||||
|
|
@ -713,32 +593,33 @@ void ReflectionProbe::processBakedCubemap()
|
||||||
mPrefilterMap->updateFaces();
|
mPrefilterMap->updateFaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPrefilterMap == nullptr || !mPrefilterMap->mCubemap->isInitialized())
|
if (mPrefilterMap == nullptr || mPrefilterMap->mCubemap.isNull())
|
||||||
{
|
{
|
||||||
Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str());
|
Con::errorf("ReflectionProbe::processDynamicCubemap() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mProbeInfo->mPrefilterCubemap = mPrefilterMap->mCubemap;
|
mProbeInfo.mPrefilterCubemap = mPrefilterMap->mCubemap;
|
||||||
mProbeInfo->mIrradianceCubemap = mIrridianceMap->mCubemap;
|
mProbeInfo.mIrradianceCubemap = mIrridianceMap->mCubemap;
|
||||||
|
|
||||||
if (mEnabled && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized())
|
if (mEnabled && mProbeInfo.mPrefilterCubemap->isInitialized() && mProbeInfo.mIrradianceCubemap->isInitialized())
|
||||||
{
|
{
|
||||||
mProbeInfo->mIsEnabled = true;
|
mProbeInfo.mIsEnabled = true;
|
||||||
|
|
||||||
mCubemapDirty = false;
|
mCubemapDirty = false;
|
||||||
|
|
||||||
//Update the probe manager with our new texture!
|
//Update the probe manager with our new texture!
|
||||||
PROBEMGR->updateProbeTexture(mProbeInfo);
|
PROBEMGR->updateProbeTexture(&mProbeInfo);
|
||||||
|
|
||||||
|
//now, cleanup
|
||||||
|
mProbeInfo.mPrefilterCubemap.free();
|
||||||
|
mProbeInfo.mIrradianceCubemap.free();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReflectionProbe::processStaticCubemap()
|
void ReflectionProbe::processStaticCubemap()
|
||||||
{
|
{
|
||||||
if (!mProbeInfo)
|
mProbeInfo.mIsEnabled = false;
|
||||||
return;
|
|
||||||
|
|
||||||
mProbeInfo->mIsEnabled = false;
|
|
||||||
|
|
||||||
String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
|
String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
|
||||||
|
|
||||||
|
|
@ -747,45 +628,31 @@ void ReflectionProbe::processStaticCubemap()
|
||||||
|
|
||||||
if (Platform::isFile(irradFileName))
|
if (Platform::isFile(irradFileName))
|
||||||
{
|
{
|
||||||
if (mIrridianceMap == nullptr)
|
|
||||||
{
|
|
||||||
Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked irradiance map at %s", irradFileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mIrridianceMap->setCubemapFile(FileName(irradFileName));
|
mIrridianceMap->setCubemapFile(FileName(irradFileName));
|
||||||
|
|
||||||
if (mIrridianceMap->mCubemap.isNull())
|
|
||||||
{
|
|
||||||
Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked irradiance map at %s", irradFileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mIrridianceMap->updateFaces();
|
mIrridianceMap->updateFaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mIrridianceMap == nullptr || mIrridianceMap->mCubemap.isNull())
|
||||||
|
{
|
||||||
|
Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked irradiance map at %s", irradFileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char prefilterFileName[256];
|
char prefilterFileName[256];
|
||||||
dSprintf(prefilterFileName, 256, "%s%s_Prefilter.dds", path.c_str(), mCubemapName.c_str());
|
dSprintf(prefilterFileName, 256, "%s%s_Prefilter.dds", path.c_str(), mCubemapName.c_str());
|
||||||
|
|
||||||
if (Platform::isFile(prefilterFileName))
|
if (Platform::isFile(prefilterFileName))
|
||||||
{
|
{
|
||||||
if (mPrefilterMap == nullptr)
|
|
||||||
{
|
|
||||||
Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked prefilter map at %s", prefilterFileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPrefilterMap->setCubemapFile(FileName(prefilterFileName));
|
mPrefilterMap->setCubemapFile(FileName(prefilterFileName));
|
||||||
|
|
||||||
if (mPrefilterMap->mCubemap.isNull())
|
|
||||||
{
|
|
||||||
Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked prefilter map at %s", prefilterFileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPrefilterMap->updateFaces();
|
mPrefilterMap->updateFaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mPrefilterMap == nullptr || mPrefilterMap->mCubemap.isNull())
|
||||||
|
{
|
||||||
|
Con::errorf("ReflectionProbe::processStaticCubemap() - Unable to load baked prefilter map at %s", prefilterFileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Platform::isFile(prefilterFileName) || !Platform::isFile(irradFileName))
|
if (!Platform::isFile(prefilterFileName) || !Platform::isFile(irradFileName))
|
||||||
{
|
{
|
||||||
//If we are missing either of the files, just re-run the bake
|
//If we are missing either of the files, just re-run the bake
|
||||||
|
|
@ -823,34 +690,29 @@ void ReflectionProbe::processStaticCubemap()
|
||||||
IBLUtilities::SaveCubeMap(prefilterFileName, mPrefilterMap->mCubemap);
|
IBLUtilities::SaveCubeMap(prefilterFileName, mPrefilterMap->mCubemap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mIrridianceMap != nullptr && !mIrridianceMap->mCubemap.isNull()) && (mPrefilterMap != nullptr && !mPrefilterMap->mCubemap.isNull()))
|
if ((mIrridianceMap != nullptr || !mIrridianceMap->mCubemap.isNull()) && (mPrefilterMap != nullptr || !mPrefilterMap->mCubemap.isNull()))
|
||||||
{
|
{
|
||||||
mProbeInfo->mPrefilterCubemap = mPrefilterMap->mCubemap;
|
mProbeInfo.mPrefilterCubemap = mPrefilterMap->mCubemap;
|
||||||
mProbeInfo->mIrradianceCubemap = mIrridianceMap->mCubemap;
|
mProbeInfo.mIrradianceCubemap = mIrridianceMap->mCubemap;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mEnabled && mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized())
|
if (mEnabled && mProbeInfo.mPrefilterCubemap->isInitialized() && mProbeInfo.mIrradianceCubemap->isInitialized())
|
||||||
{
|
{
|
||||||
mProbeInfo->mIsEnabled = true;
|
mProbeInfo.mIsEnabled = true;
|
||||||
|
|
||||||
mCubemapDirty = false;
|
mCubemapDirty = false;
|
||||||
|
|
||||||
//Update the probe manager with our new texture!
|
//Update the probe manager with our new texture!
|
||||||
PROBEMGR->updateProbeTexture(mProbeInfo);
|
PROBEMGR->updateProbeTexture(&mProbeInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReflectionProbe::createClientResources()
|
bool ReflectionProbe::createClientResources()
|
||||||
{
|
{
|
||||||
if (mProbeInfo == nullptr)
|
PROBEMGR->registerProbe(&mProbeInfo);
|
||||||
{
|
|
||||||
mProbeInfo = PROBEMGR->registerProbe();
|
|
||||||
if (!mProbeInfo)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
mProbeInfo->mIsEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mProbeInfo.mIsEnabled = false;
|
||||||
|
|
||||||
//irridiance resources
|
//irridiance resources
|
||||||
if (!mIrridianceMap)
|
if (!mIrridianceMap)
|
||||||
{
|
{
|
||||||
|
|
@ -909,12 +771,10 @@ String ReflectionProbe::getIrradianceMapPath()
|
||||||
|
|
||||||
void ReflectionProbe::bake()
|
void ReflectionProbe::bake()
|
||||||
{
|
{
|
||||||
bool writeFile = mReflectionModeType == BakedCubemap ? true : false;
|
if (mReflectionModeType != BakedCubemap)
|
||||||
|
|
||||||
if (mReflectionModeType == StaticCubemap)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PROBEMGR->bakeProbe(this, writeFile);
|
PROBEMGR->bakeProbe(this);
|
||||||
|
|
||||||
setMaskBits(-1);
|
setMaskBits(-1);
|
||||||
}
|
}
|
||||||
|
|
@ -922,8 +782,9 @@ void ReflectionProbe::bake()
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//Rendering of editing/debug stuff
|
//Rendering of editing/debug stuff
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ReflectionProbe::createGeometry()
|
void ReflectionProbe::createEditorResources()
|
||||||
{
|
{
|
||||||
|
#ifdef TORQUE_TOOLS
|
||||||
// Clean up our previous shape
|
// Clean up our previous shape
|
||||||
if (mEditorShapeInst)
|
if (mEditorShapeInst)
|
||||||
SAFE_DELETE(mEditorShapeInst);
|
SAFE_DELETE(mEditorShapeInst);
|
||||||
|
|
@ -938,6 +799,7 @@ void ReflectionProbe::createGeometry()
|
||||||
{
|
{
|
||||||
mEditorShapeInst = new TSShapeInstance(mEditorShape, isClientObject());
|
mEditorShapeInst = new TSShapeInstance(mEditorShape, isClientObject());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReflectionProbe::prepRenderImage(SceneRenderState *state)
|
void ReflectionProbe::prepRenderImage(SceneRenderState *state)
|
||||||
|
|
@ -951,16 +813,14 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
|
||||||
//Culling distance. Can be adjusted for performance options considerations via the scalar
|
//Culling distance. Can be adjusted for performance options considerations via the scalar
|
||||||
if (dist > mMaxDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0))
|
if (dist > mMaxDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0))
|
||||||
{
|
{
|
||||||
mProbeInfo->mScore = mMaxDrawDistance;
|
mProbeInfo.mScore = mMaxDrawDistance;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS))
|
if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS))
|
||||||
{
|
{
|
||||||
//bake();
|
bake();
|
||||||
mDynamicLastBakeMS = Platform::getRealMilliseconds();
|
mDynamicLastBakeMS = Platform::getRealMilliseconds();
|
||||||
|
|
||||||
processDynamicCubemap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Submit our probe to actually do the probe action
|
//Submit our probe to actually do the probe action
|
||||||
|
|
@ -968,20 +828,20 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
|
||||||
//RenderPassManager *renderPass = state->getRenderPass();
|
//RenderPassManager *renderPass = state->getRenderPass();
|
||||||
|
|
||||||
//Update our score based on our radius, distance
|
//Update our score based on our radius, distance
|
||||||
mProbeInfo->mScore = mProbeInfo->mRadius/mMax(dist,1.0f);
|
mProbeInfo.mScore = mMax(dist, 1.0f);
|
||||||
|
|
||||||
Point3F vect = distVec;
|
Point3F vect = distVec;
|
||||||
vect.normalizeSafe();
|
vect.normalizeSafe();
|
||||||
|
|
||||||
mProbeInfo->mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f);
|
//mProbeInfo.mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f);
|
||||||
|
|
||||||
//Register
|
PROBEMGR->submitProbe(mProbeInfo);
|
||||||
//PROBEMGR->registerProbe(mProbeInfoIdx);
|
|
||||||
|
|
||||||
|
#ifdef TORQUE_TOOLS
|
||||||
if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mPrefilterMap != nullptr)
|
if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mPrefilterMap != nullptr)
|
||||||
{
|
{
|
||||||
if(!mEditorShapeInst)
|
if(!mEditorShapeInst)
|
||||||
createGeometry();
|
createEditorResources();
|
||||||
|
|
||||||
GFXTransformSaver saver;
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
|
@ -1039,7 +899,7 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
|
||||||
saver.restore();
|
saver.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the light is selected or light visualization
|
// If the probe is selected or probe visualization
|
||||||
// is enabled then register the callback.
|
// is enabled then register the callback.
|
||||||
const bool isSelectedInEditor = (gEditingMission && isSelected());
|
const bool isSelectedInEditor = (gEditingMission && isSelected());
|
||||||
if (isSelectedInEditor)
|
if (isSelectedInEditor)
|
||||||
|
|
@ -1049,6 +909,7 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
|
||||||
ri->type = RenderPassManager::RIT_Editor;
|
ri->type = RenderPassManager::RIT_Editor;
|
||||||
state->getRenderPass()->addInst(ri);
|
state->getRenderPass()->addInst(ri);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
|
void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
|
||||||
|
|
@ -1127,7 +988,7 @@ DefineEngineMethod(ReflectionProbe, postApply, void, (), ,
|
||||||
}
|
}
|
||||||
|
|
||||||
DefineEngineMethod(ReflectionProbe, Bake, void, (), ,
|
DefineEngineMethod(ReflectionProbe, Bake, void, (), ,
|
||||||
"@brief returns true if control object is inside the fog\n\n.")
|
"@brief Bakes the cubemaps for a reflection probe\n\n.")
|
||||||
{
|
{
|
||||||
ReflectionProbe *clientProbe = (ReflectionProbe*)object->getClientObject();
|
ReflectionProbe *clientProbe = (ReflectionProbe*)object->getClientObject();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,9 @@ class ReflectionProbe : public SceneObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to dictate what sort of cubemap the probes use when using IBL
|
||||||
|
/// </summary>
|
||||||
enum ReflectionModeType
|
enum ReflectionModeType
|
||||||
{
|
{
|
||||||
NoReflection = 0,
|
NoReflection = 0,
|
||||||
|
|
@ -87,36 +90,84 @@ protected:
|
||||||
NextFreeMask = Parent::NextFreeMask << 3
|
NextFreeMask = Parent::NextFreeMask << 3
|
||||||
};
|
};
|
||||||
|
|
||||||
bool mBake;
|
/// <summary>
|
||||||
|
/// Only used for interfacing with the editor's inspector bake button
|
||||||
|
/// </summary>
|
||||||
|
bool mBakeReflections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this probe is enabled or not
|
||||||
|
/// </summary>
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
|
|
||||||
bool mDirty;
|
bool mDirty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this probe's cubemap is dirty or not
|
||||||
|
/// </summary>
|
||||||
bool mCubemapDirty;
|
bool mCubemapDirty;
|
||||||
|
|
||||||
|
#ifdef TORQUE_TOOLS
|
||||||
|
/// <summary>
|
||||||
|
/// Used only when the editor is loaded, this is the shape data used for the probe viewing(aka, a sphere)
|
||||||
|
/// </summary>
|
||||||
Resource<TSShape> mEditorShape;
|
Resource<TSShape> mEditorShape;
|
||||||
|
/// <summary>
|
||||||
|
/// This is the shape instance of the editor shape data
|
||||||
|
/// </summary>
|
||||||
TSShapeInstance* mEditorShapeInst;
|
TSShapeInstance* mEditorShapeInst;
|
||||||
|
#endif // TORQUE_TOOLS
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Rendering variables
|
// Rendering variables
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// The shape of the probe
|
||||||
|
/// </summary>
|
||||||
ProbeRenderInst::ProbeShapeType mProbeShapeType;
|
ProbeRenderInst::ProbeShapeType mProbeShapeType;
|
||||||
|
|
||||||
ProbeRenderInst* mProbeInfo;
|
/// <summary>
|
||||||
|
/// This is effectively a packed cache of the probe data actually utilized for rendering.
|
||||||
|
/// The RenderProbeManager uses this via the probe calling registerProbe on creation, and unregisterProbe on destruction
|
||||||
|
/// When the manager goes to render it has the compacted data to read over more efficiently for setting up what probes should
|
||||||
|
/// Actually render in that frame
|
||||||
|
/// </summary>
|
||||||
|
ProbeRenderInst mProbeInfo;
|
||||||
|
|
||||||
//Reflection Contribution stuff
|
/// <summary>
|
||||||
|
/// Used to dictate what sort of cubemap the probes use when using IBL
|
||||||
|
/// </summary>
|
||||||
ReflectionModeType mReflectionModeType;
|
ReflectionModeType mReflectionModeType;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The radius of the probe's influence. Only really relevent in Sphere probes
|
||||||
|
/// </summary>
|
||||||
F32 mRadius;
|
F32 mRadius;
|
||||||
|
/// <summary>
|
||||||
|
/// The reference positional offset for the probe. This is used for adjusting the perceived center and area of influence.
|
||||||
|
/// Helpful in adjusting parallax issues
|
||||||
|
/// </summary>
|
||||||
Point3F mProbeRefOffset;
|
Point3F mProbeRefOffset;
|
||||||
|
/// <summary>
|
||||||
|
/// The reference scale for the probe. This is used for adjusting the perceived center and area of influence.
|
||||||
|
/// Helpful in adjusting parallax issues
|
||||||
|
/// </summary>
|
||||||
Point3F mProbeRefScale;
|
Point3F mProbeRefScale;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only used for interfacing with the editor's inspector edit offset button
|
||||||
|
/// </summary>
|
||||||
bool mEditPosOffset;
|
bool mEditPosOffset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is used when a static cubemap is used. The name of the cubemap is looked up and loaded for the IBL calculations
|
||||||
|
/// </summary>
|
||||||
String mCubemapName;
|
String mCubemapName;
|
||||||
CubemapData *mStaticCubemap;
|
CubemapData *mStaticCubemap;
|
||||||
GFXCubemapHandle mDynamicCubemap;
|
GFXCubemapHandle mDynamicCubemap;
|
||||||
|
|
||||||
String cubeDescName;
|
String cubeDescName;
|
||||||
U32 cubeDescId;
|
U32 cubeDescId;
|
||||||
CubeReflector mCubeReflector;
|
|
||||||
ReflectorDesc *reflectorDesc;
|
ReflectorDesc *reflectorDesc;
|
||||||
|
|
||||||
//Utilized in dynamic reflections
|
//Utilized in dynamic reflections
|
||||||
|
|
@ -133,19 +184,12 @@ protected:
|
||||||
U32 mPrefilterMipLevels;
|
U32 mPrefilterMipLevels;
|
||||||
U32 mPrefilterSize;
|
U32 mPrefilterSize;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is calculated based on the object's persistantID. Effectively a unique hash ID to set it apart from other probes
|
||||||
|
/// Used to ensure the cubemaps named when baking are unique
|
||||||
|
/// </summary>
|
||||||
String mProbeUniqueID;
|
String mProbeUniqueID;
|
||||||
|
|
||||||
// Define our vertex format here so we don't have to
|
|
||||||
// change it in multiple spots later
|
|
||||||
typedef GFXVertexPNTTB VertexType;
|
|
||||||
|
|
||||||
// The GFX vertex and primitive buffers
|
|
||||||
GFXVertexBufferHandle< VertexType > mVertexBuffer;
|
|
||||||
GFXPrimitiveBufferHandle mPrimitiveBuffer;
|
|
||||||
|
|
||||||
U32 mSphereVertCount;
|
|
||||||
U32 mSpherePrimitiveCount;
|
|
||||||
|
|
||||||
//Debug rendering
|
//Debug rendering
|
||||||
static bool smRenderPreviewProbes;
|
static bool smRenderPreviewProbes;
|
||||||
|
|
||||||
|
|
@ -188,6 +232,10 @@ public:
|
||||||
bool onAdd();
|
bool onAdd();
|
||||||
void onRemove();
|
void onRemove();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is called when the object is deleted. It allows us to do special-case cleanup actions
|
||||||
|
/// In probes' case, it's used to delete baked cubemap files
|
||||||
|
/// </summary>
|
||||||
virtual void handleDeleteAction();
|
virtual void handleDeleteAction();
|
||||||
|
|
||||||
// Override this so that we can dirty the network flag when it is called
|
// Override this so that we can dirty the network flag when it is called
|
||||||
|
|
@ -215,14 +263,26 @@ public:
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
// Create the geometry for rendering
|
// Create the geometry for rendering
|
||||||
void createGeometry();
|
void createEditorResources();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the probe rendering data
|
||||||
|
/// </summary>
|
||||||
virtual void updateProbeParams();
|
virtual void updateProbeParams();
|
||||||
|
|
||||||
bool createClientResources();
|
bool createClientResources();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the probe's cubemaps in the array when using dynamic reflections
|
||||||
|
/// </summary>
|
||||||
void processDynamicCubemap();
|
void processDynamicCubemap();
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the probe's cubemaps in the array when using baked cubemaps
|
||||||
|
/// </summary>
|
||||||
void processBakedCubemap();
|
void processBakedCubemap();
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the probe's cubemaps in the array when using a static cubemaps
|
||||||
|
/// </summary>
|
||||||
void processStaticCubemap();
|
void processStaticCubemap();
|
||||||
|
|
||||||
// This is the function that allows this object to submit itself for rendering
|
// This is the function that allows this object to submit itself for rendering
|
||||||
|
|
@ -234,9 +294,22 @@ public:
|
||||||
|
|
||||||
void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
|
void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
|
||||||
|
|
||||||
//Baking
|
/// <summary>
|
||||||
|
/// This gets the filepath to the prefilter cubemap associated to this probe.
|
||||||
|
/// In the event the probe is set to use a static cubemap, it is the prefiltered version of the cubemap's file
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The filepath to the prefilter cubemap</returns>
|
||||||
String getPrefilterMapPath();
|
String getPrefilterMapPath();
|
||||||
|
/// <summary>
|
||||||
|
/// This gets the filepath to the irradiance cubemap associated to this probe.
|
||||||
|
/// In the event the probe is set to use a static cubemap, it is the irradiance version of the cubemap's file
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The filepath to the irradiance cubemap</returns>
|
||||||
String getIrradianceMapPath();
|
String getIrradianceMapPath();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes a cubemap bake action for this probe
|
||||||
|
/// </summary>
|
||||||
void bake();
|
void bake();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,11 @@ void Skylight::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
{
|
{
|
||||||
// Let the Parent read any info it sent
|
// Let the Parent read any info it sent
|
||||||
Parent::unpackUpdate(conn, stream);
|
Parent::unpackUpdate(conn, stream);
|
||||||
|
|
||||||
|
if (mDirty)
|
||||||
|
{
|
||||||
|
updateProbeParams();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -143,9 +148,6 @@ void Skylight::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
|
|
||||||
void Skylight::updateProbeParams()
|
void Skylight::updateProbeParams()
|
||||||
{
|
{
|
||||||
if (!mProbeInfo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mProbeShapeType = ProbeRenderInst::Skylight;
|
mProbeShapeType = ProbeRenderInst::Skylight;
|
||||||
Parent::updateProbeParams();
|
Parent::updateProbeParams();
|
||||||
}
|
}
|
||||||
|
|
@ -157,24 +159,17 @@ void Skylight::prepRenderImage(SceneRenderState *state)
|
||||||
|
|
||||||
//special hook-in for skylights
|
//special hook-in for skylights
|
||||||
Point3F camPos = state->getCameraPosition();
|
Point3F camPos = state->getCameraPosition();
|
||||||
mProbeInfo->mBounds.setCenter(camPos);
|
mProbeInfo.mBounds.setCenter(camPos);
|
||||||
|
|
||||||
mProbeInfo->setPosition(camPos);
|
mProbeInfo.setPosition(camPos);
|
||||||
|
|
||||||
if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS))
|
|
||||||
{
|
|
||||||
//bake();
|
|
||||||
mDynamicLastBakeMS = Platform::getRealMilliseconds();
|
|
||||||
|
|
||||||
processDynamicCubemap();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Submit our probe to actually do the probe action
|
//Submit our probe to actually do the probe action
|
||||||
// Get a handy pointer to our RenderPassmanager
|
// Get a handy pointer to our RenderPassmanager
|
||||||
//RenderPassManager *renderPass = state->getRenderPass();
|
//RenderPassManager *renderPass = state->getRenderPass();
|
||||||
|
|
||||||
//PROBEMGR->registerSkylight(mProbeInfo, this);
|
PROBEMGR->submitProbe(mProbeInfo);
|
||||||
|
|
||||||
|
#ifdef TORQUE_TOOLS
|
||||||
if (Skylight::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
|
if (Skylight::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
|
||||||
{
|
{
|
||||||
GFXTransformSaver saver;
|
GFXTransformSaver saver;
|
||||||
|
|
@ -235,6 +230,7 @@ void Skylight::prepRenderImage(SceneRenderState *state)
|
||||||
if (isSelectedInEditor)
|
if (isSelectedInEditor)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skylight::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
|
void Skylight::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,11 @@ void SphereEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream
|
||||||
{
|
{
|
||||||
// Let the Parent read any info it sent
|
// Let the Parent read any info it sent
|
||||||
Parent::unpackUpdate(conn, stream);
|
Parent::unpackUpdate(conn, stream);
|
||||||
|
|
||||||
|
if (mDirty)
|
||||||
|
{
|
||||||
|
updateProbeParams();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -139,9 +144,6 @@ void SphereEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream
|
||||||
|
|
||||||
void SphereEnvironmentProbe::updateProbeParams()
|
void SphereEnvironmentProbe::updateProbeParams()
|
||||||
{
|
{
|
||||||
if (!mProbeInfo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mProbeShapeType = ProbeRenderInst::Sphere;
|
mProbeShapeType = ProbeRenderInst::Sphere;
|
||||||
Parent::updateProbeParams();
|
Parent::updateProbeParams();
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +153,7 @@ void SphereEnvironmentProbe::prepRenderImage(SceneRenderState *state)
|
||||||
if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
|
if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef TORQUE_TOOLS
|
||||||
if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
|
if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
|
||||||
{
|
{
|
||||||
GFXTransformSaver saver;
|
GFXTransformSaver saver;
|
||||||
|
|
@ -215,6 +218,7 @@ void SphereEnvironmentProbe::prepRenderImage(SceneRenderState *state)
|
||||||
ri->type = RenderPassManager::RIT_Editor;
|
ri->type = RenderPassManager::RIT_Editor;
|
||||||
state->getRenderPass()->addInst(ri);
|
state->getRenderPass()->addInst(ri);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SphereEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
|
void SphereEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ void SimSet::findObjectByType( Vector<T*> &foundObjects )
|
||||||
curSet = dynamic_cast<SimSet*>( *itr );
|
curSet = dynamic_cast<SimSet*>( *itr );
|
||||||
|
|
||||||
// If child object is a set, call recursively into it.
|
// If child object is a set, call recursively into it.
|
||||||
if ( curSet )
|
if ( curSet && curSet->size() != 0)
|
||||||
curSet->findObjectByType( foundObjects );
|
curSet->findObjectByType( foundObjects );
|
||||||
|
|
||||||
// Add this child object if appropriate.
|
// Add this child object if appropriate.
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@
|
||||||
//For our cameraQuery setup
|
//For our cameraQuery setup
|
||||||
#include "T3D/gameTSCtrl.h"
|
#include "T3D/gameTSCtrl.h"
|
||||||
|
|
||||||
|
#include "T3D/Scene.h"
|
||||||
|
|
||||||
#define TORQUE_GFX_VISUAL_DEBUG //renderdoc debugging
|
#define TORQUE_GFX_VISUAL_DEBUG //renderdoc debugging
|
||||||
|
|
||||||
IMPLEMENT_CONOBJECT(RenderProbeMgr);
|
IMPLEMENT_CONOBJECT(RenderProbeMgr);
|
||||||
|
|
@ -59,6 +61,8 @@ ConsoleDocClass( RenderProbeMgr,
|
||||||
RenderProbeMgr *RenderProbeMgr::smProbeManager = NULL;
|
RenderProbeMgr *RenderProbeMgr::smProbeManager = NULL;
|
||||||
|
|
||||||
bool RenderProbeMgr::smRenderReflectionProbes = true;
|
bool RenderProbeMgr::smRenderReflectionProbes = true;
|
||||||
|
F32 RenderProbeMgr::smMaxProbeDrawDistance = 100;
|
||||||
|
S32 RenderProbeMgr::smMaxProbesPerFrame = 8;
|
||||||
|
|
||||||
S32 QSORT_CALLBACK AscendingReflectProbeInfluence(const void* a, const void* b)
|
S32 QSORT_CALLBACK AscendingReflectProbeInfluence(const void* a, const void* b)
|
||||||
{
|
{
|
||||||
|
|
@ -87,7 +91,6 @@ ProbeRenderInst::ProbeRenderInst() :
|
||||||
mProbeRefScale(1,1,1),
|
mProbeRefScale(1,1,1),
|
||||||
mAtten(0.0),
|
mAtten(0.0),
|
||||||
mCubemapIndex(0),
|
mCubemapIndex(0),
|
||||||
mIsSkylight(false),
|
|
||||||
mProbeIdx(0),
|
mProbeIdx(0),
|
||||||
mProbeShapeType(Box)
|
mProbeShapeType(Box)
|
||||||
{
|
{
|
||||||
|
|
@ -113,7 +116,6 @@ void ProbeRenderInst::set(const ProbeRenderInst *probeInfo)
|
||||||
mRadius = probeInfo->mRadius;
|
mRadius = probeInfo->mRadius;
|
||||||
mProbeShapeType = probeInfo->mProbeShapeType;
|
mProbeShapeType = probeInfo->mProbeShapeType;
|
||||||
mBounds = probeInfo->mBounds;
|
mBounds = probeInfo->mBounds;
|
||||||
mIsSkylight = probeInfo->mIsSkylight;
|
|
||||||
mScore = probeInfo->mScore;
|
mScore = probeInfo->mScore;
|
||||||
mAtten = probeInfo->mAtten;
|
mAtten = probeInfo->mAtten;
|
||||||
}
|
}
|
||||||
|
|
@ -125,8 +127,7 @@ ProbeShaderConstants::ProbeShaderConstants()
|
||||||
mShader(NULL),
|
mShader(NULL),
|
||||||
mProbePositionSC(NULL),
|
mProbePositionSC(NULL),
|
||||||
mProbeRefPosSC(NULL),
|
mProbeRefPosSC(NULL),
|
||||||
mRefBoxMinSC(NULL),
|
mRefScaleSC(NULL),
|
||||||
mRefBoxMaxSC(NULL),
|
|
||||||
mProbeConfigDataSC(NULL),
|
mProbeConfigDataSC(NULL),
|
||||||
mProbeSpecularCubemapSC(NULL),
|
mProbeSpecularCubemapSC(NULL),
|
||||||
mProbeIrradianceCubemapSC(NULL),
|
mProbeIrradianceCubemapSC(NULL),
|
||||||
|
|
@ -160,8 +161,7 @@ void ProbeShaderConstants::init(GFXShader* shader)
|
||||||
//Reflection Probes
|
//Reflection Probes
|
||||||
mProbePositionSC = shader->getShaderConstHandle(ShaderGenVars::probePosition);
|
mProbePositionSC = shader->getShaderConstHandle(ShaderGenVars::probePosition);
|
||||||
mProbeRefPosSC = shader->getShaderConstHandle(ShaderGenVars::probeRefPos);
|
mProbeRefPosSC = shader->getShaderConstHandle(ShaderGenVars::probeRefPos);
|
||||||
mRefBoxMinSC = shader->getShaderConstHandle(ShaderGenVars::refBoxMin);
|
mRefScaleSC = shader->getShaderConstHandle(ShaderGenVars::refScale);
|
||||||
mRefBoxMaxSC = shader->getShaderConstHandle(ShaderGenVars::refBoxMax);
|
|
||||||
mWorldToObjArraySC = shader->getShaderConstHandle(ShaderGenVars::worldToObjArray);
|
mWorldToObjArraySC = shader->getShaderConstHandle(ShaderGenVars::worldToObjArray);
|
||||||
mProbeConfigDataSC = shader->getShaderConstHandle(ShaderGenVars::probeConfigData);
|
mProbeConfigDataSC = shader->getShaderConstHandle(ShaderGenVars::probeConfigData);
|
||||||
mProbeSpecularCubemapSC = shader->getShaderConstHandle(ShaderGenVars::specularCubemapAR);
|
mProbeSpecularCubemapSC = shader->getShaderConstHandle(ShaderGenVars::specularCubemapAR);
|
||||||
|
|
@ -179,8 +179,7 @@ bool ProbeShaderConstants::isValid()
|
||||||
{
|
{
|
||||||
if (mProbePositionSC->isValid() ||
|
if (mProbePositionSC->isValid() ||
|
||||||
mProbeConfigDataSC->isValid() ||
|
mProbeConfigDataSC->isValid() ||
|
||||||
mRefBoxMinSC->isValid() ||
|
mRefScaleSC->isValid() ||
|
||||||
mRefBoxMaxSC->isValid() ||
|
|
||||||
mProbeSpecularCubemapSC->isValid() ||
|
mProbeSpecularCubemapSC->isValid() ||
|
||||||
mProbeIrradianceCubemapSC->isValid())
|
mProbeIrradianceCubemapSC->isValid())
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -204,8 +203,7 @@ RenderProbeMgr::RenderProbeMgr()
|
||||||
mHasSkylight(false),
|
mHasSkylight(false),
|
||||||
mSkylightCubemapIdx(-1),
|
mSkylightCubemapIdx(-1),
|
||||||
mCubeMapCount(0),
|
mCubeMapCount(0),
|
||||||
mDefaultSkyLight(nullptr),
|
mDefaultSkyLight(nullptr)
|
||||||
mBakeRenderTarget(nullptr)
|
|
||||||
{
|
{
|
||||||
mEffectiveProbeCount = 0;
|
mEffectiveProbeCount = 0;
|
||||||
mMipCount = 0;
|
mMipCount = 0;
|
||||||
|
|
@ -221,6 +219,9 @@ RenderProbeMgr::RenderProbeMgr()
|
||||||
{
|
{
|
||||||
mCubeMapSlots[i] = false;
|
mCubeMapSlots[i] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mPrefilterSize = 64;
|
||||||
|
mPrefilterMipLevels = mLog2(F32(mPrefilterSize)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
|
RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
|
||||||
|
|
@ -236,6 +237,10 @@ RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 proce
|
||||||
mLastConstants = nullptr;
|
mLastConstants = nullptr;
|
||||||
mMipCount = 0;
|
mMipCount = 0;
|
||||||
mProbesDirty = false;
|
mProbesDirty = false;
|
||||||
|
mUseHDRCaptures = true;
|
||||||
|
|
||||||
|
mPrefilterSize = 64;
|
||||||
|
mPrefilterMipLevels = mLog2(F32(mPrefilterSize)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderProbeMgr::~RenderProbeMgr()
|
RenderProbeMgr::~RenderProbeMgr()
|
||||||
|
|
@ -303,35 +308,22 @@ void RenderProbeMgr::initPersistFields()
|
||||||
Parent::initPersistFields();
|
Parent::initPersistFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderProbeMgr::addElement(RenderInst *inst)
|
void RenderProbeMgr::consoleInit()
|
||||||
{
|
{
|
||||||
// If this instance is translucent handle it in RenderTranslucentMgr
|
Parent::consoleInit();
|
||||||
//if (inst->translucentSort)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//AssertFatal(inst->defaultKey != 0, "RenderMeshMgr::addElement() - Got null sort key... did you forget to set it?");
|
// Vars for debug rendering while the RoadEditor is open, only used if smEditorOpen is true.
|
||||||
|
Con::addVariable("$pref::maxProbeDrawDistance", TypeF32, &RenderProbeMgr::smMaxProbeDrawDistance, "Max distance for reflection probes to render.\n");
|
||||||
/*internalAddElement(inst);
|
Con::addVariable("$pref::MaxProbesPerFrame", TypeS32, &RenderProbeMgr::smMaxProbesPerFrame, "Max number of Environment Probes that can be rendered per-frame.\n");
|
||||||
|
|
||||||
ProbeRenderInst* probeInst = static_cast<ProbeRenderInst*>(inst);
|
|
||||||
|
|
||||||
if (probeInst->mIsSkylight)
|
|
||||||
{
|
|
||||||
addSkylightProbe(probeInst);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (probeInst->mProbeShapeType == ProbeInfo::Sphere)
|
|
||||||
addSphereReflectionProbe(probeInst);
|
|
||||||
else
|
|
||||||
addConvexReflectionProbe(probeInst);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProbeRenderInst* RenderProbeMgr::registerProbe()
|
void RenderProbeMgr::registerProbe(ProbeRenderInst* newProbe)
|
||||||
{
|
{
|
||||||
mRegisteredProbes.increment();
|
//Can't have over the probe limit
|
||||||
ProbeRenderInst* newProbe = &mRegisteredProbes.last();
|
if (mRegisteredProbes.size() + 1 >= PROBE_MAX_COUNT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mRegisteredProbes.push_back(newProbe);
|
||||||
|
|
||||||
newProbe->mProbeIdx = mRegisteredProbes.size() - 1;
|
newProbe->mProbeIdx = mRegisteredProbes.size() - 1;
|
||||||
|
|
||||||
|
|
@ -339,7 +331,7 @@ ProbeRenderInst* RenderProbeMgr::registerProbe()
|
||||||
if (cubeIndex == INVALID_CUBE_SLOT)
|
if (cubeIndex == INVALID_CUBE_SLOT)
|
||||||
{
|
{
|
||||||
Con::warnf("RenderProbeMgr::addProbe: Invalid cubemap slot.");
|
Con::warnf("RenderProbeMgr::addProbe: Invalid cubemap slot.");
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if we need to resize the cubemap array
|
//check if we need to resize the cubemap array
|
||||||
|
|
@ -372,8 +364,6 @@ ProbeRenderInst* RenderProbeMgr::registerProbe()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mProbesDirty = true;
|
mProbesDirty = true;
|
||||||
|
|
||||||
return newProbe;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderProbeMgr::unregisterProbe(U32 probeIdx)
|
void RenderProbeMgr::unregisterProbe(U32 probeIdx)
|
||||||
|
|
@ -382,11 +372,11 @@ void RenderProbeMgr::unregisterProbe(U32 probeIdx)
|
||||||
if (probeIdx >= mRegisteredProbes.size())
|
if (probeIdx >= mRegisteredProbes.size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mRegisteredProbes[probeIdx].mCubemapIndex == INVALID_CUBE_SLOT)
|
if (mRegisteredProbes[probeIdx]->mCubemapIndex == INVALID_CUBE_SLOT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//mark cubemap slot as available now
|
//mark cubemap slot as available now
|
||||||
mCubeMapSlots[mRegisteredProbes[probeIdx].mCubemapIndex] = false;
|
mCubeMapSlots[mRegisteredProbes[probeIdx]->mCubemapIndex] = false;
|
||||||
mCubeMapCount--;
|
mCubeMapCount--;
|
||||||
|
|
||||||
mRegisteredProbes.erase(probeIdx);
|
mRegisteredProbes.erase(probeIdx);
|
||||||
|
|
@ -394,13 +384,18 @@ void RenderProbeMgr::unregisterProbe(U32 probeIdx)
|
||||||
//recalculate all the probe's indicies just to be sure
|
//recalculate all the probe's indicies just to be sure
|
||||||
for (U32 i = 0; i < mRegisteredProbes.size(); i++)
|
for (U32 i = 0; i < mRegisteredProbes.size(); i++)
|
||||||
{
|
{
|
||||||
mRegisteredProbes[i].mProbeIdx = i;
|
mRegisteredProbes[i]->mProbeIdx = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
//rebuild our probe data
|
//rebuild our probe data
|
||||||
mProbesDirty = true;
|
mProbesDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::submitProbe(const ProbeRenderInst& newProbe)
|
||||||
|
{
|
||||||
|
mActiveProbes.push_back(newProbe);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
PostEffect* RenderProbeMgr::getProbeArrayEffect()
|
PostEffect* RenderProbeMgr::getProbeArrayEffect()
|
||||||
|
|
@ -425,75 +420,6 @@ void RenderProbeMgr::updateProbes()
|
||||||
mProbesDirty = true;
|
mProbesDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderProbeMgr::_setupStaticParameters()
|
|
||||||
{
|
|
||||||
//Array rendering
|
|
||||||
U32 probeCount = mRegisteredProbes.size();
|
|
||||||
|
|
||||||
mEffectiveProbeCount = 0;
|
|
||||||
mMipCount = 1;
|
|
||||||
|
|
||||||
mHasSkylight = false;
|
|
||||||
mSkylightCubemapIdx = -1;
|
|
||||||
|
|
||||||
if (probePositionsData.size() != MAXPROBECOUNT)
|
|
||||||
{
|
|
||||||
probePositionsData.setSize(MAXPROBECOUNT);
|
|
||||||
probeRefPositionsData.setSize(MAXPROBECOUNT);
|
|
||||||
probeWorldToObjData.setSize(MAXPROBECOUNT);
|
|
||||||
refBoxMinData.setSize(MAXPROBECOUNT);
|
|
||||||
refBoxMaxData.setSize(MAXPROBECOUNT);
|
|
||||||
probeConfigData.setSize(MAXPROBECOUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
probePositionsData.fill(Point4F::Zero);
|
|
||||||
probeRefPositionsData.fill(Point4F::Zero);
|
|
||||||
probeWorldToObjData.fill(MatrixF::Identity);
|
|
||||||
refBoxMinData.fill(Point4F::Zero);
|
|
||||||
refBoxMaxData.fill(Point4F::Zero);
|
|
||||||
probeConfigData.fill(Point4F(-1,0,0,0));
|
|
||||||
|
|
||||||
for (U32 i = 0; i < probeCount; i++)
|
|
||||||
{
|
|
||||||
if (mEffectiveProbeCount >= MAXPROBECOUNT)
|
|
||||||
break;
|
|
||||||
|
|
||||||
const ProbeRenderInst& curEntry = mRegisteredProbes[i];
|
|
||||||
if (!curEntry.mIsEnabled)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
U32 mips = mRegisteredProbes[i].mPrefilterCubemap.getPointer()->getMipMapLevels();
|
|
||||||
mMipCount = (mips != 0 && mips >= mMipCount) ? mips : 0;
|
|
||||||
|
|
||||||
if (curEntry.mIsSkylight)
|
|
||||||
{
|
|
||||||
mSkylightCubemapIdx = curEntry.mCubemapIndex;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Setup
|
|
||||||
Point3F probePos = curEntry.getPosition();
|
|
||||||
Point3F refPos = curEntry.getPosition() +curEntry.mProbeRefOffset;
|
|
||||||
probePositionsData[mEffectiveProbeCount] = Point4F(probePos.x, probePos.y, probePos.z,0);
|
|
||||||
probeRefPositionsData[mEffectiveProbeCount] = Point4F(refPos.x, refPos.y, refPos.z, 0);
|
|
||||||
|
|
||||||
probeWorldToObjData[mEffectiveProbeCount] = curEntry.getTransform();
|
|
||||||
Point3F bbMin = refPos - curEntry.mProbeRefScale/2 * curEntry.getTransform().getScale();
|
|
||||||
Point3F bbMax = refPos + curEntry.mProbeRefScale/2 * curEntry.getTransform().getScale();
|
|
||||||
refBoxMinData[mEffectiveProbeCount] = Point4F(bbMin.x, bbMin.y, bbMin.z, 0);
|
|
||||||
refBoxMaxData[mEffectiveProbeCount] = Point4F(bbMax.x, bbMax.y, bbMax.z, 0);
|
|
||||||
|
|
||||||
probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType,
|
|
||||||
curEntry.mRadius,
|
|
||||||
curEntry.mAtten,
|
|
||||||
curEntry.mCubemapIndex);
|
|
||||||
|
|
||||||
mEffectiveProbeCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
mProbesDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderProbeMgr::updateProbeTexture(ProbeRenderInst* probeInfo)
|
void RenderProbeMgr::updateProbeTexture(ProbeRenderInst* probeInfo)
|
||||||
{
|
{
|
||||||
if (probeInfo->mIrradianceCubemap.isNull() || !probeInfo->mIrradianceCubemap->isInitialized())
|
if (probeInfo->mIrradianceCubemap.isNull() || !probeInfo->mIrradianceCubemap->isInitialized())
|
||||||
|
|
@ -523,7 +449,7 @@ void RenderProbeMgr::reloadTextures()
|
||||||
U32 probeCount = mRegisteredProbes.size();
|
U32 probeCount = mRegisteredProbes.size();
|
||||||
for (U32 i = 0; i < probeCount; i++)
|
for (U32 i = 0; i < probeCount; i++)
|
||||||
{
|
{
|
||||||
updateProbeTexture(&mRegisteredProbes[i]);
|
updateProbeTexture(mRegisteredProbes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
mProbesDirty = true;
|
mProbesDirty = true;
|
||||||
|
|
@ -532,6 +458,10 @@ void RenderProbeMgr::reloadTextures()
|
||||||
void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
|
void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
|
PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
|
||||||
|
|
||||||
|
mProbeData = ProbeDataSet(smMaxProbesPerFrame);
|
||||||
|
|
||||||
|
getBestProbes(state->getCameraPosition(), &mProbeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuffer* buffer)
|
ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuffer* buffer)
|
||||||
|
|
@ -579,6 +509,12 @@ ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuff
|
||||||
return mLastConstants;
|
return mLastConstants;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::setupSGData(SceneData& data, const SceneRenderState* state, LightInfo* light)
|
||||||
|
{
|
||||||
|
//ensure they're sorted for forward rendering
|
||||||
|
mActiveProbes.sort(_probeScoreCmp);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
|
void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
|
||||||
MatrixSet &matSet,
|
MatrixSet &matSet,
|
||||||
ProbeShaderConstants *probeShaderConsts,
|
ProbeShaderConstants *probeShaderConsts,
|
||||||
|
|
@ -586,10 +522,8 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE(ProbeManager_Update4ProbeConsts);
|
PROFILE_SCOPE(ProbeManager_Update4ProbeConsts);
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Skip over gathering lights if we don't have to!
|
// Skip over gathering lights if we don't have to!
|
||||||
//if (probeShaderConsts->isValid())
|
if (probeShaderConsts->isValid())
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
|
PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
|
||||||
|
|
||||||
|
|
@ -600,17 +534,29 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
|
||||||
|
|
||||||
getBestProbes(sgData.objTrans->getPosition(), &probeSet);
|
getBestProbes(sgData.objTrans->getPosition(), &probeSet);
|
||||||
|
|
||||||
|
static AlignedArray<Point4F> probePositionAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
|
||||||
|
static AlignedArray<Point4F> refScaleAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
|
||||||
|
static AlignedArray<Point4F> probeRefPositionAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
|
||||||
|
static AlignedArray<Point4F> probeConfigAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
|
||||||
|
|
||||||
|
for (U32 i = 0; i < probeSet.maxProbeCount; i++)
|
||||||
|
{
|
||||||
|
probePositionAlignedArray[i] = probeSet.probePositionArray[i];
|
||||||
|
probeRefPositionAlignedArray[i] = probeSet.probeRefPositionArray[i];
|
||||||
|
refScaleAlignedArray[i] = probeSet.refScaleArray[i];
|
||||||
|
probeConfigAlignedArray[i] = probeSet.probeConfigArray[i];
|
||||||
|
}
|
||||||
|
|
||||||
shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (S32)probeSet.effectiveProbeCount);
|
shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (S32)probeSet.effectiveProbeCount);
|
||||||
|
|
||||||
shaderConsts->setSafe(probeShaderConsts->mProbePositionSC, probeSet.probePositionArray);
|
shaderConsts->setSafe(probeShaderConsts->mProbePositionSC, probePositionAlignedArray);
|
||||||
shaderConsts->setSafe(probeShaderConsts->mProbeRefPosSC, probeSet.probeRefPositionArray);
|
shaderConsts->setSafe(probeShaderConsts->mProbeRefPosSC, probeRefPositionAlignedArray);
|
||||||
|
|
||||||
if(probeShaderConsts->isValid())
|
if(probeShaderConsts->isValid())
|
||||||
shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeSet.probeWorldToObjArray.address(), probeSet.effectiveProbeCount, GFXSCT_Float4x4);
|
shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeSet.probeWorldToObjArray.address(), probeSet.effectiveProbeCount, GFXSCT_Float4x4);
|
||||||
|
|
||||||
shaderConsts->setSafe(probeShaderConsts->mRefBoxMinSC, probeSet.refBoxMinArray);
|
shaderConsts->setSafe(probeShaderConsts->mRefScaleSC, refScaleAlignedArray);
|
||||||
shaderConsts->setSafe(probeShaderConsts->mRefBoxMaxSC, probeSet.refBoxMaxArray);
|
shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataSC, probeConfigAlignedArray);
|
||||||
shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataSC, probeSet.probeConfigArray);
|
|
||||||
|
|
||||||
shaderConsts->setSafe(probeShaderConsts->mSkylightCubemapIdxSC, (float)probeSet.skyLightIdx);
|
shaderConsts->setSafe(probeShaderConsts->mSkylightCubemapIdxSC, (float)probeSet.skyLightIdx);
|
||||||
|
|
||||||
|
|
@ -624,81 +570,71 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
S32 QSORT_CALLBACK RenderProbeMgr::_probeScoreCmp(const ProbeRenderInst* a, const ProbeRenderInst* b)
|
||||||
|
{
|
||||||
|
F32 diff = a->getScore() - b->getScore();
|
||||||
|
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void RenderProbeMgr::getBestProbes(const Point3F& objPosition, ProbeDataSet* probeDataSet)
|
void RenderProbeMgr::getBestProbes(const Point3F& objPosition, ProbeDataSet* probeDataSet)
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE(ProbeManager_getBestProbes);
|
PROFILE_SCOPE(ProbeManager_getBestProbes);
|
||||||
|
|
||||||
// Skip over gathering lights if we don't have to!
|
//Array rendering
|
||||||
//if (probeShaderConsts->isValid())
|
U32 probeCount = mActiveProbes.size();
|
||||||
|
|
||||||
|
Vector<S8> bestPickProbes;
|
||||||
|
bestPickProbes.setSize(probeDataSet->maxProbeCount);
|
||||||
|
bestPickProbes.fill(-1);
|
||||||
|
|
||||||
|
probeDataSet->effectiveProbeCount = 0;
|
||||||
|
for (U32 i = 0; i < probeCount; i++)
|
||||||
{
|
{
|
||||||
//Array rendering
|
if (probeDataSet->skyLightIdx != -1 && probeDataSet->effectiveProbeCount >= probeDataSet->maxProbeCount)
|
||||||
U32 probeCount = mRegisteredProbes.size();
|
break;
|
||||||
|
|
||||||
Vector<S8> bestPickProbes;
|
const ProbeRenderInst& curEntry = mActiveProbes[i];
|
||||||
|
if (!curEntry.mIsEnabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
probeDataSet->effectiveProbeCount = 0;
|
if (curEntry.mProbeShapeType != ProbeRenderInst::Skylight)
|
||||||
for (U32 i = 0; i < probeCount; i++)
|
|
||||||
{
|
{
|
||||||
const ProbeRenderInst& curEntry = mRegisteredProbes[i];
|
if (probeDataSet->effectiveProbeCount < probeDataSet->maxProbeCount)
|
||||||
if (!curEntry.mIsEnabled)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!curEntry.mIsSkylight)
|
|
||||||
{
|
{
|
||||||
F32 dist = Point3F(objPosition - curEntry.getPosition()).len();
|
bestPickProbes[probeDataSet->effectiveProbeCount] = i;
|
||||||
|
probeDataSet->effectiveProbeCount++;
|
||||||
if (dist > curEntry.mRadius || dist > curEntry.mExtents.len())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
S32 bestPickIndex = -1;
|
|
||||||
for (U32 p = 0; p < bestPickProbes.size(); p++)
|
|
||||||
{
|
|
||||||
if (p > probeDataSet->MAX_PROBE_COUNT)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (bestPickProbes[p] == -1 || (Point3F(objPosition - mRegisteredProbes[bestPickProbes[p]].mPosition).len() > dist))
|
|
||||||
bestPickIndex = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Can't have over our max count. Otherwise, if we haven't found a good slot for our best pick, insert it
|
|
||||||
//if we have a best pick slot, update it
|
|
||||||
if (bestPickIndex == -1 || bestPickProbes.size() >= probeDataSet->MAX_PROBE_COUNT)
|
|
||||||
bestPickProbes.push_back(i);
|
|
||||||
else
|
|
||||||
bestPickProbes[bestPickIndex] = i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
probeDataSet->skyLightIdx = curEntry.mCubemapIndex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
//Grab our best probe picks
|
|
||||||
for (U32 i = 0; i < bestPickProbes.size(); i++)
|
|
||||||
{
|
{
|
||||||
if (bestPickProbes[i] == -1)
|
probeDataSet->skyLightIdx = curEntry.mCubemapIndex;
|
||||||
continue;
|
|
||||||
|
|
||||||
const ProbeRenderInst& curEntry = mRegisteredProbes[bestPickProbes[i]];
|
|
||||||
|
|
||||||
probeDataSet->probePositionArray[probeDataSet->effectiveProbeCount] = curEntry.getPosition();
|
|
||||||
probeDataSet->probeRefPositionArray[probeDataSet->effectiveProbeCount] = curEntry.mProbeRefOffset;
|
|
||||||
probeDataSet->probeWorldToObjArray[probeDataSet->effectiveProbeCount] = curEntry.getTransform();
|
|
||||||
|
|
||||||
Point3F refPos = curEntry.getPosition() + curEntry.mProbeRefOffset;
|
|
||||||
Point3F refBoxMin = refPos - curEntry.mProbeRefScale * curEntry.getTransform().getScale();
|
|
||||||
Point3F refBoxMax = refPos + curEntry.mProbeRefScale * curEntry.getTransform().getScale();
|
|
||||||
|
|
||||||
probeDataSet->refBoxMinArray[probeDataSet->effectiveProbeCount] = Point4F(refBoxMin.x, refBoxMin.y, refBoxMin.z, 0);
|
|
||||||
probeDataSet->refBoxMaxArray[probeDataSet->effectiveProbeCount] = Point4F(refBoxMax.x, refBoxMax.y, refBoxMax.z, 0);
|
|
||||||
probeDataSet->probeConfigArray[probeDataSet->effectiveProbeCount] = Point4F(curEntry.mProbeShapeType,
|
|
||||||
curEntry.mRadius,
|
|
||||||
curEntry.mAtten,
|
|
||||||
curEntry.mCubemapIndex);
|
|
||||||
|
|
||||||
probeDataSet->effectiveProbeCount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Grab our best probe picks
|
||||||
|
for (U32 i = 0; i < bestPickProbes.size(); i++)
|
||||||
|
{
|
||||||
|
if (bestPickProbes[i] == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const ProbeRenderInst& curEntry = mActiveProbes[bestPickProbes[i]];
|
||||||
|
|
||||||
|
MatrixF p2A = curEntry.getTransform();
|
||||||
|
p2A.inverse();
|
||||||
|
probeDataSet->refScaleArray[i] = curEntry.mProbeRefScale / p2A.getScale();
|
||||||
|
|
||||||
|
Point3F probePos = curEntry.getPosition();
|
||||||
|
Point3F refPos = probePos + curEntry.mProbeRefOffset * probeDataSet->refScaleArray[i].asPoint3F();
|
||||||
|
probeDataSet->probeWorldToObjArray[i] = curEntry.getTransform();
|
||||||
|
|
||||||
|
probeDataSet->probePositionArray[i] = Point4F(probePos.x, probePos.y, probePos.z, 0);
|
||||||
|
probeDataSet->probeRefPositionArray[i] = Point4F(refPos.x, refPos.y, refPos.z, 0);
|
||||||
|
|
||||||
|
probeDataSet->probeConfigArray[i] = Point4F(curEntry.mProbeShapeType,
|
||||||
|
curEntry.mRadius,
|
||||||
|
curEntry.mAtten,
|
||||||
|
curEntry.mCubemapIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderProbeMgr::getProbeTextureData(ProbeTextureArrayData* probeTextureSet)
|
void RenderProbeMgr::getProbeTextureData(ProbeTextureArrayData* probeTextureSet)
|
||||||
|
|
@ -720,9 +656,6 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
|
||||||
if (sgData.binType == SceneData::DeferredBin)
|
if (sgData.binType == SceneData::DeferredBin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if (mRegisteredProbes.empty())
|
|
||||||
// return;
|
|
||||||
|
|
||||||
PROFILE_SCOPE(ProbeManager_setProbeInfo);
|
PROFILE_SCOPE(ProbeManager_setProbeInfo);
|
||||||
|
|
||||||
ProbeShaderConstants *psc = getProbeShaderConstants(shaderConsts);
|
ProbeShaderConstants *psc = getProbeShaderConstants(shaderConsts);
|
||||||
|
|
@ -747,26 +680,29 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
|
||||||
void RenderProbeMgr::render( SceneRenderState *state )
|
void RenderProbeMgr::render( SceneRenderState *state )
|
||||||
{
|
{
|
||||||
if (getProbeArrayEffect() == nullptr)
|
if (getProbeArrayEffect() == nullptr)
|
||||||
|
{
|
||||||
|
mActiveProbes.clear();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mProbesDirty)
|
GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE);
|
||||||
_setupStaticParameters();
|
|
||||||
|
//Sort the active probes
|
||||||
|
mActiveProbes.sort(_probeScoreCmp);
|
||||||
|
|
||||||
|
// Initialize and set the per-frame data
|
||||||
|
_setupPerFrameParameters(state);
|
||||||
|
|
||||||
// Early out if nothing to draw.
|
// Early out if nothing to draw.
|
||||||
if (!RenderProbeMgr::smRenderReflectionProbes || (!state->isDiffusePass() && !state->isReflectPass()) || (mEffectiveProbeCount == 0 && mSkylightCubemapIdx == -1))
|
if (!RenderProbeMgr::smRenderReflectionProbes || (!state->isDiffusePass() && !state->isReflectPass()) || (mProbeData.effectiveProbeCount == 0 && mProbeData.skyLightIdx == -1))
|
||||||
{
|
{
|
||||||
getProbeArrayEffect()->setSkip(true);
|
getProbeArrayEffect()->setSkip(true);
|
||||||
|
mActiveProbes.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXTransformSaver saver;
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE);
|
|
||||||
|
|
||||||
// Initialize and set the per-frame parameters after getting
|
|
||||||
// the vector light material as we use lazy creation.
|
|
||||||
//_setupPerFrameParameters(state);
|
|
||||||
|
|
||||||
//Visualization
|
//Visualization
|
||||||
String useDebugAtten = Con::getVariable("$Probes::showAttenuation", "0");
|
String useDebugAtten = Con::getVariable("$Probes::showAttenuation", "0");
|
||||||
mProbeArrayEffect->setShaderMacro("DEBUGVIZ_ATTENUATION", useDebugAtten);
|
mProbeArrayEffect->setShaderMacro("DEBUGVIZ_ATTENUATION", useDebugAtten);
|
||||||
|
|
@ -780,11 +716,14 @@ void RenderProbeMgr::render( SceneRenderState *state )
|
||||||
String useDebugContrib = Con::getVariable("$Probes::showProbeContrib", "0");
|
String useDebugContrib = Con::getVariable("$Probes::showProbeContrib", "0");
|
||||||
mProbeArrayEffect->setShaderMacro("DEBUGVIZ_CONTRIB", useDebugContrib);
|
mProbeArrayEffect->setShaderMacro("DEBUGVIZ_CONTRIB", useDebugContrib);
|
||||||
|
|
||||||
if(mSkylightCubemapIdx != -1 && mEffectiveProbeCount == 0)
|
if(mProbeData.skyLightIdx != -1 && mProbeData.effectiveProbeCount == 0)
|
||||||
mProbeArrayEffect->setShaderMacro("SKYLIGHT_ONLY", "1");
|
mProbeArrayEffect->setShaderMacro("SKYLIGHT_ONLY", "1");
|
||||||
else
|
else
|
||||||
mProbeArrayEffect->setShaderMacro("SKYLIGHT_ONLY", "0");
|
mProbeArrayEffect->setShaderMacro("SKYLIGHT_ONLY", "0");
|
||||||
|
|
||||||
|
String probePerFrame = Con::getVariable("$pref::MaxProbesPerFrame", "8");
|
||||||
|
mProbeArrayEffect->setShaderMacro("MAX_PROBES", probePerFrame);
|
||||||
|
|
||||||
//ssao mask
|
//ssao mask
|
||||||
if (AdvancedLightBinManager::smUseSSAOMask)
|
if (AdvancedLightBinManager::smUseSSAOMask)
|
||||||
{
|
{
|
||||||
|
|
@ -795,7 +734,6 @@ void RenderProbeMgr::render( SceneRenderState *state )
|
||||||
{
|
{
|
||||||
mProbeArrayEffect->setShaderMacro("USE_SSAO_MASK");
|
mProbeArrayEffect->setShaderMacro("USE_SSAO_MASK");
|
||||||
mProbeArrayEffect->setTexture(6, pTexObj);
|
mProbeArrayEffect->setTexture(6, pTexObj);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -807,24 +745,24 @@ void RenderProbeMgr::render( SceneRenderState *state )
|
||||||
mProbeArrayEffect->setCubemapArrayTexture(4, mPrefilterArray);
|
mProbeArrayEffect->setCubemapArrayTexture(4, mPrefilterArray);
|
||||||
mProbeArrayEffect->setCubemapArrayTexture(5, mIrradianceArray);
|
mProbeArrayEffect->setCubemapArrayTexture(5, mIrradianceArray);
|
||||||
|
|
||||||
mProbeArrayEffect->setShaderConst("$numProbes", (S32)mEffectiveProbeCount);
|
mProbeArrayEffect->setShaderConst("$numProbes", (S32)mProbeData.effectiveProbeCount);
|
||||||
mProbeArrayEffect->setShaderConst("$skylightCubemapIdx", (S32)mSkylightCubemapIdx);
|
mProbeArrayEffect->setShaderConst("$skylightCubemapIdx", (S32)mProbeData.skyLightIdx);
|
||||||
|
|
||||||
mProbeArrayEffect->setShaderConst("$cubeMips", (float)mMipCount);
|
mProbeArrayEffect->setShaderConst("$cubeMips", (float)mMipCount);
|
||||||
|
|
||||||
//also set up some colors
|
//also set up some colors
|
||||||
Vector<Point4F> contribColors;
|
Vector<Point4F> contribColors;
|
||||||
|
|
||||||
contribColors.setSize(MAXPROBECOUNT);
|
contribColors.setSize(mProbeData.effectiveProbeCount);
|
||||||
|
|
||||||
if (mEffectiveProbeCount != 0)
|
if (mProbeData.effectiveProbeCount != 0)
|
||||||
{
|
{
|
||||||
if (useDebugContrib == String("1"))
|
if (useDebugContrib == String("1"))
|
||||||
{
|
{
|
||||||
MRandomLCG RandomGen;
|
MRandomLCG RandomGen;
|
||||||
RandomGen.setSeed(mEffectiveProbeCount);
|
RandomGen.setSeed(mProbeData.effectiveProbeCount);
|
||||||
|
|
||||||
for (U32 i = 0; i < mEffectiveProbeCount; i++)
|
for (U32 i = 0; i < mProbeData.effectiveProbeCount; i++)
|
||||||
{
|
{
|
||||||
//we're going to cheat here a little for consistent debugging behavior. The first 3 probes will always have R G and then B for their colors, every other will be random
|
//we're going to cheat here a little for consistent debugging behavior. The first 3 probes will always have R G and then B for their colors, every other will be random
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
|
@ -841,20 +779,19 @@ void RenderProbeMgr::render( SceneRenderState *state )
|
||||||
|
|
||||||
mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
|
mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
|
||||||
|
|
||||||
mProbeArrayEffect->setShaderConst("$inProbePosArray", probePositionsData);
|
mProbeArrayEffect->setShaderConst("$inProbePosArray", mProbeData.probePositionArray);
|
||||||
mProbeArrayEffect->setShaderConst("$inRefPosArray", probeRefPositionsData);
|
mProbeArrayEffect->setShaderConst("$inRefPosArray", mProbeData.probeRefPositionArray);
|
||||||
mProbeArrayEffect->setShaderConst("$worldToObjArray", probeWorldToObjData);
|
mProbeArrayEffect->setShaderConst("$worldToObjArray", mProbeData.probeWorldToObjArray);
|
||||||
mProbeArrayEffect->setShaderConst("$refBoxMinArray", refBoxMinData);
|
mProbeArrayEffect->setShaderConst("$refScaleArray", mProbeData.refScaleArray);
|
||||||
mProbeArrayEffect->setShaderConst("$refBoxMaxArray", refBoxMaxData);
|
mProbeArrayEffect->setShaderConst("$probeConfigData", mProbeData.probeConfigArray);
|
||||||
mProbeArrayEffect->setShaderConst("$probeConfigData", probeConfigData);
|
|
||||||
|
|
||||||
// Make sure the effect is gonna render.
|
// Make sure the effect is gonna render.
|
||||||
getProbeArrayEffect()->setSkip(false);
|
getProbeArrayEffect()->setSkip(false);
|
||||||
|
|
||||||
//PROFILE_END();
|
mActiveProbes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
|
void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
|
||||||
{
|
{
|
||||||
GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
|
GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
|
||||||
|
|
||||||
|
|
@ -863,15 +800,15 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
|
||||||
|
|
||||||
String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
|
String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
|
||||||
U32 resolution = Con::getIntVariable("$pref::ReflectionProbes::BakeResolution", 64);
|
U32 resolution = Con::getIntVariable("$pref::ReflectionProbes::BakeResolution", 64);
|
||||||
U32 prefilterMipLevels = mLog2(F32(resolution))+1;
|
U32 prefilterMipLevels = mLog2(F32(resolution)) + 1;
|
||||||
bool renderWithProbes = Con::getIntVariable("$pref::ReflectionProbes::RenderWithProbes", false);
|
bool renderWithProbes = Con::getIntVariable("$pref::ReflectionProbes::RenderWithProbes", false);
|
||||||
|
|
||||||
ReflectionProbe* clientProbe = nullptr;
|
ReflectionProbe* clientProbe = nullptr;
|
||||||
|
|
||||||
if (probe->isClientObject())
|
if (probe->isServerObject())
|
||||||
clientProbe = probe;
|
|
||||||
else
|
|
||||||
clientProbe = static_cast<ReflectionProbe*>(probe->getClientObject());
|
clientProbe = static_cast<ReflectionProbe*>(probe->getClientObject());
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
if (clientProbe == nullptr)
|
if (clientProbe == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
@ -901,7 +838,7 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
|
||||||
reflDesc.texSize = resolution;
|
reflDesc.texSize = resolution;
|
||||||
reflDesc.farDist = farPlane;
|
reflDesc.farDist = farPlane;
|
||||||
reflDesc.detailAdjust = 1;
|
reflDesc.detailAdjust = 1;
|
||||||
reflDesc.objectTypeMask = probe->mCaptureMask;
|
reflDesc.objectTypeMask = probe->mProbeShapeType == ProbeRenderInst::ProbeShapeType::Skylight ? SKYLIGHT_CAPTURE_TYPEMASK : REFLECTION_PROBE_CAPTURE_TYPEMASK;
|
||||||
|
|
||||||
CubeReflector cubeRefl;
|
CubeReflector cubeRefl;
|
||||||
cubeRefl.registerReflector(probe, &reflDesc);
|
cubeRefl.registerReflector(probe, &reflDesc);
|
||||||
|
|
@ -939,13 +876,16 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
|
||||||
|
|
||||||
GFXFormat reflectFormat;
|
GFXFormat reflectFormat;
|
||||||
|
|
||||||
if (clientProbe->mUseHDRCaptures)
|
if (mUseHDRCaptures)
|
||||||
reflectFormat = GFXFormatR16G16B16A16F;
|
reflectFormat = GFXFormatR16G16B16A16F;
|
||||||
else
|
else
|
||||||
reflectFormat = GFXFormatR8G8B8A8;
|
reflectFormat = GFXFormatR8G8B8A8;
|
||||||
const GFXFormat oldRefFmt = REFLECTMGR->getReflectFormat();
|
const GFXFormat oldRefFmt = REFLECTMGR->getReflectFormat();
|
||||||
REFLECTMGR->setReflectFormat(reflectFormat);
|
REFLECTMGR->setReflectFormat(reflectFormat);
|
||||||
cubeRefl.updateReflection(reflParams);
|
|
||||||
|
mProbeArrayEffect->setShaderConst("$CAPTURING", true);
|
||||||
|
cubeRefl.updateReflection(reflParams, clientProbe->getTransform().getPosition()+clientProbe->mProbeRefOffset);
|
||||||
|
mProbeArrayEffect->setShaderConst("$CAPTURING", false);
|
||||||
|
|
||||||
//Now, save out the maps
|
//Now, save out the maps
|
||||||
//create irridiance cubemap
|
//create irridiance cubemap
|
||||||
|
|
@ -958,34 +898,24 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
|
||||||
clientProbe->mIrridianceMap->mCubemap->initDynamic(resolution, reflectFormat);
|
clientProbe->mIrridianceMap->mCubemap->initDynamic(resolution, reflectFormat);
|
||||||
clientProbe->mPrefilterMap->mCubemap->initDynamic(resolution, reflectFormat);
|
clientProbe->mPrefilterMap->mCubemap->initDynamic(resolution, reflectFormat);
|
||||||
|
|
||||||
if (mBakeRenderTarget == nullptr)
|
GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
|
||||||
mBakeRenderTarget = GFX->allocRenderToTextureTarget(false);
|
|
||||||
else
|
|
||||||
mBakeRenderTarget->resurrect();
|
|
||||||
|
|
||||||
IBLUtilities::GenerateIrradianceMap(mBakeRenderTarget, cubeRefl.getCubemap(), clientProbe->mIrridianceMap->mCubemap);
|
IBLUtilities::GenerateIrradianceMap(renderTarget, cubeRefl.getCubemap(), clientProbe->mIrridianceMap->mCubemap);
|
||||||
IBLUtilities::GeneratePrefilterMap(mBakeRenderTarget, cubeRefl.getCubemap(), prefilterMipLevels, clientProbe->mPrefilterMap->mCubemap);
|
IBLUtilities::GeneratePrefilterMap(renderTarget, cubeRefl.getCubemap(), prefilterMipLevels, clientProbe->mPrefilterMap->mCubemap);
|
||||||
|
|
||||||
U32 endMSTime = Platform::getRealMilliseconds();
|
U32 endMSTime = Platform::getRealMilliseconds();
|
||||||
F32 diffTime = F32(endMSTime - startMSTime);
|
F32 diffTime = F32(endMSTime - startMSTime);
|
||||||
Con::warnf("RenderProbeMgr::bake() - Finished Capture! Took %g milliseconds", diffTime);
|
Con::warnf("RenderProbeMgr::bake() - Finished Capture! Took %g milliseconds", diffTime);
|
||||||
|
Con::warnf("RenderProbeMgr::bake() - Beginning save now!");
|
||||||
|
|
||||||
if (writeFiles)
|
IBLUtilities::SaveCubeMap(clientProbe->getIrradianceMapPath(), clientProbe->mIrridianceMap->mCubemap);
|
||||||
{
|
IBLUtilities::SaveCubeMap(clientProbe->getPrefilterMapPath(), clientProbe->mPrefilterMap->mCubemap);
|
||||||
Con::warnf("RenderProbeMgr::bake() - Beginning save now!");
|
|
||||||
|
|
||||||
IBLUtilities::SaveCubeMap(clientProbe->getIrradianceMapPath(), clientProbe->mIrridianceMap->mCubemap);
|
|
||||||
IBLUtilities::SaveCubeMap(clientProbe->getPrefilterMapPath(), clientProbe->mPrefilterMap->mCubemap);
|
|
||||||
}
|
|
||||||
|
|
||||||
mBakeRenderTarget->zombify();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Con::errorf("RenderProbeMgr::bake() - Didn't generate a valid scene capture cubemap, unable to generate prefilter and irradiance maps!");
|
Con::errorf("RenderProbeMgr::bake() - Didn't generate a valid scene capture cubemap, unable to generate prefilter and irradiance maps!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!renderWithProbes)
|
if (!renderWithProbes)
|
||||||
RenderProbeMgr::smRenderReflectionProbes = probeRenderState;
|
RenderProbeMgr::smRenderReflectionProbes = probeRenderState;
|
||||||
|
|
||||||
|
|
@ -1002,12 +932,27 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe* probe, bool writeFiles)
|
||||||
|
|
||||||
void RenderProbeMgr::bakeProbes()
|
void RenderProbeMgr::bakeProbes()
|
||||||
{
|
{
|
||||||
//TODO: make this just find every probe in the current missionGroup and run the bake on it automagically
|
Vector<ReflectionProbe*> probes;
|
||||||
|
|
||||||
|
Scene::getRootScene()->findObjectByType<ReflectionProbe>(probes);
|
||||||
|
|
||||||
|
for (U32 i = 0; i < probes.size(); i++)
|
||||||
|
{
|
||||||
|
if (probes[i]->isClientObject())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bakeProbe(probes[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DefineEngineMethod(RenderProbeMgr, bakeProbe, void, (ReflectionProbe* probe), (nullAsType< ReflectionProbe*>()),
|
DefineEngineMethod(RenderProbeMgr, bakeProbe, void, (ReflectionProbe* probe), (nullAsType< ReflectionProbe*>()),
|
||||||
"@brief returns true if control object is inside the fog\n\n.")
|
"@brief Bakes the cubemaps for a reflection probe\n\n.")
|
||||||
{
|
{
|
||||||
if(probe != nullptr)
|
if(probe != nullptr)
|
||||||
object->bakeProbe(probe);
|
object->bakeProbe(probe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(RenderProbeMgr, bakeProbes, void, (),, "@brief Iterates over all reflection probes in the scene and bakes their cubemaps\n\n.")
|
||||||
|
{
|
||||||
|
object->bakeProbes();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,6 @@ struct ProbeRenderInst
|
||||||
/// when prioritizing lights for rendering.
|
/// when prioritizing lights for rendering.
|
||||||
F32 mScore;
|
F32 mScore;
|
||||||
|
|
||||||
bool mIsSkylight;
|
|
||||||
|
|
||||||
enum ProbeShapeType
|
enum ProbeShapeType
|
||||||
{
|
{
|
||||||
Box = 0, ///< Sphere shaped
|
Box = 0, ///< Sphere shaped
|
||||||
|
|
@ -115,9 +113,6 @@ public:
|
||||||
Point3F getPosition() const { return mPosition; }
|
Point3F getPosition() const { return mPosition; }
|
||||||
void setPosition(const Point3F &pos) { mPosition = pos; }
|
void setPosition(const Point3F &pos) { mPosition = pos; }
|
||||||
|
|
||||||
VectorF getDirection() const { return mTransform.getForwardVector(); }
|
|
||||||
void setDirection(const VectorF &val);
|
|
||||||
|
|
||||||
void setPriority(F32 priority) { mPriority = priority; }
|
void setPriority(F32 priority) { mPriority = priority; }
|
||||||
F32 getPriority() const { return mPriority; }
|
F32 getPriority() const { return mPriority; }
|
||||||
|
|
||||||
|
|
@ -141,8 +136,7 @@ struct ProbeShaderConstants
|
||||||
//Reflection Probes
|
//Reflection Probes
|
||||||
GFXShaderConstHandle *mProbePositionSC;
|
GFXShaderConstHandle *mProbePositionSC;
|
||||||
GFXShaderConstHandle *mProbeRefPosSC;
|
GFXShaderConstHandle *mProbeRefPosSC;
|
||||||
GFXShaderConstHandle *mRefBoxMinSC;
|
GFXShaderConstHandle *mRefScaleSC;
|
||||||
GFXShaderConstHandle *mRefBoxMaxSC;
|
|
||||||
GFXShaderConstHandle *mWorldToObjArraySC;
|
GFXShaderConstHandle *mWorldToObjArraySC;
|
||||||
GFXShaderConstHandle *mProbeConfigDataSC;
|
GFXShaderConstHandle *mProbeConfigDataSC;
|
||||||
GFXShaderConstHandle *mProbeSpecularCubemapSC;
|
GFXShaderConstHandle *mProbeSpecularCubemapSC;
|
||||||
|
|
@ -167,39 +161,43 @@ typedef Map<GFXShader*, ProbeShaderConstants*> ProbeConstantMap;
|
||||||
|
|
||||||
struct ProbeDataSet
|
struct ProbeDataSet
|
||||||
{
|
{
|
||||||
AlignedArray<Point4F> probePositionArray;
|
Vector<Point4F> probePositionArray;
|
||||||
AlignedArray<Point4F> refBoxMinArray;
|
Vector<Point4F> refScaleArray;
|
||||||
AlignedArray<Point4F> refBoxMaxArray;
|
Vector<Point4F> probeRefPositionArray;
|
||||||
AlignedArray<Point4F> probeRefPositionArray;
|
Vector<Point4F> probeConfigArray;
|
||||||
AlignedArray<Point4F> probeConfigArray;
|
|
||||||
|
|
||||||
Vector<MatrixF> probeWorldToObjArray;
|
Vector<MatrixF> probeWorldToObjArray;
|
||||||
|
|
||||||
S32 skyLightIdx;
|
S32 skyLightIdx;
|
||||||
|
|
||||||
U32 effectiveProbeCount;
|
U32 effectiveProbeCount;
|
||||||
|
U32 maxProbeCount;
|
||||||
|
|
||||||
U32 MAX_PROBE_COUNT;
|
ProbeDataSet()
|
||||||
|
|
||||||
ProbeDataSet(U32 maxProbeCount)
|
|
||||||
{
|
{
|
||||||
MAX_PROBE_COUNT = maxProbeCount;
|
probePositionArray.setSize(0);
|
||||||
|
refScaleArray.setSize(0);
|
||||||
|
probeRefPositionArray.setSize(0);
|
||||||
|
probeConfigArray.setSize(0);
|
||||||
|
|
||||||
probePositionArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
|
probeWorldToObjArray.setSize(0);
|
||||||
refBoxMinArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
|
|
||||||
refBoxMaxArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
|
skyLightIdx = -1;
|
||||||
probeRefPositionArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
|
effectiveProbeCount = 0;
|
||||||
probeConfigArray = AlignedArray<Point4F>(maxProbeCount, sizeof(Point4F));
|
maxProbeCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeDataSet(U32 _maxProbeCount)
|
||||||
|
{
|
||||||
|
maxProbeCount = _maxProbeCount;
|
||||||
|
|
||||||
|
probePositionArray.setSize(maxProbeCount);
|
||||||
|
refScaleArray.setSize(maxProbeCount);
|
||||||
|
probeRefPositionArray.setSize(maxProbeCount);
|
||||||
|
probeConfigArray.setSize(maxProbeCount);
|
||||||
|
|
||||||
probeWorldToObjArray.setSize(maxProbeCount);
|
probeWorldToObjArray.setSize(maxProbeCount);
|
||||||
|
|
||||||
// Need to clear the buffers so that we don't leak
|
|
||||||
// lights from previous passes or have NaNs.
|
|
||||||
dMemset(probePositionArray.getBuffer(), 0, probePositionArray.getBufferSize());
|
|
||||||
dMemset(refBoxMinArray.getBuffer(), 0, refBoxMinArray.getBufferSize());
|
|
||||||
dMemset(refBoxMaxArray.getBuffer(), 0, refBoxMaxArray.getBufferSize());
|
|
||||||
dMemset(probeRefPositionArray.getBuffer(), 0, probeRefPositionArray.getBufferSize());
|
|
||||||
dMemset(probeConfigArray.getBuffer(), 0, probeConfigArray.getBufferSize());
|
|
||||||
skyLightIdx = -1;
|
skyLightIdx = -1;
|
||||||
effectiveProbeCount = 0;
|
effectiveProbeCount = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -219,10 +217,11 @@ class RenderProbeMgr : public RenderBinManager
|
||||||
{
|
{
|
||||||
typedef RenderBinManager Parent;
|
typedef RenderBinManager Parent;
|
||||||
|
|
||||||
Vector<ProbeRenderInst> mRegisteredProbes;
|
Vector<ProbeRenderInst*> mRegisteredProbes;
|
||||||
|
|
||||||
bool mProbesDirty;
|
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;
|
||||||
|
|
@ -236,27 +235,17 @@ public:
|
||||||
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 S32 smMaxProbesPerFrame;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//Array rendering
|
//Array rendering
|
||||||
U32 mEffectiveProbeCount;
|
U32 mEffectiveProbeCount;
|
||||||
S32 mMipCount;
|
S32 mMipCount;
|
||||||
Vector<Point4F> probePositionsData;
|
|
||||||
Vector<Point4F> probeRefPositionsData;
|
|
||||||
Vector<MatrixF> probeWorldToObjData;
|
|
||||||
Vector<Point4F> refBoxMinData;
|
|
||||||
Vector<Point4F> refBoxMaxData;
|
|
||||||
Vector<Point4F> probeConfigData;
|
|
||||||
|
|
||||||
bool mHasSkylight;
|
bool mHasSkylight;
|
||||||
S32 mSkylightCubemapIdx;
|
S32 mSkylightCubemapIdx;
|
||||||
|
|
||||||
AlignedArray<Point4F> mProbePositions;
|
|
||||||
AlignedArray<Point4F> mRefBoxMin;
|
|
||||||
AlignedArray<Point4F> mRefBoxMax;
|
|
||||||
AlignedArray<float> mProbeUseSphereMode;
|
|
||||||
AlignedArray<float> mProbeRadius;
|
|
||||||
AlignedArray<float> mProbeAttenuation;
|
|
||||||
|
|
||||||
//number of cubemaps
|
//number of cubemaps
|
||||||
U32 mCubeMapCount;
|
U32 mCubeMapCount;
|
||||||
//number of cubemap slots allocated
|
//number of cubemap slots allocated
|
||||||
|
|
@ -280,8 +269,12 @@ private:
|
||||||
|
|
||||||
GFXTexHandle mBRDFTexture;
|
GFXTexHandle mBRDFTexture;
|
||||||
|
|
||||||
GFXTextureTargetRef mBakeRenderTarget;
|
ProbeDataSet mProbeData;
|
||||||
|
///Prevents us from saving out the cubemaps(for now) but allows us the full HDR range on the in-memory cubemap captures
|
||||||
|
bool mUseHDRCaptures;
|
||||||
|
|
||||||
|
U32 mPrefilterMipLevels;
|
||||||
|
U32 mPrefilterSize;
|
||||||
public:
|
public:
|
||||||
RenderProbeMgr();
|
RenderProbeMgr();
|
||||||
RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder);
|
RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder);
|
||||||
|
|
@ -291,6 +284,8 @@ public:
|
||||||
|
|
||||||
// ConsoleObject
|
// ConsoleObject
|
||||||
static void initPersistFields();
|
static void initPersistFields();
|
||||||
|
static void consoleInit();
|
||||||
|
|
||||||
DECLARE_CONOBJECT(RenderProbeMgr);
|
DECLARE_CONOBJECT(RenderProbeMgr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -306,7 +301,7 @@ protected:
|
||||||
|
|
||||||
void _setupStaticParameters();
|
void _setupStaticParameters();
|
||||||
void _setupPerFrameParameters(const SceneRenderState *state);
|
void _setupPerFrameParameters(const SceneRenderState *state);
|
||||||
virtual void addElement(RenderInst *inst);
|
virtual void addElement(RenderInst* inst) {};
|
||||||
virtual void render(SceneRenderState * state);
|
virtual void render(SceneRenderState * state);
|
||||||
|
|
||||||
ProbeShaderConstants* getProbeShaderConstants(GFXShaderConstBuffer* buffer);
|
ProbeShaderConstants* getProbeShaderConstants(GFXShaderConstBuffer* buffer);
|
||||||
|
|
@ -331,8 +326,11 @@ public:
|
||||||
/// Returns the active LM.
|
/// Returns the active LM.
|
||||||
static inline RenderProbeMgr* getProbeManager();
|
static inline RenderProbeMgr* getProbeManager();
|
||||||
|
|
||||||
ProbeRenderInst* registerProbe();
|
void registerProbe(ProbeRenderInst* newProbe);
|
||||||
void unregisterProbe(U32 probeIdx);
|
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,
|
virtual void setProbeInfo(ProcessedMaterial *pmat,
|
||||||
const Material *mat,
|
const Material *mat,
|
||||||
|
|
@ -341,6 +339,8 @@ public:
|
||||||
U32 pass,
|
U32 pass,
|
||||||
GFXShaderConstBuffer *shaderConsts);
|
GFXShaderConstBuffer *shaderConsts);
|
||||||
|
|
||||||
|
void setupSGData(SceneData& data, const SceneRenderState* state, LightInfo* light);
|
||||||
|
|
||||||
void updateProbeTexture(ProbeRenderInst* probeInfo);
|
void updateProbeTexture(ProbeRenderInst* probeInfo);
|
||||||
|
|
||||||
void reloadTextures();
|
void reloadTextures();
|
||||||
|
|
@ -348,7 +348,7 @@ public:
|
||||||
/// Debug rendering
|
/// Debug rendering
|
||||||
static bool smRenderReflectionProbes;
|
static bool smRenderReflectionProbes;
|
||||||
|
|
||||||
void bakeProbe(ReflectionProbe *probeInfo, bool writeFile = true);
|
void bakeProbe(ReflectionProbe *probeInfo);
|
||||||
void bakeProbes();
|
void bakeProbes();
|
||||||
|
|
||||||
void getProbeTextureData(ProbeTextureArrayData* probeTextureSet);
|
void getProbeTextureData(ProbeTextureArrayData* probeTextureSet);
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,7 @@ void CubeReflector::unregisterReflector()
|
||||||
mEnabled = false;
|
mEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubeReflector::updateReflection( const ReflectParams ¶ms )
|
void CubeReflector::updateReflection( const ReflectParams ¶ms, Point3F explicitPostion)
|
||||||
{
|
{
|
||||||
GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateReflection, ColorI::WHITE );
|
GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateReflection, ColorI::WHITE );
|
||||||
|
|
||||||
|
|
@ -336,7 +336,7 @@ void CubeReflector::updateReflection( const ReflectParams ¶ms )
|
||||||
|
|
||||||
|
|
||||||
for ( U32 i = 0; i < 6; i++ )
|
for ( U32 i = 0; i < 6; i++ )
|
||||||
updateFace( params, i );
|
updateFace( params, i, explicitPostion);
|
||||||
|
|
||||||
|
|
||||||
GFX->popActiveRenderTarget();
|
GFX->popActiveRenderTarget();
|
||||||
|
|
@ -347,7 +347,7 @@ void CubeReflector::updateReflection( const ReflectParams ¶ms )
|
||||||
mLastTexSize = texDim;
|
mLastTexSize = texDim;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubeReflector::updateFace( const ReflectParams ¶ms, U32 faceidx )
|
void CubeReflector::updateFace( const ReflectParams ¶ms, U32 faceidx, Point3F explicitPostion)
|
||||||
{
|
{
|
||||||
GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateFace, ColorI::WHITE );
|
GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateFace, ColorI::WHITE );
|
||||||
|
|
||||||
|
|
@ -402,7 +402,15 @@ void CubeReflector::updateFace( const ReflectParams ¶ms, U32 faceidx )
|
||||||
matView.setColumn( 0, cross );
|
matView.setColumn( 0, cross );
|
||||||
matView.setColumn( 1, vLookatPt );
|
matView.setColumn( 1, vLookatPt );
|
||||||
matView.setColumn( 2, vUpVec );
|
matView.setColumn( 2, vUpVec );
|
||||||
matView.setPosition( mObject->getPosition() );
|
|
||||||
|
if (explicitPostion == Point3F::Max)
|
||||||
|
{
|
||||||
|
matView.setPosition(mObject->getPosition());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matView.setPosition(explicitPostion);
|
||||||
|
}
|
||||||
matView.inverse();
|
matView.inverse();
|
||||||
|
|
||||||
GFX->setWorldMatrix(matView);
|
GFX->setWorldMatrix(matView);
|
||||||
|
|
|
||||||
|
|
@ -151,11 +151,11 @@ public:
|
||||||
ReflectorDesc *inDesc );
|
ReflectorDesc *inDesc );
|
||||||
|
|
||||||
virtual void unregisterReflector();
|
virtual void unregisterReflector();
|
||||||
virtual void updateReflection( const ReflectParams ¶ms );
|
virtual void updateReflection( const ReflectParams ¶ms, Point3F explicitPostion = Point3F::Max);
|
||||||
|
|
||||||
GFXCubemap* getCubemap() const { return mCubemap; }
|
GFXCubemap* getCubemap() const { return mCubemap; }
|
||||||
|
|
||||||
void updateFace( const ReflectParams ¶ms, U32 faceidx );
|
void updateFace( const ReflectParams ¶ms, U32 faceidx, Point3F explicitPostion = Point3F::Max);
|
||||||
F32 calcFaceScore( const ReflectParams ¶ms, U32 faceidx );
|
F32 calcFaceScore( const ReflectParams ¶ms, U32 faceidx );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -3004,15 +3004,10 @@ void ReflectionProbeFeatGLSL::processPix(Vector<ShaderComponent*>& componentList
|
||||||
inRefPosArray->uniform = true;
|
inRefPosArray->uniform = true;
|
||||||
inRefPosArray->constSortPos = cspPotentialPrimitive;
|
inRefPosArray->constSortPos = cspPotentialPrimitive;
|
||||||
|
|
||||||
Var * refBoxMinArray = new Var("inRefBoxMin", "vec4");
|
Var * refScaleArray = new Var("inRefScale", "vec4");
|
||||||
refBoxMinArray->arraySize = MAX_FORWARD_PROBES;
|
refScaleArray->arraySize = MAX_FORWARD_PROBES;
|
||||||
refBoxMinArray->uniform = true;
|
refScaleArray->uniform = true;
|
||||||
refBoxMinArray->constSortPos = cspPotentialPrimitive;
|
refScaleArray->constSortPos = cspPotentialPrimitive;
|
||||||
|
|
||||||
Var * refBoxMaxArray = new Var("inRefBoxMax", "vec4");
|
|
||||||
refBoxMaxArray->arraySize = MAX_FORWARD_PROBES;
|
|
||||||
refBoxMaxArray->uniform = true;
|
|
||||||
refBoxMaxArray->constSortPos = cspPotentialPrimitive;
|
|
||||||
|
|
||||||
Var * probeConfigData = new Var("probeConfigData", "vec4");
|
Var * probeConfigData = new Var("probeConfigData", "vec4");
|
||||||
probeConfigData->arraySize = MAX_FORWARD_PROBES;
|
probeConfigData->arraySize = MAX_FORWARD_PROBES;
|
||||||
|
|
@ -3053,11 +3048,11 @@ void ReflectionProbeFeatGLSL::processPix(Vector<ShaderComponent*>& componentList
|
||||||
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, refBoxMinArray, refBoxMaxArray, inRefPosArray,
|
meta->addStatement(new GenOp(computeForwardProbes.c_str(), curColor, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
|
||||||
skylightCubemapIdx, BRDFTexture,
|
skylightCubemapIdx, BRDFTexture,
|
||||||
irradianceCubemapAR, specularCubemapAR));
|
irradianceCubemapAR, specularCubemapAR));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,7 @@ void DebugVizHLSL::processPix(Vector<ShaderComponent*>& componentList,
|
||||||
Var* skylightCubemapIdx = (Var*)LangElement::find("skylightCubemapIdx");
|
Var* skylightCubemapIdx = (Var*)LangElement::find("skylightCubemapIdx");
|
||||||
Var* inProbePosArray = (Var*)LangElement::find("inProbePosArray");
|
Var* inProbePosArray = (Var*)LangElement::find("inProbePosArray");
|
||||||
Var* inRefPosArray = (Var*)LangElement::find("inRefPosArray");
|
Var* inRefPosArray = (Var*)LangElement::find("inRefPosArray");
|
||||||
Var* refBoxMinArray = (Var*)LangElement::find("inRefBoxMin");
|
Var* refScaleArray = (Var*)LangElement::find("inRefScale");
|
||||||
Var* refBoxMaxArray = (Var*)LangElement::find("inRefBoxMax");
|
|
||||||
|
|
||||||
Var* probeConfigData = (Var*)LangElement::find("probeConfigData");
|
Var* probeConfigData = (Var*)LangElement::find("probeConfigData");
|
||||||
Var* worldToObjArray = (Var*)LangElement::find("worldToObjArray");
|
Var* worldToObjArray = (Var*)LangElement::find("worldToObjArray");
|
||||||
|
|
@ -181,11 +180,11 @@ void DebugVizHLSL::processPix(Vector<ShaderComponent*>& componentList,
|
||||||
dSprintf(buf, sizeof(buf), " @ = %s;\r\n", showDiff);
|
dSprintf(buf, sizeof(buf), " @ = %s;\r\n", showDiff);
|
||||||
meta->addStatement(new GenOp(buf, new DecOp(showDiffVar)));
|
meta->addStatement(new GenOp(buf, new DecOp(showDiffVar)));
|
||||||
|
|
||||||
String computeForwardProbes = String::String(" @ = debugVizForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
|
String computeForwardProbes = String::String(" @ = debugVizForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t");
|
||||||
computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t");
|
computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t");
|
||||||
computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@), @, @, @, @).rgb; \r\n");
|
computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@), @, @, @, @).rgb; \r\n");
|
||||||
|
|
||||||
meta->addStatement(new GenOp(computeForwardProbes.c_str(), ibl, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refBoxMinArray, refBoxMaxArray, inRefPosArray,
|
meta->addStatement(new GenOp(computeForwardProbes.c_str(), ibl, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
|
||||||
skylightCubemapIdx, BRDFTexture,
|
skylightCubemapIdx, BRDFTexture,
|
||||||
irradianceCubemapAR, specularCubemapAR,
|
irradianceCubemapAR, specularCubemapAR,
|
||||||
showAttenVar, showContribVar, showSpecVar, showDiffVar));
|
showAttenVar, showContribVar, showSpecVar, showDiffVar));
|
||||||
|
|
|
||||||
|
|
@ -3075,15 +3075,10 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
|
||||||
inRefPosArray->uniform = true;
|
inRefPosArray->uniform = true;
|
||||||
inRefPosArray->constSortPos = cspPotentialPrimitive;
|
inRefPosArray->constSortPos = cspPotentialPrimitive;
|
||||||
|
|
||||||
Var * refBoxMinArray = new Var("inRefBoxMin", "float4");
|
Var * refScaleArray = new Var("inRefScale", "float4");
|
||||||
refBoxMinArray->arraySize = MAX_FORWARD_PROBES;
|
refScaleArray->arraySize = MAX_FORWARD_PROBES;
|
||||||
refBoxMinArray->uniform = true;
|
refScaleArray->uniform = true;
|
||||||
refBoxMinArray->constSortPos = cspPotentialPrimitive;
|
refScaleArray->constSortPos = cspPotentialPrimitive;
|
||||||
|
|
||||||
Var * refBoxMaxArray = new Var("inRefBoxMax", "float4");
|
|
||||||
refBoxMaxArray->arraySize = MAX_FORWARD_PROBES;
|
|
||||||
refBoxMaxArray->uniform = true;
|
|
||||||
refBoxMaxArray->constSortPos = cspPotentialPrimitive;
|
|
||||||
|
|
||||||
Var *probeConfigData = new Var("probeConfigData", "float4");
|
Var *probeConfigData = new Var("probeConfigData", "float4");
|
||||||
probeConfigData->arraySize = MAX_FORWARD_PROBES;
|
probeConfigData->arraySize = MAX_FORWARD_PROBES;
|
||||||
|
|
@ -3142,11 +3137,11 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
|
||||||
ibl = new Var("ibl", "float3");
|
ibl = new Var("ibl", "float3");
|
||||||
}
|
}
|
||||||
|
|
||||||
String computeForwardProbes = String::String(" @ = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
|
String computeForwardProbes = String::String(" @ = computeForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t");
|
||||||
computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t");
|
computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t");
|
||||||
computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n");
|
computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n");
|
||||||
|
|
||||||
meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refBoxMinArray, refBoxMaxArray, inRefPosArray,
|
meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
|
||||||
skylightCubemapIdx, BRDFTexture,
|
skylightCubemapIdx, BRDFTexture,
|
||||||
irradianceCubemapAR, specularCubemapAR));
|
irradianceCubemapAR, specularCubemapAR));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,7 @@ const String ShaderGenVars::glowMul("$glowMul");
|
||||||
//Reflection Probes
|
//Reflection Probes
|
||||||
const String ShaderGenVars::probePosition("$inProbePosArray");
|
const String ShaderGenVars::probePosition("$inProbePosArray");
|
||||||
const String ShaderGenVars::probeRefPos("$inRefPosArray");
|
const String ShaderGenVars::probeRefPos("$inRefPosArray");
|
||||||
const String ShaderGenVars::refBoxMin("$inRefBoxMin");
|
const String ShaderGenVars::refScale("$inRefScale");
|
||||||
const String ShaderGenVars::refBoxMax("$inRefBoxMax");
|
|
||||||
const String ShaderGenVars::worldToObjArray("$worldToObjArray");
|
const String ShaderGenVars::worldToObjArray("$worldToObjArray");
|
||||||
const String ShaderGenVars::probeConfigData("$probeConfigData");
|
const String ShaderGenVars::probeConfigData("$probeConfigData");
|
||||||
const String ShaderGenVars::specularCubemapAR("$specularCubemapAR");
|
const String ShaderGenVars::specularCubemapAR("$specularCubemapAR");
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,7 @@ struct ShaderGenVars
|
||||||
//Reflection Probes
|
//Reflection Probes
|
||||||
const static String probePosition;
|
const static String probePosition;
|
||||||
const static String probeRefPos;
|
const static String probeRefPos;
|
||||||
const static String refBoxMin;
|
const static String refScale;
|
||||||
const static String refBoxMax;
|
|
||||||
const static String worldToObjArray;
|
const static String worldToObjArray;
|
||||||
const static String probeConfigData;
|
const static String probeConfigData;
|
||||||
const static String specularCubemapAR;
|
const static String specularCubemapAR;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,10 @@ uniform vec4 albedo;
|
||||||
|
|
||||||
#endif // !TORQUE_SHADERGEN
|
#endif // !TORQUE_SHADERGEN
|
||||||
|
|
||||||
#define MAX_PROBES 50
|
#ifndef MAX_PROBES
|
||||||
|
#define MAX_PROBES 8
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_FORWARD_PROBES 4
|
#define MAX_FORWARD_PROBES 4
|
||||||
|
|
||||||
#define MAX_FORWARD_LIGHT 4
|
#define MAX_FORWARD_LIGHT 4
|
||||||
|
|
@ -216,7 +219,12 @@ vec3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight)
|
||||||
float D = D_GGX(surfaceToLight.NdotH, surface.linearRoughnessSq);
|
float D = D_GGX(surfaceToLight.NdotH, surface.linearRoughnessSq);
|
||||||
vec3 Fr = D * F * Vis;
|
vec3 Fr = D * F * Vis;
|
||||||
|
|
||||||
|
#if CAPTURING == true
|
||||||
|
return mix(Fd + Fr,surface.f0,surface.metalness);
|
||||||
|
#else
|
||||||
return Fd + Fr;
|
return Fd + Fr;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 getDirectionalLight(Surface surface, SurfaceToLight surfaceToLight, vec3 lightColor, float lightIntensity, float shadow)
|
vec3 getDirectionalLight(Surface surface, SurfaceToLight surfaceToLight, vec3 lightColor, float lightIntensity, float shadow)
|
||||||
|
|
@ -331,14 +339,14 @@ float defineBoxSpaceInfluence(vec3 wsPosition, mat4 worldToObj, float attenuatio
|
||||||
// Box Projected IBL Lighting
|
// Box Projected IBL Lighting
|
||||||
// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
|
// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
|
||||||
// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
||||||
vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 refBoxMin, vec3 refBoxMax, vec3 refPosition)
|
vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 refScale, vec3 refPosition)
|
||||||
{
|
{
|
||||||
vec3 RayLS = tMul(worldToObj, vec4(wsReflectVec, 0.0)).xyz;
|
vec3 RayLS = tMul(worldToObj, vec4(wsReflectVec, 0.0)).xyz;
|
||||||
vec3 PositionLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz;
|
vec3 PositionLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz;
|
||||||
|
|
||||||
vec3 unit = refBoxMax.xyz - refBoxMin.xyz;
|
vec3 unit = refScale;
|
||||||
vec3 plane1vec = (unit / 2 - PositionLS) / RayLS;
|
vec3 plane1vec = (unit - PositionLS) / RayLS;
|
||||||
vec3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
|
vec3 plane2vec = (-unit - PositionLS) / RayLS;
|
||||||
vec3 furthestPlane = max(plane1vec, plane2vec);
|
vec3 furthestPlane = max(plane1vec, plane2vec);
|
||||||
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
|
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
|
||||||
vec3 posonbox = wsPosition + wsReflectVec * dist;
|
vec3 posonbox = wsPosition + wsReflectVec * dist;
|
||||||
|
|
@ -348,7 +356,7 @@ vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 refBox
|
||||||
|
|
||||||
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 worldToObjArray[MAX_FORWARD_PROBES], vec4 probeConfigData[MAX_FORWARD_PROBES],
|
||||||
vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refBoxMinArray[MAX_FORWARD_PROBES], vec4 refBoxMaxArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
|
vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refScaleArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
|
||||||
float skylightCubemapIdx, sampler2D BRDFTexture,
|
float skylightCubemapIdx, sampler2D BRDFTexture,
|
||||||
samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR)
|
samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR)
|
||||||
{
|
{
|
||||||
|
|
@ -452,7 +460,7 @@ vec4 computeForwardProbes(Surface surface,
|
||||||
if (contrib > 0.0f)
|
if (contrib > 0.0f)
|
||||||
{
|
{
|
||||||
float cubemapIdx = int(probeConfigData[i].a);
|
float cubemapIdx = int(probeConfigData[i].a);
|
||||||
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
|
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
|
||||||
|
|
||||||
irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
|
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;
|
||||||
|
|
@ -490,7 +498,7 @@ vec4 computeForwardProbes(Surface surface,
|
||||||
|
|
||||||
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 worldToObjArray[MAX_FORWARD_PROBES], vec4 probeConfigData[MAX_FORWARD_PROBES],
|
||||||
vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refBoxMinArray[MAX_FORWARD_PROBES], vec4 refBoxMaxArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
|
vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 refScaleArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
|
||||||
float skylightCubemapIdx, sampler2D BRDFTexture,
|
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)
|
||||||
{
|
{
|
||||||
|
|
@ -601,7 +609,7 @@ vec4 debugVizForwardProbes(Surface surface,
|
||||||
if (contrib > 0.0f)
|
if (contrib > 0.0f)
|
||||||
{
|
{
|
||||||
float cubemapIdx = probeConfigData[i].a;
|
float cubemapIdx = probeConfigData[i].a;
|
||||||
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
|
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
|
||||||
|
|
||||||
irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
|
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;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,10 @@ uniform float4 albedo;
|
||||||
|
|
||||||
#endif // !TORQUE_SHADERGEN
|
#endif // !TORQUE_SHADERGEN
|
||||||
|
|
||||||
#define MAX_PROBES 50
|
#ifndef MAX_PROBES
|
||||||
|
#define MAX_PROBES 8
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_FORWARD_PROBES 4
|
#define MAX_FORWARD_PROBES 4
|
||||||
|
|
||||||
#define MAX_FORWARD_LIGHT 4
|
#define MAX_FORWARD_LIGHT 4
|
||||||
|
|
@ -216,8 +219,13 @@ float3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight)
|
||||||
float Vis = V_SmithGGXCorrelated(surface.NdotV, surfaceToLight.NdotL, surface.linearRoughnessSq);
|
float Vis = V_SmithGGXCorrelated(surface.NdotV, surfaceToLight.NdotL, surface.linearRoughnessSq);
|
||||||
float D = D_GGX(surfaceToLight.NdotH, surface.linearRoughnessSq);
|
float D = D_GGX(surfaceToLight.NdotH, surface.linearRoughnessSq);
|
||||||
float3 Fr = D * F * Vis;
|
float3 Fr = D * F * Vis;
|
||||||
|
|
||||||
|
#if CAPTURING == true
|
||||||
|
return lerp(Fd + Fr,surface.f0,surface.metalness);
|
||||||
|
#else
|
||||||
return Fd + Fr;
|
return Fd + Fr;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 getDirectionalLight(Surface surface, SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float shadow)
|
float3 getDirectionalLight(Surface surface, SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float shadow)
|
||||||
|
|
@ -335,14 +343,14 @@ float defineBoxSpaceInfluence(float3 wsPosition, float4x4 worldToObj, float atte
|
||||||
// Box Projected IBL Lighting
|
// Box Projected IBL Lighting
|
||||||
// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
|
// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
|
||||||
// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
||||||
float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, float3 refBoxMin, float3 refBoxMax, float3 refPosition)
|
float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, float3 refScale, float3 refPosition)
|
||||||
{
|
{
|
||||||
float3 RayLS = mul(worldToObj, float4(wsReflectVec, 0.0)).xyz;
|
float3 RayLS = mul(worldToObj, float4(wsReflectVec, 0.0)).xyz;
|
||||||
float3 PositionLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
|
float3 PositionLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
|
||||||
|
|
||||||
float3 unit = refBoxMax.xyz - refBoxMin.xyz;
|
float3 unit = refScale;
|
||||||
float3 plane1vec = (unit / 2 - PositionLS) / RayLS;
|
float3 plane1vec = (unit - PositionLS) / RayLS;
|
||||||
float3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
|
float3 plane2vec = (-unit - PositionLS) / RayLS;
|
||||||
float3 furthestPlane = max(plane1vec, plane2vec);
|
float3 furthestPlane = max(plane1vec, plane2vec);
|
||||||
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
|
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
|
||||||
float3 posonbox = wsPosition + wsReflectVec * dist;
|
float3 posonbox = wsPosition + wsReflectVec * dist;
|
||||||
|
|
@ -352,7 +360,7 @@ 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 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES],
|
||||||
float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refBoxMinArray[MAX_FORWARD_PROBES], float4 refBoxMaxArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
|
float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refScaleArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
|
||||||
float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture),
|
float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture),
|
||||||
TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR))
|
TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR))
|
||||||
{
|
{
|
||||||
|
|
@ -456,7 +464,7 @@ float4 computeForwardProbes(Surface surface,
|
||||||
if (contrib > 0.0f)
|
if (contrib > 0.0f)
|
||||||
{
|
{
|
||||||
int cubemapIdx = probeConfigData[i].a;
|
int cubemapIdx = probeConfigData[i].a;
|
||||||
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
|
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
|
||||||
|
|
||||||
irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
|
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,7 +502,7 @@ float4 computeForwardProbes(Surface surface,
|
||||||
|
|
||||||
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 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES],
|
||||||
float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refBoxMinArray[MAX_FORWARD_PROBES], float4 refBoxMaxArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
|
float4 inProbePosArray[MAX_FORWARD_PROBES], float4 refScaleArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
|
||||||
float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture),
|
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)
|
||||||
{
|
{
|
||||||
|
|
@ -605,7 +613,7 @@ float4 debugVizForwardProbes(Surface surface,
|
||||||
if (contrib > 0.0f)
|
if (contrib > 0.0f)
|
||||||
{
|
{
|
||||||
int cubemapIdx = probeConfigData[i].a;
|
int cubemapIdx = probeConfigData[i].a;
|
||||||
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
|
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
|
||||||
|
|
||||||
irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
|
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;
|
||||||
|
|
|
||||||
|
|
@ -127,4 +127,5 @@ void main()
|
||||||
{
|
{
|
||||||
vec3 N = getCubeDir(face, uv0);
|
vec3 N = getCubeDir(face, uv0);
|
||||||
OUT_col = prefilterEnvMap(N);
|
OUT_col = prefilterEnvMap(N);
|
||||||
|
OUT_col.a = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -33,8 +33,7 @@ uniform vec4 rtParams6;
|
||||||
uniform vec4 inProbePosArray[MAX_PROBES];
|
uniform vec4 inProbePosArray[MAX_PROBES];
|
||||||
uniform vec4 inRefPosArray[MAX_PROBES];
|
uniform vec4 inRefPosArray[MAX_PROBES];
|
||||||
uniform mat4 worldToObjArray[MAX_PROBES];
|
uniform mat4 worldToObjArray[MAX_PROBES];
|
||||||
uniform vec4 refBoxMinArray[MAX_PROBES];
|
uniform vec4 refScaleArray[MAX_PROBES];
|
||||||
uniform vec4 refBoxMaxArray[MAX_PROBES];
|
|
||||||
uniform vec4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
|
uniform vec4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
|
||||||
|
|
||||||
#if DEBUGVIZ_CONTRIB
|
#if DEBUGVIZ_CONTRIB
|
||||||
|
|
@ -180,7 +179,7 @@ void main()
|
||||||
if (contrib > 0.0f)
|
if (contrib > 0.0f)
|
||||||
{
|
{
|
||||||
float cubemapIdx = probeConfigData[i].a;
|
float cubemapIdx = probeConfigData[i].a;
|
||||||
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
|
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
|
||||||
|
|
||||||
irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
|
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;
|
||||||
|
|
|
||||||
|
|
@ -126,5 +126,5 @@ float4 prefilterEnvMap(float3 R)
|
||||||
float4 main(ConnectData IN) : TORQUE_TARGET0
|
float4 main(ConnectData IN) : TORQUE_TARGET0
|
||||||
{
|
{
|
||||||
float3 N = getCubeDir(face, IN.uv);
|
float3 N = getCubeDir(face, IN.uv);
|
||||||
return prefilterEnvMap(N);
|
return float4(prefilterEnvMap(N).rgb,1.0);
|
||||||
}
|
}
|
||||||
|
|
@ -30,8 +30,7 @@ uniform float4 rtParams6;
|
||||||
uniform float4 inProbePosArray[MAX_PROBES];
|
uniform float4 inProbePosArray[MAX_PROBES];
|
||||||
uniform float4 inRefPosArray[MAX_PROBES];
|
uniform float4 inRefPosArray[MAX_PROBES];
|
||||||
uniform float4x4 worldToObjArray[MAX_PROBES];
|
uniform float4x4 worldToObjArray[MAX_PROBES];
|
||||||
uniform float4 refBoxMinArray[MAX_PROBES];
|
uniform float4 refScaleArray[MAX_PROBES];
|
||||||
uniform float4 refBoxMaxArray[MAX_PROBES];
|
|
||||||
uniform float4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
|
uniform float4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
|
||||||
|
|
||||||
#if DEBUGVIZ_CONTRIB
|
#if DEBUGVIZ_CONTRIB
|
||||||
|
|
@ -172,7 +171,7 @@ float4 main(PFXVertToPix IN) : SV_TARGET
|
||||||
if (contrib > 0.0f)
|
if (contrib > 0.0f)
|
||||||
{
|
{
|
||||||
int cubemapIdx = probeConfigData[i].a;
|
int cubemapIdx = probeConfigData[i].a;
|
||||||
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refBoxMinArray[i].xyz, refBoxMaxArray[i].xyz, inRefPosArray[i].xyz);
|
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], refScaleArray[i].xyz, inRefPosArray[i].xyz);
|
||||||
|
|
||||||
irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
|
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;
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,11 @@ function ProbeBakeDlg_RunBake::onClick(%this)
|
||||||
if(%iter != 0)
|
if(%iter != 0)
|
||||||
$pref::ReflectionProbes::RenderWithProbes = true;
|
$pref::ReflectionProbes::RenderWithProbes = true;
|
||||||
|
|
||||||
for(%i=0; %i < %probeCount; %i++)
|
$pref::ReflectionProbes::CurrentLevelPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
|
||||||
{
|
ProbeBin.bakeProbes();
|
||||||
%probe = getWord(%probeIds, %i);
|
|
||||||
|
%currentProgressValue += %progressStep;
|
||||||
$pref::ReflectionProbes::CurrentLevelPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
|
ProbeBakeDlg_Progress.setValue(%currentProgressValue);
|
||||||
ProbeBin.bakeProbe(%probe);
|
|
||||||
|
|
||||||
%currentProgressValue += %progressStep;
|
|
||||||
ProbeBakeDlg_Progress.setValue(%currentProgressValue);
|
|
||||||
Canvas.repaint();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EWorldEditor.isDirty = true;
|
EWorldEditor.isDirty = true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue