SSAO 工作但有一个奇怪的红色覆盖

SSAO working but has a weird Red colour overlay

ssao 有效,但有 奇怪的红色叠加层,因为 ssao 当然只使用红色通道 这显示了在下图中..

红色 SSAO 问题

但是,当我执行 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 时,红色消失了,但是ssao 也一样。

执行 glClear() 后的结果。不再有 SSAO

这是您需要的所有代码...

// ------------------------------ LIGHT PASS -------------------------------- //
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shaders[LIGHT_PASS]->UseProgram();  // Bind light pass shader

    // Parse the camera position
    LightPass::Render(Content::_map->GetCamera(), Content::_map->GetCamera()->GetPosition());   

    GBuffer::Render();  // bind the gbuffer textures (includes SSAO)

    renderQuad();   // Render the screen rectangle
    // -------------------------------------------------------------------- //

几何密码..

// ----------------------------- GEOMETRY PASS ----------------------------- //
    GBuffer::Bind();    // Bind the world gbuffer frame buffer
    shaders[GEOMETRY_PASS]->UseProgram();   // Bind geometry shader
    GeometryPass::Render();     // Render geometry
    glBindFramebuffer(GL_FRAMEBUFFER, 0);   // Unbind the gbuffer
    // --------------------------------------------------------------------- //

SSAO 密码..

static inline void Initialise(unsigned int ssao_program, unsigned int ssaoblur_program) 
    {
        program = ssao_program;
        program2 = ssaoblur_program;

        // SSAO color fbo
        glGenTextures(1, &ssaoColorBuffer);
        glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1920, 1080, 0, GL_RGB, GL_FLOAT, NULL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBuffer, 0);
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            std::cout << "SSAO Framebuffer not complete!" << std::endl;

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        // blur fbo
        glGenFramebuffers(1, &ssaoBlurFBO);
        glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO);

        // SSAO color buffer
        glGenTextures(1, &ssaoColorBufferBlur);
        glBindTexture(GL_TEXTURE_2D, ssaoColorBufferBlur);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1920, 1080, 0, GL_RGB, GL_FLOAT, NULL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBufferBlur, 0);
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            std::cout << "SSAO Framebuffer not complete!" << std::endl;

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        std::uniform_real_distribution<GLfloat> randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0
        std::default_random_engine generator;

        for (unsigned int i = 0; i < 64; ++i)
        {
            glm::vec3 sample(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, randomFloats(generator));
            sample = glm::normalize(sample);
            sample *= randomFloats(generator);
            float scale = float(i) / 64.0;

            // scale samples s.t. they're more aligned to center of kernel
            scale = lerp(0.1f, 1.0f, scale * scale);
            sample *= scale;
            ssaoKernel.push_back(sample);
        }

        for (unsigned int i = 0; i < 16; i++)
        {
            glm::vec3 noise(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, 0.0f); // rotate around z-axis (in tangent space)
            ssaoNoise.push_back(noise);
        }
        glGenTextures(1, &noiseTexture);
        glBindTexture(GL_TEXTURE_2D, noiseTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 4, 4, 0, GL_RGB, GL_FLOAT, &ssaoNoise[0]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

        glUseProgram(ssao_program);
        glUniform1i(glGetUniformLocation(ssao_program, "gPosition"), 0); // the positions texture in the gbuffer
        glUniform1i(glGetUniformLocation(ssao_program, "gNormal"), 1); // the normals texture in the gbuffer
        glUniform1i(glGetUniformLocation(ssao_program, "texNoise"), 2); // the albedospec texture within the gbuffe

        glUseProgram(ssaoblur_program);
        glUniform1i(glGetUniformLocation(ssaoblur_program, "ssaoInput"), 0); // the positions texture in the gbuffer
    }

static inline void Render(Camera* _camera) 
    {
        // generate SSAO texture
        glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO);
        glClear(GL_COLOR_BUFFER_BIT);
        glUseProgram(program);

        for (unsigned int i = 0; i < 64; ++i)
            glUniform3fv(glGetUniformLocation(program, ("samples[" + std::to_string(i) + "]").c_str()), 1, glm::value_ptr(ssaoKernel[i]));

        glUniformMatrix4fv(glGetUniformLocation(program, "proj"), 1, GL_FALSE, glm::value_ptr(_camera->GetProjectionMatrix()));

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, GBuffer::GetPositions());
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, GBuffer::GetNormals());
        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D, noiseTexture);

        renderQuad();

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        // Blur ssao texture
        glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(program2);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer);

        renderQuad();

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

GBuffer 顶点着色器..

#version 420 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 texcoord;
layout(location = 2) in vec3 normal;
layout(location = 3) in vec3 tangent;

out vec3 _texcoord;
out vec3 _normal;
out vec3 _tangent;
out vec3 _frag_pos;

uniform mat4 mod;
uniform mat4 view;
uniform mat4 proj;


void main()
{
    vec4 view_space = view * mod * vec4(position, 1.0);
    _frag_pos = view_space.xyz;
    _texcoord = texcoord;

    _normal = ((view * mod) * vec4(normal, 0.0)).xyz;
    _tangent = (mod * vec4(tangent, 0.0)).xyz;

    gl_Position = proj * view_space;
}

GBuffer 片段着色器...

#version 420 core

layout(location = 0) out vec3 gPosition;    // Position texel colour
layout(location = 1) out vec3 gNormal;  // Normal texel colour
layout(location = 2) out vec4 gAlbedo;  // Albedo texel colour
layout(location = 3) out vec3 gSpecular;    // Cubemap texel colour
layout(location = 4) out vec3 gMetalness;   // Cubemap texel colour

in vec3 _texcoord;
in vec3 _normal;
in vec3 _tangent;
in vec3 _frag_pos;

uniform vec3        camera_pos;

uniform sampler2D   normal;     // Normal map
uniform sampler2D   albedo;     // Albedo and specular map
uniform sampler2D   specular;   // Specular map
uniform sampler2D   metalness;  // Metalness map

uniform samplerCube cubemap;    // Local cubemap reflection sampler


vec3 TBN()
{
    vec3 Normal = normalize(_normal);   // Optimise normal
    vec3 Tangent = normalize(_tangent);     // Optimise tangent

    vec3 Bitangent = cross(Tangent, Normal);    // Calculate bitangent
    vec3 BumpMapNormal = texture(normal, vec2(_texcoord).st).rgb;   // Assign rgb values from normal map

    BumpMapNormal = 2.0 * BumpMapNormal - vec3(1.0, 1.0, 1.0);  // normalise the normal map between -1 to 1

    mat3 TBN = mat3(Tangent, Bitangent, Normal);    // Create tangent, bitangent and normal matrix

    vec3 NewNormal;     // Create a new normal variable
    NewNormal = TBN * vec3(BumpMapNormal.r, -BumpMapNormal.g, BumpMapNormal.b);     // Flip green component for OpenGL
    NewNormal = normalize(NewNormal);   // Normalise the new normal

    return NewNormal;   // Return the newly calculated normal
}

vec4 Convolute()
{
    vec4 result = vec4(0.0);

    const float kernel[] = float[25] ( 0,1,2,1,0,
                                       1,2,3,2,1,
                                       2,3,4,3,2,
                                       1,2,3,2,1,
                                       0,1,2,1,0);

    vec2 delta = 1.0 / textureSize(albedo, 0);
    int index = 24;

    for (int j = -1; j <= 1; j++)
    {
        for (int i = -1; i <= 1; i++)
        {
            //for (int k = -1; k <= 1; k++)
            result += kernel[index--] * texture(albedo, vec2(_texcoord).st + (vec2(i, j) * delta));
        }
    }

    result /= 25.0;
    return result;
}

void main()
{
    gPosition = _frag_pos;
    gNormal = normalize(TBN());

    vec3 I = normalize(_frag_pos - camera_pos);     // Calculate eye to fragment direction
    vec3 R = reflect(I, normalize(TBN()));  // Reflect I with the vertex normal
    float M = texture(metalness, vec2(_texcoord.st)).r;

    //vec4 gaussian = Convolute();
    gAlbedo = texture(albedo, vec2(_texcoord.st));  // Assign albedo
    gSpecular = texture(specular, vec2(_texcoord.st)).rgb;  // Assign specular
    gMetalness = (texture(cubemap, R).rgb) * M;     // Assign metalness
}

灯光着色器...

#version 420 core

out vec4 FragColor;

in vec2 _texcoord;


uniform vec3        camera_pos;
uniform sampler2D   gPosition;
uniform sampler2D   gNormal;
uniform sampler2D   gAlbedo;
uniform sampler2D   gSpecular;
uniform sampler2D   gMetalness;
uniform sampler2D   gSsao;

uniform vec3 lightPos;


void main(void)
{
    vec3 FragPos = texture(gPosition, _texcoord).rgb;
    vec3 Normal = texture(gNormal, _texcoord).rgb;
    vec3 Diffuse = texture(gAlbedo, _texcoord).rgb;
    float Emissive = texture(gAlbedo, _texcoord).a;
    vec3 Specular = texture(gAlbedo, _texcoord).rgb;
    vec3 Metalness = texture(gMetalness, _texcoord).rgb;    // Reflection pass

    float AmbientOcclusion = texture(gSsao, _texcoord).r;

    vec3 light_colour = vec3(1.0f, 0.8, 0.7);

    vec3 lighting = vec3(0.3 * Diffuse * AmbientOcclusion);
    vec3 viewDir = normalize(-FragPos);
    vec3 lightDir = normalize(lightPos - FragPos);
    vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * light_colour;    // Light colour

    vec3 halfwayDir = normalize(lightDir + viewDir);
    float spec = pow(max(dot(Normal, halfwayDir), 0.0), 32.0);
    vec3 specular = (Specular * light_colour) * spec;

    vec3 metalness = Metalness * Diffuse;

    lighting += diffuse + specular + metalness;

    FragColor = vec4(lighting, 1.0);
}

需要更多代码就问。感谢您提供的任何帮助

编辑 问题已修复,是由于立方体贴图反射,现在一切正常

如果查找纹理,并且纹理中不存在特定纹理通道,则函数 texture 将为绿色和蓝色通道 return 0.0 和 alpha 1.0频道。

这可以通过纹理调配参数进行更改GL_TEXTURE_SWIZZLE_R, GL_TEXTURE_SWIZZLE_G, GL_TEXTURE_SWIZZLE_B and GL_TEXTURE_SWIZZLE_A

如果您希望绿色和蓝色通道 return 与红色通道具有相同的值,那么可以这样做:

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED );

将此参数应用于纹理对象 ssaoColorBufferssaoColorBufferBlur,以解决问题。


参见OpenGL 4.6 API Core Profile Specification; 15.2. SHADER EXECUTION; page 487]:

When a texture lookup is performed in a fragment shader, the GL computes the filtered texture value ... and converts it to a texture base color Cb as shown in table 15.1,

Texture Base Texture base color Internal Format    Cb              Ab
RED                                                (Rt, 0, 0)      1
RG                                                 (Rt, Gt, 0)     1
RGB                                                (Rt, Gt, Bt)    1
RGBA                                               (Rt, Gt, Bt)    At

Table 15.1: Correspondence of filtered texture components to texture base components.

followed by swizzling the components of Cb, controlled by the values of the texture parameters TEXTURE_SWIZZLE_R, TEXTURE_SWIZZLE_G, TEXTURE_SWIZZLE_B, and TEXTURE_SWIZZLE_A. If the value of TEXTURE_SWIZZLE_R is denoted by swizzler, swizzling computes the first component of Cs according to

if (swizzler == RED)
Cs[0] = Cb[0];
else if (swizzler == GREEN)
Cs[0] = Cb[1];
else if (swizzler == BLUE)
Cs[0] = Cb[2];
else if (swizzler == ALPHA)
Cs[0] = Ab;
else if (swizzler == ZERO)
Cs[0] = 0;
else if (swizzler == ONE)
Cs[0] = 1; // float or int depending on texture component type