glClear()不服从剪刀区域[关闭]

Posted

技术标签:

【中文标题】glClear()不服从剪刀区域[关闭]【英文标题】:glClear() not obeying scissor region [closed] 【发布时间】:2014-06-23 14:32:59 【问题描述】:

我正在使用双缓冲在已打开的任意 Windows 7 窗口(例如 Windows 记事本窗口)中绘制 Open GL 内容(直接 Win32 - 不使用 GLUT、FreeGLUT、GLFW 等)。我有窗口句柄,可以按预期绘制我想要的内容,但我看到 glClear() 函数出现奇怪的行为。

据我了解,glClear() 函数应该只影响屏幕上由glScissor() 函数定义的区域内的像素。我已经用glScissor() 定义了剪刀区域,然后使用glEnable(GL_SCISSOR_TEST) 启用了剪刀功能。 glClearColor 设置为白色 (0,0,0,1)。我正在使用glClear() 命令清除颜色和深度缓冲区。

当执行SwapBuffers() 命令以在屏幕上呈现时,我选择的白色透明颜色按照我的要求在剪刀区域内绘制,但窗口的其余部分OUTSIDE剪刀区域被涂成黑色,而不是像我预期的那样保持这些像素不变。

如图所示,剪刀区域(白色)和对象(3D 立方体)绘制正确,但记事本窗口的其余像素设置为黑色,并且之前在记事本窗口中绘制的任何内容都被覆盖了.

glClearColor(1.0f, 1.0f, 1.0f, 1.0f);               // white background
glViewport(0, 0, 300, 300);
glScissor(0, 0, 250, 400);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//... draw cube inside glBegin()/glEnd()...
SwapBuffers(hDC);

【问题讨论】:

您是否清除过整个视口?缓冲区交换可能会使您永远无法清除的屏幕部分未定义。 【参考方案1】:

如果我的描述正确,glClear 会按预期工作。

您不能仅仅因为您在屏幕上看到某些东西,就认为它也存在于后台缓冲区中。您看到的记事本窗口的内容要么是 front 缓冲区,要么是被 blitted 到 DWM 自己的秘密渲染缓冲区中的前端缓冲区的副本(取决于您是否进行了合成)。或者,其他的东西,一个被 blitted 到 DWM 缓冲区的 GDI 缓冲区,等等。很可能是后者,因为它使用 GDI 进行渲染。

当您翻转缓冲区时,后台缓冲区会显示在该区域中屏幕上的任何内容上,并且您得到的是全黑缓冲区(实际上未初始化,但可能驱动程序非常友好地将内存归零)除了您清除为白色的区域。 这正是您所期望的——您的glClear 仅影响了一个子区域,其余部分未定义,它恰好为零(黑色)。

顺便说一句,如果没有启用合成,您在屏幕上看到的内容可以从大多数显卡的前端缓冲区复制到后端缓冲区,因此您仍然可以看到原始内容记事本窗口的内容,如果您希望这样的话。但是,您将永远神奇地在后台缓冲区中拥有 GDI 窗口的内容(这也不适用于 DWM,也不能保证工作,它只是在大多数情况下偶然工作) .

如果您想要窗口的原始内容,干净的解决方案是将BitBlt 从 DC 传输到内存,创建纹理,然后将其绘制(或 blit)到后台缓冲区。

【讨论】:

好的,谢谢达蒙的回复。很高兴知道这是预期的行为,而不是我的代码中的一些奇怪问题。您提出的解决方案似乎是一种让 OpenGL 在刷新期间仅更新给定窗口中像素子集的一种迂回方法,但我可能会试一试。我假设由于我的剪刀区域之外的像素可能会根据其他不相关的过程而发生变化,因此每次更新 OpenGL 内容时我都必须重新 BitBlt 窗口——这听起来计算成本很高,因为 BitBlt 使用的是 CPU 而不是 GPU,对吗? @user3666612:它往返,但没有干净的方法可以做任何不同的事情。您绘制到的“表面”(后台缓冲区)包含“未初始化”或您在其中绘制的内容,其中包括清除。这与屏幕上的表面不同(想想剪裁或重叠窗口,显然情况并非如此)。因此,如果您想让原始窗口的内容(即 GDI 图形)出现在 OpenGL 表面上,则必须在其中绘制/blit/复制该像素数据。

以上是关于glClear()不服从剪刀区域[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Node.js:telnet“石头、纸、剪刀”程序不工作

仿真器:glClear:466 GL错误0x502

剪刀石头布游戏

学习OpenGL时找不到glClear

来自 glClear() 的 OpenGL 帧缓冲区错误

如何使用多个着色器程序? [关闭]