Merge pull request #942 from secondlife/geenz/mirrors-quality-pass-1
#681 Mirrors quality pass 1.master
commit
cca461647f
|
|
@ -133,6 +133,7 @@ uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlpha
|
|||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
in vec4[2] vary_coords;
|
||||
#endif
|
||||
in vec3 vary_position;
|
||||
in vec3 vary_normal;
|
||||
in vec3 vary_tangent;
|
||||
flat in float vary_sign;
|
||||
|
|
@ -140,11 +141,14 @@ in vec4 vary_texcoord0;
|
|||
in vec4 vary_texcoord1;
|
||||
|
||||
vec2 encode_normal(vec3 n);
|
||||
void mirrorClip(vec3 position);
|
||||
|
||||
float terrain_mix(TerrainMix tm, vec4 tms4);
|
||||
|
||||
void main()
|
||||
{
|
||||
// Make sure we clip the terrain if we're in a mirror.
|
||||
mirrorClip(vary_position);
|
||||
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
TerrainCoord terrain_texcoord = vary_coords;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
uniform mat3 normal_matrix;
|
||||
uniform mat4 texture_matrix0;
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
||||
in vec3 position;
|
||||
|
|
@ -42,6 +43,7 @@ out vec3 vary_tangent;
|
|||
flat out float vary_sign;
|
||||
out vec4 vary_texcoord0;
|
||||
out vec4 vary_texcoord1;
|
||||
out vec3 vary_position;
|
||||
|
||||
// *HACK: tangent_space_transform should use texture_normal_transform, or maybe
|
||||
// we shouldn't use tangent_space_transform at all. See the call to
|
||||
|
|
@ -55,6 +57,7 @@ void main()
|
|||
{
|
||||
//transform vertex
|
||||
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
|
||||
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
|
||||
|
||||
vec3 n = normal_matrix * normal;
|
||||
vary_vertex_normal = normal;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ layout (std140) uniform ReflectionProbes
|
|||
/// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation
|
||||
// box[3][0..2] - plane thickness
|
||||
mat4 refBox[MAX_REFMAP_COUNT];
|
||||
mat4 heroBox;
|
||||
// list of bounding spheres for reflection probes sorted by distance to camera (closest first)
|
||||
vec4 refSphere[MAX_REFMAP_COUNT];
|
||||
// extra parameters
|
||||
|
|
@ -56,6 +57,7 @@ layout (std140) uniform ReflectionProbes
|
|||
// z - fade in
|
||||
// w - znear
|
||||
vec4 refParams[MAX_REFMAP_COUNT];
|
||||
vec4 heroSphere;
|
||||
// index of cube map in reflectionProbes for a corresponding reflection probe
|
||||
// e.g. cube map channel of refSphere[2] is stored in refIndex[2]
|
||||
// refIndex.x - cubemap channel in reflectionProbes
|
||||
|
|
@ -71,6 +73,10 @@ layout (std140) uniform ReflectionProbes
|
|||
|
||||
// number of reflection probes present in refSphere
|
||||
int refmapCount;
|
||||
|
||||
int heroShape;
|
||||
int heroMipCount;
|
||||
int heroProbeCount;
|
||||
};
|
||||
|
||||
// Inputs
|
||||
|
|
@ -366,11 +372,11 @@ return texCUBE(envMap, ReflDirectionWS);
|
|||
// i - probe index in refBox/refSphere
|
||||
// d - distance to nearest wall in clip space
|
||||
// scale - scale of box, default 1.0
|
||||
vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d, float scale)
|
||||
vec3 boxIntersect(vec3 origin, vec3 dir, mat4 i, out float d, float scale)
|
||||
{
|
||||
// Intersection with OBB convert to unit box space
|
||||
// Transform in local unit parallax cube space (scaled and rotated)
|
||||
mat4 clipToLocal = refBox[i];
|
||||
mat4 clipToLocal = i;
|
||||
|
||||
vec3 RayLS = mat3(clipToLocal) * dir;
|
||||
vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz;
|
||||
|
|
@ -389,7 +395,7 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d, float scale)
|
|||
return IntersectPositionCS;
|
||||
}
|
||||
|
||||
vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d)
|
||||
vec3 boxIntersect(vec3 origin, vec3 dir, mat4 i, out float d)
|
||||
{
|
||||
return boxIntersect(origin, dir, i, d, 1.0);
|
||||
}
|
||||
|
|
@ -444,9 +450,9 @@ void boxIntersectionDebug( in vec3 ro, in vec3 p, vec3 boxSize, inout vec4 col)
|
|||
}
|
||||
|
||||
|
||||
void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
|
||||
void boxIntersectDebug(vec3 origin, vec3 pos, mat4 i, inout vec4 col)
|
||||
{
|
||||
mat4 clipToLocal = refBox[i];
|
||||
mat4 clipToLocal = i;
|
||||
|
||||
// transform into unit cube space
|
||||
origin = (clipToLocal * vec4(origin, 1.0)).xyz;
|
||||
|
|
@ -463,7 +469,7 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
|
|||
// r - radius of probe influence volume
|
||||
// i - index of probe in refSphere
|
||||
// dw - distance weight
|
||||
float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, int i, out float dw)
|
||||
float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, vec4 i, out float dw)
|
||||
{
|
||||
float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down)
|
||||
vec3 delta = pos.xyz - origin;
|
||||
|
|
@ -472,7 +478,7 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, int i, out float dw
|
|||
float atten = 1.0 - max(d2 - r1, 0.0) / max((r - r1), 0.001);
|
||||
float w = 1.0 / d2;
|
||||
|
||||
w *= refParams[i].z;
|
||||
w *= i.z;
|
||||
|
||||
dw = w * atten * max(r, 1.0)*4;
|
||||
|
||||
|
|
@ -498,7 +504,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c,
|
|||
if (refIndex[i].w < 0)
|
||||
{ // box probe
|
||||
float d = 0;
|
||||
v = boxIntersect(pos, dir, i, d);
|
||||
v = boxIntersect(pos, dir, refBox[i], d);
|
||||
|
||||
w = max(d, 0.001);
|
||||
}
|
||||
|
|
@ -512,7 +518,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c,
|
|||
refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
|
||||
rr);
|
||||
|
||||
w = sphereWeight(pos, dir, refSphere[i].xyz, r, i, dw);
|
||||
w = sphereWeight(pos, dir, refSphere[i].xyz, r, refParams[i], dw);
|
||||
}
|
||||
|
||||
v -= c;
|
||||
|
|
@ -538,7 +544,7 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int
|
|||
if (refIndex[i].w < 0)
|
||||
{
|
||||
float d = 0.0;
|
||||
v = boxIntersect(pos, dir, i, d, 3.0);
|
||||
v = boxIntersect(pos, dir, refBox[i], d, 3.0);
|
||||
w = max(d, 0.001);
|
||||
}
|
||||
else
|
||||
|
|
@ -552,7 +558,7 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int
|
|||
refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
|
||||
rr);
|
||||
|
||||
w = sphereWeight(pos, dir, refSphere[i].xyz, r, i, dw);
|
||||
w = sphereWeight(pos, dir, refSphere[i].xyz, r, refParams[i], dw);
|
||||
}
|
||||
|
||||
v -= c;
|
||||
|
|
@ -682,23 +688,37 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit)
|
|||
return col[1]+col[0];
|
||||
}
|
||||
|
||||
|
||||
#if defined(HERO_PROBES)
|
||||
|
||||
uniform vec4 clipPlane;
|
||||
uniform samplerCubeArray heroProbes;
|
||||
uniform samplerCubeArray heroProbes;
|
||||
|
||||
void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
|
||||
{
|
||||
float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w;
|
||||
if (clipDist > 0.0 && clipDist < 0.1 && glossiness > 0.8)
|
||||
float w = 0;
|
||||
float dw = 0;
|
||||
float falloffMult = 10;
|
||||
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
|
||||
if (heroShape < 1)
|
||||
{
|
||||
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
|
||||
if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0)
|
||||
{
|
||||
glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*10).xyz;
|
||||
}
|
||||
float d = 0;
|
||||
boxIntersect(pos, norm, heroBox, d, 1.0);
|
||||
|
||||
w = max(d, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
float r = heroSphere.w;
|
||||
|
||||
w = sphereWeight(pos, refnormpersp, heroSphere.xyz, r, vec4(1), dw);
|
||||
}
|
||||
|
||||
clipDist = clipDist * 0.95 + 0.05;
|
||||
clipDist = clamp(clipDist * falloffMult, 0, 1);
|
||||
w = clamp(w * falloffMult * clipDist, 0, 1);
|
||||
|
||||
glossenv = mix(glossenv, textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz, w);
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -779,7 +799,7 @@ void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
|
|||
{
|
||||
if (refIndex[i].w < 0)
|
||||
{
|
||||
boxIntersectDebug(origin, pos, i, col);
|
||||
boxIntersectDebug(origin, pos, refBox[i], col);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,16 +32,6 @@ uniform sampler2D specularRect;
|
|||
uniform sampler2D normalMap;
|
||||
uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
|
||||
|
||||
uniform samplerCubeArray heroProbes;
|
||||
|
||||
#if defined(HERO_PROBES)
|
||||
layout (std140) uniform HeroProbeData
|
||||
{
|
||||
vec4 heroPosition[1];
|
||||
int heroProbeCount;
|
||||
};
|
||||
#endif
|
||||
|
||||
const float M_PI = 3.14159265;
|
||||
|
||||
#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ void LLHeroProbeManager::update()
|
|||
|
||||
// Collect the list of faces that need updating based upon the camera's rotation.
|
||||
LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion();
|
||||
cam_direction.normalize();
|
||||
|
||||
static LLVector3 cubeFaces[6] = {
|
||||
LLVector3(1, 0, 0),
|
||||
|
|
@ -163,7 +164,7 @@ void LLHeroProbeManager::update()
|
|||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5;
|
||||
float shouldUpdate = fminf(1, (fmaxf(-1, cam_direction * cubeFaces[i]) * 0.5 + 0.5));
|
||||
|
||||
int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier);
|
||||
|
||||
|
|
@ -215,6 +216,9 @@ void LLHeroProbeManager::update()
|
|||
mRenderingMirror = false;
|
||||
|
||||
gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass;
|
||||
|
||||
mProbes[0]->mViewerObject = mNearestHero;
|
||||
mProbes[0]->autoAdjustOrigin();
|
||||
}
|
||||
|
||||
mCurrentProbeUpdateFrame++;
|
||||
|
|
@ -417,55 +421,43 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe)
|
|||
|
||||
void LLHeroProbeManager::updateUniforms()
|
||||
{
|
||||
if (!LLPipeline::sReflectionProbesEnabled)
|
||||
if (!gPipeline.RenderMirrors)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
|
||||
struct HeroProbeData
|
||||
{
|
||||
LLVector4 heroPosition[1];
|
||||
GLint heroProbeCount = 1;
|
||||
};
|
||||
|
||||
HeroProbeData hpd;
|
||||
|
||||
LLMatrix4a modelview;
|
||||
modelview.loadu(gGLModelView);
|
||||
LLVector4a oa; // scratch space for transformed origin
|
||||
oa.set(0, 0, 0, 0);
|
||||
hpd.heroProbeCount = 1;
|
||||
modelview.affineTransform(mProbes[0]->mOrigin, oa);
|
||||
hpd.heroPosition[0].set(oa.getF32ptr());
|
||||
|
||||
//copy rpd into uniform buffer object
|
||||
if (mUBO == 0)
|
||||
mHeroData.heroProbeCount = 1;
|
||||
|
||||
if (mNearestHero != nullptr && !mNearestHero->isDead())
|
||||
{
|
||||
glGenBuffers(1, &mUBO);
|
||||
if (mNearestHero->getReflectionProbeIsBox())
|
||||
{
|
||||
LLVector3 s = mNearestHero->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f));
|
||||
mProbes[0]->mRadius = s.magVec();
|
||||
}
|
||||
else
|
||||
{
|
||||
mProbes[0]->mRadius = mNearestHero->getScale().mV[0] * 0.5f;
|
||||
}
|
||||
|
||||
modelview.affineTransform(mProbes[0]->mOrigin, oa);
|
||||
mHeroData.heroShape = 0;
|
||||
if (!mProbes[0]->getBox(mHeroData.heroBox))
|
||||
{
|
||||
mHeroData.heroShape = 1;
|
||||
}
|
||||
|
||||
mHeroData.heroSphere.set(oa.getF32ptr());
|
||||
mHeroData.heroSphere.mV[3] = mProbes[0]->mRadius;
|
||||
}
|
||||
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer");
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, mUBO);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::setUniforms()
|
||||
{
|
||||
if (!LLPipeline::sReflectionProbesEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mUBO == 0)
|
||||
{
|
||||
updateUniforms();
|
||||
}
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
|
||||
|
||||
mHeroData.heroMipCount = mMipChain.size();
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::renderDebug()
|
||||
|
|
@ -554,9 +546,6 @@ void LLHeroProbeManager::cleanup()
|
|||
|
||||
mDefaultProbe = nullptr;
|
||||
mUpdatingProbe = nullptr;
|
||||
|
||||
glDeleteBuffers(1, &mUBO);
|
||||
mUBO = 0;
|
||||
|
||||
mHeroVOList.clear();
|
||||
mNearestHero = nullptr;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,15 @@ class LLViewerObject;
|
|||
// number of reflection probes to keep in vram
|
||||
#define LL_MAX_HERO_PROBE_COUNT 2
|
||||
|
||||
struct HeroProbeData
|
||||
{
|
||||
LLMatrix4 heroBox;
|
||||
LLVector4 heroSphere;
|
||||
GLint heroShape;
|
||||
GLint heroMipCount;
|
||||
GLint heroProbeCount;
|
||||
};
|
||||
|
||||
class alignas(16) LLHeroProbeManager
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
|
|
@ -74,16 +83,17 @@ public:
|
|||
bool isMirrorPass() const { return mRenderingMirror; }
|
||||
|
||||
LLVector3 mMirrorPosition;
|
||||
LLVector3 mMirrorNormal;
|
||||
LLVector3 mMirrorNormal;
|
||||
HeroProbeData mHeroData;
|
||||
|
||||
private:
|
||||
friend class LLPipeline;
|
||||
friend class LLReflectionMapManager;
|
||||
|
||||
// update UBO used for rendering (call only once per render pipe flush)
|
||||
void updateUniforms();
|
||||
|
||||
// bind UBO used for rendering
|
||||
void setUniforms();
|
||||
|
||||
// render target for cube snapshots
|
||||
// used to generate mipmaps without doing a copy-to-texture
|
||||
|
|
@ -109,9 +119,6 @@ private:
|
|||
// list of active reflection maps
|
||||
std::vector<LLPointer<LLReflectionMap>> mProbes;
|
||||
|
||||
// handle to UBO
|
||||
U32 mUBO = 0;
|
||||
|
||||
// list of maps being used for rendering
|
||||
std::vector<LLReflectionMap*> mReflectionMaps;
|
||||
|
||||
|
|
@ -141,5 +148,6 @@ private:
|
|||
|
||||
std::vector<LLVOVolume*> mHeroVOList;
|
||||
LLVOVolume* mNearestHero;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ void LLReflectionMap::autoAdjustOrigin()
|
|||
|
||||
}
|
||||
}
|
||||
else if (mViewerObject)
|
||||
else if (mViewerObject && !mViewerObject->isDead())
|
||||
{
|
||||
mPriority = 1;
|
||||
mOrigin.load3(mViewerObject->getPositionAgent().mV);
|
||||
|
|
|
|||
|
|
@ -906,6 +906,8 @@ void LLReflectionMapManager::updateUniforms()
|
|||
// the box probe
|
||||
LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
|
||||
LLMatrix4 heroBox;
|
||||
|
||||
// for sphere probes, origin (xyz) and radius (w) of refmaps in clip space
|
||||
LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
|
||||
|
|
@ -916,6 +918,8 @@ void LLReflectionMapManager::updateUniforms()
|
|||
// w - znear
|
||||
LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
|
||||
LLVector4 heroSphere;
|
||||
|
||||
// indices used by probe:
|
||||
// [i][0] - cubemap array index for this probe
|
||||
// [i][1] - index into "refNeighbor" for probes that intersect this probe
|
||||
|
|
@ -929,6 +933,10 @@ void LLReflectionMapManager::updateUniforms()
|
|||
GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth
|
||||
// numbrer of active refmaps
|
||||
GLint refmapCount;
|
||||
|
||||
GLint heroShape;
|
||||
GLint heroMipCount;
|
||||
GLint heroProbeCount;
|
||||
};
|
||||
|
||||
mReflectionMaps.resize(mReflectionProbeCount);
|
||||
|
|
@ -1016,7 +1024,6 @@ void LLReflectionMapManager::updateUniforms()
|
|||
{
|
||||
refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f;
|
||||
}
|
||||
|
||||
}
|
||||
modelview.affineTransform(refmap->mOrigin, oa);
|
||||
rpd.refSphere[count].set(oa.getF32ptr());
|
||||
|
|
@ -1119,6 +1126,16 @@ void LLReflectionMapManager::updateUniforms()
|
|||
|
||||
rpd.refmapCount = count;
|
||||
|
||||
gPipeline.mHeroProbeManager.updateUniforms();
|
||||
|
||||
// Get the hero data.
|
||||
|
||||
rpd.heroBox = gPipeline.mHeroProbeManager.mHeroData.heroBox;
|
||||
rpd.heroSphere = gPipeline.mHeroProbeManager.mHeroData.heroSphere;
|
||||
rpd.heroShape = gPipeline.mHeroProbeManager.mHeroData.heroShape;
|
||||
rpd.heroMipCount = gPipeline.mHeroProbeManager.mHeroData.heroMipCount;
|
||||
rpd.heroProbeCount = gPipeline.mHeroProbeManager.mHeroData.heroProbeCount;
|
||||
|
||||
//copy rpd into uniform buffer object
|
||||
if (mUBO == 0)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue