Added tonemapping and sector based exposure control

This commit is contained in:
Magnus Norddahl 2016-07-29 00:36:43 +02:00
parent 69f52cc898
commit 0efee85bd8
12 changed files with 284 additions and 30 deletions

View file

@ -1108,6 +1108,7 @@ set( FASTMATH_SOURCES
gl/shaders/gl_presentshader.cpp
gl/shaders/gl_bloomshader.cpp
gl/shaders/gl_blurshader.cpp
gl/shaders/gl_tonemapshader.cpp
gl/system/gl_interface.cpp
gl/system/gl_framebuffer.cpp
gl/system/gl_menu.cpp

View file

@ -97,10 +97,16 @@ void FGLRenderBuffers::Clear()
glDeleteTextures(1, &mSceneTexture);
if (mSceneDepthStencil != 0)
glDeleteRenderbuffers(1, &mSceneDepthStencil);
if (mHudFB != 0)
glDeleteFramebuffers(1, &mHudFB);
if (mHudTexture != 0)
glDeleteTextures(1, &mHudTexture);
mSceneFB = 0;
mSceneTexture = 0;
mSceneDepthStencil = 0;
mHudFB = 0;
mHudTexture = 0;
mWidth = 0;
mHeight = 0;
}
@ -122,7 +128,9 @@ void FGLRenderBuffers::Setup(int width, int height)
glActiveTexture(GL_TEXTURE0);
glGenFramebuffers(1, &mSceneFB);
glGenFramebuffers(1, &mHudFB);
glGenTextures(1, &mSceneTexture);
glGenTextures(1, &mHudTexture);
glGenRenderbuffers(1, &mSceneDepthStencil);
glBindTexture(GL_TEXTURE_2D, mSceneTexture);
@ -139,6 +147,16 @@ void FGLRenderBuffers::Setup(int width, int height)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mSceneTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mSceneDepthStencil);
glBindTexture(GL_TEXTURE_2D, mHudTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, mHudFB);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mHudTexture, 0);
int bloomWidth = MAX(width / 2, 1);
int bloomHeight = MAX(height / 2, 1);
for (int i = 0; i < NumBloomLevels; i++)
@ -191,6 +209,17 @@ void FGLRenderBuffers::BindSceneFB()
glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB);
}
//==========================================================================
//
// Makes the 2D/HUD frame buffer active
//
//==========================================================================
void FGLRenderBuffers::BindHudFB()
{
glBindFramebuffer(GL_FRAMEBUFFER, mHudFB);
}
//==========================================================================
//
// Makes the screen frame buffer active
@ -213,3 +242,15 @@ void FGLRenderBuffers::BindSceneTexture(int index)
glActiveTexture(GL_TEXTURE0 + index);
glBindTexture(GL_TEXTURE_2D, mSceneTexture);
}
//==========================================================================
//
// Binds the 2D/HUD frame buffer texture to the specified texture unit
//
//==========================================================================
void FGLRenderBuffers::BindHudTexture(int index)
{
glActiveTexture(GL_TEXTURE0 + index);
glBindTexture(GL_TEXTURE_2D, mHudTexture);
}

View file

@ -22,8 +22,10 @@ public:
void Setup(int width, int height);
void BindSceneFB();
void BindHudFB();
void BindOutputFB();
void BindSceneTexture(int index);
void BindHudTexture(int index);
static bool IsSupported() { return gl.version >= 3.3f; }
@ -39,6 +41,8 @@ private:
GLuint mSceneTexture = 0;
GLuint mSceneDepthStencil = 0;
GLuint mSceneFB = 0;
GLuint mHudTexture = 0;
GLuint mHudFB = 0;
GLuint mOutputFB = 0;
};

View file

@ -64,6 +64,7 @@
#include "gl/shaders/gl_shader.h"
#include "gl/shaders/gl_bloomshader.h"
#include "gl/shaders/gl_blurshader.h"
#include "gl/shaders/gl_tonemapshader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/textures/gl_texture.h"
#include "gl/textures/gl_translate.h"
@ -115,6 +116,7 @@ void FGLRenderer::Initialize()
mBloomExtractShader = new FBloomExtractShader();
mBloomCombineShader = new FBloomCombineShader();
mBlurShader = new FBlurShader();
mTonemapShader = new FTonemapShader();
mPresentShader = new FPresentShader();
// Only needed for the core profile, because someone decided it was a good idea to remove the default VAO.
@ -168,6 +170,7 @@ FGLRenderer::~FGLRenderer()
if (mBloomExtractShader) delete mBloomExtractShader;
if (mBloomCombineShader) delete mBloomCombineShader;
if (mBlurShader) delete mBlurShader;
if (mTonemapShader) delete mTonemapShader;
}
//==========================================================================
@ -235,7 +238,10 @@ void FGLRenderer::Begin2D()
if (FGLRenderBuffers::IsSupported())
{
mBuffers->Setup(framebuffer->GetWidth(), framebuffer->GetHeight());
mBuffers->BindSceneFB();
if (mDrawingScene2D)
mBuffers->BindSceneFB();
else
mBuffers->BindHudFB();
glViewport(0, 0, mOutputViewport.width, mOutputViewport.height);
}
else

View file

@ -22,6 +22,7 @@ class FGLRenderBuffers;
class FBloomExtractShader;
class FBloomCombineShader;
class FBlurShader;
class FTonemapShader;
class FPresentShader;
inline float DEG2RAD(float deg)
@ -88,6 +89,7 @@ public:
FBloomExtractShader *mBloomExtractShader;
FBloomCombineShader *mBloomCombineShader;
FBlurShader *mBlurShader;
FTonemapShader *mTonemapShader;
FPresentShader *mPresentShader;
FTexture *gllight;
@ -106,6 +108,8 @@ public:
GL_IRECT mOutputViewportLB;
GL_IRECT mOutputViewport;
bool mDrawingScene2D = false;
float mCameraExposure = 1.0f;
FGLRenderer(OpenGLFrameBuffer *fb);
~FGLRenderer() ;
@ -154,6 +158,7 @@ public:
void WriteSavePic (player_t *player, FILE *file, int width, int height);
void EndDrawScene(sector_t * viewsector);
void BloomScene();
void TonemapScene();
void Flush();
void SetProjection(float fov, float ratio, float fovratio);

View file

@ -74,6 +74,7 @@
#include "gl/shaders/gl_shader.h"
#include "gl/shaders/gl_bloomshader.h"
#include "gl/shaders/gl_blurshader.h"
#include "gl/shaders/gl_tonemapshader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/stereo3d/gl_stereo3d.h"
#include "gl/stereo3d/scoped_view_shifter.h"
@ -219,11 +220,9 @@ void FGLRenderer::BloomScene()
const float blurAmount = 4.0f;
int sampleCount = 5; // Note: must be uneven number 3 to 15
float exposure = 2.0f;
float exposure = mCameraExposure;
auto vbo = GLRenderer->mVBO;
// TODO: Need a better way to share state with other parts of the pipeline
// TBD: Maybe need a better way to share state with other parts of the pipeline
GLboolean blendEnabled, scissorEnabled;
GLint currentProgram, blendEquationRgb, blendEquationAlpha, blendSrcRgb, blendSrcAlpha, blendDestRgb, blendDestAlpha;
glGetBooleanv(GL_BLEND, &blendEnabled);
@ -251,12 +250,12 @@ void FGLRenderer::BloomScene()
mBloomExtractShader->SceneTexture.Set(0);
mBloomExtractShader->Exposure.Set(exposure);
{
FFlatVertex *ptr = vbo->GetBuffer();
FFlatVertex *ptr = mVBO->GetBuffer();
ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++;
ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++;
vbo->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -266,8 +265,8 @@ void FGLRenderer::BloomScene()
{
const auto &level = mBuffers->BloomLevels[i];
const auto &next = mBuffers->BloomLevels[i + 1];
mBlurShader->BlurHorizontal(vbo, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height);
mBlurShader->BlurVertical(vbo, blurAmount, sampleCount, level.HTexture, next.VFramebuffer, next.Width, next.Height);
mBlurShader->BlurHorizontal(mVBO, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height);
mBlurShader->BlurVertical(mVBO, blurAmount, sampleCount, level.HTexture, next.VFramebuffer, next.Width, next.Height);
}
// Blur and upscale:
@ -276,8 +275,8 @@ void FGLRenderer::BloomScene()
const auto &level = mBuffers->BloomLevels[i];
const auto &next = mBuffers->BloomLevels[i - 1];
mBlurShader->BlurHorizontal(vbo, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height);
mBlurShader->BlurVertical(vbo, blurAmount, sampleCount, level.HTexture, level.VFramebuffer, level.Width, level.Height);
mBlurShader->BlurHorizontal(mVBO, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height);
mBlurShader->BlurVertical(mVBO, blurAmount, sampleCount, level.HTexture, level.VFramebuffer, level.Width, level.Height);
// Linear upscale:
glBindFramebuffer(GL_FRAMEBUFFER, next.VFramebuffer);
@ -289,17 +288,17 @@ void FGLRenderer::BloomScene()
mBloomCombineShader->Bind();
mBloomCombineShader->BloomTexture.Set(0);
{
FFlatVertex *ptr = vbo->GetBuffer();
FFlatVertex *ptr = mVBO->GetBuffer();
ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++;
ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++;
vbo->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
}
}
mBlurShader->BlurHorizontal(vbo, blurAmount, sampleCount, level0.VTexture, level0.HFramebuffer, level0.Width, level0.Height);
mBlurShader->BlurVertical(vbo, blurAmount, sampleCount, level0.HTexture, level0.VFramebuffer, level0.Width, level0.Height);
mBlurShader->BlurHorizontal(mVBO, blurAmount, sampleCount, level0.VTexture, level0.HFramebuffer, level0.Width, level0.Height);
mBlurShader->BlurVertical(mVBO, blurAmount, sampleCount, level0.HTexture, level0.VFramebuffer, level0.Width, level0.Height);
// Add bloom back to scene texture:
mBuffers->BindSceneFB();
@ -314,12 +313,12 @@ void FGLRenderer::BloomScene()
mBloomCombineShader->Bind();
mBloomCombineShader->BloomTexture.Set(0);
{
FFlatVertex *ptr = vbo->GetBuffer();
FFlatVertex *ptr = mVBO->GetBuffer();
ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++;
ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++;
vbo->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
}
if (blendEnabled)
@ -332,7 +331,41 @@ void FGLRenderer::BloomScene()
//-----------------------------------------------------------------------------
//
// Run post processing steps and copy to frame buffer
// Tonemap scene texture and place the result in the HUD/2D texture
//
//-----------------------------------------------------------------------------
void FGLRenderer::TonemapScene()
{
GLboolean blendEnabled, scissorEnabled;
glGetBooleanv(GL_BLEND, &blendEnabled);
glGetBooleanv(GL_SCISSOR_TEST, &scissorEnabled);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
mBuffers->BindHudFB();
mBuffers->BindSceneTexture(0);
mTonemapShader->Bind();
mTonemapShader->SceneTexture.Set(0);
mTonemapShader->Exposure.Set(mCameraExposure);
FFlatVertex *ptr = mVBO->GetBuffer();
ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++;
ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++;
mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
if (blendEnabled)
glEnable(GL_BLEND);
if (scissorEnabled)
glEnable(GL_SCISSOR_TEST);
}
//-----------------------------------------------------------------------------
//
// Gamma correct while copying to frame buffer
//
//-----------------------------------------------------------------------------
@ -406,7 +439,7 @@ void FGLRenderer::Flush()
mPresentShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
}
mBuffers->BindSceneTexture(0);
mBuffers->BindHudTexture(0);
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++;
@ -938,6 +971,7 @@ void FGLRenderer::EndDrawScene(sector_t * viewsector)
glDisable(GL_SCISSOR_TEST);
BloomScene();
TonemapScene();
}
@ -1042,6 +1076,13 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
mViewActor=camera;
}
if (toscreen)
{
float light = viewsector->lightlevel / 255.0f;
float exposure = MAX(1.0f + (1.0f - light * light) * 1.5f, 0.5f);
mCameraExposure = mCameraExposure * 0.98f + exposure * 0.02f;
}
// 'viewsector' will not survive the rendering so it cannot be used anymore below.
retval = viewsector;
@ -1056,6 +1097,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
// TODO: stereo specific viewport - needed when implementing side-by-side modes etc.
SetOutputViewport(bounds);
Set3DViewport();
mDrawingScene2D = true;
mCurrentFoV = fov;
// Stereo mode specific perspective projection
SetProjection( eye->GetProjection(fov, ratio, fovratio) );
@ -1073,6 +1115,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
ProcessScene(toscreen);
if (mainview) EndDrawScene(retval); // do not call this for camera textures.
mDrawingScene2D = false;
eye->TearDown();
}
stereo3dMode.TearDown();

View file

@ -80,32 +80,29 @@ void FBlurShader::BlurHorizontal(FFlatVertexBuffer *vbo, float blurAmount, int s
void FBlurShader::Blur(FFlatVertexBuffer *vbo, float blurAmount, int sampleCount, GLuint inputTexture, GLuint outputFrameBuffer, int width, int height, bool vertical)
{
int error = glGetError();
BlurSetup *setup = GetSetup(blurAmount, sampleCount);
error = glGetError();
if (vertical)
setup->VerticalShader->Bind();
else
setup->HorizontalShader->Bind();
error = glGetError();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, inputTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
error = glGetError();
glBindFramebuffer(GL_FRAMEBUFFER, outputFrameBuffer);
glViewport(0, 0, width, height);
glDisable(GL_BLEND);
error = glGetError();
FFlatVertex *ptr = vbo->GetBuffer();
ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.0f); ptr++;
ptr->Set(1.0f, -1.0f, 0, 1.0f, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++;
vbo->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
error = glGetError();
}
//==========================================================================
@ -138,9 +135,7 @@ FBlurShader::BlurSetup *FBlurShader::GetSetup(float blurAmount, int sampleCount)
blurSetup.VerticalShader->SetAttribLocation(0, "PositionInProjection");
blurSetup.VerticalShader->Link("vertical blur");
blurSetup.VerticalShader->Bind();
int error = glGetError();
glUniform1i(glGetUniformLocation(*blurSetup.VerticalShader.get(), "SourceTexture"), 0);
error = glGetError();
blurSetup.HorizontalShader = std::make_shared<FShaderProgram>();
blurSetup.HorizontalShader->Compile(FShaderProgram::Vertex, "horizontal blur vertex shader", vertexCode);

View file

@ -0,0 +1,65 @@
/*
** gl_tonemapshader.cpp
** Converts a HDR texture to 0-1 range by applying a tonemap operator
**
**---------------------------------------------------------------------------
** Copyright 2016 Magnus Norddahl
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be
** covered by the terms of the GNU Lesser General Public License as published
** by the Free Software Foundation; either version 2.1 of the License, or (at
** your option) any later version.
** 5. Full disclosure of the entire project's source code, except for third
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "gl/system/gl_system.h"
#include "files.h"
#include "m_swap.h"
#include "v_video.h"
#include "gl/gl_functions.h"
#include "vectors.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_tonemapshader.h"
void FTonemapShader::Bind()
{
if (!mShader)
{
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/tonemap.vp");
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/tonemap.fp");
mShader.SetFragDataLocation(0, "FragColor");
mShader.Link("shaders/glsl/tonemap");
mShader.SetAttribLocation(0, "PositionInProjection");
SceneTexture.Init(mShader, "InputTexture");
Exposure.Init(mShader, "ExposureAdjustment");
}
mShader.Bind();
}

View file

@ -0,0 +1,18 @@
#ifndef __GL_TONEMAPSHADER_H
#define __GL_TONEMAPSHADER_H
#include "gl_shaderprogram.h"
class FTonemapShader
{
public:
void Bind();
FBufferedUniform1i SceneTexture;
FBufferedUniform1f Exposure;
private:
FShaderProgram mShader;
};
#endif

View file

@ -158,7 +158,7 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
if (FGLRenderBuffers::IsSupported())
{
GLRenderer->mBuffers->BindSceneFB();
GLRenderer->mBuffers->BindHudFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);
}
else
@ -193,7 +193,7 @@ void OpenGLFrameBuffer::WipeEndScreen()
wipeendscreen->Bind(0, false, false);
if (FGLRenderBuffers::IsSupported())
GLRenderer->mBuffers->BindSceneFB();
GLRenderer->mBuffers->BindHudFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -232,7 +232,7 @@ bool OpenGLFrameBuffer::WipeDo(int ticks)
if (FGLRenderBuffers::IsSupported())
{
GLRenderer->mBuffers->BindSceneFB();
GLRenderer->mBuffers->BindHudFB();
glViewport(0, 0, GLRenderer->mOutputViewport.width, GLRenderer->mOutputViewport.height);
}

View file

@ -0,0 +1,65 @@
#version 330
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D InputTexture;
uniform float ExposureAdjustment;
vec3 Linear(vec3 c)
{
//return pow(c, 2.2);
return c * c; // cheaper, but assuming gamma of 2.0 instead of 2.2
}
vec3 sRGB(vec3 c)
{
//return pow(c, vec3(1.0 / 2.2));
return sqrt(c); // cheaper, but assuming gamma of 2.0 instead of 2.2
}
vec3 TonemapLinear(vec3 color)
{
return sRGB(color);
}
vec3 TonemapReinhard(vec3 color)
{
color = color / (1 + color);
return sRGB(color);
}
vec3 TonemapHejlDawson(vec3 color)
{
vec3 x = max(vec3(0), color - 0.004);
return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); // no sRGB needed
}
vec3 Uncharted2Tonemap(vec3 x)
{
float A = 0.15;
float B = 0.50;
float C = 0.10;
float D = 0.20;
float E = 0.02;
float F = 0.30;
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
}
vec3 TonemapUncharted2(vec3 color)
{
float W = 11.2;
float ExposureBias = 2.0;
vec3 curr = Uncharted2Tonemap(ExposureBias * color);
vec3 whiteScale = vec3(1) / Uncharted2Tonemap(vec3(W));
return sRGB(curr * whiteScale);
}
void main()
{
vec3 color = texture(InputTexture, TexCoord).rgb;
color = color * ExposureAdjustment;
color = Linear(color); // needed because gzdoom's scene texture is not linear at the moment
FragColor = vec4(TonemapUncharted2(color), 1.0);
}

View file

@ -0,0 +1,11 @@
#version 330
in vec4 PositionInProjection;
out vec2 TexCoord;
void main()
{
gl_Position = PositionInProjection;
TexCoord = PositionInProjection.xy * 0.5 + 0.5;
}