首页 > 其他分享 >Opengl-Bloom

Opengl-Bloom

时间:2023-03-07 16:44:14浏览次数:50  
标签:Opengl int TEXTURE 2D result horizontal GL Bloom

The bloom chapter is complicated. It combines all the ideas from the chapters we have learn.

  • Extracting bright color
  • Gaussian blur
  • Blending both textures

Extracting bright color

We first create one frame buffer with two colorbuffers attached to store the normal scene and the brighter part. And use one render buffer to store the depth data.

// set up floating point framebuffer to render scene to
unsigned int hdrFBO;
glGenFramebuffers(1, &hdrFBO);
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
unsigned int colorBuffers[2];
glGenTextures(2, colorBuffers);
for (unsigned int i = 0; i < 2; i++)
{
    glBindTexture(GL_TEXTURE_2D, colorBuffers[i]);
    glTexImage2D(
        GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL
    );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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_T, GL_CLAMP_TO_EDGE);
    // attach texture to framebuffer
    glFramebufferTexture2D(
        GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, colorBuffers[i], 0
    );
}

create render buffer, render buffer is good at dealing with depth data. using the code below we can attch the depth data to framebuffer created above.

    unsigned int rboDepth;
    glGenRenderbuffers(1, &rboDepth);
    glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);

Now we have a framebuffer with two colorbuffers and one depthbuffer(renderbuffer). For now opengl dont know how to recognize these two color buffers. we need to tell opengl.

// tell opengl to render to two colorbuffers
unsigned int attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, attachments);  

After create color buffer, we need to tell opengl that in the shader file which output variable is according to which colorbuffer.

#version 330 core
layout (location = 0) out vec4 FragColor;
layout (location = 1) out vec4 BrightColor;

[...]

void main()
{            
    [...] // first do normal lighting calculations and output results
    FragColor = vec4(lighting, 1.0);
    // check whether fragment output is higher than threshold, if so output as brightness color
    float brightness = dot(FragColor.rgb, vec3(0.2126, 0.7152, 0.0722));
    if(brightness > 1.0)
        BrightColor = vec4(FragColor.rgb, 1.0);
    else
        BrightColor = vec4(0.0, 0.0, 0.0, 1.0);
}

layout location here correponding to attachment number.

Gaussian blur

Blur is mainly mathematic, we create two framebuffer to blur in a loop. which is called pingpong. we blur in horizontal, then use this horizontally blurred buffer as texture for the vertical framebuffer. and then horizontal.

Create pingpong framebuffer

unsigned int pingpongFBO[2];
unsigned int pingpongBuffer[2];
glGenFramebuffers(2, pingpongFBO);
glGenTextures(2, pingpongBuffer);
for (unsigned int i = 0; i < 2; i++)
{
    glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]);
    glBindTexture(GL_TEXTURE_2D, pingpongBuffer[i]);
    glTexImage2D(
        GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL
    );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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_T, GL_CLAMP_TO_EDGE);
    glFramebufferTexture2D(
        GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongBuffer[i], 0
    );
}

Loop blur

bool horizontal = true, first_iteration = true;
int amount = 10;
shaderBlur.use();
for (unsigned int i = 0; i < amount; i++)
{
    glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); 
    shaderBlur.setInt("horizontal", horizontal);
    glBindTexture(
        GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongBuffers[!horizontal]
    ); 
    RenderQuad();
    horizontal = !horizontal;
    if (first_iteration)
        first_iteration = false;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); 

Math in fragment shader

#version 330 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);
}

Blending both textures

All the framebuffer are HDR, we need to change
it to LDR.

#version 330 core
out vec4 FragColor;
  
in vec2 TexCoords;

uniform sampler2D scene;
uniform sampler2D bloomBlur;
uniform float exposure;

void main()
{             
    const float gamma = 2.2;
    vec3 hdrColor = texture(scene, TexCoords).rgb;      
    vec3 bloomColor = texture(bloomBlur, TexCoords).rgb;
    hdrColor += bloomColor; // additive blending
    // tone mapping
    vec3 result = vec3(1.0) - exp(-hdrColor * exposure);
    // also gamma correct while we're at it       
    result = pow(result, vec3(1.0 / gamma));
    FragColor = vec4(result, 1.0);
}  

Reference
https://learnopengl.com/Advanced-Lighting/Bloom

标签:Opengl,int,TEXTURE,2D,result,horizontal,GL,Bloom
From: https://www.cnblogs.com/zhaobangliu/p/17188569.html

相关文章

  • 【转】【OpenGL】OpenGL显示文字--显示汉字
    OpenGL显示文字--显示汉字    原则上,显示中文和显示英文并无不同,同样是把要显示的字符做成显示列表,然后进行调用。但是有一个问题,英文字母很少,最多只有几百个,为每个......
  • OpenGL 4.4 pipeline
    svg版本见:https://raw.githubusercontent.com/g-truc/website/d17f404f103caf537564fd1dc5a3b9b71f1d6070/doc/OpenGL%204.4%20Pipeline%20Map.svg 更多请参考:https://g......
  • 【转】OpenGL光照设置
    1.设置光源(1)光源的种类环境光环境光是一种无处不在的光。环境光源放出的光线被认为来自任何方向。因此,当你仅为场景指定环境光时,所有的物体无论法向量如何,都将表现为同......
  • Qt-FFmpeg开发-视频播放【软解码 + OpenGL显示RGB图像】(3)
    Qt-FFmpeg开发-视频播放【软解码+OpenGL显示RGB图像】目录Qt-FFmpeg开发-视频播放【软解码+OpenGL显示RGB图像】1、概述2、实现效果3、FFmpeg软解码流程4、主要代码4.......
  • FFmpeg开发-视频播放【软/硬解码 + OpenGL显示YUV/NV12】05 转载
    1、概述最近研究了一下FFmpeg开发,功能实在是太强大了,网上ffmpeg3、4的文章还是很多的,但是学习嘛,最新的还是不能放过,就选了一个最新的ffmpegn5.1.2版本,和3、4版本api变化......
  • OpenGL Program渲染框架
    Program.h#pragmaonce#ifndefProgram_h#defineProgram_hclassProgram{public:///ConstructorforarenderingprogramProgram(conststd::......
  • OpenGL体素化&什么是SSBO?
    [1]TheBasicsofGPUVoxelization:https%3A//developer.nvidia.com/content/basics-gpu-voxelization[2]体素化Voxelization:基于GPU的三维体素化:https%3A//yangwc.com/20......
  • WebGL和OpenGL的区别及关系
    什么是WebGLWebGL™是一个跨平台的,免版税的开放Web标准,用于基于OpenGLES的低级3D图形API,通过HTML5Canvas元素向ECMAScript公开。熟悉OpenGLES2.0的开发人员将使用GLSL......
  • OpenGL-GLES 1.x
    首先了解下着色器:着色器是一段包含着色信息的源代码字符串,分为顶点着色器和片元着色器,两个着色器分别写在不同的文件中。着色器代码和OpenGL代码不是一起编译的,OpenGL代码......
  • OpenGL ES 2.0编程指导阅读笔记(七)图元装配和光栅化
    图元装配阶段在顶点着色之后,在图元装配阶段执行裁剪、透视变换和视窗变换。光栅化是将图元转换成一系列两位片元的过程。图元OpenGLES2.0中可以绘制的图元有三角形、......