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

I was working on teaching OpenGL and was tasked with creating the picture below: Correct image

This was my intention, but the first time I wrote it, I buffer the colors as floats from 0 to 255 instead of 0.0 to 1.0. Obviously this was wrong, but this is what was shown: Incorrect image

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

My shaders look like this:

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 is the code I am using to buffer the drawing data and 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);
}

      

+3


source to share


1 answer


Since your values ​​are so high, any points within the triangle will have a bit of each color angle. Each corner gives one of the RGB components. Let's evaluate a pixel a short distance from the red corner. This pixel can receive unclipped vec3 values ​​(253.0f, 1.2f, 1.9f). If we copy this value in the 0.0f - 1.0f range, you can see that it becomes vec3 (1.0f, 1.0f, 1.0f) or white.

The reason the edges are not white is because 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 along the line between the red and blue dot there is so little green that it does not overflow 1.0, so we end up with a purple line. If you look closely at the corners, you will also see that this is the only place where there is only the color of the corner (or at least a small amount from other corners).

Anywhere else in the triangle will snap to vec3 (1.0f, 1.0f, 1.0f) and you will get a white triangle.



EDIT: The reason the triangle on the left doesn't have these edges is because the corners have full intensity (255.0f) on the two 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). Starting just slightly from one of the corners, a single 0.0f component will interpolate towards 255.0f, since the other corner will always have full intensity on that particular RGB component. So, as soon as you move a little away from the corner, you will get a value like vec3 (255.0f, 253.7f, 1.3f). It will depend on white, because in that case the edges will also be white. If you increase the resolution, you can see that exactly on the corner there can be one pixel,which is not completely white, but I'm not sure about that.

The triangle on the right has full intensity for all RGB components in all corners except black. Once you move a little away from the black corner, the values ​​will be the same as vec3 (1.3f, 1.3f, 1.3f), copied towards white, and the entire triangle will turn white. Again, if you increase the resolution, you will see a black dot in the black corner.

+4


source







All Articles