简体   繁体   中英

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: 正确的形象

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: 图像不正确

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);
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM