【问题标题】:Why does OpenGL act this way when I use color values greater than 1.0f?当我使用大于 1.0f 的颜色值时,为什么 OpenGL 会这样做?
【发布时间】:2014-09-19 04:04:38
【问题描述】:

我正在学习 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;
}

片段:

in vec4 vertexColor0;

void main() {
    gl_FragColor = vertexColor0;
}

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

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

【问题讨论】:

  • 你可能使用 glColor3ub 并且实际上使用了无符号字节。
  • 很可能是溢出了。由于您使用的是整数,因此每次都会溢出到相同的值
  • @Basic 怎么会溢出? 255 可以表示为浮点数。在乘以 255 后,他们必须在某个点将其转换为无符号字节。我真的不明白这种转换如何导致溢出,通常只是将 mod 转换为目标的最大大小。一些文档说 floats > 1.0f 会导致未定义的行为,否则会很好。
  • @Fsmv 我在考虑整数,它占用了最低有效的 8 位。你说得对,这不适用于浮动。

标签: c++ opengl freeglut


【解决方案1】:

由于您的值如此之高,三角形内的任何点都会有一点点的每个颜色角。每个角给出一个 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) ,它将向白色剪切,整个三角形将显示为白色。同样,如果您提高分辨率,您可能会在黑角处看到一个黑点。

【讨论】:

  • 但这并不能解释为什么左边的三角形和中间的三角形表现不同(即:中心的一个得到彩色边缘,而另一个没有)。这是为什么?我敢打赌是某种溢出,但无法弄清楚。
  • 谢谢@bofjas!这是有道理的,基本上直角三角形中的所有颜色分量总是 > 1.0,因此到处都是白色。中间的三角形具有至少一个颜色分量 = 0 的边缘颜色,因此您可以“看到一些东西”,因为它不是白色的。太好了!
  • 这很棒,它甚至不像我想的那样是未定义的行为。所以基本上颜色在插值后会被夹住?
  • 是的。光栅化不知道顶点着色器输出将用于片段着色器中的用途。我只看到一个 vec4 可以是任何东西(某种形式的位置或正常)。如果在插值之前要对颜色进行限制,那么 GLSL 编译器将需要以某种方式推断顶点着色器输出将用于什么。
猜你喜欢
  • 1970-01-01
  • 2017-09-01
  • 2018-10-12
  • 1970-01-01
  • 2012-06-13
  • 2017-02-09
  • 1970-01-01
  • 1970-01-01
  • 2017-03-06
相关资源
最近更新 更多