3

I have an application which draws a tetrahedron with

glDrawElements(GL_TRIANGLES,...)

I would now like to color the tetrahedron's faces with a single flat color each.

If i understand correctly, i have to triplicate my 4 vertices so that every face has 'unique' vertices to which the same color value can be assigned.

Currently i handle the vertices and their indices like this

    glGenBuffers(1, &position_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, position_buffer);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vertex_positions),
                 vertex_positions,
                 GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(0);

    glGenBuffers(1, &index_buffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                 sizeof(vertex_indices),
                 vertex_indices,
                 GL_STATIC_DRAW);

In the vertex shader the vertices are accessed with

 in vec4 position;

Should i pass the colors in an additional GL_ARRAY_BUFFER?

If yes, can i use the same GL_ELEMENT_ARRAY_BUFFER (and use glEnableVertexAttribArray(1))?

How can i then access the colors from inside the vertex shader?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
user1479670
  • 1,145
  • 3
  • 10
  • 22

1 Answers1

3

Should i pass the colors in an additional GL_ARRAY_BUFFER?

In general you have to possibilities,

either you have 2 buffers, a separated vertex buffer and color buffer:

GLuint vertex_attr_inx = 0;
GLuint color_attr_inx = 1;

GLfloat vertex_positions[] = .... ; // x0, y0, z0, x1, y1, z1, ...
GLfloat vertex_colors[]    = .... ; // R0, G0, B0, A0, R1, G1, B1, A1, ... 

GLuint vbo[2];
glGenBuffers(2, vbo);

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_positions), vertex_positions, GL_STATIC_DRAW);
glVertexAttribPointer(vertex_attr_inx, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(vertex_attr_inx);

glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_colors), vertex_colors, GL_STATIC_DRAW);
glVertexAttribPointer(color_attr_inx, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(color_attr_inx);

Or you have a combind buffer for the vertex psoitions and color attributes:

GLfloat vertex_attributes[] = ; // x0, y0, z0, R0, G0, B0, A0, x1, y1, z1, R1, G1, B1, A1, ...

GLsizei attrSize  = 7*sizeof(float); // 7 -> x, y, z, R, G, B, A
GLsizei colorOffs = 3*sizeof(float);

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_attributes), vertex_attributes, GL_STATIC_DRAW);

glVertexAttribPointer(vertex_attr_inx, 3, GL_FLOAT, GL_FALSE, attrSize, 0);
glEnableVertexAttribArray(vertex_attr_inx);

glVertexAttribPointer(color_attr_inx, 4, GL_FLOAT, GL_FALSE, attrSize, colorOffs);
glEnableVertexAttribArray(color_attr_inx);


In the vertex shader you have to use to 2 attributes.

I recommend to use layout locations to specify the attribute indices (requires at least GLSL Version 3.30; this should be the case, since you tagged the question "opengl-4"):

#version 330

layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;

Of course you can also queries the attribute locations, for earlier versions of OpenGL/GLSL (blow OpenGL 3.3 and GLSL 3.30):

in vec4 position;
in vec4 color;

GLuint vertex_attr_inx = glGetAttribLocation( shaderProgram, "position" );
GLuint color_attr_inx  = glGetAttribLocation( shaderProgram, "color" );



If yes, can i use the same GL_ELEMENT_ARRAY_BUFFER?

The index buffer (GL_ELEMNT_ARRAY_BUFFER) would be the same in both cases. You can use the code of your questions as it is.

glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Thanks! I used the first variation and was able access the color data from within the vertex shader by 'in vec4 color;' immediately following the 'in vec4 position;', without the layout locations. Was i just lucky, or is the order in which i declare my 'in' data the same as in the vertex attributes? – user1479670 Feb 14 '18 at 13:09
  • @user1479670 If you do so it's an undefined behavior. Either you have to specify the layout locations or you query the attribute indices. But in my experience it is usually the case that the attribute indices are in the same order as the declaration of the variables in the shader source code. Note, this is not granted by the specification, so it is luck. – Rabbid76 Feb 14 '18 at 13:14
  • @user1479670 Did the answer solve your issue? Are there any remaining questions? – Rabbid76 Nov 17 '18 at 15:46
  • @user1479670 You'r welcome. But why the answer is still not acceptable? – Rabbid76 Nov 18 '18 at 19:46