Pragyan Choudhury
Pragyan Choudhury

Reputation: 81

Fragment shader color error with multiple buffers

I've been trying OpenGL recently and are stuck again in an issue. If in my program I set colors via uniforms, I can draw multiple vertex arrays with any color of my choice. But passing of two buffers to be generated for an vertex array object results in weird coloration, where 0 is for vertex location and 1 is for color.

My main function :

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;
}

My vertex shaders :

#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;
}

My fragment shaders :

#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;
}

My buffer class in case its needed to be corrected:

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);
}

EDIT:

code of the vertexArray Class:

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();

}

there are calls to vertex attrib pointer in this class.

Upvotes: 2

Views: 145

Answers (1)

Rabbid76
Rabbid76

Reputation: 211278

glVertexAttribPointer refers to the currently bound array buffer. This means you have to bind the array buffer befor you use 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();
}


See OpenGL 4.6 Specification - 10.3.9 Vertex Arrays in Buffer Objects:

A buffer object binding point is added to the client state associated with each vertex array index. The commands that specify the locations and organizations of vertex arrays copy the buffer object name that is bound to ARRAY_BUFFER to the binding point corresponding to the vertex array index being specified. For example, the VertexAttribPointer command copies the value of ARRAY_BUFFER_BINDING.

Upvotes: 2

Related Questions