DRTVWR-559 Dynamic exposure followup -- stochastic sampling, weight based on luminance and distance to center of screen, rebalance night, don't rely on blending not clamping R16F.

master
Dave Parks 2023-03-29 13:24:07 -05:00
parent 4f651bceab
commit b130831106
6 changed files with 82 additions and 54 deletions

View File

@ -31,12 +31,22 @@ out vec4 frag_color;
uniform sampler2D diffuseRect;
uniform sampler2D emissiveRect;
uniform sampler2D exposureMap;
uniform float dt;
uniform vec2 noiseVec;
// calculate luminance the same way LLColor4::calcHSL does
float lum(vec3 col)
{
float mx = max(max(col.r, col.g), col.b);
float mn = min(min(col.r, col.g), col.b);
return (mx + mn) * 0.5;
}
void main()
{
int samples = 16;
float step = 1.0/(samples-4);
float step = 1.0/32.0;
float start = step;
float end = 1.0-step;
@ -45,23 +55,38 @@ void main()
vec3 col;
vec2 nz = noiseVec * step * 0.5;
for (float x = start; x <= end; x += step)
{
for (float y = start; y <= end; y += step)
{
vec2 tc = vec2(x,y);
w += 1.0;
col += texture(diffuseRect, tc).rgb + texture(emissiveRect, tc).rgb;
vec2 tc = vec2(x,y) + nz;
vec3 c = texture(diffuseRect, tc).rgb + texture(emissiveRect, tc).rgb;
float L = max(lum(c), 0.25);
float d = length(vec2(0.5)-tc);
d = 1.0-d;
d *= d;
d *= d;
d *= d;
L *= d;
w += L;
col += c * L;
}
}
col /= w;
// calculate luminance the same way LLColor4::calcHSL does
float mx = max(max(col.r, col.g), col.b);
float mn = min(min(col.r, col.g), col.b);
float lum = (mx + mn) * 0.5;
float L = lum(col);
frag_color = vec4(lum, lum, lum, dt);
float s = clamp(0.1/L, 0.5, 4.0);
float prev = texture(exposureMap, vec2(0.5,0.5)).r;
s = mix(prev, s, min(dt*2.0, 0.04));
frag_color = vec4(s, s, s, dt);
}

View File

@ -108,9 +108,8 @@ uniform float gamma;
vec3 toneMap(vec3 color)
{
float exp_sample = texture(exposureMap, vec2(0.5,0.5)).r;
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
float exp_scale = clamp(0.1/exp_sample, 0.5, 8.0);
color *= exposure * exp_scale;
#ifdef TONEMAP_ACES_NARKOWICZ

View File

@ -91,7 +91,7 @@ void main()
vary_LightNormPosDot = rel_pos_lightnorm_dot;
// Initialize temp variables
vec3 sunlight = (sun_up_factor == 1) ? sunlight_color*2.0 : moonlight_color*0.5;
vec3 sunlight = (sun_up_factor == 1) ? sunlight_color*2.0 : moonlight_color*0.75;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes

View File

@ -63,7 +63,7 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
vec3 rel_pos_norm = normalize(rel_pos);
float rel_pos_len = length(rel_pos);
float scale = 2.0;
vec3 sunlight = (sun_up_factor == 1) ? sunlight_color * scale: moonlight_color/scale;
vec3 sunlight = (sun_up_factor == 1) ? sunlight_color * scale: moonlight_color*0.75;
// sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes

View File

@ -116,27 +116,7 @@
#include "llenvironment.h"
#include "llsettingsvo.h"
#ifdef _DEBUG
// Debug indices is disabled for now for debug performance - djs 4/24/02
//#define DEBUG_INDICES
#else
//#define DEBUG_INDICES
#endif
// Expensive and currently broken
//
#define MATERIALS_IN_REFLECTIONS 0
// NOTE: Keep in sync with indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
// NOTE: Unused consts are commented out since some compilers (on macOS) may complain about unused variables.
// const S32 WATER_REFLECT_NONE_WATER_OPAQUE = -2;
//const S32 WATER_REFLECT_NONE_WATER_TRANSPARENT = -1;
//const S32 WATER_REFLECT_MINIMAL = 0;
// const S32 WATER_REFLECT_TERRAIN = 1;
//const S32 WATER_REFLECT_STATIC_OBJECTS = 2;
//const S32 WATER_REFLECT_AVATARS = 3;
//const S32 WATER_REFLECT_EVERYTHING = 4;
extern BOOL gSnapshot;
bool gShiftFrame = false;
//cached settings
@ -851,11 +831,6 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
mPostMap.allocate(resX, resY, GL_RGBA);
mExposureMap.allocate(1, 1, GL_R16F);
mExposureMap.bindTarget();
mExposureMap.clear();
mExposureMap.flush();
//HACK make screenbuffer allocations start failing after 30 seconds
if (gSavedSettings.getBOOL("SimulateFBOFailure"))
{
@ -1086,8 +1061,6 @@ void LLPipeline::releaseGLBuffers()
mSceneMap.release();
mExposureMap.release();
mPostMap.release();
for (U32 i = 0; i < 3; i++)
@ -1110,6 +1083,10 @@ void LLPipeline::releaseLUTBuffers()
}
mPbrBrdfLut.release();
mExposureMap.release();
mLastExposure.release();
}
void LLPipeline::releaseShadowBuffers()
@ -1286,6 +1263,13 @@ void LLPipeline::createLUTBuffers()
gDeferredGenBrdfLutProgram.unbind();
mPbrBrdfLut.flush();
mExposureMap.allocate(1, 1, GL_R16F);
mExposureMap.bindTarget();
mExposureMap.clear();
mExposureMap.flush();
mLastExposure.allocate(1, 1, GL_R16F);
}
@ -7407,30 +7391,50 @@ void LLPipeline::renderFinalize()
// exposure sample
{
LL_PROFILE_GPU_ZONE("exposure sample");
{
// copy last frame's exposure into mLastExposure
mLastExposure.bindTarget();
gCopyProgram.bind();
gGL.getTexUnit(0)->bind(&mExposureMap);
mScreenTriangleVB->setBuffer();
mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
mLastExposure.flush();
}
mExposureMap.bindTarget();
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
gExposureProgram.bind();
S32 channel = 0;
channel = gExposureProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screenTarget()->getUsage());
channel = gExposureProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE);
if (channel > -1)
{
screenTarget()->bindTexture(0, channel, LLTexUnit::TFO_POINT);
}
channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE, screenTarget()->getUsage());
channel = gExposureProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE);
if (channel > -1)
{
mGlow[1].bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
mGlow[1].bindTexture(0, channel);
}
channel = gExposureProgram.enableTexture(LLShaderMgr::EXPOSURE_MAP);
if (channel > -1)
{
mLastExposure.bindTexture(0, channel);
}
static LLStaticHashedString dt("dt");
static LLStaticHashedString noiseVec("noiseVec");
gExposureProgram.uniform1f(dt, gFrameIntervalSeconds);
gExposureProgram.uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0);
mScreenTriangleVB->setBuffer();
mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
@ -7562,9 +7566,8 @@ void LLPipeline::renderFinalize()
2.f / width * scale_x, 2.f / height * scale_y);
{
// at this point we should pointed at the backbuffer
llassert(LLRenderTarget::sCurFBO == 0);
// at this point we should pointed at the backbuffer (or a snapshot render target)
llassert(gSnapshot || LLRenderTarget::sCurFBO == 0);
LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true);
@ -7577,8 +7580,8 @@ void LLPipeline::renderFinalize()
}
else
{
// at this point we should pointed at the backbuffer
llassert(LLRenderTarget::sCurFBO == 0);
// at this point we should pointed at the backbuffer (or a snapshot render target)
llassert(gSnapshot || LLRenderTarget::sCurFBO == 0);
LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);

View File

@ -679,6 +679,7 @@ public:
// exposure map for getting average color in scene
LLRenderTarget mExposureMap;
LLRenderTarget mLastExposure;
// tonemapped and gamma corrected render ready for post
LLRenderTarget mPostMap;