简体   繁体   English

如何创建模糊着色器

[英]How to create a blur shader

I am following the following shader to create a blur.我正在遵循以下着色器来创建模糊。

OpenGL es 2.0 Gaussian blur on triangle OpenGL es 2.0 三角形上的高斯模糊

First i generate framebuffers.首先我生成帧缓冲区。

glGenTextures(2, texObj);
    glGenFramebuffers(2, fbObj);
    glActiveTexture(GL_TEXTURE0);
    for (int i = 0; i < 2; i++)
    {
        glBindTexture(GL_TEXTURE_2D, texObj[i]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        glGenerateMipmap(GL_TEXTURE_2D);
        glBindFramebuffer(GL_FRAMEBUFFER, fbObj[i]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texObj[i], 0);
        GLuint renderbuffer;
        glGenRenderbuffers(1, &renderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 1920, 1080);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);

    }
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

Than i follow these steps.比我遵循这些步骤。

    // first create a image of the scene
    GLint drawFrameBuffer;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &drawFrameBuffer);    
    glBindFramebuffer(GL_FRAMEBUFFER, fbObj[0]);  
    ResourceManager::GetShader("BasicShader").Use();
    //ResourceManager::GetShader("BasicShader").SetInteger("UseColorMap", false);
    glDisable(GL_DEPTH_TEST);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT );
    geom->draw();   
    
    
    // Set the Blur in X direction
    glBindFramebuffer(GL_FRAMEBUFFER, fbObj[1]);
    ResourceManager::GetShader("shaderTest").Use();
    // Set the blur shader properties
    ResourceManager::GetShader("shaderTest").SetFloat("u_sigma", intensity);
    ResourceManager::GetShader("shaderTest").SetFloat("u_radius", blur);
    ResourceManager::GetShader("shaderTest").SetVector2f("u_dir", glm::vec2(1.0, 0.0));
    ResourceManager::GetShader("shaderTest").SetVector2f("u_textureSize", glm::vec2(1920.0, 1080.0));   
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, texObj[0]);
    glGenerateMipmap(GL_TEXTURE_2D);
    drawFullScreenQuad();


    // Set the Blur in Y direction
    glBindFramebuffer(GL_FRAMEBUFFER, fbObj[0]);
    ResourceManager::GetShader("shaderTest").Use();
    // Set the blur shader properties
    ResourceManager::GetShader("shaderTest").SetFloat("u_sigma", intensity);
    ResourceManager::GetShader("shaderTest").SetFloat("u_radius", blur);
    ResourceManager::GetShader("shaderTest").SetVector2f("u_dir", glm::vec2(0.0, 1.0));
    ResourceManager::GetShader("shaderTest").SetVector2f("u_textureSize", glm::vec2(1920.0, 1080.0));
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, texObj[1]);
    glGenerateMipmap(GL_TEXTURE_2D);
    drawFullScreenQuad();

    
    // Render the result to full screen.
    glBindFramebuffer(GL_FRAMEBUFFER, drawFrameBuffer); 
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);
    glActiveTexture(GL_TEXTURE0);
    ResourceManager::GetShader("Screen").Use();
    glBindTexture(GL_TEXTURE_2D, texObj[0]);    
    glGenerateMipmap(GL_TEXTURE_2D);
    drawFullScreenQuad();
    ResourceManager::GetShader("BasicShader").Use();

These are the shaders.这些是着色器。

#version 430 core
layout (location = 0) in vec2 aPos;
out vec2 pos;

void main()
{
    pos = aPos;
    gl_Position =   vec4(aPos, 0.0 , 1.0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// ///////////////////////////////////////////////// ////

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

// texture sampler
uniform sampler2D u_texture;
uniform vec2      u_textureSize;
uniform float     u_sigma;
uniform float     u_radius;
uniform vec2      u_dir;

float CalcGauss( float x, float sigma)
{
   if( sigma <= 0.0 )
    return 0.0;
return exp( -(x * x) / ( 2.0 * sigma)) / ( 2.0 * 3.14157 * sigma);

}

void main()
{
    vec2 texC     = pos.st * 0.5 + 0.5;
    vec4 texCol   = texture2D( u_texture, texC );
    vec4 gaussCol = vec4( texCol.rgb, 1.0 );
    vec2 step     = u_dir / u_textureSize;
    float weight;
    for ( int i = 1; i <= 16; ++ i )
    {
        weight = CalcGauss( float(i) / 16.0, u_sigma * 0.5 );
        if ( weight < 1.0/255.0 )
            break;
        texCol    = texture2D( u_texture, texC + u_radius * step * float(i) );
        gaussCol += vec4( texCol.rgb * weight, weight );
        texCol    = texture2D( u_texture, texC - u_radius * step * float(i) );
        gaussCol += vec4( texCol.rgb * weight, weight );
    }
    
   gaussCol.rgb = clamp( gaussCol.rgb / gaussCol.w, 0.0, 1.0 );
   FragColor = vec4( gaussCol.rgb , 1.0 );

}

When the value for u_radius and u_sigma is 1 than the blur is smooth.当 u_radius 和 u_sigma 的值为 1 时,模糊是平滑的。

在此处输入图片说明

when u_sigma is 10 and u_radius is 30 than the blur looks like this.当 u_sigma 为 10 且 u_radius 为 30 时,模糊看起来像这样。

在此处输入图片说明

Since that example is using webgl and i am using Opengl would the results vary ?由于该示例使用的是 webgl 而我使用的是 Opengl,结果会有所不同吗?

The new image after values given by Rabbid76. Rabbid76 给出的值之后的新图像。

在此处输入图片说明

In the implementation of the shader, the value for sigma has to be in range [0.0, 1.0].在着色器的实现中, sigma的值必须在 [0.0, 1.0] 范围内。 A radius of 30 seems to be to large. 30 的半径似乎太大了。 Start with u_sigma = 0.5 and u_radius = 10 .u_sigma = 0.5u_radius = 10


The the shader effect still looks wrong, because the computation of the alpha channel is wrong.着色器效果看起来仍然是错误的,因为 alpha 通道的计算是错误的。
You have copied the shader form a WebGL .您已经从WebGL复制了着色器。 WebGL by default uses premultiplied alpha , but your desktop application does not.默认情况下,WebGL 使用预乘 alpha ,但您的桌面应用程序不使用。 See Straight versus premultiplied .请参阅Straight 与 premultiplied
Skip the division of the weighted sum of the color channels by the weighted sum of the alpha channel:跳过颜色通道的加权和除以 alpha 通道的加权和:

gaussCol.rgb = clamp( gaussCol.rgb / gaussCol.w, 0.0, 1.0 );

gaussCol.rgb = clamp(gaussCol.rgb, 0.0, 1.0);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM