Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does OpenGL act this way when I use color values greater than 1.0f?

I was working on learning OpenGL and I was tasked with creating the figure below: Correct image

This is what my intention was, but the first time I wrote it I buffered the colors as floats from 0 - 255 instead of 0.0 - 1.0. Clearly that was wrong, but this is what was displayed: Incorrect image

Only the center triangle is displayed, only with outlines and the colors are the first three vertex colors. Why did this happen? What does OpenGL do when I buffer colors that aren't in the range [0.0, 1.0]? I couldn't find documentation on this.

My shaders are as follows:

vertex:

layout (location = 0) in vec3 Position;
layout (location = 2) in vec4 vertexColor;

out vec4 vertexColor0;

void main() {
    gl_Position = vec4(Position, 1.0f);
    vertexColor0 = vertexColor;
}

fragment:

in vec4 vertexColor0;

void main() {
    gl_FragColor = vertexColor0;
}

And here's the code I use for buffering data and drawing data:

static const int npoints = 9;
static const glm::vec3 points[npoints] = {
                                glm::vec3(-0.5, 0.5, 0.0),
                                glm::vec3(-0.7, 0.0, 0.0),
                                glm::vec3(-0.3, 0.0, 0.0),

                                glm::vec3(0.2, 0.0, 0.0),
                                glm::vec3(-0.2, 0.0, 0.0),
                                glm::vec3(0.0, -0.5, 0.0),

                                glm::vec3(0.5, 0.5, 0.0),
                                glm::vec3(0.3, 0.0, 0.0),
                                glm::vec3(0.7, 0.0, 0.0)
                            };

//the incorrect version, in the correct version 255 is replaced with 1.0f and 127 with 0.5f
static const glm::vec4 colors[npoints] = {
                                glm::vec4(0, 255, 255, 255),
                                glm::vec4(255, 0, 255, 255),
                                glm::vec4(255, 255, 0, 255),

                                glm::vec4(255, 0, 0, 255),
                                glm::vec4(0, 255, 0, 255),
                                glm::vec4(0, 0, 255, 255),

                                glm::vec4(0, 0, 0, 255),
                                glm::vec4(255, 255, 255, 255),
                                glm::vec4(127, 127, 127, 255)
                            };

//Create the VAO and the buffer data
void Figure::initialize() {
    glUseProgram(shaderProgram); //shaderProgram is a member set to the built shader above

    glGenVertexArrays(1, &vertexArrayObject); //vertexArrayObject is also a member
    glBindVertexArray(vertexArrayObject);

    GLuint VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER,
                 npoints * sizeof(glm::vec3),
                 points,
                 GL_STATIC_DRAW);

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

    GLuint CBO;
    glGenBuffers(1, &CBO);
    glBindBuffer(GL_ARRAY_BUFFER, CBO);
    glBufferData(GL_ARRAY_BUFFER,
                 npoints * sizeof(glm::vec4),
                 colors,
                 GL_STATIC_DRAW);

    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(2);
}

//draw the figure
void Figure::draw() {
    glUseProgram(shaderProgram);
    glBindVertexArray(vertexArrayObject);
    glDrawArrays(GL_TRIANGLES, 0, npoints);
}
like image 264
Fsmv Avatar asked Sep 19 '14 04:09

Fsmv


People also ask

How do you change the color of OpenGL?

Here are some examples of commands for setting drawing colors in OpenGL: glColor3f(0,0,0); // Draw in black. glColor3f(1,1,1); // Draw in white. glColor3f(1,0,0); // Draw in full-intensity red.

What is blending OpenGL?

Blending is the stage of OpenGL rendering pipeline that takes the fragment color outputs from the Fragment Shader and combines them with the colors in the color buffers that these outputs map to. Blending parameters can allow the source and destination colors for each output to be combined in various ways.

What is glColor3f in OpenGL?

glColor3f can be called in between glBegin and glEnd. When it is used this way, it can be used to give each vertex its own color. The resulting rectangle is then shaded with an attractive color gradient, as shown on the right.


1 Answers

Since your values are so high, any points inside the triangle will have a little bit of each color corner. Each corner gives one of the RGB components. Let's evaluate a pixel a small distance away from the red corner. This pixel might get the unclipped values vec3(253.0f, 1.2f, 1.9f). If we clip this value to the range 0.0f - 1.0f, you will see that this becomes vec3(1.0f,1.0f,1.0f) or white.

The reason the edges are not white is that this is the only place where the interpolation distance is low enough that 0.0f - 255.0f does not overflow 1.0f for one of the components. Anywhere on the line between the red and blue point there is so little green that it does not overflow 1.0, therefore we get a purple line. If you look closely at the corners, you also see that this is the only place where there is only the color of the corner (or at least a small amount from the other corners).

Anywhere else on the triangle will be clipped to vec3(1.0f,1.0f,1.0f) and you get a white triangle.

EDIT: The reason why the triangle on the left does not have these edges is because the corners have full intensity (255.0f) on two of the RGB components (vec3(255.0f,255.0f,0.0f),vec3(0.0f,255.0f,255,f) and vec3(255.0f,0.0f,255.0f)). On one of the edges it interpolates between vec3(255.0f,255.0f,0.0f) and vec3(255.0f,0.0f,255.0f). Going only slightly away from one of the corners, the only component being 0.0f will interpolate towards 255.0f since the other corner will always have fully intensity on that particular RGB component. So as soon as you move slightly away from the corner you will get a value like for instance vec3(255.0f,253.7f,1.3f). This will clip to white there for in this case the edges will also be white. If you increase the resolution you might see that exactly on the corner there might be one pixel that is not fully white, but I am not sure about that.

The triangle on the right have full intensity on all RGB components in all corners except the one that is black. As soon as you move slightly away from the black corner, the values will be something like vec3(1.3f, 1.3f, 1.3f) which will clip towards white and the entire triangle will appear white. Again, if you increase the resolution you might see a black dot at the black corner.

like image 67
bofjas Avatar answered Oct 21 '22 02:10

bofjas