具有多个缓冲区的片段着色器颜色错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有多个缓冲区的片段着色器颜色错误相关的知识,希望对你有一定的参考价值。

我最近一直在尝试使用OpenGL,并再次陷入困境。如果在我的程序中我通过制服设置颜色,我可以使用我选择的任何颜色绘制多个顶点数组。但是为顶点数组对象传递两个缓冲区会导致奇怪的着色,其中0表示顶点位置,1表示颜色。

我的主要功能:

int main(){
    Window window(960,540);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    Reader read1("src/shaders/test.vert");
    Reader read2("src/shaders/test.frag");
    char * r1 = read1.getData();
    char * r2 = read2.getData();

    GLfloat vert[] = {
        0, 0, 0,
        0, 3, 0,
        8, 3, 0,
        8, 0, 0
    };
    GLushort indices[] = { 
        0,1,2, 
        2,3,0
    };

    GLfloat colors[] = {
        1, 0, 1, 1,
        1, 0, 1, 1,
        1, 0, 1, 1,
        1, 0, 1, 1,
    };

    VertexArray vao;
    Buffer* vbo = new Buffer(vert, 4 * 4, 3);

    vao.addBuffer(vbo, 0);
    vao.addBuffer(new Buffer(colors,4 * 4 , 4), 1);


    indexBuffer ibo(indices, 6);
    Shader shader(r1, r2);
    shader.enable();
    shader.setUniformMat4("pr_matrix", mat4::orthographic(0.0f, 16.0f, 0.0f, 9.0f, -1.0f, 1.0f));
    shader.setUniformMat4("ml_matrix", mat4::translation(vec3(4, 3, 0)));

    shader.setUniform2f("light_pos", vec2(8.0f, 4.5f));
    shader.setUniform4f("colour", vec4(0.2, 0.3, 0.8, 1));

    while (!window.closed()){
        window.clear();

        double x, y;
        x = window.getX();
        y = window.getY();

        shader.setUniform2f("light_pos", vec2((float)((x)*16.0f / 960.0f), (float)(9 - 9 * (y) / 540.0f)));

        vao.bind();
        ibo.bind();
        shader.setUniform4f("colour", vec4(0.2, 0.3, 0.8, 1));
        shader.setUniformMat4("ml_matrix", mat4::translation(vec3(4, 3, 0)));
        glDrawElements(GL_TRIANGLES, ibo.getCount(), GL_UNSIGNED_SHORT, 0);
        ibo.unbind();
        vao.unbind();

        window.update();
    }
    return 0;
}

我的顶点着色器:

#version 410 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;

uniform mat4 pr_matrix ;
uniform mat4 vw_matrix = mat4(1.0f);
uniform mat4 ml_matrix = mat4(1.0f);

out DATA{
    vec4 position;
    vec4 color;
} vs_out;

out vec4 pos;

void main(){
    gl_Position = pr_matrix * vw_matrix * ml_matrix * vec4(position,1) ;
    vs_out.position = ml_matrix * vec4(position,1);
    vs_out.color = color;
}

我的片段着色器:

#version 410 core
layout(location = 0) out vec4 color ;

uniform vec4 colour;
uniform vec2 light_pos;

in DATA{
    vec4 position;
    vec4 color;
} fs_in;

void main(){
    float intensity = 1.0f / length(fs_in.position.xy - light_pos);
    //color = fs_in.color * intensity;
    color = fs_in.color * intensity;
}

我的缓冲类,以防需要纠正:

Buffer::Buffer(GLfloat *data, GLsizei count, GLuint compCountExt) : compCount (compCountExt) {

    glGenBuffers(1, &bufferId);
    glBindBuffer(GL_ARRAY_BUFFER,bufferId);
    glBufferData(GL_ARRAY_BUFFER, count* sizeof(GLfloat), data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
}

void Buffer::bind() const {
    glBindBuffer(GL_ARRAY_BUFFER, bufferId);
}

void Buffer::unbind() const {
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

编辑:

vertexArray类的代码:

VertexArray::VertexArray(){
    glGenVertexArrays(1,&arrayID);

}
void VertexArray::bind() const{
    glBindVertexArray(arrayID);
}
void VertexArray::unbind() const{
    glBindVertexArray(0);
}
VertexArray::~VertexArray(){
}
void VertexArray::addBuffer(Buffer* buffer, GLuint index){
    bind();

    glBindBuffer(GL_ARRAY_BUFFER, arrayID);
    glEnableVertexAttribArray(index);
    glVertexAttribPointer(index, buffer->getComCount(), GL_FLOAT, GL_FALSE, 0, 0);

    buffer->unbind();
    unbind();

}

在此类中调用顶点属性指针。

答案

glVertexAttribPointer指的是当前绑定的数组缓冲区。这意味着你必须绑定数组缓冲区,因为你使用glVertexAttribPointer

void VertexArray::addBuffer(Buffer* buffer, GLuint index){
    bind();

    // glBindBuffer(GL_ARRAY_BUFFER, arrayID);    <---- skip
    buffer->bind();                            // <---- bind the array buffer
    glEnableVertexAttribArray(index);
    glVertexAttribPointer(index, buffer->getComCount(), GL_FLOAT, GL_FALSE, 0, 0);

    buffer->unbind();
    unbind();
}

OpenGL 4.6 Specification - 10.3.9 Vertex Arrays in Buffer Objects

将缓冲区对象绑定点添加到与每个顶点数组索引关联的客户端状态。指定顶点数组的位置和组织的命令将绑定到ARRAY_BUFFER的缓冲区对象名称复制到与指定的顶点数组索引对应的绑定点。例如,VertexAttribPointer命令复制ARRAY_BUFFER_BINDING的值。

以上是关于具有多个缓冲区的片段着色器颜色错误的主要内容,如果未能解决你的问题,请参考以下文章

从片段着色器中的地形高程数据计算法线

在片段着色器问题中读取 image1d

金属着色器混合片段接收错误的颜色值

片段着色器会覆盖光栅化生成的片段颜色吗?

为啥在 Metal 中不允许从片段着色器中写入缓冲区?

如何在渲染之间更改片段着色器颜色?