【问题标题】:glClear function: Question about the parametersglClear 函数:关于参数的问题
【发布时间】:2011-09-13 09:52:32
【问题描述】:

我想深入了解 glClear 函数。我理解它的一般解释 -> 清除颜色、深度、模板和累积的缓冲区,但我还有其他问题。 我的朋友假设您清除了内存(堆栈?)中代表颜色、深度、模板和累积的位。通过指定和应用参数:(例如,只有颜色和深度)“掩码”,您只清除内存中的那些位(因此是“按位运算”)。

举个例子:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

www.khronos.org 对“mask”参数的解释。 掩码:指示要清除的缓冲区的掩码的按位或。

这是我的问题:

  • 参数 GL_COLOR_BUFFER_BIT 和 GL_DEPTH_BUFFER_BIT 是否分别代表 1 位内存?或者它们代表多少位(我想了解位掩码的实际应用方式)?
  • 我看不到“OR”掩码如何取消位?如果您在标记为“set”(而不是“unset”)的位上使用“OR”,它仍将返回零(1 OR 0 仍返回 1)?我是否认为这完全错误/我在这里遗漏了什么?
  • “或”符号(管道)是怎么回事?为什么这些参数没有用通常的逗号分隔,并且不是在实际函数中声明的按位运算“OR”?

也许我很困惑,因为我是这个领域的新手。 你能给我一个详尽的解释吗?当我继续使用 OpenGL 时,我不想跳过这些问题。我想知道我在做什么,并且有这种理解可能会帮助我一路走来。谢谢!

【问题讨论】:

  • 这实际上与 OpenGL 无关。发生的事情是,这是一种所谓的位域掩码,一种在 C 程序中广泛使用的技术,用于在单个调用中指定一组不互斥的选项/任务。

标签: c memory opengl bits


【解决方案1】:

当您指定要清除的内容时,编写内容的方式允许更大的灵活性。这里如何定义标志:

#define GL_COLOR_BUFFER_BIT 1 // 0000 0001
#define GL_DEPTH_BUFFER_BIT 2 // 0000 0010

如您所见,这些是 2 的幂。这样,在内存中,每个标志只有一位设置为 1(显然在不同的位置)。 当您对这些标志进行按位 OR 计算时,您会得到 0000 0011。要知道结果值中是否设置了标志,您只需使用选中的标志计算按位与。

int foo = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; // foo = 0000 0011

if (foo & GL_COLOR_BUFFER_BIT) { // 0000 0011 & 0000 0001 => 0000 0001 (!= 0)
    // clear color buffer(which is located at a position OpenGL knows)
}
if (foo & GL_DEPTH_BUFFER_BIT) { // 0000 0011 & 0000 0010 => 0000 0010 (!= 0)
    // clear depth buffer
}

【讨论】:

  • 非常感谢,现在很清楚了!我不认为我会自己解决这个问题!
【解决方案2】:

您提供给 glClear 的按位组合不是用于清除缓冲区的位。缓冲区使用其特定的清除颜色(glClearColor)或清除深度值(glClearDepth,我认为?)单独清除。 glClear 的按位标志只告诉它要清除哪些缓冲区。这些是按位排序的,以简单地指定多个要清除的缓冲区。

编辑:您可以想象它的工作方式如下:

void glClear(unsigned int bits)
{
    if(bits & GL_COLOR_BUFFER_BIT)    //color bit is set
    {
        //clear color buffer using current clear color
    }
    if(bits & GL_DEPTH_BUFFER_BIT)    //depth bit is set
    {
        //clear depth buffer using current clear depth value (usually 1)
    }
    if(bits & GL_STENCIL_BUFFER_BIT)  //stencil bit is set
    {
        //clear stencil buffer using current clear stencil value (usually 0)
    }
}

【讨论】:

  • 那么……幕后到底发生了什么?你能提供某种类型的插图吗?我的错,但我还不明白......我找到的关于按位“或”的解释如下:(按位或)如果其操作数中的一个或两个相应位为 1,则将一个位设置为 1 , 如果两个相应的位都是 0,则为 0。我无法适应这个故事中的解释......
【解决方案3】:

正如其他人所说,那些GL_COLOR_BUFFER_BIT 和相关的位掩码与写入各种缓冲区的最终清除值无关。每个都只是glClear() 在内部检查的标志(使用按位与,正如其他人指出的那样)以决定对哪些缓冲区进行操作。

一旦检查了缓冲区标志,从概念上讲,glClear() 只会遍历帧缓冲区中的每个像素并将其设置为“清除”值,这样您就可以在空白板上绘图了。这些值是用glClearColor() 等设置的。你可能会这样想:

void glClear(GLuint buffers)
{
  if (buffers & GL_COLOR_BUFFER_BIT) {
    for (int i = 0; i < height; ++i) {
      for (int j = 0; j < width; ++j) {
        colorBuffer[i][j].r = clearColor.r;
        colorBuffer[i][j].g = clearColor.g;
        colorBuffer[i][j].b = clearColor.b;
        colorBuffer[i][j].a = clearColor.a;
      }
    }
  }

  if (buffers & GL_DEPTH_BUFFER_BIT) {
    // Etc, using depthBuffer and glClearDepth value instead here
  }

  // etc. for accum & aux buffers.
}

【讨论】:

  • 如果您觉得需要提供另一个答案,它显示了实际清晰代码的概念循环,那么请不要忘记 alpha 组件。
  • 这真的是 clear 的执行方式吗?这可能不是有点慢......?谢谢
  • @Christian Rau:添加了 alpha。我添加了我的答案 b/c 不清楚 OP 是否理解位掩码与实际清除值无关。只是想更明确一点。如果您在答案中添加类似的说明,我会很乐意取消我的。
  • @user917467:真的吗?几乎可以肯定不是。它很可能是驱动程序级别的高度并行化 bitblt,但从概念上讲,这就是它的作用。同意,如果这是实际的实现,那将会非常缓慢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多