作者:i_dovelemon
日期:2016 / 07 / 24
主题:HDR, Bloom, Tone mapping, Post-process, Blur
int32_t tex_id = 0;
glGenTextures(1, reinterpret_cast(&tex_id));
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glGenerateMipmap(GL_TEXTURE_2D);
glDrawBuffer(GL_COLOR_ATTACHMENTX);
glReadBuffer(GL_COLOR_ATTACHMENT0);
GLvoid* pixel = new GLfloat[4 * g_WindowWidth * g_WindowHeight];
glReadPixels(0, 0, g_WindowWidth, g_WindowHeight, GL_RGBA, GL_FLOAT, pixel);
glReadBuffer(GL_COLOR_ATTACHMENT0);
GLvoid* pixel = new GLfloat[4 * g_WindowWidth * g_WindowHeight];
glReadPixels(0, 0, g_WindowWidth, g_WindowHeight, GL_RGBA, GL_FLOAT, pixel);
GLenum error = glGetError();
GLfloat* buffer = reinterpret_cast(pixel);
float lum = 0.0f;
for (int32_t i = 0; i < g_WindowHeight; i++) {
for (int32_t j = 0; j < g_WindowWidth; j++) {
float r = buffer[i * g_WindowWidth * 4 + j * 4 + 0];
float g = buffer[i * g_WindowWidth * 4 + j * 4 + 1];
float b = buffer[i * g_WindowWidth * 4 + j * 4 + 2];
float cur_lum = r * 0.27f + g * 0.67f + b * 0.06f;
lum += cur_lum;
}
}
g_RenderTarget->DisableRenderTarget();
g_AverageLum = lum / (g_WindowWidth * g_WindowHeight);
delete[] pixel;
pixel = NULL;
gethighlight.vs
//-----------------------------------------------------------
// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.
// Author: i_dovelemon[[email protected]]
// Date: 2016 / 07 / 24
// Brief: Get high light pass through shader
//-----------------------------------------------------------
#version 330
in vec2 vertex;
in vec2 texcoord;
out vec2 vs_texcoord;
void main() {
gl_Position = vec4(vertex, 0.0, 1.0);
vs_texcoord = texcoord;
}
gethgihlight.ps
//-----------------------------------------------------------
// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.
// Author: i_dovelemon[[email protected]]
// Date: 2016 / 07 / 24
// Brief: Get high light
//-----------------------------------------------------------
#version 330
in vec2 vs_texcoord;
out vec4 color;
uniform float lum_average;
uniform sampler2D hdr_tex;
const float kKey = 0.5;
const float kHighLight = 0.80;
void main() {
vec3 hdr_color = texture2D(hdr_tex, vs_texcoord).xyz;
float lum = hdr_color.x * 0.27 + hdr_color.y * 0.67 + hdr_color.z * 0.06;
float lum_after_tonemapping = (kKey * lum) / lum_average;
lum_after_tonemapping = lum_after_tonemapping / (1.0 + lum_after_tonemapping);
if (lum_after_tonemapping > kHighLight) {
color = vec4(hdr_color, 0.5);
} else {
color = vec4(0.0, 0.0, 0.0, 0.0);
}
}
blur.vs
//--------------------------------------------------------------------
// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.
// Author: i_dovelemon[[email protected]]
// Date: 2016 / 06 / 29
// Brief: Gauss blur pass through vertex shader
//--------------------------------------------------------------------
#version 330
in vec3 vertex;
in vec2 texcoord;
out vec2 vs_texcoord;
void main() {
gl_Position = vec4(vertex, 1.0);
vs_texcoord = texcoord;
}
blurh.ps
//--------------------------------------------------------------------
// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.
// Author: i_dovelemon[[email protected]]
// Date: 2016 / 06 / 29
// Brief: Gauss blur horizontal pass shader
//--------------------------------------------------------------------
#version 330
in vec2 vs_texcoord;
out vec4 color;
uniform sampler2D tex;
uniform float tex_width;
uniform float gauss_num[21];
void main() {
color = texture2D(tex, vs_texcoord) * gauss_num[0];
float step = 1.0 / tex_width;
for (int i = 1; i < 21; i++) {
if (vs_texcoord.x - i * step >= 0.0) {
color += texture2D(tex, vec2(vs_texcoord.x - i * step, vs_texcoord.y)) * gauss_num[i];
}
if (vs_texcoord.x + i * step <= 1.0) {
color += texture2D(tex, vec2(vs_texcoord.x + i * step, vs_texcoord.y)) * gauss_num[i];
}
}
}
blurv.ps
//--------------------------------------------------------------------
// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.
// Author: i_dovelemon[[email protected]]
// Date: 2016 / 06 / 29
// Brief: Gauss blur vertical pass shader
//--------------------------------------------------------------------
#version 330
in vec2 vs_texcoord;
out vec4 color;
uniform sampler2D tex;
uniform float tex_height;
uniform float gauss_num[21];
void main() {
color = texture2D(tex, vs_texcoord) * gauss_num[0];
float step = 1.0 / tex_height;
for (int i = 0; i <21; i++) {
if (vs_texcoord.y - i * step >= 0.0) {
color += texture2D(tex, vec2(vs_texcoord.x, vs_texcoord.y - i * step)) * gauss_num[i];
}
if (vs_texcoord.y + i * step <= 1.0) {
color += texture2D(tex, vec2(vs_texcoord.x, vs_texcoord.y + i * step)) * gauss_num[i];
}
}
}
tonemap.vs
//-----------------------------------------------------------
// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.
// Author: i_dovelemon[[email protected]]
// Date: 2016 / 07 / 24
// Brief: Tone map pass through shader
//-----------------------------------------------------------
#version 330
in vec2 vertex;
in vec2 texcoord;
out vec2 vs_texcoord;
void main() {
gl_Position = vec4(vertex, 0.0, 1.0);
vs_texcoord = texcoord;
}
//--------------------------------------------------------
// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.
// Author: i_dovelemon[[email protected]]
// Date: 2016 / 07 / 24
// Brief: Tone mapping the HDR scene
//--------------------------------------------------------
#version 330
in vec2 vs_texcoord;
out vec4 color;
uniform float lum_average;
uniform sampler2D hdr_tex;
uniform sampler2D bloom_tex;
const float key = 0.5;
void main() {
vec4 hdr_color = texture2D(hdr_tex, vs_texcoord);
vec4 bloom_color = texture2D(bloom_tex, vs_texcoord);
float lum = hdr_color.x * 0.27 + hdr_color.y * 0.67 + hdr_color.z * 0.06;
float lum_after_tonemapping = (key * lum) / lum_average;
vec4 blend_color = hdr_color * (1.0 - bloom_color.w) + bloom_color * bloom_color.w;
color = blend_color * lum_after_tonemapping;
color /= vec4(1.0 + color.x, 1.0 + color.y, 1.0 + color.z, 1.0);
}
static float time = 0.0f;
float ratio = std::sin(3.1415f * 0.5f * (time / 120.0f));
g_UsedLum = 1.0f + (g_AverageLum - 1.0f) * ratio;
time = time + 1.0f;
if (time > 120.0f) {
time = 120.0f;
}
if (GetKeyState('F') & 0x8000) {
time = 0;
}
void glb_display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glb_draw_scene_to_texture();
glb_calc_average_lum();
glb_draw_to_get_highlight_texture();
glb_draw_hpass_bloom_highlight_to_texture();
glb_draw_vpass_bloom_highlight_to_texture();
glb_draw_hdr_scene();
glutSwapBuffers();
}