mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-27 06:02:18 +00:00
Added tonemapping and sector based exposure control
This commit is contained in:
parent
69f52cc898
commit
0efee85bd8
12 changed files with 284 additions and 30 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
65
src/gl/shaders/gl_tonemapshader.cpp
Normal file
65
src/gl/shaders/gl_tonemapshader.cpp
Normal 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();
|
||||||
|
}
|
18
src/gl/shaders/gl_tonemapshader.h
Normal file
18
src/gl/shaders/gl_tonemapshader.h
Normal 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
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
65
wadsrc/static/shaders/glsl/tonemap.fp
Normal file
65
wadsrc/static/shaders/glsl/tonemap.fp
Normal 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);
|
||||||
|
}
|
11
wadsrc/static/shaders/glsl/tonemap.vp
Normal file
11
wadsrc/static/shaders/glsl/tonemap.vp
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue