0
\$\begingroup\$

Recently I have been working with OpenGL and have decided to use colors instead of textures. However, since the project I am working on is going to have a low-poly look, I want each color to stand out, and not be drawn as a gradient like OpenGl usually does.

The problem I am having is with the flat modifier. While it does give the nice non-gradient look, it uses a provoking vertex, which is not not good in this case.

Here is an example of what I got and what I wanted:

Render Comparison(original link)

I tried looking into different solutions, and the one I think would work would be to store one color per face. However, I am not sure how to do that. Any suggestions are appreciated.

Thanks!

\$\endgroup\$
  • \$\begingroup\$ Looks like you are not duplicating vertices for each face. Are also using IBO? \$\endgroup\$ – wondra Sep 14 '15 at 18:22
  • \$\begingroup\$ Hello, I do not think I am duplicating vertices for each of the faces, I am storing each index, color, and position in one VBO, and then I call it with glDrawElements. \$\endgroup\$ – Prynok Sep 14 '15 at 18:36
  • \$\begingroup\$ You can't get that kind of look without some sort of lighting in the scene. What you're looking for is called flat shading. Basically, compute a shared normal for each face, then calculate lighting with it. \$\endgroup\$ – glampert Sep 15 '15 at 1:59
  • \$\begingroup\$ Thanks for the reply, glampert, I am going to add lighting, however, I am trying to get face colors working first. \$\endgroup\$ – Prynok Sep 15 '15 at 2:23
1
\$\begingroup\$

It seems to me you will need to generate 3 vertices for each triangle. Because you want to use a different color per face (as opposed to per vertex), you cannot share the indices of your vertices. While you still can use an IBO (index buffer object), you will not be able to reuse any of the vertices, rendering it useless while taking up extra memory on the GPU.

With index buffers, you create a vertex and color buffer of the same length. Then each vertex in the vertex buffer corresponds to each color in the same index of the color buffer. When you draw your geometry using glDrawElements(), you are picking vertices (and the associated colors) by the indices listed in your IBO.

I suggest instead you use glDrawArrays with the mode set to GL_TRIANGLES. Then, you must provide your vertex and color buffers. These buffers must have the same length and should look something like this:

int NUM_VERTICES = 6;

//I'm explicitly showing dimensions for clarity...
float[] vertices = new float[NUM_VERTICES * 3];
float[] colors = new float[NUM_VERTICES * 3];

//Vertex buffer
vertices = new float[]
{
    -1.0f,  1.0f,  0.0f, //Vertex 1
    -1.0f, -1.0f   0.0f, //Vertex 2
     0.0f,  0.0f,  0.0f, //Vertex 3
     0.0f,  0.0f,  0.0f, //Vertex 4 (shared location with Vertex 3)
     1.0f,  1.0f,  0.0f, //Vertex 5
    -1.0f,  1.0f,  0.0f  //Vertex 6 (shared location with Vertex 1)
};

//Color buffer
colors = new float[]
{
     1.0f,  0.0f,  0.0f, //Make Vertex 1 red.
     1.0f,  0.0f,  0.0f, //Make Vertex 2 red.
     1.0f,  0.0f,  0.0f, //Make Vertex 3 red.
     0.0f,  0.0f,  1.0f, //Make Vertex 4 blue.
     0.0f,  0.0f,  1.0f, //Make Vertex 5 blue.
     0.0f,  0.0f,  1.0f  //Make Vertex 6 blue.
};

This creates 2 triangles. The triangles have their own set of vertices. Because each of the 3 vertices for a particular triangle all have the same corresponding color, there will not be the gradient (interpolation) within each face's 3 colors. Despite appearing as a per-face color, the colors are actually per-vertex (and not a single vertex is used for two poly's).

A faster method would be to use a shader program to dictate the color per face. This would allow you to just use a single set of vertices. You would use an IBO as normal, but you would need to send extra data down the graphics pipeline to control the color on a truly per-face basis. This is a tad complicated and left to you as an excercise ;)

I recommend you implement a basic model first. The data provided is simple enough.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.