mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-07 03:13:49 +00:00
Implement multi-pass bloom post-processing effect.
This commit is contained in:
parent
4f1a636c20
commit
5af3ed1197
|
@ -405,7 +405,7 @@ void FrameBufferList::renderBuffer(u32 _address)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
PostProcessor::get().processTexture(pBuffer->m_pTexture);
|
PostProcessor::get().process(pBuffer);
|
||||||
#endif
|
#endif
|
||||||
// glDisable(GL_SCISSOR_TEST) does not affect glBlitFramebuffer, at least on AMD
|
// glDisable(GL_SCISSOR_TEST) does not affect glBlitFramebuffer, at least on AMD
|
||||||
glScissor(0, 0, ogl.getScreenWidth(), ogl.getScreenHeight());
|
glScissor(0, 0, ogl.getScreenWidth(), ogl.getScreenHeight());
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
#include "N64.h"
|
#include "N64.h"
|
||||||
#include "gSP.h"
|
#include "gSP.h"
|
||||||
#include "PostProcessor.h"
|
#include "PostProcessor.h"
|
||||||
#include "GLSLCombiner.h"
|
#include "FrameBuffer.h"
|
||||||
|
|
||||||
const char * vertexShader =
|
static const char * vertexShader =
|
||||||
"#version 330 core \n"
|
"#version 330 core \n"
|
||||||
"in highp vec2 aPosition; \n"
|
"in highp vec2 aPosition; \n"
|
||||||
"in highp vec2 aTexCoord; \n"
|
"in highp vec2 aTexCoord; \n"
|
||||||
|
@ -16,7 +16,159 @@ const char * vertexShader =
|
||||||
"} \n"
|
"} \n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static const char* bloomShader =
|
static const char* extractBloomShader =
|
||||||
|
"#version 330 core \n"
|
||||||
|
"in mediump vec2 vTexCoord; \n"
|
||||||
|
"layout(binding = 0) uniform sampler2D tex; \n"
|
||||||
|
"out lowp vec4 fragColor; \n"
|
||||||
|
" \n"
|
||||||
|
"uniform lowp int ThresholdLevel; \n"
|
||||||
|
" \n"
|
||||||
|
"void main() \n"
|
||||||
|
"{ \n"
|
||||||
|
" lowp vec4 color = texture2D(tex, vTexCoord); \n"
|
||||||
|
" \n"
|
||||||
|
" mediump float lum = dot(vec4(0.30, 0.59, 0.11, 0.0), color);\n"
|
||||||
|
" mediump float scale = lum; \n"
|
||||||
|
" lowp int level = clamp(ThresholdLevel, 2, 6); \n"
|
||||||
|
" for (int i = 1; i < level; ++i) \n"
|
||||||
|
" scale *= lum; \n"
|
||||||
|
" fragColor = scale*color; \n"
|
||||||
|
" fragColor.a = 1.0; \n"
|
||||||
|
"} \n"
|
||||||
|
;
|
||||||
|
|
||||||
|
static const char* seperableBlurShader =
|
||||||
|
/// Author: Nathaniel Meyer
|
||||||
|
///
|
||||||
|
/// Copyright: Nutty Software
|
||||||
|
/// http://www.nutty.ca
|
||||||
|
///
|
||||||
|
/// Fragment shader for performing a seperable blur on the specified texture.
|
||||||
|
"#version 330 core \n"
|
||||||
|
"#ifdef GL_ES \n"
|
||||||
|
" precision highp float; \n"
|
||||||
|
"#endif \n"
|
||||||
|
" \n"
|
||||||
|
// Uniform variables.
|
||||||
|
"layout(binding = 0) uniform sampler2D Sample0; \n"
|
||||||
|
"uniform vec2 TexelSize; \n"
|
||||||
|
" \n"
|
||||||
|
"uniform int Orientation; \n"
|
||||||
|
"uniform int BlurAmount; \n"
|
||||||
|
"uniform float BlurScale; \n"
|
||||||
|
"uniform float BlurStrength; \n"
|
||||||
|
" \n"
|
||||||
|
"in mediump vec2 vTexCoord; \n"
|
||||||
|
"out lowp vec4 fragColor; \n"
|
||||||
|
" \n"
|
||||||
|
// Gets the Gaussian value in the first dimension.
|
||||||
|
// "x" Distance from origin on the x-axis.
|
||||||
|
// "deviation" Standard deviation.
|
||||||
|
// returns The gaussian value on the x-axis.
|
||||||
|
"float Gaussian (float x, float deviation) \n"
|
||||||
|
"{ \n"
|
||||||
|
" return (1.0 / sqrt(2.0 * 3.141592 * deviation)) * exp(-((x * x) / (2.0 * deviation))); \n"
|
||||||
|
"} \n"
|
||||||
|
" \n"
|
||||||
|
// Fragment shader entry.
|
||||||
|
"void main () \n"
|
||||||
|
"{ \n"
|
||||||
|
" // Locals \n"
|
||||||
|
" float halfBlur = float(BlurAmount) * 0.5; \n"
|
||||||
|
" vec4 colour = vec4(0.0); \n"
|
||||||
|
" \n"
|
||||||
|
" // Gaussian deviation \n"
|
||||||
|
" float deviation = halfBlur * 0.35; \n"
|
||||||
|
" deviation *= deviation; \n"
|
||||||
|
" float strength = 1.0 - BlurStrength; \n"
|
||||||
|
" \n"
|
||||||
|
" if ( Orientation == 0 ) \n"
|
||||||
|
" { \n"
|
||||||
|
" // Horizontal blur \n"
|
||||||
|
" for (int i = 0; i < BlurAmount; ++i) \n"
|
||||||
|
" { \n"
|
||||||
|
" float offset = float(i) - halfBlur; \n"
|
||||||
|
" colour += texture2D(Sample0, vTexCoord + vec2(offset * TexelSize.x * BlurScale, 0.0)) * Gaussian(offset * strength, deviation); \n"
|
||||||
|
" } \n"
|
||||||
|
" } \n"
|
||||||
|
" else \n"
|
||||||
|
" { \n"
|
||||||
|
" // Vertical blur \n"
|
||||||
|
" for (int i = 0; i < BlurAmount; ++i) \n"
|
||||||
|
" { \n"
|
||||||
|
" float offset = float(i) - halfBlur; \n"
|
||||||
|
" colour += texture2D(Sample0, vTexCoord + vec2(0.0, offset * TexelSize.y * BlurScale)) * Gaussian(offset * strength, deviation); \n"
|
||||||
|
" } \n"
|
||||||
|
" } \n"
|
||||||
|
" \n"
|
||||||
|
" // Apply colour \n"
|
||||||
|
" fragColor = clamp(colour, 0.0, 1.0); \n"
|
||||||
|
" fragColor.a = 1.0; \n"
|
||||||
|
"} \n"
|
||||||
|
;
|
||||||
|
|
||||||
|
static const char* glowShader =
|
||||||
|
/// Author: Nathaniel Meyer
|
||||||
|
///
|
||||||
|
/// Copyright: Nutty Software
|
||||||
|
/// http://www.nutty.ca
|
||||||
|
///
|
||||||
|
/// Fragment shader for blending two textures using an algorithm that overlays the glowmap.
|
||||||
|
"#version 330 core \n"
|
||||||
|
"#ifdef GL_ES \n"
|
||||||
|
" precision highp float; \n"
|
||||||
|
"#endif \n"
|
||||||
|
" \n"
|
||||||
|
// Uniform variables.
|
||||||
|
"layout(binding = 0) uniform sampler2D Sample0; \n"
|
||||||
|
"layout(binding = 1) uniform sampler2D Sample1; \n"
|
||||||
|
"uniform int BlendMode; \n"
|
||||||
|
" \n"
|
||||||
|
"in mediump vec2 vTexCoord; \n"
|
||||||
|
"out lowp vec4 fragColor; \n"
|
||||||
|
" \n"
|
||||||
|
// Fragment shader entry.
|
||||||
|
"void main () \n"
|
||||||
|
"{ \n"
|
||||||
|
" vec4 dst = texture2D(Sample0, vTexCoord); // rendered scene \n"
|
||||||
|
" vec4 src = texture2D(Sample1, vTexCoord); // glowmap \n"
|
||||||
|
" \n"
|
||||||
|
" if ( BlendMode == 0 ) \n"
|
||||||
|
" { \n"
|
||||||
|
" // Additive blending (strong result, high overexposure) \n"
|
||||||
|
" fragColor = min(src + dst, 1.0); \n"
|
||||||
|
" } \n"
|
||||||
|
" else if ( BlendMode == 1 ) \n"
|
||||||
|
" { \n"
|
||||||
|
" // Screen blending (mild result, medium overexposure) \n"
|
||||||
|
" fragColor = clamp((src + dst) - (src * dst), 0.0, 1.0); \n"
|
||||||
|
" fragColor.a = 1.0; \n"
|
||||||
|
" } \n"
|
||||||
|
" else if ( BlendMode == 2 ) \n"
|
||||||
|
" { \n"
|
||||||
|
" // Softlight blending (light result, no overexposure) \n"
|
||||||
|
" // Due to the nature of soft lighting, we need to bump the black region of the glowmap \n"
|
||||||
|
" // to 0.5, otherwise the blended result will be dark (black soft lighting will darken \n"
|
||||||
|
" // the image). \n"
|
||||||
|
" src = (src * 0.5) + 0.5; \n"
|
||||||
|
" \n"
|
||||||
|
" fragColor.rgb = vec3((src.x <= 0.5) ? (dst.x - (1.0 - 2.0 * src.x) * dst.x * (1.0 - dst.x)) : (((src.x > 0.5) && (dst.x <= 0.25)) ? (dst.x + (2.0 * src.x - 1.0) * (4.0 * dst.x * (4.0 * dst.x + 1.0) * (dst.x - 1.0) + 7.0 * dst.x)) : (dst.x + (2.0 * src.x - 1.0) * (sqrt(dst.x) - dst.x))), \n"
|
||||||
|
" (src.y <= 0.5) ? (dst.y - (1.0 - 2.0 * src.y) * dst.y * (1.0 - dst.y)) : (((src.y > 0.5) && (dst.y <= 0.25)) ? (dst.y + (2.0 * src.y - 1.0) * (4.0 * dst.y * (4.0 * dst.y + 1.0) * (dst.y - 1.0) + 7.0 * dst.y)) : (dst.y + (2.0 * src.y - 1.0) * (sqrt(dst.y) - dst.y))), \n"
|
||||||
|
" (src.z <= 0.5) ? (dst.z - (1.0 - 2.0 * src.z) * dst.z * (1.0 - dst.z)) : (((src.z > 0.5) && (dst.z <= 0.25)) ? (dst.z + (2.0 * src.z - 1.0) * (4.0 * dst.z * (4.0 * dst.z + 1.0) * (dst.z - 1.0) + 7.0 * dst.z)) : (dst.z + (2.0 * src.z - 1.0) * (sqrt(dst.z) - dst.z))));\n"
|
||||||
|
" fragColor.a = 1.0; \n"
|
||||||
|
" } \n"
|
||||||
|
" else \n"
|
||||||
|
" { \n"
|
||||||
|
" // Show just the glow map \n"
|
||||||
|
" fragColor = src; \n"
|
||||||
|
" } \n"
|
||||||
|
"} \n"
|
||||||
|
;
|
||||||
|
|
||||||
|
static const char* simpleBloomShader =
|
||||||
|
// glsl bloom shader by krischan
|
||||||
|
// http://wp.applesandoranges.eu/
|
||||||
"#version 330 core \n"
|
"#version 330 core \n"
|
||||||
"in mediump vec2 vTexCoord; \n"
|
"in mediump vec2 vTexCoord; \n"
|
||||||
"layout(binding = 0) uniform sampler2D bgl_RenderedTexture; \n"
|
"layout(binding = 0) uniform sampler2D bgl_RenderedTexture; \n"
|
||||||
|
@ -28,41 +180,52 @@ static const char* bloomShader =
|
||||||
" int j; \n"
|
" int j; \n"
|
||||||
" int i; \n"
|
" int i; \n"
|
||||||
" \n"
|
" \n"
|
||||||
" for( i= -4 ; i < 4; i++) \n"
|
" for( i= -4 ; i < 4; i++) { \n"
|
||||||
" { \n"
|
|
||||||
" for (j = -3; j < 3; j++) \n"
|
" for (j = -3; j < 3; j++) \n"
|
||||||
" { \n"
|
|
||||||
" sum += texture2D(bgl_RenderedTexture, texcoord + vec2(j, i)*0.004) * 0.25; \n"
|
" sum += texture2D(bgl_RenderedTexture, texcoord + vec2(j, i)*0.004) * 0.25; \n"
|
||||||
" } \n"
|
" } \n"
|
||||||
" } \n"
|
" if (texture2D(bgl_RenderedTexture, texcoord).r < 0.3) { \n"
|
||||||
" if (texture2D(bgl_RenderedTexture, texcoord).r < 0.3) \n"
|
|
||||||
" { \n"
|
|
||||||
" fragColor = sum*sum*0.012 + texture2D(bgl_RenderedTexture, texcoord); \n"
|
" fragColor = sum*sum*0.012 + texture2D(bgl_RenderedTexture, texcoord); \n"
|
||||||
" } \n"
|
" } else { \n"
|
||||||
" else \n"
|
|
||||||
" { \n"
|
|
||||||
" if (texture2D(bgl_RenderedTexture, texcoord).r < 0.5) \n"
|
" if (texture2D(bgl_RenderedTexture, texcoord).r < 0.5) \n"
|
||||||
" { \n"
|
|
||||||
" fragColor = sum*sum*0.009 + texture2D(bgl_RenderedTexture, texcoord); \n"
|
" fragColor = sum*sum*0.009 + texture2D(bgl_RenderedTexture, texcoord); \n"
|
||||||
" } \n"
|
|
||||||
" else \n"
|
" else \n"
|
||||||
" { \n"
|
|
||||||
" fragColor = sum*sum*0.0075 + texture2D(bgl_RenderedTexture, texcoord); \n"
|
" fragColor = sum*sum*0.0075 + texture2D(bgl_RenderedTexture, texcoord); \n"
|
||||||
" } \n"
|
" } \n"
|
||||||
"} \n"
|
"} \n"
|
||||||
"} \n"
|
|
||||||
;
|
;
|
||||||
|
|
||||||
static const char* copyShader =
|
static const GLsizei nShaderLogSize = 1024;
|
||||||
"#version 330 core \n"
|
static
|
||||||
"in mediump vec2 vTexCoord; \n"
|
bool check_shader_compile_status(GLuint obj)
|
||||||
"layout(binding = 0) uniform sampler2D bgl_RenderedTexture; \n"
|
{
|
||||||
"out lowp vec4 fragColor; \n"
|
GLint status;
|
||||||
"void main() \n"
|
glGetShaderiv(obj, GL_COMPILE_STATUS, &status);
|
||||||
"{ \n"
|
if (status == GL_FALSE)
|
||||||
" fragColor = texture2D(bgl_RenderedTexture, vTexCoord); \n"
|
{
|
||||||
"} \n"
|
GLchar shader_log[nShaderLogSize];
|
||||||
;
|
GLsizei nLogSize = nShaderLogSize;
|
||||||
|
glGetShaderInfoLog(obj, nShaderLogSize, &nLogSize, shader_log);
|
||||||
|
shader_log[nLogSize] = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool check_program_link_status(GLuint obj)
|
||||||
|
{
|
||||||
|
GLint status;
|
||||||
|
glGetProgramiv(obj, GL_LINK_STATUS, &status);
|
||||||
|
if (status == GL_FALSE)
|
||||||
|
{
|
||||||
|
GLsizei nLogSize = nShaderLogSize;
|
||||||
|
GLchar shader_log[nShaderLogSize];
|
||||||
|
glGetProgramInfoLog(obj, nShaderLogSize, &nLogSize, shader_log);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
GLuint _createShaderProgram(const char * _strVertex, const char * _strFragment)
|
GLuint _createShaderProgram(const char * _strVertex, const char * _strFragment)
|
||||||
|
@ -70,10 +233,12 @@ GLuint _createShaderProgram(const char * _strVertex, const char * _strFragment)
|
||||||
GLuint vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);
|
GLuint vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);
|
||||||
glShaderSource(vertex_shader_object, 1, &_strVertex, NULL);
|
glShaderSource(vertex_shader_object, 1, &_strVertex, NULL);
|
||||||
glCompileShader(vertex_shader_object);
|
glCompileShader(vertex_shader_object);
|
||||||
|
assert(check_shader_compile_status(vertex_shader_object));
|
||||||
|
|
||||||
GLuint fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
|
GLuint fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glShaderSource(fragment_shader_object, 1, &_strFragment, NULL);
|
glShaderSource(fragment_shader_object, 1, &_strFragment, NULL);
|
||||||
glCompileShader(fragment_shader_object);
|
glCompileShader(fragment_shader_object);
|
||||||
|
assert(check_shader_compile_status(fragment_shader_object));
|
||||||
|
|
||||||
GLuint program = glCreateProgram();
|
GLuint program = glCreateProgram();
|
||||||
glBindAttribLocation(program, SC_POSITION, "aPosition");
|
glBindAttribLocation(program, SC_POSITION, "aPosition");
|
||||||
|
@ -83,61 +248,127 @@ GLuint _createShaderProgram(const char * _strVertex, const char * _strFragment)
|
||||||
glLinkProgram(program);
|
glLinkProgram(program);
|
||||||
glDeleteShader(vertex_shader_object);
|
glDeleteShader(vertex_shader_object);
|
||||||
glDeleteShader(fragment_shader_object);
|
glDeleteShader(fragment_shader_object);
|
||||||
|
assert(check_program_link_status(program));
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
void PostProcessor::init()
|
CachedTexture * _createTexture()
|
||||||
{
|
{
|
||||||
m_bloomProgram = _createShaderProgram(vertexShader, bloomShader);
|
CachedTexture * pTexture = textureCache().addFrameBufferTexture();
|
||||||
m_copyProgram = _createShaderProgram(vertexShader, copyShader);
|
pTexture->format = G_IM_FMT_RGBA;
|
||||||
|
pTexture->clampS = 1;
|
||||||
|
pTexture->clampT = 1;
|
||||||
|
pTexture->frameBufferTexture = TRUE;
|
||||||
|
pTexture->maskS = 0;
|
||||||
|
pTexture->maskT = 0;
|
||||||
|
pTexture->mirrorS = 0;
|
||||||
|
pTexture->mirrorT = 0;
|
||||||
|
pTexture->realWidth = video().getWidth();
|
||||||
|
pTexture->realHeight = video().getHeight();
|
||||||
|
pTexture->textureBytes = pTexture->realWidth * pTexture->realHeight * 4;
|
||||||
|
textureCache().addFrameBufferTextureSize(pTexture->textureBytes);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, pTexture->glName);
|
||||||
|
|
||||||
m_pTexture = textureCache().addFrameBufferTexture();
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pTexture->realWidth, pTexture->realHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
m_pTexture->format = G_IM_FMT_RGBA;
|
|
||||||
m_pTexture->clampS = 1;
|
|
||||||
m_pTexture->clampT = 1;
|
|
||||||
m_pTexture->frameBufferTexture = TRUE;
|
|
||||||
m_pTexture->maskS = 0;
|
|
||||||
m_pTexture->maskT = 0;
|
|
||||||
m_pTexture->mirrorS = 0;
|
|
||||||
m_pTexture->mirrorT = 0;
|
|
||||||
m_pTexture->realWidth = video().getWidth();
|
|
||||||
m_pTexture->realHeight = video().getHeight();
|
|
||||||
m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 4;
|
|
||||||
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_pTexture->realWidth, m_pTexture->realHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
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_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
return pTexture;
|
||||||
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
static
|
||||||
glGenFramebuffers(1, &m_FBO);
|
GLuint _createFBO(CachedTexture * _pTexture)
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
{
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->glName, 0);
|
GLuint FBO;
|
||||||
GLuint attachments[1] = { GL_COLOR_ATTACHMENT0 };
|
glGenFramebuffers(1, &FBO);
|
||||||
glDrawBuffers(1, attachments);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);
|
||||||
// check if everything is OK
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _pTexture->glName, 0);
|
||||||
assert(checkFBO());
|
assert(checkFBO());
|
||||||
assert(!isGLError());
|
return FBO;
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
}
|
||||||
|
|
||||||
|
void PostProcessor::init()
|
||||||
|
{
|
||||||
|
m_extractBloomProgram = _createShaderProgram(vertexShader, extractBloomShader);
|
||||||
|
glUseProgram(m_extractBloomProgram);
|
||||||
|
int loc = glGetUniformLocation(m_extractBloomProgram, "ThresholdLevel");
|
||||||
|
assert(loc >= 0);
|
||||||
|
glUniform1i(loc, 4);
|
||||||
|
|
||||||
|
m_seperableBlurProgram = _createShaderProgram(vertexShader, seperableBlurShader);
|
||||||
|
glUseProgram(m_seperableBlurProgram);
|
||||||
|
loc = glGetUniformLocation(m_seperableBlurProgram, "TexelSize");
|
||||||
|
assert(loc >= 0);
|
||||||
|
glUniform2f(loc, 1.0f/video().getWidth(), 1.0f/video().getHeight());
|
||||||
|
loc = glGetUniformLocation(m_seperableBlurProgram, "Orientation");
|
||||||
|
assert(loc >= 0);
|
||||||
|
glUniform1i(loc, 0);
|
||||||
|
loc = glGetUniformLocation(m_seperableBlurProgram, "BlurAmount");
|
||||||
|
assert(loc >= 0);
|
||||||
|
glUniform1i(loc, 10);
|
||||||
|
loc = glGetUniformLocation(m_seperableBlurProgram, "BlurScale");
|
||||||
|
assert(loc >= 0);
|
||||||
|
glUniform1f(loc, 1.0f);
|
||||||
|
loc = glGetUniformLocation(m_seperableBlurProgram, "BlurStrength");
|
||||||
|
assert(loc >= 0);
|
||||||
|
glUniform1f(loc, 0.5f);
|
||||||
|
|
||||||
|
m_glowProgram = _createShaderProgram(vertexShader, glowShader);
|
||||||
|
glUseProgram(m_glowProgram);
|
||||||
|
loc = glGetUniformLocation(m_glowProgram, "BlendMode");
|
||||||
|
assert(loc >= 0);
|
||||||
|
glUniform1i(loc, 1);
|
||||||
|
|
||||||
|
m_bloomProgram = _createShaderProgram(vertexShader, simpleBloomShader);
|
||||||
|
|
||||||
|
glUseProgram(0);
|
||||||
|
|
||||||
|
m_pTextureOriginal = _createTexture();
|
||||||
|
m_pTextureGlowMap = _createTexture();
|
||||||
|
m_pTextureBlur = _createTexture();
|
||||||
|
|
||||||
|
m_FBO_original = _createFBO(m_pTextureOriginal);
|
||||||
|
m_FBO_glowMap = _createFBO(m_pTextureGlowMap);
|
||||||
|
m_FBO_blur = _createFBO(m_pTextureBlur);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PostProcessor::destroy()
|
void PostProcessor::destroy()
|
||||||
{
|
{
|
||||||
|
if (m_extractBloomProgram != 0)
|
||||||
|
glDeleteProgram(m_extractBloomProgram);
|
||||||
|
m_extractBloomProgram = 0;
|
||||||
|
if (m_seperableBlurProgram != 0)
|
||||||
|
glDeleteProgram(m_seperableBlurProgram);
|
||||||
|
m_seperableBlurProgram = 0;
|
||||||
|
if (m_glowProgram != 0)
|
||||||
|
glDeleteProgram(m_glowProgram);
|
||||||
|
m_glowProgram = 0;
|
||||||
if (m_bloomProgram != 0)
|
if (m_bloomProgram != 0)
|
||||||
glDeleteProgram(m_bloomProgram);
|
glDeleteProgram(m_bloomProgram);
|
||||||
|
m_bloomProgram = 0;
|
||||||
|
|
||||||
if (m_copyProgram != 0)
|
if (m_FBO_original != 0)
|
||||||
glDeleteProgram(m_copyProgram);
|
glDeleteFramebuffers(1, &m_FBO_original);
|
||||||
|
m_FBO_original = 0;
|
||||||
|
if (m_FBO_glowMap != 0)
|
||||||
|
glDeleteFramebuffers(1, &m_FBO_glowMap);
|
||||||
|
m_FBO_glowMap = 0;
|
||||||
|
if (m_FBO_blur != 0)
|
||||||
|
glDeleteFramebuffers(1, &m_FBO_blur);
|
||||||
|
m_FBO_blur = 0;
|
||||||
|
|
||||||
if (m_FBO != 0)
|
if (m_pTextureOriginal != NULL)
|
||||||
glDeleteFramebuffers(1, &m_FBO);
|
textureCache().removeFrameBufferTexture(m_pTextureOriginal);
|
||||||
|
m_pTextureOriginal = NULL;
|
||||||
if (m_pTexture != NULL)
|
if (m_pTextureGlowMap != NULL)
|
||||||
textureCache().removeFrameBufferTexture(m_pTexture);
|
textureCache().removeFrameBufferTexture(m_pTextureGlowMap);
|
||||||
|
m_pTextureGlowMap = NULL;
|
||||||
|
if (m_pTextureBlur != NULL)
|
||||||
|
textureCache().removeFrameBufferTexture(m_pTextureBlur);
|
||||||
|
m_pTextureBlur = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PostProcessor & PostProcessor::get()
|
PostProcessor & PostProcessor::get()
|
||||||
|
@ -169,28 +400,54 @@ void _setGLState() {
|
||||||
glViewport(0, 0, video().getWidth(), video().getHeight());
|
glViewport(0, 0, video().getWidth(), video().getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PostProcessor::processTexture(CachedTexture * _pTexture)
|
void PostProcessor::process(FrameBuffer * _pBuffer)
|
||||||
{
|
{
|
||||||
_setGLState();
|
_setGLState();
|
||||||
|
OGLVideo & ogl = video();
|
||||||
|
|
||||||
textureCache().activateTexture(0, _pTexture);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, _pBuffer->m_FBO);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO_original);
|
||||||
|
glBlitFramebuffer(
|
||||||
|
0, 0, ogl.getWidth(), ogl.getHeight(),
|
||||||
|
0, 0, ogl.getWidth(), ogl.getHeight(),
|
||||||
|
GL_COLOR_BUFFER_BIT, GL_LINEAR
|
||||||
|
);
|
||||||
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
#if 0
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _pBuffer->m_FBO);
|
||||||
|
textureCache().activateTexture(0, m_pTextureOriginal);
|
||||||
glUseProgram(m_bloomProgram);
|
glUseProgram(m_bloomProgram);
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
#else
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO_glowMap);
|
||||||
textureCache().activateTexture(0, m_pTexture);
|
textureCache().activateTexture(0, m_pTextureOriginal);
|
||||||
GLuint copyFBO = 0;
|
glUseProgram(m_extractBloomProgram);
|
||||||
glGenFramebuffers(1, ©FBO);
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFBO);
|
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _pTexture->glName, 0);
|
|
||||||
assert(checkFBO());
|
|
||||||
glUseProgram(m_copyProgram);
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO_blur);
|
||||||
|
textureCache().activateTexture(0, m_pTextureGlowMap);
|
||||||
|
glUseProgram(m_seperableBlurProgram);
|
||||||
|
int loc = glGetUniformLocation(m_seperableBlurProgram, "Orientation");
|
||||||
|
assert(loc >= 0);
|
||||||
|
glUniform1i(loc, 0);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO_glowMap);
|
||||||
|
textureCache().activateTexture(0, m_pTextureBlur);
|
||||||
|
glUniform1i(loc, 1);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _pBuffer->m_FBO);
|
||||||
|
textureCache().activateTexture(0, m_pTextureOriginal);
|
||||||
|
textureCache().activateTexture(1, m_pTextureGlowMap);
|
||||||
|
glUseProgram(m_glowProgram);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
#endif
|
||||||
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
glDeleteFramebuffers(1, ©FBO);
|
|
||||||
video().getRender().dropRenderState();
|
video().getRender().dropRenderState();
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
gSP.changed = CHANGED_VIEWPORT | CHANGED_TEXTURE;
|
gSP.changed = CHANGED_VIEWPORT | CHANGED_TEXTURE;
|
||||||
|
|
|
@ -10,19 +10,29 @@ public:
|
||||||
void init();
|
void init();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
void processTexture(CachedTexture * _pTexture);
|
void process(FrameBuffer * _pBuffer);
|
||||||
|
|
||||||
static PostProcessor & get();
|
static PostProcessor & get();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PostProcessor() : m_bloomProgram(0), m_copyProgram(0), m_FBO(0), m_pTexture(NULL) {};
|
PostProcessor() :
|
||||||
|
m_extractBloomProgram(0), m_seperableBlurProgram(0), m_glowProgram(0), m_bloomProgram(0),
|
||||||
|
m_FBO_original(0), m_FBO_glowMap(0), m_FBO_blur(0),
|
||||||
|
m_pTextureOriginal(NULL), m_pTextureGlowMap(NULL), m_pTextureBlur(NULL) {};
|
||||||
PostProcessor(const PostProcessor & _other);
|
PostProcessor(const PostProcessor & _other);
|
||||||
|
|
||||||
|
GLuint m_extractBloomProgram;
|
||||||
|
GLuint m_seperableBlurProgram;
|
||||||
|
GLuint m_glowProgram;
|
||||||
GLuint m_bloomProgram;
|
GLuint m_bloomProgram;
|
||||||
GLuint m_copyProgram;
|
|
||||||
|
|
||||||
GLuint m_FBO;
|
GLuint m_FBO_original;
|
||||||
CachedTexture * m_pTexture;
|
GLuint m_FBO_glowMap;
|
||||||
|
GLuint m_FBO_blur;
|
||||||
|
|
||||||
|
CachedTexture * m_pTextureOriginal;
|
||||||
|
CachedTexture * m_pTextureGlowMap;
|
||||||
|
CachedTexture * m_pTextureBlur;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // POST_PROCESSOR_H
|
#endif // POST_PROCESSOR_H
|
||||||
|
|
Loading…
Reference in New Issue
Block a user