How to change the color of each rendered object in opengl C++ with shaders?

Asked

Viewed 124 times

1

I’m learning now Vbos and Vaos, and I can’t draw objects of different colors, they are rendered with the same color. I tried to use Uniform but I couldn’t make it work, how can I do it?

Fragment Shader:

#version 130
out vec4 color;

void main(){
  color = vec4(1,0,0,1);
}

Initialization of Shader:

// Set "clearing" or background color
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black and opaque

    // Create and compile our GLSL program from the shaders
    GLint vertexShaderId = this->loadAndCompileShader("shader/hello.vp",
                                                      GL_VERTEX_SHADER);
    GLint fragmentShaderId = this->loadAndCompileShader("shader/hello.fp",
                                                        GL_FRAGMENT_SHADER);
    this->programId = this->linkShaderProgram(vertexShaderId, fragmentShaderId);

    // Set up vertex data (and buffer(s)) and attribute pointers
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

And then I want to draw each object a different color:

// Clear the colorbuffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //load everthing back
    glUseProgram(this->programId);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo1[0]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vboC[0].data());

    glDrawArrays(GL_TRIANGLE_FAN, 0, 360);

1 answer

0


To use different colors in Opengl with shaders, you’ll basically have two ways to do this:

  • Uniform
  • buffer

Uniform: this way you will define the same color for a whole call draw*, that is, everything drawn in this draw function will use that color defined by Uniform, here just upload the color via glUniform3f, for example, declare a uniform vec3 uColor in Fragment Shader and assign this value to the builtin variable outColor, ex:

// aplicação
// ...
GLint uniColor = glGetUniformLocation(shaderProgram, "uColor");
glUniform3f(uniColor, 1.0f, 0.0f, 0.0f); //cor vermelha
glDrawArrays(GL_TRIANGLES, 0, 3);
// fragment shader
uniform vec3 uColor;

out vec4 outColor;

void main()
{
    outColor = vec4(uColor, 1.0);
}

buffer: through the buffer it is possible to insert any information you want so that it is drawn later choosing the color per vertex, being possible to draw the colors of a prism for example. In this case you need to add the color information in the vertices, probably your triangle vertex array looks like this:

// vértices organizados em:
// X, Y,
// X, Y,
// X, Y
GLfloat vertices[] = {
    0.0f,  0.5f,
    0.5f, -0.5f,
    -0.5f, -0.5f
};

to add color information by vertices do so:

// vértices organizados em:
// X, Y, R, G, B,
// X, Y, R, G, B,
// X, Y, R, G, B
GLfloat vertices[] = {
    0.0f,  0.5f, 1.0f, 0.0f, 0.0f,
    0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
    -0.5f, -0.5f, 0.0f, 0.0f, 1.0f
};

No upload will change anything in glBufferData, but you need to tell how each information is organized in the buffer, using the function glVertexAttribPointer, for each information there will be a function call, as we have 2 information (position and color), we must call this function 2 times.

// aplicação
// ...
// a informação posição possui 2 valores, a cada 5 espaços inicia-se um novo vértice, começando pelo index 0
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);

// ...
// a informação cor possui 3 valores, a cada 5 espaços inicia-se um novo vértice, começa ignorando os 2 primeiros valores (pq são as informação de posição)
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));

these values are captured by Vertex Shader and must be passed to Fragment Shader, only then will be used:

//vertex shader
in vec2 position;
in vec3 color;

out vec3 Color;

void main()
{
    Color = color;
    gl_Position = vec4(position, 0.0, 1.0);
}
fragment shader
in vec3 Color;

out vec4 outColor;

void main()
{
    outColor = vec4(Color, 1.0);
}

Opengl is ultra low level, so things are not so simple to be done, I leave here two links that can help you a lot, unfortunately Portuguese content in this area is almost non-existent.

open.Gl

learnopengl

Browser other questions tagged

You are not signed in. Login or sign up in order to post.