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:
Areloch 2020-10-19 00:53:09 -05:00
parent 072b5ecb19
commit 6a3603c737
22 changed files with 490 additions and 610 deletions

View file

@ -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();
} }

View file

@ -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();

View file

@ -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();
}; };

View file

@ -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)

View file

@ -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)

View file

@ -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.

View file

@ -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();
}

View file

@ -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);

View file

@ -295,7 +295,7 @@ void CubeReflector::unregisterReflector()
mEnabled = false; mEnabled = false;
} }
void CubeReflector::updateReflection( const ReflectParams &params ) void CubeReflector::updateReflection( const ReflectParams &params, Point3F explicitPostion)
{ {
GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateReflection, ColorI::WHITE ); GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateReflection, ColorI::WHITE );
@ -336,7 +336,7 @@ void CubeReflector::updateReflection( const ReflectParams &params )
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 &params )
mLastTexSize = texDim; mLastTexSize = texDim;
} }
void CubeReflector::updateFace( const ReflectParams &params, U32 faceidx ) void CubeReflector::updateFace( const ReflectParams &params, 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 &params, 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);

View file

@ -151,11 +151,11 @@ public:
ReflectorDesc *inDesc ); ReflectorDesc *inDesc );
virtual void unregisterReflector(); virtual void unregisterReflector();
virtual void updateReflection( const ReflectParams &params ); virtual void updateReflection( const ReflectParams &params, Point3F explicitPostion = Point3F::Max);
GFXCubemap* getCubemap() const { return mCubemap; } GFXCubemap* getCubemap() const { return mCubemap; }
void updateFace( const ReflectParams &params, U32 faceidx ); void updateFace( const ReflectParams &params, U32 faceidx, Point3F explicitPostion = Point3F::Max);
F32 calcFaceScore( const ReflectParams &params, U32 faceidx ); F32 calcFaceScore( const ReflectParams &params, U32 faceidx );
protected: protected:

View file

@ -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));

View file

@ -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));

View file

@ -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));

View file

@ -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");

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;

View file

@ -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);
} }

View file

@ -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;

View file

@ -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;