如何创建模糊着色器

问题描述

我正在按照以下着色器创建模糊。

OpenGL es 2.0 Gaussian blur on triangle

首先我生成帧缓冲区。

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,GL_RGBA8,1920,1080,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,1080);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,renderbuffer);

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

比我遵循这些步骤。

    // 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);
    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);
    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",glm::vec2(0.0,1.0));
    ResourceManager::GetShader("shaderTest").SetVector2f("u_textureSize",1080.0));
    glClearColor(0.0,texObj[1]);
    glGenerateMipmap(GL_TEXTURE_2D);
    drawFullScreenQuad();

    
    // Render the result to full screen.
    glBindFramebuffer(GL_FRAMEBUFFER,drawFrameBuffer); 
    glClearColor(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();

这些是着色器。

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

void main()
{
    pos = aPos;
    gl_Position =   vec4(aPos,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,1.0 );
   FragColor = vec4( gaussCol.rgb,1.0 );

}

当u_radius和u_sigma的值为1时,模糊是平滑的。

enter image description here

当u_sigma为10且u_radius为30时,模糊看起来像这样。

enter image description here

由于该示例使用的是webgl,而我使用的是Opengl,结果会有所不同吗?

Rabbid76给出的值之后的新图像。

enter image description here

解决方法

在着色器的实现中, sigma 的值必须在[0.0,1.0]范围内。 半径为30似乎很大。以u_sigma = 0.5u_radius = 10开头。


由于Alpha通道的计算错误,着色器效果仍然看起来不正确。
您已经从WebGL复制了着色器。默认情况下,WebGL使用premultiplied alpha,但您的桌面应用程序则不使用。参见Straight versus premultiplied
跳过颜色通道的加权和除以alpha通道的加权和:

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

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

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...