为什么当我使用大于 1.0f 的颜色值时 OpenGL 会这样?

Fsm*_*smv 7 c++ opengl freeglut

我正在学习 OpenGL,我的任务是创建下图: 正确的图像

这就是我的意图,但在我第一次编写它时,我将颜色缓冲为 0 - 255 而不是 0.0 - 1.0 的浮点数。显然这是错误的,但这是显示的内容: 图片不正确

仅显示中心三角形,仅显示轮廓,颜色为前三个顶点颜色。为什么会这样?当我缓冲不在 [0.0, 1.0] 范围内的颜色时,OpenGL 会做什么?我找不到这方面的文档。

我的着色器如下:

顶点:

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;
}
Run Code Online (Sandbox Code Playgroud)

分段:

in vec4 vertexColor0;

void main() {
    gl_FragColor = vertexColor0;
}
Run Code Online (Sandbox Code Playgroud)

这是我用于缓冲数据和绘制数据的代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

bof*_*jas 6

由于您的值如此之高,三角形内的任何点都会有每个颜色角的一点点。每个角给出一个 RGB 分量。让我们评估一个离红角不远的像素。这个像素可能会得到未裁剪的值 vec3(253.0f, 1.2f, 1.9f)。如果我们将此值剪辑到 0.0f - 1.0f 范围内,您将看到它变为 vec3(1.0f,1.0f,1.0f) 或白色。

边缘不是白色的原因是这是唯一一个插值距离足够低的地方,0.0f - 255.0f 不会溢出 1.0f 对于其中一个组件。在红色和蓝色点之间的线上的任何地方,绿色都很少,不会溢出 1.0,因此我们得到一条紫色线。如果你仔细观察角落,你还会发现这是唯一一个只有角落颜色的地方(或者至少来自其他角落的少量颜色)。

三角形上的任何其他地方都将被裁剪为 vec3(1.0f,1.0f,1.0f) 并且您会得到一个白色三角形。

编辑:左边的三角形没有这些边的原因是因为角在两个 RGB 分量 (vec3(255.0f,255.0f,0.0f),vec3(0.0f, 255.0f,255,f) 和 vec3(255.0f,0.0f,255.0f))。在其中一条边上,它在 vec3(255.0f,255.0f,0.0f) 和 vec3(255.0f,0.0f,255.0f) 之间进行插值。仅稍微远离一个角,唯一的 0.0f 分量将向 255.0f 内插,因为另一个角在该特定 RGB 分量上始终具有完全强度。因此,只要您稍微远离角落,您就会得到一个值,例如 vec3(255.0f,253.7f,1.3f)。这将在那里剪成白色,因为在这种情况下,边缘也将是白色的。如果您提高分辨率,您可能会看到在拐角处可能有一个不是全白的像素,

右边的三角形在所有角落的所有 RGB 分量上都具有完整的强度,除了黑色的那个。一旦您稍微远离黑色角落,值将类似于 vec3(1.3f, 1.3f, 1.3f) ,它将向白色剪裁,整个三角形将显示为白色。同样,如果您提高分辨率,您可能会在黑角看到一个黑点。