mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 12:32:34 +00:00
Added bloom shaders
This commit is contained in:
parent
c9f93d9c88
commit
69f52cc898
16 changed files with 696 additions and 14 deletions
|
@ -1106,6 +1106,8 @@ set( FASTMATH_SOURCES
|
||||||
gl/shaders/gl_texshader.cpp
|
gl/shaders/gl_texshader.cpp
|
||||||
gl/shaders/gl_shaderprogram.cpp
|
gl/shaders/gl_shaderprogram.cpp
|
||||||
gl/shaders/gl_presentshader.cpp
|
gl/shaders/gl_presentshader.cpp
|
||||||
|
gl/shaders/gl_bloomshader.cpp
|
||||||
|
gl/shaders/gl_blurshader.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
|
||||||
|
|
|
@ -72,12 +72,37 @@ FGLRenderBuffers::FGLRenderBuffers()
|
||||||
|
|
||||||
FGLRenderBuffers::~FGLRenderBuffers()
|
FGLRenderBuffers::~FGLRenderBuffers()
|
||||||
{
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGLRenderBuffers::Clear()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NumBloomLevels; i++)
|
||||||
|
{
|
||||||
|
auto &level = BloomLevels[i];
|
||||||
|
if (level.HFramebuffer != 0)
|
||||||
|
glDeleteFramebuffers(1, &level.HFramebuffer);
|
||||||
|
if (level.VFramebuffer != 0)
|
||||||
|
glDeleteFramebuffers(1, &level.VFramebuffer);
|
||||||
|
if (level.HTexture != 0)
|
||||||
|
glDeleteTextures(1, &level.HTexture);
|
||||||
|
if (level.VTexture != 0)
|
||||||
|
glDeleteTextures(1, &level.VTexture);
|
||||||
|
level = FGLBloomTextureLevel();
|
||||||
|
}
|
||||||
|
|
||||||
if (mSceneFB != 0)
|
if (mSceneFB != 0)
|
||||||
glDeleteFramebuffers(1, &mSceneFB);
|
glDeleteFramebuffers(1, &mSceneFB);
|
||||||
if (mSceneTexture != 0)
|
if (mSceneTexture != 0)
|
||||||
glDeleteTextures(1, &mSceneTexture);
|
glDeleteTextures(1, &mSceneTexture);
|
||||||
if (mSceneDepthStencil != 0)
|
if (mSceneDepthStencil != 0)
|
||||||
glDeleteRenderbuffers(1, &mSceneDepthStencil);
|
glDeleteRenderbuffers(1, &mSceneDepthStencil);
|
||||||
|
|
||||||
|
mSceneFB = 0;
|
||||||
|
mSceneTexture = 0;
|
||||||
|
mSceneDepthStencil = 0;
|
||||||
|
mWidth = 0;
|
||||||
|
mHeight = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -92,12 +117,9 @@ void FGLRenderBuffers::Setup(int width, int height)
|
||||||
if (width <= mWidth && height <= mHeight)
|
if (width <= mWidth && height <= mHeight)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mSceneFB != 0)
|
Clear();
|
||||||
glDeleteFramebuffers(1, &mSceneFB);
|
|
||||||
if (mSceneTexture != 0)
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glDeleteTextures(1, &mSceneTexture);
|
|
||||||
if (mSceneDepthStencil != 0)
|
|
||||||
glDeleteRenderbuffers(1, &mSceneDepthStencil);
|
|
||||||
|
|
||||||
glGenFramebuffers(1, &mSceneFB);
|
glGenFramebuffers(1, &mSceneFB);
|
||||||
glGenTextures(1, &mSceneTexture);
|
glGenTextures(1, &mSceneTexture);
|
||||||
|
@ -109,15 +131,49 @@ void FGLRenderBuffers::Setup(int width, int height)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_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);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, mSceneDepthStencil);
|
glBindRenderbuffer(GL_RENDERBUFFER, mSceneDepthStencil);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB);
|
glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB);
|
||||||
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);
|
||||||
|
|
||||||
|
int bloomWidth = MAX(width / 2, 1);
|
||||||
|
int bloomHeight = MAX(height / 2, 1);
|
||||||
|
for (int i = 0; i < NumBloomLevels; i++)
|
||||||
|
{
|
||||||
|
auto &level = BloomLevels[i];
|
||||||
|
level.Width = MAX(bloomWidth / 2, 1);
|
||||||
|
level.Height = MAX(bloomHeight / 2, 1);
|
||||||
|
|
||||||
|
glGenTextures(1, &level.VTexture);
|
||||||
|
glGenTextures(1, &level.HTexture);
|
||||||
|
glGenFramebuffers(1, &level.VFramebuffer);
|
||||||
|
glGenFramebuffers(1, &level.HFramebuffer);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, level.VTexture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, level.Width, level.Height, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, level.HTexture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, level.Width, level.Height, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||||
|
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, level.VFramebuffer);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, level.VTexture, 0);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, level.HFramebuffer);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, level.HTexture, 0);
|
||||||
|
|
||||||
|
bloomWidth = level.Width;
|
||||||
|
bloomHeight = level.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mOutputFB);
|
glBindFramebuffer(GL_FRAMEBUFFER, mOutputFB);
|
||||||
|
|
||||||
mWidth = width;
|
mWidth = width;
|
||||||
|
@ -154,6 +210,6 @@ void FGLRenderBuffers::BindOutputFB()
|
||||||
|
|
||||||
void FGLRenderBuffers::BindSceneTexture(int index)
|
void FGLRenderBuffers::BindSceneTexture(int index)
|
||||||
{
|
{
|
||||||
glActiveTexture(index);
|
glActiveTexture(GL_TEXTURE0 + index);
|
||||||
glBindTexture(GL_TEXTURE_2D, mSceneTexture);
|
glBindTexture(GL_TEXTURE_2D, mSceneTexture);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,17 @@
|
||||||
|
|
||||||
#include "gl/shaders/gl_shader.h"
|
#include "gl/shaders/gl_shader.h"
|
||||||
|
|
||||||
|
class FGLBloomTextureLevel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLuint VTexture = 0;
|
||||||
|
GLuint VFramebuffer = 0;
|
||||||
|
GLuint HTexture = 0;
|
||||||
|
GLuint HFramebuffer = 0;
|
||||||
|
GLuint Width = 0;
|
||||||
|
GLuint Height = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class FGLRenderBuffers
|
class FGLRenderBuffers
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -16,7 +27,12 @@ public:
|
||||||
|
|
||||||
static bool IsSupported() { return gl.version >= 3.3f; }
|
static bool IsSupported() { return gl.version >= 3.3f; }
|
||||||
|
|
||||||
|
enum { NumBloomLevels = 4 };
|
||||||
|
FGLBloomTextureLevel BloomLevels[NumBloomLevels];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void Clear();
|
||||||
|
|
||||||
int mWidth = 0;
|
int mWidth = 0;
|
||||||
int mHeight = 0;
|
int mHeight = 0;
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,8 @@
|
||||||
#include "gl/data/gl_vertexbuffer.h"
|
#include "gl/data/gl_vertexbuffer.h"
|
||||||
#include "gl/scene/gl_drawinfo.h"
|
#include "gl/scene/gl_drawinfo.h"
|
||||||
#include "gl/shaders/gl_shader.h"
|
#include "gl/shaders/gl_shader.h"
|
||||||
|
#include "gl/shaders/gl_bloomshader.h"
|
||||||
|
#include "gl/shaders/gl_blurshader.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"
|
||||||
|
@ -110,6 +112,9 @@ void gl_FlushModels();
|
||||||
void FGLRenderer::Initialize()
|
void FGLRenderer::Initialize()
|
||||||
{
|
{
|
||||||
mBuffers = new FGLRenderBuffers();
|
mBuffers = new FGLRenderBuffers();
|
||||||
|
mBloomExtractShader = new FBloomExtractShader();
|
||||||
|
mBloomCombineShader = new FBloomCombineShader();
|
||||||
|
mBlurShader = new FBlurShader();
|
||||||
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.
|
||||||
|
@ -160,6 +165,9 @@ FGLRenderer::~FGLRenderer()
|
||||||
}
|
}
|
||||||
if (mBuffers) delete mBuffers;
|
if (mBuffers) delete mBuffers;
|
||||||
if (mPresentShader) delete mPresentShader;
|
if (mPresentShader) delete mPresentShader;
|
||||||
|
if (mBloomExtractShader) delete mBloomExtractShader;
|
||||||
|
if (mBloomCombineShader) delete mBloomCombineShader;
|
||||||
|
if (mBlurShader) delete mBlurShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -19,6 +19,9 @@ class FLightBuffer;
|
||||||
class FSamplerManager;
|
class FSamplerManager;
|
||||||
class DPSprite;
|
class DPSprite;
|
||||||
class FGLRenderBuffers;
|
class FGLRenderBuffers;
|
||||||
|
class FBloomExtractShader;
|
||||||
|
class FBloomCombineShader;
|
||||||
|
class FBlurShader;
|
||||||
class FPresentShader;
|
class FPresentShader;
|
||||||
|
|
||||||
inline float DEG2RAD(float deg)
|
inline float DEG2RAD(float deg)
|
||||||
|
@ -82,6 +85,9 @@ public:
|
||||||
int mOldFBID;
|
int mOldFBID;
|
||||||
|
|
||||||
FGLRenderBuffers *mBuffers;
|
FGLRenderBuffers *mBuffers;
|
||||||
|
FBloomExtractShader *mBloomExtractShader;
|
||||||
|
FBloomCombineShader *mBloomCombineShader;
|
||||||
|
FBlurShader *mBlurShader;
|
||||||
FPresentShader *mPresentShader;
|
FPresentShader *mPresentShader;
|
||||||
|
|
||||||
FTexture *gllight;
|
FTexture *gllight;
|
||||||
|
@ -147,6 +153,7 @@ public:
|
||||||
void SetFixedColormap (player_t *player);
|
void SetFixedColormap (player_t *player);
|
||||||
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 Flush();
|
void Flush();
|
||||||
|
|
||||||
void SetProjection(float fov, float ratio, float fovratio);
|
void SetProjection(float fov, float ratio, float fovratio);
|
||||||
|
|
|
@ -72,6 +72,8 @@
|
||||||
#include "gl/scene/gl_drawinfo.h"
|
#include "gl/scene/gl_drawinfo.h"
|
||||||
#include "gl/scene/gl_portal.h"
|
#include "gl/scene/gl_portal.h"
|
||||||
#include "gl/shaders/gl_shader.h"
|
#include "gl/shaders/gl_shader.h"
|
||||||
|
#include "gl/shaders/gl_bloomshader.h"
|
||||||
|
#include "gl/shaders/gl_blurshader.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"
|
||||||
|
@ -204,6 +206,130 @@ void FGLRenderer::Set3DViewport()
|
||||||
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
|
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Adds bloom contribution to scene texture
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FGLRenderer::BloomScene()
|
||||||
|
{
|
||||||
|
if (!FGLRenderBuffers::IsSupported())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const float blurAmount = 4.0f;
|
||||||
|
int sampleCount = 5; // Note: must be uneven number 3 to 15
|
||||||
|
float exposure = 2.0f;
|
||||||
|
|
||||||
|
auto vbo = GLRenderer->mVBO;
|
||||||
|
|
||||||
|
// TODO: 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);
|
||||||
|
glGetBooleanv(GL_SCISSOR_TEST, &scissorEnabled);
|
||||||
|
glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram);
|
||||||
|
glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRgb);
|
||||||
|
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
|
||||||
|
glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRgb);
|
||||||
|
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
|
||||||
|
glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRgb);
|
||||||
|
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
const auto &level0 = mBuffers->BloomLevels[0];
|
||||||
|
|
||||||
|
// Extract blooming pixels from scene texture:
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, level0.VFramebuffer);
|
||||||
|
glViewport(0, 0, level0.Width, level0.Height);
|
||||||
|
mBuffers->BindSceneTexture(0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
mBloomExtractShader->Bind();
|
||||||
|
mBloomExtractShader->SceneTexture.Set(0);
|
||||||
|
mBloomExtractShader->Exposure.Set(exposure);
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
// Blur and downscale:
|
||||||
|
for (int i = 0; i < FGLRenderBuffers::NumBloomLevels - 1; i++)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blur and upscale:
|
||||||
|
for (int i = FGLRenderBuffers::NumBloomLevels - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Linear upscale:
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, next.VFramebuffer);
|
||||||
|
glViewport(0, 0, next.Width, next.Height);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, level.VTexture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
mBloomCombineShader->Bind();
|
||||||
|
mBloomCombineShader->BloomTexture.Set(0);
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Add bloom back to scene texture:
|
||||||
|
mBuffers->BindSceneFB();
|
||||||
|
glViewport(0, 0, mOutputViewport.width, mOutputViewport.height);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, level0.VTexture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
mBloomCombineShader->Bind();
|
||||||
|
mBloomCombineShader->BloomTexture.Set(0);
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blendEnabled)
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
if (scissorEnabled)
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glBlendEquationSeparate(blendEquationRgb, blendEquationAlpha);
|
||||||
|
glBlendFuncSeparate(blendSrcRgb, blendDestRgb, blendSrcAlpha, blendDestAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Run post processing steps and copy to frame buffer
|
// Run post processing steps and copy to frame buffer
|
||||||
|
@ -810,6 +936,8 @@ void FGLRenderer::EndDrawScene(sector_t * viewsector)
|
||||||
gl_RenderState.ResetColor();
|
gl_RenderState.ResetColor();
|
||||||
gl_RenderState.EnableTexture(true);
|
gl_RenderState.EnableTexture(true);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
BloomScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
79
src/gl/shaders/gl_bloomshader.cpp
Normal file
79
src/gl/shaders/gl_bloomshader.cpp
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
** gl_bloomshader.cpp
|
||||||
|
** Shaders used to do bloom
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** 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_bloomshader.h"
|
||||||
|
|
||||||
|
void FBloomExtractShader::Bind()
|
||||||
|
{
|
||||||
|
if (!mShader)
|
||||||
|
{
|
||||||
|
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/bloomextract.vp");
|
||||||
|
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/bloomextract.fp");
|
||||||
|
mShader.SetFragDataLocation(0, "FragColor");
|
||||||
|
mShader.Link("shaders/glsl/bloomextract");
|
||||||
|
mShader.SetAttribLocation(0, "PositionInProjection");
|
||||||
|
SceneTexture.Init(mShader, "SceneTexture");
|
||||||
|
Exposure.Init(mShader, "ExposureAdjustment");
|
||||||
|
}
|
||||||
|
mShader.Bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBloomCombineShader::Bind()
|
||||||
|
{
|
||||||
|
if (!mShader)
|
||||||
|
{
|
||||||
|
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/bloomcombine.vp");
|
||||||
|
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/bloomcombine.fp");
|
||||||
|
mShader.SetFragDataLocation(0, "FragColor");
|
||||||
|
mShader.Link("shaders/glsl/bloomcombine");
|
||||||
|
mShader.SetAttribLocation(0, "PositionInProjection");
|
||||||
|
BloomTexture.Init(mShader, "Bloom");
|
||||||
|
}
|
||||||
|
mShader.Bind();
|
||||||
|
}
|
29
src/gl/shaders/gl_bloomshader.h
Normal file
29
src/gl/shaders/gl_bloomshader.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef __GL_BLOOMSHADER_H
|
||||||
|
#define __GL_BLOOMSHADER_H
|
||||||
|
|
||||||
|
#include "gl_shaderprogram.h"
|
||||||
|
|
||||||
|
class FBloomExtractShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Bind();
|
||||||
|
|
||||||
|
FBufferedUniform1i SceneTexture;
|
||||||
|
FBufferedUniform1f Exposure;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FShaderProgram mShader;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FBloomCombineShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Bind();
|
||||||
|
|
||||||
|
FBufferedUniform1i BloomTexture;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FShaderProgram mShader;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
265
src/gl/shaders/gl_blurshader.cpp
Normal file
265
src/gl/shaders/gl_blurshader.cpp
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
** gl_blurshader.cpp
|
||||||
|
** Gaussian blur shader
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** 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_blurshader.h"
|
||||||
|
#include "gl/data/gl_vertexbuffer.h"
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Performs a vertical gaussian blur pass
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FBlurShader::BlurVertical(FFlatVertexBuffer *vbo, float blurAmount, int sampleCount, GLuint inputTexture, GLuint outputFrameBuffer, int width, int height)
|
||||||
|
{
|
||||||
|
Blur(vbo, blurAmount, sampleCount, inputTexture, outputFrameBuffer, width, height, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Performs a horizontal gaussian blur pass
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FBlurShader::BlurHorizontal(FFlatVertexBuffer *vbo, float blurAmount, int sampleCount, GLuint inputTexture, GLuint outputFrameBuffer, int width, int height)
|
||||||
|
{
|
||||||
|
Blur(vbo, blurAmount, sampleCount, inputTexture, outputFrameBuffer, width, height, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Helper for BlurVertical and BlurHorizontal. Executes the actual pass
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Compiles the blur shaders needed for the specified blur amount and
|
||||||
|
// kernel size
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FBlurShader::BlurSetup *FBlurShader::GetSetup(float blurAmount, int sampleCount)
|
||||||
|
{
|
||||||
|
for (size_t mBlurSetupIndex = 0; mBlurSetupIndex < mBlurSetups.Size(); mBlurSetupIndex++)
|
||||||
|
{
|
||||||
|
if (mBlurSetups[mBlurSetupIndex].blurAmount == blurAmount && mBlurSetups[mBlurSetupIndex].sampleCount == sampleCount)
|
||||||
|
{
|
||||||
|
return &mBlurSetups[mBlurSetupIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlurSetup blurSetup(blurAmount, sampleCount);
|
||||||
|
|
||||||
|
FString vertexCode = VertexShaderCode();
|
||||||
|
FString horizontalCode = FragmentShaderCode(blurAmount, sampleCount, false);
|
||||||
|
FString verticalCode = FragmentShaderCode(blurAmount, sampleCount, true);
|
||||||
|
|
||||||
|
blurSetup.VerticalShader = std::make_shared<FShaderProgram>();
|
||||||
|
blurSetup.VerticalShader->Compile(FShaderProgram::Vertex, "vertical blur vertex shader", vertexCode);
|
||||||
|
blurSetup.VerticalShader->Compile(FShaderProgram::Fragment, "vertical blur fragment shader", verticalCode);
|
||||||
|
blurSetup.VerticalShader->SetFragDataLocation(0, "FragColor");
|
||||||
|
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);
|
||||||
|
blurSetup.HorizontalShader->Compile(FShaderProgram::Fragment, "horizontal blur fragment shader", horizontalCode);
|
||||||
|
blurSetup.HorizontalShader->SetFragDataLocation(0, "FragColor");
|
||||||
|
blurSetup.HorizontalShader->SetAttribLocation(0, "PositionInProjection");
|
||||||
|
blurSetup.HorizontalShader->Link("horizontal blur");
|
||||||
|
blurSetup.HorizontalShader->Bind();
|
||||||
|
glUniform1i(glGetUniformLocation(*blurSetup.HorizontalShader.get(), "SourceTexture"), 0);
|
||||||
|
|
||||||
|
mBlurSetups.Push(blurSetup);
|
||||||
|
|
||||||
|
return &mBlurSetups[mBlurSetups.Size() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// The vertex shader GLSL code
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString FBlurShader::VertexShaderCode()
|
||||||
|
{
|
||||||
|
return R"(
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec4 PositionInProjection;
|
||||||
|
out vec2 TexCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = PositionInProjection;
|
||||||
|
TexCoord = (gl_Position.xy + 1.0) * 0.5;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Generates the fragment shader GLSL code for a specific blur setup
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString FBlurShader::FragmentShaderCode(float blurAmount, int sampleCount, bool vertical)
|
||||||
|
{
|
||||||
|
TArray<float> sampleWeights;
|
||||||
|
TArray<int> sampleOffsets;
|
||||||
|
ComputeBlurSamples(sampleCount, blurAmount, sampleWeights, sampleOffsets);
|
||||||
|
|
||||||
|
const char *fragmentShader =
|
||||||
|
R"(
|
||||||
|
#version 330
|
||||||
|
in vec2 TexCoord;
|
||||||
|
uniform sampler2D SourceTexture;
|
||||||
|
out vec4 FragColor;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = %s;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
FString loopCode;
|
||||||
|
for (int i = 0; i < sampleCount; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
loopCode += " + ";
|
||||||
|
|
||||||
|
if (vertical)
|
||||||
|
loopCode.AppendFormat("\r\n\t\t\ttextureOffset(SourceTexture, TexCoord, ivec2(0, %d)) * %f", sampleOffsets[i], (double)sampleWeights[i]);
|
||||||
|
else
|
||||||
|
loopCode.AppendFormat("\r\n\t\t\ttextureOffset(SourceTexture, TexCoord, ivec2(%d, 0)) * %f", sampleOffsets[i], (double)sampleWeights[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FString code;
|
||||||
|
code.Format(fragmentShader, loopCode.GetChars());
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Calculates the sample weight for a specific offset in the kernel
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
float FBlurShader::ComputeGaussian(float n, float theta) // theta = Blur Amount
|
||||||
|
{
|
||||||
|
return (float)((1.0f / sqrtf(2 * (float)M_PI * theta)) * expf(-(n * n) / (2.0f * theta * theta)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Calculates the sample weights and offsets
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FBlurShader::ComputeBlurSamples(int sampleCount, float blurAmount, TArray<float> &sampleWeights, TArray<int> &sampleOffsets)
|
||||||
|
{
|
||||||
|
sampleWeights.Resize(sampleCount);
|
||||||
|
sampleOffsets.Resize(sampleCount);
|
||||||
|
|
||||||
|
sampleWeights[0] = ComputeGaussian(0, blurAmount);
|
||||||
|
sampleOffsets[0] = 0;
|
||||||
|
|
||||||
|
float totalWeights = sampleWeights[0];
|
||||||
|
|
||||||
|
for (int i = 0; i < sampleCount / 2; i++)
|
||||||
|
{
|
||||||
|
float weight = ComputeGaussian(i + 1.0f, blurAmount);
|
||||||
|
|
||||||
|
sampleWeights[i * 2 + 1] = weight;
|
||||||
|
sampleWeights[i * 2 + 2] = weight;
|
||||||
|
sampleOffsets[i * 2 + 1] = i + 1;
|
||||||
|
sampleOffsets[i * 2 + 2] = -i - 1;
|
||||||
|
|
||||||
|
totalWeights += weight * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sampleCount; i++)
|
||||||
|
{
|
||||||
|
sampleWeights[i] /= totalWeights;
|
||||||
|
}
|
||||||
|
}
|
39
src/gl/shaders/gl_blurshader.h
Normal file
39
src/gl/shaders/gl_blurshader.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef __GL_BLURSHADER_H
|
||||||
|
#define __GL_BLURSHADER_H
|
||||||
|
|
||||||
|
#include "gl_shaderprogram.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class FFlatVertexBuffer;
|
||||||
|
|
||||||
|
class FBlurShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void BlurVertical(FFlatVertexBuffer *vbo, float blurAmount, int sampleCount, GLuint inputTexture, GLuint outputFrameBuffer, int width, int height);
|
||||||
|
void BlurHorizontal(FFlatVertexBuffer *vbo, float blurAmount, int sampleCount, GLuint inputTexture, GLuint outputFrameBuffer, int width, int height);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Blur(FFlatVertexBuffer *vbo, float blurAmount, int sampleCount, GLuint inputTexture, GLuint outputFrameBuffer, int width, int height, bool vertical);
|
||||||
|
|
||||||
|
struct BlurSetup
|
||||||
|
{
|
||||||
|
BlurSetup(float blurAmount, int sampleCount) : blurAmount(blurAmount), sampleCount(sampleCount) { }
|
||||||
|
|
||||||
|
float blurAmount;
|
||||||
|
int sampleCount;
|
||||||
|
std::shared_ptr<FShaderProgram> VerticalShader;
|
||||||
|
std::shared_ptr<FShaderProgram> HorizontalShader;
|
||||||
|
};
|
||||||
|
|
||||||
|
BlurSetup *GetSetup(float blurAmount, int sampleCount);
|
||||||
|
|
||||||
|
FString VertexShaderCode();
|
||||||
|
FString FragmentShaderCode(float blurAmount, int sampleCount, bool vertical);
|
||||||
|
|
||||||
|
float ComputeGaussian(float n, float theta);
|
||||||
|
void ComputeBlurSamples(int sampleCount, float blurAmount, TArray<float> &sample_weights, TArray<int> &sample_offsets);
|
||||||
|
|
||||||
|
TArray<BlurSetup> mBlurSetups;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -95,13 +95,17 @@ void FShaderProgram::CreateShader(ShaderType type)
|
||||||
|
|
||||||
void FShaderProgram::Compile(ShaderType type, const char *lumpName)
|
void FShaderProgram::Compile(ShaderType type, const char *lumpName)
|
||||||
{
|
{
|
||||||
CreateShader(type);
|
|
||||||
|
|
||||||
const auto &handle = mShaders[type];
|
|
||||||
|
|
||||||
int lump = Wads.CheckNumForFullName(lumpName);
|
int lump = Wads.CheckNumForFullName(lumpName);
|
||||||
if (lump == -1) I_Error("Unable to load '%s'", lumpName);
|
if (lump == -1) I_Error("Unable to load '%s'", lumpName);
|
||||||
FString code = Wads.ReadLump(lump).GetString().GetChars();
|
FString code = Wads.ReadLump(lump).GetString().GetChars();
|
||||||
|
Compile(type, lumpName, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FShaderProgram::Compile(ShaderType type, const char *name, const FString &code)
|
||||||
|
{
|
||||||
|
CreateShader(type);
|
||||||
|
|
||||||
|
const auto &handle = mShaders[type];
|
||||||
|
|
||||||
int lengths[1] = { (int)code.Len() };
|
int lengths[1] = { (int)code.Len() };
|
||||||
const char *sources[1] = { code.GetChars() };
|
const char *sources[1] = { code.GetChars() };
|
||||||
|
@ -113,7 +117,7 @@ void FShaderProgram::Compile(ShaderType type, const char *lumpName)
|
||||||
glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
|
glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
|
||||||
if (status == GL_FALSE)
|
if (status == GL_FALSE)
|
||||||
{
|
{
|
||||||
I_Error("Compile Shader '%s':\n%s\n", lumpName, GetShaderInfoLog(handle).GetChars());
|
I_Error("Compile Shader '%s':\n%s\n", name, GetShaderInfoLog(handle).GetChars());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void Compile(ShaderType type, const char *lumpName);
|
void Compile(ShaderType type, const char *lumpName);
|
||||||
|
void Compile(ShaderType type, const char *name, const FString &code);
|
||||||
void SetFragDataLocation(int index, const char *name);
|
void SetFragDataLocation(int index, const char *name);
|
||||||
void Link(const char *name);
|
void Link(const char *name);
|
||||||
void SetAttribLocation(int index, const char *name);
|
void SetAttribLocation(int index, const char *name);
|
||||||
|
|
12
wadsrc/static/shaders/glsl/bloomcombine.fp
Normal file
12
wadsrc/static/shaders/glsl/bloomcombine.fp
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D Bloom;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vec4(texture(Bloom, TexCoord).rgb, 0.0);
|
||||||
|
}
|
11
wadsrc/static/shaders/glsl/bloomcombine.vp
Normal file
11
wadsrc/static/shaders/glsl/bloomcombine.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;
|
||||||
|
}
|
14
wadsrc/static/shaders/glsl/bloomextract.fp
Normal file
14
wadsrc/static/shaders/glsl/bloomextract.fp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D SceneTexture;
|
||||||
|
uniform float ExposureAdjustment;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 color = texture(SceneTexture, TexCoord);
|
||||||
|
FragColor = max(vec4(color.rgb * ExposureAdjustment - 1, 1), vec4(0));
|
||||||
|
}
|
11
wadsrc/static/shaders/glsl/bloomextract.vp
Normal file
11
wadsrc/static/shaders/glsl/bloomextract.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