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_presentshader.cpp
gl/shaders/gl_bloomshader.cpp gl/shaders/gl_bloomshader.cpp
gl/shaders/gl_blurshader.cpp gl/shaders/gl_blurshader.cpp
gl/shaders/gl_tonemapshader.cpp
gl/system/gl_interface.cpp gl/system/gl_interface.cpp
gl/system/gl_framebuffer.cpp gl/system/gl_framebuffer.cpp
gl/system/gl_menu.cpp gl/system/gl_menu.cpp

View file

@ -97,10 +97,16 @@ void FGLRenderBuffers::Clear()
glDeleteTextures(1, &mSceneTexture); glDeleteTextures(1, &mSceneTexture);
if (mSceneDepthStencil != 0) if (mSceneDepthStencil != 0)
glDeleteRenderbuffers(1, &mSceneDepthStencil); glDeleteRenderbuffers(1, &mSceneDepthStencil);
if (mHudFB != 0)
glDeleteFramebuffers(1, &mHudFB);
if (mHudTexture != 0)
glDeleteTextures(1, &mHudTexture);
mSceneFB = 0; mSceneFB = 0;
mSceneTexture = 0; mSceneTexture = 0;
mSceneDepthStencil = 0; mSceneDepthStencil = 0;
mHudFB = 0;
mHudTexture = 0;
mWidth = 0; mWidth = 0;
mHeight = 0; mHeight = 0;
} }
@ -122,7 +128,9 @@ void FGLRenderBuffers::Setup(int width, int height)
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glGenFramebuffers(1, &mSceneFB); glGenFramebuffers(1, &mSceneFB);
glGenFramebuffers(1, &mHudFB);
glGenTextures(1, &mSceneTexture); glGenTextures(1, &mSceneTexture);
glGenTextures(1, &mHudTexture);
glGenRenderbuffers(1, &mSceneDepthStencil); glGenRenderbuffers(1, &mSceneDepthStencil);
glBindTexture(GL_TEXTURE_2D, mSceneTexture); 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); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mSceneTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mSceneDepthStencil); 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 bloomWidth = MAX(width / 2, 1);
int bloomHeight = MAX(height / 2, 1); int bloomHeight = MAX(height / 2, 1);
for (int i = 0; i < NumBloomLevels; i++) for (int i = 0; i < NumBloomLevels; i++)
@ -191,6 +209,17 @@ void FGLRenderBuffers::BindSceneFB()
glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB); glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB);
} }
//==========================================================================
//
// Makes the 2D/HUD frame buffer active
//
//==========================================================================
void FGLRenderBuffers::BindHudFB()
{
glBindFramebuffer(GL_FRAMEBUFFER, mHudFB);
}
//========================================================================== //==========================================================================
// //
// Makes the screen frame buffer active // Makes the screen frame buffer active
@ -213,3 +242,15 @@ void FGLRenderBuffers::BindSceneTexture(int index)
glActiveTexture(GL_TEXTURE0 + index); glActiveTexture(GL_TEXTURE0 + index);
glBindTexture(GL_TEXTURE_2D, mSceneTexture); 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 Setup(int width, int height);
void BindSceneFB(); void BindSceneFB();
void BindHudFB();
void BindOutputFB(); void BindOutputFB();
void BindSceneTexture(int index); void BindSceneTexture(int index);
void BindHudTexture(int index);
static bool IsSupported() { return gl.version >= 3.3f; } static bool IsSupported() { return gl.version >= 3.3f; }
@ -39,6 +41,8 @@ private:
GLuint mSceneTexture = 0; GLuint mSceneTexture = 0;
GLuint mSceneDepthStencil = 0; GLuint mSceneDepthStencil = 0;
GLuint mSceneFB = 0; GLuint mSceneFB = 0;
GLuint mHudTexture = 0;
GLuint mHudFB = 0;
GLuint mOutputFB = 0; GLuint mOutputFB = 0;
}; };

View file

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

View file

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

View file

@ -74,6 +74,7 @@
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
#include "gl/shaders/gl_bloomshader.h" #include "gl/shaders/gl_bloomshader.h"
#include "gl/shaders/gl_blurshader.h" #include "gl/shaders/gl_blurshader.h"
#include "gl/shaders/gl_tonemapshader.h"
#include "gl/shaders/gl_presentshader.h" #include "gl/shaders/gl_presentshader.h"
#include "gl/stereo3d/gl_stereo3d.h" #include "gl/stereo3d/gl_stereo3d.h"
#include "gl/stereo3d/scoped_view_shifter.h" #include "gl/stereo3d/scoped_view_shifter.h"
@ -219,11 +220,9 @@ void FGLRenderer::BloomScene()
const float blurAmount = 4.0f; const float blurAmount = 4.0f;
int sampleCount = 5; // Note: must be uneven number 3 to 15 int sampleCount = 5; // Note: must be uneven number 3 to 15
float exposure = 2.0f; float exposure = mCameraExposure;
auto vbo = GLRenderer->mVBO; // TBD: Maybe need a better way to share state with other parts of the pipeline
// TODO: Need a better way to share state with other parts of the pipeline
GLboolean blendEnabled, scissorEnabled; GLboolean blendEnabled, scissorEnabled;
GLint currentProgram, blendEquationRgb, blendEquationAlpha, blendSrcRgb, blendSrcAlpha, blendDestRgb, blendDestAlpha; GLint currentProgram, blendEquationRgb, blendEquationAlpha, blendSrcRgb, blendSrcAlpha, blendDestRgb, blendDestAlpha;
glGetBooleanv(GL_BLEND, &blendEnabled); glGetBooleanv(GL_BLEND, &blendEnabled);
@ -251,12 +250,12 @@ void FGLRenderer::BloomScene()
mBloomExtractShader->SceneTexture.Set(0); mBloomExtractShader->SceneTexture.Set(0);
mBloomExtractShader->Exposure.Set(exposure); 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, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.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, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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 &level = mBuffers->BloomLevels[i];
const auto &next = mBuffers->BloomLevels[i + 1]; const auto &next = mBuffers->BloomLevels[i + 1];
mBlurShader->BlurHorizontal(vbo, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height); mBlurShader->BlurHorizontal(mVBO, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height);
mBlurShader->BlurVertical(vbo, blurAmount, sampleCount, level.HTexture, next.VFramebuffer, next.Width, next.Height); mBlurShader->BlurVertical(mVBO, blurAmount, sampleCount, level.HTexture, next.VFramebuffer, next.Width, next.Height);
} }
// Blur and upscale: // Blur and upscale:
@ -276,8 +275,8 @@ void FGLRenderer::BloomScene()
const auto &level = mBuffers->BloomLevels[i]; const auto &level = mBuffers->BloomLevels[i];
const auto &next = mBuffers->BloomLevels[i - 1]; const auto &next = mBuffers->BloomLevels[i - 1];
mBlurShader->BlurHorizontal(vbo, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height); mBlurShader->BlurHorizontal(mVBO, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height);
mBlurShader->BlurVertical(vbo, blurAmount, sampleCount, level.HTexture, level.VFramebuffer, level.Width, level.Height); mBlurShader->BlurVertical(mVBO, blurAmount, sampleCount, level.HTexture, level.VFramebuffer, level.Width, level.Height);
// Linear upscale: // Linear upscale:
glBindFramebuffer(GL_FRAMEBUFFER, next.VFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, next.VFramebuffer);
@ -289,17 +288,17 @@ void FGLRenderer::BloomScene()
mBloomCombineShader->Bind(); mBloomCombineShader->Bind();
mBloomCombineShader->BloomTexture.Set(0); 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, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.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, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.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->BlurHorizontal(mVBO, blurAmount, sampleCount, level0.VTexture, level0.HFramebuffer, level0.Width, level0.Height);
mBlurShader->BlurVertical(vbo, blurAmount, sampleCount, level0.HTexture, level0.VFramebuffer, level0.Width, level0.Height); mBlurShader->BlurVertical(mVBO, blurAmount, sampleCount, level0.HTexture, level0.VFramebuffer, level0.Width, level0.Height);
// Add bloom back to scene texture: // Add bloom back to scene texture:
mBuffers->BindSceneFB(); mBuffers->BindSceneFB();
@ -314,12 +313,12 @@ void FGLRenderer::BloomScene()
mBloomCombineShader->Bind(); mBloomCombineShader->Bind();
mBloomCombineShader->BloomTexture.Set(0); 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, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.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, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.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) 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->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f)); mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
} }
mBuffers->BindSceneTexture(0); mBuffers->BindHudTexture(0);
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); ptr++; 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); glDisable(GL_SCISSOR_TEST);
BloomScene(); BloomScene();
TonemapScene();
} }
@ -1042,6 +1076,13 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
mViewActor=camera; 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. // 'viewsector' will not survive the rendering so it cannot be used anymore below.
retval = viewsector; 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. // TODO: stereo specific viewport - needed when implementing side-by-side modes etc.
SetOutputViewport(bounds); SetOutputViewport(bounds);
Set3DViewport(); Set3DViewport();
mDrawingScene2D = true;
mCurrentFoV = fov; mCurrentFoV = fov;
// Stereo mode specific perspective projection // Stereo mode specific perspective projection
SetProjection( eye->GetProjection(fov, ratio, fovratio) ); SetProjection( eye->GetProjection(fov, ratio, fovratio) );
@ -1073,6 +1115,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
ProcessScene(toscreen); ProcessScene(toscreen);
if (mainview) EndDrawScene(retval); // do not call this for camera textures. if (mainview) EndDrawScene(retval); // do not call this for camera textures.
mDrawingScene2D = false;
eye->TearDown(); eye->TearDown();
} }
stereo3dMode.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) 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); BlurSetup *setup = GetSetup(blurAmount, sampleCount);
error = glGetError();
if (vertical) if (vertical)
setup->VerticalShader->Bind(); setup->VerticalShader->Bind();
else else
setup->HorizontalShader->Bind(); setup->HorizontalShader->Bind();
error = glGetError();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, inputTexture); glBindTexture(GL_TEXTURE_2D, inputTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
error = glGetError();
glBindFramebuffer(GL_FRAMEBUFFER, outputFrameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, outputFrameBuffer);
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
glDisable(GL_BLEND); glDisable(GL_BLEND);
error = glGetError();
FFlatVertex *ptr = vbo->GetBuffer(); 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, 0.0f); ptr++;
ptr->Set(-1.0f, 1.0f, 0, 0.0f, 1.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, 0.0f); ptr++;
ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++; ptr->Set(1.0f, 1.0f, 0, 1.0f, 1.0f); ptr++;
vbo->RenderCurrent(ptr, GL_TRIANGLE_STRIP); 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->SetAttribLocation(0, "PositionInProjection");
blurSetup.VerticalShader->Link("vertical blur"); blurSetup.VerticalShader->Link("vertical blur");
blurSetup.VerticalShader->Bind(); blurSetup.VerticalShader->Bind();
int error = glGetError();
glUniform1i(glGetUniformLocation(*blurSetup.VerticalShader.get(), "SourceTexture"), 0); glUniform1i(glGetUniformLocation(*blurSetup.VerticalShader.get(), "SourceTexture"), 0);
error = glGetError();
blurSetup.HorizontalShader = std::make_shared<FShaderProgram>(); blurSetup.HorizontalShader = std::make_shared<FShaderProgram>();
blurSetup.HorizontalShader->Compile(FShaderProgram::Vertex, "horizontal blur vertex shader", vertexCode); 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()) if (FGLRenderBuffers::IsSupported())
{ {
GLRenderer->mBuffers->BindSceneFB(); GLRenderer->mBuffers->BindHudFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);
} }
else else
@ -193,7 +193,7 @@ void OpenGLFrameBuffer::WipeEndScreen()
wipeendscreen->Bind(0, false, false); wipeendscreen->Bind(0, false, false);
if (FGLRenderBuffers::IsSupported()) if (FGLRenderBuffers::IsSupported())
GLRenderer->mBuffers->BindSceneFB(); GLRenderer->mBuffers->BindHudFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -232,7 +232,7 @@ bool OpenGLFrameBuffer::WipeDo(int ticks)
if (FGLRenderBuffers::IsSupported()) if (FGLRenderBuffers::IsSupported())
{ {
GLRenderer->mBuffers->BindSceneFB(); GLRenderer->mBuffers->BindHudFB();
glViewport(0, 0, GLRenderer->mOutputViewport.width, GLRenderer->mOutputViewport.height); 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;
}