当前位置:网站首页>QT With OpenGL (Bloom) (Bloom)
QT With OpenGL (Bloom) (Bloom)
2022-08-08 17:50:00 【Elsa's fanboy】
一、Render the scene toHDR帧缓存
1. HDRThe framebuffer requires two color textures–MRT(Multiple Render Targets,多渲染目标)
HDRFBO = new QOpenGLFramebufferObject(size(),QOpenGLFramebufferObject::CombinedDepthStencil,GL_TEXTURE,GL_RGBA16F);
HDRFBO->addColorAttachment(size(),GL_RGBA16F);
core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
GLenum buffers[] = {
GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
core->glDrawBuffers(2, buffers);
HDRFBO->release();
使用QOpenGLFunctions_3_3_Core
调用glDrawBuffers
显式告知OpenGL渲染到多个颜色缓冲.
补充:
QOpenGLFunctions 是OpenGL ES 2.0 API,So only part of the interface is available.
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API. More…
在官方文档中可以看到ES中没有glDrawBuffers.
2. 将场景渲染到HDR帧缓存,Extract the specular map.
修改shader,Render with multiple color buffers
//输出
layout (location = 0) out vec4 FragColor;
layout (location = 1) out vec4 BrightColor;
//Check if the pixel brightness is above a threshold
float brightness = dot(FragColor.rgb, vec3(0.2126, 0.7152, 0.0722));
if(brightness > 1.0) BrightColor = vec4(FragColor.rgb, 1.0);
3. 将HDRThe framebuffer is rendered to the screen,And switch to view the color buffer1、2
HDRFBO->release();
//HDR输出
glViewport(0,0,width(),height());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
BloomShader->bind();//shader
BloomShader->setUniformValue("RenderResult",0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,HDRFBO->textures().at(HDRNUM));
renderQuad();
BloomShader->release();
Extracting highlights is not as good as expected,按照直觉,Only the highlight effect of the glow should be extracted,But a large number of extraction points also appear in the environment.
且,If facing away from the light source(The luminous side is not visible,But glowing objects are visible),There will be no flooding phenomenon,与想象中不同.
二、 高斯模糊
理论
性质
- A 2D Gaussian blur can be applied by combining two 1D Gaussian blurs:
- Applying successive Gaussian blurs has the same effect as applying a single larger Gaussian blur,The radius of a Gaussian blur is the square root of the sum of the squares of the blur radii.
Both of these properties of the Gaussian function give us room for optimization.
垂直过滤器
uniform sampler2D image;
out vec4 FragmentColor;
uniform float offset[5] = float[](0.0, 1.0, 2.0, 3.0, 4.0);
uniform float weight[5] = float[](0.2270270270, 0.1945945946, 0.1216216216,
0.0540540541, 0.0162162162);
void main(void) {
FragmentColor = texture2D(image, vec2(gl_FragCoord) / 1024.0) * weight[0];
for (int i=1; i<5; i++) {
FragmentColor +=
texture2D(image, (vec2(gl_FragCoord) + vec2(0.0, offset[i])) / 1024.0)
* weight[i];
FragmentColor +=
texture2D(image, (vec2(gl_FragCoord) - vec2(0.0, offset[i])) / 1024.0)
* weight[i];
}
}
引用GPU硬件加速,使用GPUBilinear filter optimization
uniform sampler2D image;
out vec4 FragmentColor;
uniform float offset[3] = float[](0.0, 1.3846153846, 3.2307692308);
uniform float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703);
void main(void) {
FragmentColor = texture2D(image, vec2(gl_FragCoord) / 1024.0) * weight[0];
for (int i=1; i<3; i++) {
FragmentColor +=
texture2D(image, (vec2(gl_FragCoord) + vec2(0.0, offset[i])) / 1024.0)
* weight[i];
FragmentColor +=
texture2D(image, (vec2(gl_FragCoord) - vec2(0.0, offset[i])) / 1024.0)
* weight[i];
}
}
图解
Filter vertically once:red color blockThe color is up and down5The weighted sum of the colors of each color block
- Red weights are indicated:0.227027
- Orange weights are indicated:0.1945946
- Yellow weights are indicated:0.1216216
- Grey weights are indicated:0.054054
- White weights are indicated(没画):0.054054
再将red color block进行一次Filter horizontally,The pixels in that range are about to be done如下加权(The red color block is the final pixel block,Other color patches only represent weighted weights)
如: - red color block加权为 0.227027 * 0.227027
- Color block above red(暗黄色,柠檬黄,灰色)Weighted respectively:0.1945946 ,0.1216216, 0.054054
- Red right color block(橘黄色,土黄色,淡绿色)Weighted respectively:
0.227027 * 0.1945946
0.227027 * 0.1216216
0.227027 * 0.054054 - 棕色加权为0.1945946 * 0.1945946
- 其他类推
A Gaussian blur composed in this form can be seen,It's not strictly a Gaussian blur,but an approximation.但若继续循环如上的垂直-Filter horizontally器,The result is similar to the actual Gaussian blur effect.循环次数越多,模糊效果越强.
Applies a Gaussian blur to the specular map
(1)Write a Gaussian blurshader
使用LearnOpenGL
代码
#version 450 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D image;
uniform bool horizontal;
uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
void main()
{
vec2 tex_offset = 1.0 / textureSize(image, 0); // gets size of single texel
vec3 result = texture(image, TexCoords).rgb * weight[0]; // current fragment's contribution
if(horizontal)
{
for(int i = 1; i < 5; ++i)
{
result += texture(image, TexCoords + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
result += texture(image, TexCoords - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
}
}
else
{
for(int i = 1; i < 5; ++i)
{
result += texture(image, TexCoords + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
result += texture(image, TexCoords - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
}
}
FragColor = vec4(result, 1.0);
}
(2)使用两个FBO
//Gaussian blur buffer
GBHorizontal = new QOpenGLFramebufferObject(size(),QOpenGLFramebufferObject::NoAttachment,GL_TEXTURE_2D,GL_RGBA16F);
GBVertical = new QOpenGLFramebufferObject(size(),QOpenGLFramebufferObject::NoAttachment,GL_TEXTURE_2D,GL_RGBA16F);
注意再resizeGL中也要设置.
(3)高斯模糊
//高斯模糊
GLboolean horizontal = true, first_iteration = true;
GLuint amount = 10;
GaussianBlurShader->bind();
for (GLuint i = 0; i < amount; i++)
{
if(horizontal)GBHorizontal->bind();
else GBVertical->bind();
//glClear(GL_COLOR_BUFFER_BIT);
GaussianBlurShader->setUniformValue("horizontal",horizontal);
GaussianBlurShader->setUniformValue("image",0);
glActiveTexture(GL_TEXTURE0);
unsigned int id = 0;
if(first_iteration){
id = HDRFBO->textures().at(1);
}
else{
if(horizontal)id = GBVertical->texture();
else id = GBHorizontal->texture();
}
glBindTexture(GL_TEXTURE_2D, id);
renderQuad();
horizontal = !horizontal;
if (first_iteration)
first_iteration = false;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
结果
模糊前
模糊后
三、把两个纹理混合
有了场景的HDR纹理and blurredBright area texture,我们只需把它们结合起来就能实现泛光或称光晕效果了.最终的像素着色器(大部分和HDR教程用的差不多)要把两个纹理混合:
Easiest mix(直接相加)
#version 450 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D RenderResult;
uniform sampler2D bloomBlur;
void main()
{
vec3 hdrColor = texture(RenderResult, TexCoords).rgb;
vec3 bloomColor = texture(bloomBlur, TexCoords).rgb;
if(addBloom) hdrColor += bloomColor;
FragColor = vec4(hdrColor , 1.0f);
}
结果
Overhead light sources appear flooded
But in addition to the light source, other objects also have floodlight phenomenon(这不合理).
It should be modified so that only the light source has the blooming phenomenon
维护
待更新…
边栏推荐
猜你喜欢
Nioke 2022 Summer Multi-School 6 B Eezie and Pie (Difference on the tree + multiplication to find the kth ancestor board)
盘点检索任务中的损失函数
dp, dpi, px knowledge supplement
Cy5反式环辛烯,TCO-Cy5,Cy5 trans-cyclooctene标记生物分子
Neo4j: 1. CQL statement
canvas城市灯火夜景动画js特效
JVM内存模型和结构详解(五大模型图解)
【目标检测】小脚本:根据xml批量复制jpg图片
瑞利衰落条件下扩频通信系统误码率仿真
uri (url urn 的区别)
随机推荐
XDOJ - count the number of positive integers
DSPE-PEG-Biotin,385437-57-0,磷脂-聚乙二醇-生物素用于生物分子的检测和纯化
串行通信:常见的串行通信接口协议UART、SPI、I2C简介
为什么MySQL的主键查询这么快
21天学习第二天-类型转换
Node基于TCP建立的服务器
How big is 1dp!
【Promise.allSettled】手写Promise.allSettled方法
QT With OpenGL(泛光)(Bloom)
C语言每日一练——Day01:求最大公约数(三种方法)
C人脸识别
用皮肤“听”音乐,网友戴上这款装备听音乐会:仿佛住在钢琴里
【NodeJs篇】fs文件系统模块
史上最强IDEA工具使用教程,你想要的全都有!
记录贴:pytorch学习Part3
高维前缀和和子集dp(状压dp的一种)
多线程之不可变对象
咸阳广发证券股票开户安全吗,需要准备什么证件
【CC3200AI 实验教程4】疯壳·AI语音人脸识别(会议记录仪/人脸打卡机)-GPIO
The new version of squirrel as source change operation