c++ - 为什么无法从我的光照着色器访问 G-Buffer?

标签 c++ opengl rendering framebuffer

我在我的引擎中实现了一个新的渲染管线,现在渲染坏了。当我直接在屏幕上绘制 G-Buffer 的纹理时,它会正确显示。所以G-Buffer没问题。但不知何故,照明 channel 制造了麻烦。即使我不使用它的结果纹理,而是尝试在光照 channel 后显示来自 G-Buffer 的反照率,它也会显示纯灰色。

我无法解释这种行为,奇怪的是在任何时候都没有 OpenGL 错误。

用于绘制全屏四边形的顶点着色器。

#version 330

in vec4 vertex;

out vec2 coord;

void main()
{
    coord = vertex.xy;
    gl_Position = vertex * 2.0 - 1.0;
}

用于照明的片段着色器。

#version 330

in vec2 coord;
out vec3 image;

uniform int type = 0;
uniform sampler2D positions;
uniform sampler2D normals;
uniform vec3 light;
uniform vec3 color;
uniform float radius;
uniform float intensity = 1.0;

void main()
{
    if(type == 0) // directional light
    {
        vec3 normal = texture2D(normals, coord).xyz;
        float fraction = max(dot(normalize(light), normal) / 2.0 + 0.5, 0);
        image = intensity * color * fraction;
    }
    else if(type == 1) // point light
    {
        vec3 pixel = texture2D(positions, coord).xyz;
        vec3 normal = texture2D(normals, coord).xyz;
        float dist = max(distance(pixel, light), 1);
        float magnitude = 1 / pow(dist / radius + 1, 2);
        float cutoff = 0.4;
        float attenuation = clamp((magnitude - cutoff) / (1 - cutoff), 0, 1);
        float fraction = clamp(dot(normalize(light - pixel), normal), -1, 1);
        image = intensity * color * attenuation * max(fraction, 0.2);
    }
}

光照 channel 的目标和采样器。纹理 ID 分别映射到附件着色器位置。

unordered_map<GLenum, GLuint> targets;
targets.insert(make_pair(GL_COLOR_ATTACHMENT2, ...)); // light
targets.insert(make_pair(GL_DEPTH_STENCIL_ATTACHMENT, ...)); // depth and stencil

unordered_map<string, GLuint> samplers; 
samplers.insert(make_pair("positions", ...)); // positions from G-Buffer
samplers.insert(make_pair("normals", ...)); // normals from G-Buffer

光照 channel 的绘制函数。

void DrawLights(unordered_map<string, GLuint> Samplers, GLuint Program)
{
    auto lis = Entity->Get<Light>();

    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE);

    glUseProgram(Program);
    int n = 0; for(auto i : Samplers)
    {
        glActiveTexture(GL_TEXTURE0 + n);
        glBindTexture(GL_TEXTURE_2D, i.second);
        glUniform1i(glGetUniformLocation(Program, i.first.c_str()), n);
        n++;
    }

    mat4 view = Entity->Get<Camera>(*Global->Get<unsigned int>("camera"))->View;

    for(auto i : lis)
    {
        int type = i.second->Type == Light::DIRECTIONAL ? 0 : 1;
        vec3 pos = vec3(view * vec4(Entity->Get<Form>(i.first)->Position(), !type ? 0 : 1));
        glUniform1i(glGetUniformLocation(Program, "type"),      type);
        glUniform3f(glGetUniformLocation(Program, "light"),     pos.x, pos.y, pos.z);
        glUniform3f(glGetUniformLocation(Program, "color"),     i.second->Color.x, i.second->Color.y, i.second->Color.z);
        glUniform1f(glGetUniformLocation(Program, "radius"),    i.second->Radius);
        glUniform1f(glGetUniformLocation(Program, "intensity"), i.second->Intensity);

        glBegin(GL_QUADS);
            glVertex2i(0, 0);
            glVertex2i(1, 0);
            glVertex2i(1, 1);
            glVertex2i(0, 1);
        glEnd();
    }

    glDisable(GL_BLEND);
    glActiveTexture(GL_TEXTURE0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
}

最佳答案

我发现了这个错误,那是个愚蠢的错误。旧的渲染管道在调用该 channel 的绘制函数之前绑定(bind)了正确的帧缓冲区。但是新的没有,所以每个绘制函数都必须自己做。因此我想更新所有的绘制函数,但是我错过了光照 channel 的绘制函数。

因此 G-Buffer 的帧缓冲区仍然是绑定(bind)的,光照过程改变了它的目标。

感谢你们,你们没有发现那个错误,因为我没有发布我完整的管道系统。

关于c++ - 为什么无法从我的光照着色器访问 G-Buffer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17188482/

相关文章:

c++ - Doxygen 不记录 c++ 源文件

c++ - Opengl:视口(viewport)、裁剪、矩阵模式困惑

objective-c - 从 NSImage 获取 GLuint 纹理

c++ - 如何在 OpenGL 中渲染非平凡粒子

c# - OpenGL 3.3+ - 着色器、属性、制服、输入/输出变量 - 如何、什么、何时、为什么?

c++ - 任何想法如何使 C++ 在内核错误上抛出异常

c++ - 为什么 vector.clear() 在循环中不起作用?

html - `window.matchMedia` 是否触发回流?

c++ - Direct2D 保存渲染结果

c++ - QtQuick : QQmlApplicationEngine failed to load component qrc:/main. qml:23 无效的附加对象分配