GraphicsLab Project之HDR渲染
作者:i_dovelemon
日期:2016 / 07 / 24
主题:HDR, Bloom, Tone mapping, Post-process, Blur
引言
HDR
HDR实现原理
具体实现(OpenGL)
离屏渲染
int32_t tex_id = 0;
glGenTextures(1, reinterpret_cast<GLuint*>(&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);
你可以看到,和传统的纹理创建基本一致,只是在调用glTexImage2D的时候,需要传递不一样的参数,告知显卡,我们要保存16位的浮点数据了。
glDrawBuffer(GL_COLOR_ATTACHMENTX);
Tone mapping
Bloom
实现步骤及结果
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);
指定将要读取的COLOR_BUFFER,然后调用glReadPixel来获取纹理数据。获取了整个纹理数据之后,我们就可以通过使用前面的公式来计算整个场景的平均亮度了。只有在实验之后,我才知道调用ln和exp这样的函数,是多么的慢。对整张贴图进行这样的对数,指数运算,的确非常的卡,所以你看,明白了性能的损失了。所以,我就换了另外一种方法来计算平均亮度,也就是简单的将所有亮度值相加,然后除以像素数,这样也能够得到一个平均亮度值,而且这样的计算,似乎速度还可以,至少能够在本实例的情况下,满帧运行。下面就是计算这个平均亮度的完整代码:
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<GLfloat*>(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[1322600812@qq.com]
// Date: 2016 / 07 / 24
// Brief: Get high light pass through shader
//-----------------------------------------------------------
#version 330in 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[1322600812@qq.com]
// Date: 2016 / 07 / 24
// Brief: Get high light
//-----------------------------------------------------------
#version 330in 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);}
}
这里要解释下,我在提取高亮部分的时候,实际上是检测进行Tone mapping之后的像素数据的亮度。这样做是为了我们能够通过0.0-1.0这个范围里面,来设定高亮阀值,否则的话,我可不知道该设置成什么样的值,才能够比较准确的提取出来高亮部分。同时你还可能注意到,我这里手动的为每一个高亮的颜色值设置了0.5的alpha值,而为所有的非高亮像素设置了0.0的alpha值。这么做是为了在后面进行blend的时候,能够准确的只和高亮的部分进行blend,而不需要和非高亮的像素进行混合。
blur.vs
//--------------------------------------------------------------------
// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.
// Author: i_dovelemon[1322600812@qq.com]
// Date: 2016 / 06 / 29
// Brief: Gauss blur pass through vertex shader
//--------------------------------------------------------------------
#version 330in 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[1322600812@qq.com]
// Date: 2016 / 06 / 29
// Brief: Gauss blur horizontal pass shader
//--------------------------------------------------------------------
#version 330in 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[1322600812@qq.com]
// Date: 2016 / 06 / 29
// Brief: Gauss blur vertical pass shader
//--------------------------------------------------------------------
#version 330in 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[1322600812@qq.com]
// Date: 2016 / 07 / 24
// Brief: Tone map pass through shader
//-----------------------------------------------------------
#version 330in 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[1322600812@qq.com]
// Date: 2016 / 07 / 24
// Brief: Tone mapping the HDR scene
//--------------------------------------------------------
#version 330in 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();
}
总结
参考文献
GraphicsLab Project之HDR渲染相关推荐
- GraphicsLab Project之基于物理的着色系统(Physical based shading) - 基于图像的光照(Image Based Lighting)(Diffuse篇)
作者:i_dovelemon 日期:2018-01-21 来源:CSDN 主题:PBR, Equrectangular Map, Cube Map, Irradiance Map, HDR Image ...
- GraphicsLab Project之辉光(Glare,Glow)效果
作者:i_dovelemon 日期:2016 / 07 / 02 来源:CSDN 主题:Render to Texture, Post process, Glare, Glow, Multi-pass ...
- [转]HDR渲染器的实现(基于OpenGL)
http://dev.gameres.com/Program/Visual/3D/HDRTutorial/HDRTutorial.htm 作者:何咏(欢迎和大家交流,我的QQ:35574585,Ema ...
- OpenGL HDR渲染
OpenGL HDR渲染 HDR渲染简介 浮点帧缓冲 色调映射 HDR渲染简介 一般来说,当存储在帧缓冲(Framebuffer)中时,亮度和颜色的值是默认被限制在0.0到1.0之间的.这个看起来无辜 ...
- 优秀的HDR渲染软件:Topaz Adjust AI for Mac
Topaz Adjust AI for Mac是Topaz系列中一款专业的HDR渲染软件,topaz adjust ai mac版具备自动曝光调整算法,采用先进的算法来实现独特的曝光效果和色彩调整,T ...
- HDR渲染器的实现(基于OpenGL)
作者:何咏(欢迎和大家交流,我的QQ:35574585,Email:hyestar@126.com) 我的个人网站:http://www.graphixer.com.cn 原文出处:http://ww ...
- GraphicsLab Project之基于物理的着色系统(Physical based shading)-直接光照
作者:idovelemon 日期:2018 / 1 / 1 来源:CSDN 主题:PBS, Microfact Theory, Cook-Torrance 引言 近些年来,基于物理的光照着色系统(Ph ...
- GraphicsLab Project之简易贴画系统(Decal System)
作者:i_dovelemon 日期:2018-08-28 来源:CSDN 主题:Projection Texture Mapping, Decal System 引言 游戏开发过程中有一个非常重要的功 ...
- GraphicsLab Project之光照贴图烘焙(一)
作者:i_dovelemon 来源:CSDN 日期:2018-05-19 主题:Radiosity Algorithm, Global Illumination, Barycentric Coordi ...
最新文章
- 下载Ext JS 5.1 gpl版本的方法
- Redis学习第三课:Redis Hash类型及操作
- html 两个图片并排,HTML – 两个图像并排和响应
- 漫步最优化八——梯度信息
- 动态规划求解所有字符的组合数
- 正则表达式的性能评测
- 笔记16(shell编程)
- linux 文本编辑 软件管理
- java包限制使用时间_给jar包加壳限制使用时间
- 数据预处理—2.为什么Lasso回归可以做特征选择(变量挑选)而岭回归做不到呢?
- Android开发之来电电话挂断实现
- ListView的优化
- django常见面试题
- 如何做好一个软件测试管理者,高效带好团队呢?
- 201771010101 白玛次仁 《2018面向对象程序设计(Java)》第七周学习总结
- 【单片机】Android手机USB外接STM32单片机通过ADB实现投屏反向控制的功能
- 病原微生物高通量测序:第三节 检测原理
- window10 彻底关闭自动更新
- 计算机编写代码简介,Vcomputer简介
- [H1B/H4] H1B, H4 分别面签成功(广州)分享帖
热门文章
- 【yolact_edge】训练自己的yolact_edge模型(并部署在Jetson Xavier上)
- 关于关闭谷歌的QUERY_ALL_PACKAGES权限问题
- 程序烧录器STLINK_V2CMSIS_DAP_V2制作——DIY方案分享
- 微服务容器部署与持续集成(Jenkins)
- vue stomp 的使用笔记
- 2.15 双创园区:武汉东湖高新区
- 有哪些原创的微信公众号推荐?(it技术编程类)
- DeeplabV3+训练数据集流程(学习记录)
- Sourcetree 无法打开
- 二维码扫码登录是什么原理?