Added exposure pass calculating the bloom/tonemap exposure based on what the eye is seeing

This commit is contained in:
Magnus Norddahl 2016-09-18 15:57:22 +02:00 committed by Christoph Oelckers
commit f7b6b1433c
17 changed files with 358 additions and 40 deletions

View file

@ -75,7 +75,10 @@ CUSTOM_CVAR(Float, gl_bloom_amount, 1.4f, 0)
if (self < 0.1f) self = 0.1f;
}
CVAR(Float, gl_exposure, 0.0f, 0)
CVAR(Float, gl_exposure_scale, 0.75f, 0)
CVAR(Float, gl_exposure_min, 0.35f, 0)
CVAR(Float, gl_exposure_base, 0.35f, 0)
CVAR(Float, gl_exposure_speed, 0.05f, 0)
CUSTOM_CVAR(Int, gl_tonemap, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
@ -106,6 +109,78 @@ void FGLRenderer::RenderScreenQuad()
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
}
//-----------------------------------------------------------------------------
//
// Extracts light average from the scene and updates the camera exposure texture
//
//-----------------------------------------------------------------------------
void FGLRenderer::UpdateCameraExposure()
{
if (!gl_bloom && gl_tonemap == 0)
return;
FGLDebug::PushGroup("UpdateCameraExposure");
FGLPostProcessState savedState;
savedState.SaveTextureBinding1();
// Extract light level from scene texture:
const auto &level0 = mBuffers->ExposureLevels[0];
glBindFramebuffer(GL_FRAMEBUFFER, level0.Framebuffer);
glViewport(0, 0, level0.Width, level0.Height);
mBuffers->BindCurrentTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mExposureExtractShader->Bind();
mExposureExtractShader->SceneTexture.Set(0);
mExposureExtractShader->Scale.Set(mSceneViewport.width / (float)mScreenViewport.width, mSceneViewport.height / (float)mScreenViewport.height);
mExposureExtractShader->Offset.Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
RenderScreenQuad();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Find the average value:
for (int i = 0; i + 1 < mBuffers->ExposureLevels.Size(); i++)
{
const auto &level = mBuffers->ExposureLevels[i];
const auto &next = mBuffers->ExposureLevels[i + 1];
glBindFramebuffer(GL_FRAMEBUFFER, next.Framebuffer);
glViewport(0, 0, next.Width, next.Height);
glBindTexture(GL_TEXTURE_2D, level.Texture);
mExposureAverageShader->Bind();
mExposureAverageShader->ExposureTexture.Set(0);
RenderScreenQuad();
}
// Combine average value with current camera exposure:
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->ExposureFB);
glViewport(0, 0, 1, 1);
if (!mBuffers->FirstExposureFrame)
{
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
mBuffers->FirstExposureFrame = false;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mBuffers->ExposureLevels.Last().Texture);
mExposureCombineShader->Bind();
mExposureCombineShader->ExposureTexture.Set(0);
mExposureCombineShader->ExposureBase.Set(gl_exposure_base);
mExposureCombineShader->ExposureMin.Set(gl_exposure_min);
mExposureCombineShader->ExposureScale.Set(gl_exposure_scale);
mExposureCombineShader->ExposureSpeed.Set(gl_exposure_speed);
RenderScreenQuad();
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
FGLDebug::PopGroup();
}
//-----------------------------------------------------------------------------
//
// Adds bloom contribution to scene texture
@ -121,6 +196,7 @@ void FGLRenderer::BloomScene()
FGLDebug::PushGroup("BloomScene");
FGLPostProcessState savedState;
savedState.SaveTextureBinding1();
const float blurAmount = gl_bloom_amount;
int sampleCount = gl_bloom_kernel_size;
@ -133,9 +209,12 @@ void FGLRenderer::BloomScene()
mBuffers->BindCurrentTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, mBuffers->ExposureTexture);
glActiveTexture(GL_TEXTURE0);
mBloomExtractShader->Bind();
mBloomExtractShader->SceneTexture.Set(0);
mBloomExtractShader->Exposure.Set(mCameraExposure);
mBloomExtractShader->ExposureTexture.Set(1);
mBloomExtractShader->Scale.Set(mSceneViewport.width / (float)mScreenViewport.width, mSceneViewport.height / (float)mScreenViewport.height);
mBloomExtractShader->Offset.Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
RenderScreenQuad();
@ -220,7 +299,12 @@ void FGLRenderer::TonemapScene()
}
else
{
mTonemapShader->Exposure.Set(mCameraExposure);
savedState.SaveTextureBinding1();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, mBuffers->ExposureTexture);
glActiveTexture(GL_TEXTURE0);
mTonemapShader->ExposureTexture.Set(1);
}
RenderScreenQuad();