C++ 为什么可以';是否无法从我的照明着色器访问G缓冲区?

C++ 为什么可以';是否无法从我的照明着色器访问G缓冲区?,c++,opengl,rendering,framebuffer,C++,Opengl,Rendering,Framebuffer,我在引擎中实现了一个新的渲染管道,现在渲染已中断。当我直接在屏幕上绘制G缓冲区的纹理时,它会正确显示。所以G缓冲区是好的。但不知何故,照明通道制造了麻烦。即使我不使用它的结果纹理,但尝试在灯光经过后显示G缓冲区的反照率,它也会显示纯色灰色 我无法解释这种行为,奇怪的是,在任何时候都没有OpenGL错误 顶点着色器以绘制全屏四边形 #version 330 in vec4 vertex; out vec2 coord; void main() { coord = vertex.xy;

我在引擎中实现了一个新的渲染管道,现在渲染已中断。当我直接在屏幕上绘制G缓冲区的纹理时,它会正确显示。所以G缓冲区是好的。但不知何故,照明通道制造了麻烦。即使我不使用它的结果纹理,但尝试在灯光经过后显示G缓冲区的反照率,它也会显示纯色灰色

我无法解释这种行为,奇怪的是,在任何时候都没有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);
    }
}
照明通道的目标和采样器。纹理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
无序映射目标;
目标。插入(生成配对(GL颜色附件2,…);//光
目标。插入(制作成对(总图深度模板附件…);//深度和模板
无序地图采样器;
采样器.插入(配对(“位置”,…);//来自G缓冲区的位置
samplers.insert(生成一对(“法线”,…);//G缓冲区中的法线
绘制照明通道的功能

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);
}
void DrawLights(无序地图采样器,GLuint程序)
{
自动lis=实体->获取();
glClear(GLU颜色缓冲位);
glEnable(GL_混合物);
glBlendFunc(GL_ONE,GL_ONE);
glUseProgram(程序);
int n=0;用于(自动i:采样器)
{
玻璃纹理(GL_纹理0+n);
glBindTexture(GL_TEXTURE_2D,i.second);
glUniform1i(glGetUniformLocation(Program,i.first.c_str()),n);
n++;
}
mat4视图=实体->获取(*全局->获取(“摄影机”)->视图;
用于(自动i:lis)
{
int type=i.second->type==Light::directive?0:1;
vec3 pos=vec3(视图*vec4(实体->获取(i.first)->Position(),!类型?0:1));
glUniform1i(glGetUniformLocation(程序,“类型”),类型;
glUniform3f(glGetUniformLocation(程序,“光”),位置x、位置y、位置z;
glUniform3f(glGetUniformLocation(程序,“color”),i.second->color.x,i.second->color.y,i.second->color.z);
glUniform1f(glGetUniformLocation(程序,“半径”),即秒->半径;
glUniform1f(glGetUniformLocation(程序,“强度”),即秒->强度;
glBegin(GL_QUADS);
glVertex2i(0,0);
glVertex2i(1,0);
glVertex2i(1,1);
glVertex2i(0,1);
格伦德();
}
glDisable(GLU混合);
玻璃纹理(GL_纹理0);
glBindBuffer(GL_数组_BUFFER,0);
glBindTexture(GL_TEXTURE_2D,0);
}

我发现了错误,这是一个多么愚蠢的错误。旧的渲染管道在调用该过程的draw函数之前绑定了正确的帧缓冲区。但是新函数没有这样做,所以每个绘图函数都必须自己做。因此,我想更新所有绘图功能,但我错过了照明通道的绘图功能

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);
}
因此,G缓冲区的帧缓冲区仍处于绑定状态,照明过程更改了其目标


多亏了你们,你们并没有发现那个错误,因为我并没有发布我的完整管道系统。

你们在这里调用
glDrawBuffers
,那个么你们怎么知道要呈现给哪个附件呢?发布frag着色器的输出部分。另外,纹理附件的确切内部格式、格式和类型是什么?碎片着色器使用
layout(location=0)
等来写入附加到
GL\u COLOR\u ATTACHMENT0的目标,依此类推。对于G缓冲区通道,有三种类型的纹理
GL_RGB16F
GL_RGB
GL_FLOAT
和一种类型
GL_DEPTH24_模具8
GL_DEPTH_模具
GL_UNSIGNED_INT_24_8
。我可以说,深度和模板工作,但不是其他三个目标。根据
glGetFramebufferAttachmentParameteriv
,所有目标都得到了正确的连接。好吧,考虑到是着色器写入了G缓冲区,我想可能需要发布它们以获得更多细节。@danijar“片段着色器使用
布局(位置=0)
等等,以写入附加到
GL\u COLOR\u ATTACHMENT0的目标。“-但这并不完全正确。
location
指定要写入的绘图缓冲区(因此
location=0
将是给定给
glDrawBuffers
的数组中的第一个附件),如果您的目标没有连续无间隔地包含
GL\u COLOR\u ATTACHMENTi
,那么这两个东西就不一样了。也许这就是你错误的原因?你如何检查反照率和法线纹理是否为零?是否可能您正在采样尚未生成的mipmap级别?