SL-18190 Fix for mystery circle showing up on east side of reflection probes. Add one probe to rule them all as a fallback for pixels that aren't inside any influence volume.

meow-7.2.2
Dave Parks 2022-10-11 16:33:51 -05:00
parent 3ac80d7ec2
commit dafa933043
4 changed files with 82 additions and 95 deletions

View File

@ -114,8 +114,7 @@ bool shouldSampleProbe(int i, vec3 pos)
void preProbeSample(vec3 pos)
{
// TODO: make some sort of structure that reduces the number of distance checks
for (int i = 0; i < refmapCount; ++i)
for (int i = 1; i < refmapCount; ++i)
{
// found an influencing probe
if (shouldSampleProbe(i, pos))
@ -200,6 +199,12 @@ void preProbeSample(vec3 pos)
}
}
}
if (probeInfluences == 0)
{ // probe at index 0 is a special fallback probe
probeIndex[0] = 0;
probeInfluences = 1;
}
}
// from https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection
@ -316,7 +321,7 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i)
// c - center of probe
// r2 - radius of probe squared
// i - index of probe
vec3 tapRefMap(vec3 pos, vec3 dir, out vec3 vi, out vec3 wi, float lod, vec3 c, float r2, int i)
vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float lod, vec3 c, int i)
{
//lod = max(lod, 1);
// parallax adjustment
@ -326,10 +331,26 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out vec3 vi, out vec3 wi, float lod, vec3 c,
if (refIndex[i].w < 0)
{
v = boxIntersect(pos, dir, i);
w = 1.0;
}
else
{
v = sphereIntersect(pos, dir, c, r2);
float r = refSphere[i].w; // radius of sphere volume
float rr = r * r; // radius squared
v = sphereIntersect(pos, dir, c, rr);
float p = float(abs(refIndex[i].w)); // priority
float r1 = r * 0.1; // 90% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz - refSphere[i].xyz;
float d2 = max(dot(delta, delta), 0.001);
float r2 = r1 * r1;
float atten = 1.0 - max(d2 - r2, 0.0) / max((rr - r2), 0.001);
w = 1.0 / d2;
w *= atten;
}
vi = v;
@ -352,19 +373,32 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out vec3 vi, out vec3 wi, float lod, vec3 c,
// c - center of probe
// r2 - radius of probe squared
// i - index of probe
vec3 tapIrradianceMap(vec3 pos, vec3 dir, vec3 c, float r2, int i)
vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
{
//lod = max(lod, 1);
// parallax adjustment
vec3 v;
if (refIndex[i].w < 0)
{
v = boxIntersect(pos, dir, i);
w = 1.0;
}
else
{
v = sphereIntersect(pos, dir, c, r2);
float r = refSphere[i].w; // radius of sphere volume
float p = float(abs(refIndex[i].w)); // priority
float rr = r * r; // radius squred
v = sphereIntersect(pos, dir, c, rr);
float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz - refSphere[i].xyz;
float d2 = dot(delta, delta);
float r2 = r1 * r1;
w = 1.0 / d2;
float atten = 1.0 - max(d2 - r2, 0.0) / (rr - r2);
w *= atten;
}
v -= c;
@ -387,26 +421,17 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, bool errorCorrect)
{
continue;
}
float r = refSphere[i].w; // radius of sphere volume
float p = float(abs(refIndex[i].w)); // priority
float rr = r*r; // radius squred
float r1 = r * 0.1; // 90% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz-refSphere[i].xyz;
float d2 = dot(delta,delta);
float r2 = r1*r1;
float w;
vec3 vi, wi;
vec3 refcol;
{
vec3 vi, wi;
float atten = 1.0 - max(d2 - r2, 0.0) / (rr - r2);
float w;
vec3 refcol;
if (errorCorrect && refIndex[i].w >= 0)
{ // error correction is on and this probe is a sphere
//take a sample to get depth value, then error correct
refcol = tapRefMap(pos, dir, vi, wi, abs(lod + 2), refSphere[i].xyz, rr, i);
refcol = tapRefMap(pos, dir, w, vi, wi, abs(lod + 2), refSphere[i].xyz, i);
//adjust lookup by distance result
float d = length(vi - wi);
@ -425,43 +450,15 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, bool errorCorrect)
}
else
{
w = 1.0 / d2;
refcol = tapRefMap(pos, dir, vi, wi, lod, refSphere[i].xyz, rr, i);
refcol = tapRefMap(pos, dir, w, vi, wi, lod, refSphere[i].xyz, i);
}
w *= atten;
//w *= p; // boost weight based on priority
col += refcol.rgb*w;
wsum += w;
}
}
if (probeInfluences < 1)
{ //edge-of-scene probe or no probe influence, mix in with embiggened version of probes closest to camera
for (int idx = 0; idx < 8; ++idx)
{
if (refIndex[idx].w < 0)
{ // don't fallback to box probes, they are *very* specific
continue;
}
int i = idx;
vec3 delta = pos.xyz-refSphere[i].xyz;
float d2 = dot(delta,delta);
{
vec3 vi, wi;
vec3 refcol = tapRefMap(pos, dir, vi, wi, lod, refSphere[i].xyz, d2, i);
float w = 1.0/d2;
w *= w;
col += refcol.rgb*w;
wsum += w;
}
}
}
if (wsum > 0.0)
{
col *= 1.0/wsum;
@ -487,52 +484,17 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir)
{
continue;
}
float r = refSphere[i].w; // radius of sphere volume
float p = float(abs(refIndex[i].w)); // priority
float rr = r*r; // radius squred
float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz-refSphere[i].xyz;
float d2 = dot(delta,delta);
float r2 = r1*r1;
{
vec3 refcol = tapIrradianceMap(pos, dir, refSphere[i].xyz, rr, i);
float w = 1.0/d2;
float w;
vec3 refcol = tapIrradianceMap(pos, dir, w, refSphere[i].xyz, i);
float atten = 1.0-max(d2-r2, 0.0)/(rr-r2);
w *= atten;
//w *= p; // boost weight based on priority
col += refcol*w;
wsum += w;
}
}
if (probeInfluences <= 1)
{ //edge-of-scene probe or no probe influence, mix in with embiggened version of probes closest to camera
for (int idx = 0; idx < 8; ++idx)
{
if (refIndex[idx].w < 0)
{ // don't fallback to box probes, they are *very* specific
continue;
}
int i = idx;
vec3 delta = pos.xyz-refSphere[i].xyz;
float d2 = dot(delta,delta);
{
vec3 refcol = tapIrradianceMap(pos, dir, refSphere[i].xyz, d2, i);
float w = 1.0/d2;
w *= w;
col += refcol*w;
wsum += w;
}
}
}
if (wsum > 0.0)
{
col *= 1.0/wsum;

View File

@ -41,10 +41,13 @@ extern BOOL gTeleportDisplay;
LLReflectionMapManager::LLReflectionMapManager()
{
for (int i = 0; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i)
for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i)
{
mCubeFree[i] = true;
}
// cube index 0 is reserved for the fallback probe
mCubeFree[0] = false;
}
struct CompareReflectionMapDistance
@ -102,6 +105,15 @@ void LLReflectionMapManager::update()
}
if (mDefaultProbe.isNull())
{
mDefaultProbe = addProbe();
mDefaultProbe->mDistance = -4096.f; // hack to make sure the default probe is always first in sort order
mDefaultProbe->mRadius = 4096.f;
}
mDefaultProbe->mOrigin.load3(LLViewerCamera::getInstance()->getOrigin().mV);
LLVector4a camera_pos;
camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
@ -174,8 +186,11 @@ void LLReflectionMapManager::update()
closestDynamic = probe;
}
d.setSub(camera_pos, probe->mOrigin);
probe->mDistance = d.getLength3().getF32()-probe->mRadius;
if (probe != mDefaultProbe)
{
d.setSub(camera_pos, probe->mOrigin);
probe->mDistance = d.getLength3().getF32() - probe->mRadius;
}
}
if (realtime && closestDynamic != nullptr)
@ -196,7 +211,8 @@ void LLReflectionMapManager::update()
if (probe->mCubeIndex == -1)
{
probe->mCubeArray = mTexture;
probe->mCubeIndex = allocateCubeIndex();
probe->mCubeIndex = probe == mDefaultProbe ? 0 : allocateCubeIndex();
}
probe->autoAdjustOrigin();
@ -346,6 +362,8 @@ void LLReflectionMapManager::deleteProbe(U32 i)
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
LLReflectionMap* probe = mProbes[i];
llassert(probe != mDefaultProbe);
if (probe->mCubeIndex != -1)
{ // mark the cube index used by this probe as being free
mCubeFree[probe->mCubeIndex] = true;
@ -429,7 +447,6 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
{
LL_PROFILE_GPU_ZONE("probe mip");
mMipChain[i].bindTarget();
if (i == 0)
{
@ -607,6 +624,10 @@ void LLReflectionMapManager::shift(const LLVector4a& offset)
void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (mDefaultProbe == probe)
{
return;
}
//remove from existing neighbors
{
@ -627,7 +648,7 @@ void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search");
for (auto& other : mProbes)
{
if (other != probe)
if (other != mDefaultProbe && other != probe)
{
if (probe->intersects(other))
{

View File

@ -155,6 +155,8 @@ private:
LLReflectionMap* mUpdatingProbe = nullptr;
U32 mUpdatingFace = 0;
LLPointer<LLReflectionMap> mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0)
// number of reflection probes to use for rendering (based on saved setting RenderReflectionProbeCount)
U32 mReflectionProbeCount;
};

View File

@ -1235,6 +1235,7 @@ U32 LLViewerRegion::getNumOfVisibleGroups() const
void LLViewerRegion::updateReflectionProbes()
{
#if 1
const F32 probe_spacing = 32.f;
const F32 probe_radius = sqrtf((probe_spacing * 0.5f) * (probe_spacing * 0.5f) * 3.f);
const F32 hover_height = 2.f;
@ -1270,6 +1271,7 @@ void LLViewerRegion::updateReflectionProbes()
mReflectionMaps[idx]->mRadius = probe_radius;
}
}
#endif
}
void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)