模板的OpenGL修剪/内联轮廓

Posted

技术标签:

【中文标题】模板的OpenGL修剪/内联轮廓【英文标题】:OpenGL trim/inline contour of stencil 【发布时间】:2021-02-02 16:13:43 【问题描述】:

我在模板缓冲区中创建了一个形状(下图中为黑色)。现在我想渲染到后台缓冲区。我想在我的模板(红色)的外部像素(比如 4 个像素)上使用一个纹理,在其余像素(红色)上使用另一个纹理。

我已经阅读了几种涉及缩放的解决方案,但是当没有明显的形状中心时,这将不起作用。

如何获得想要的效果?

【问题讨论】:

【参考方案1】:

模板缓冲区非常适合doing operations on the specific fragments being overlaid onto them。但是,对于需要查看像素而不是与正在呈现的片段对应的像素的操作,它并不是那么好。为了做轮廓,你必须询问相邻像素的值,这是模板操作所不允许的。

因此,如果可以将您要测试的模板数据放在非模板格式的图像中(即:彩色图像,可能是整数纹理格式),这会使事情变得更简单。您可以直接在片段着色器中使用discard 来完成模板丢弃的效果。由于您可以从纹理中任意获取(只要您不尝试修改它),您可以获取相邻像素并测试它们的值。您可以使用它来识别片段何时靠近边界。

但是,如果您依赖专门的模板操作来构建模板数据本身(如按位操作),那么情况会更加复杂。您将不得不使用stencil texturing operations,因此您将不得不渲染到具有深度/模板格式的 FBO 纹理。而且您必须对其进行设置以允许您从纹理的模板方面进行读取。这是 OpenGL 4.3 的一项功能。

这有效地将其转换为 8 位无符号整数纹理。这使您可以玩任何需要的游戏。但是如果您想使用模板测试来丢弃片段,您还需要texture barrier functionality 以允许您从附加到当前 FBO 的图像中读取。但是您不需要实际使用屏障,因为您应该屏蔽模板书写。您只需要 GL 4.5 或 NV/ARB_texture_barrier 扩展可用,它们普遍可用。

无论发生这种情况,最大的困难是改变边框的大小。很容易只测试相邻的 9 个像素,看看它是否在边界处。但是边框尺寸越大,每个片段必须测试的像素面积就越大。那时,我建议尝试寻找不同的解决方案,该解决方案基于对写入模板缓冲区的模式的一些了解。

也就是说,如果放置模板的渲染操作对形状有一些了解,那么它可以以某种方式计算到形状边缘的距离。这可能需要以包含距离信息的方式构建几何。

【讨论】:

我可以轻松地将模板数据放入颜色缓冲区,甚至是 z 缓冲区。但我不太了解您提出的解决方案。我应该写一个专门的片段着色器吗? 如果我理解正确,那么我应该首先将模板渲染为纹理。然后使用自定义片段着色器将此纹理渲染到屏幕上。这是你的建议吗?

以上是关于模板的OpenGL修剪/内联轮廓的主要内容,如果未能解决你的问题,请参考以下文章

在 OpenGL 中绘制 2D 形状的轮廓,同时更改线条粗细

一步步学OpenGL 39 -《模型轮廓识别检测[阴影锥1]》

一步步学OpenGL 39 -《模型轮廓识别检测[阴影锥1]》

根据OpenGL / DirectX中的道路轮廓进行地形变形

为啥模板测试不丢弃片段?

c_cpp 一个OpenGL / GLUT代码模板。用于OpenGL / GLUT源代码的代码模板