写入 OpenGL 模板缓冲区

问题描述 投票:0回答:2

我一直在阅读有关 OpenGL 中的模板缓冲区的内容。基本概念是有道理的;仅当片段与模板缓冲区中的值进行按位与运算后满足特定条件时才会绘制片段。但我不明白的一件事是你实际上如何写入模板缓冲区。我这里缺少什么功能吗?

附注当我说写入时,我的意思是指定模板缓冲区中的特定值。

c++ opengl glfw stencil-buffer
2个回答
14
投票

模板缓冲区理论上是一个类似于后台缓冲区和深度缓冲区的缓冲区。它们三个同时写入(启用时)。您可以通过特定调用启用/禁用对它们的写入:

  • glColorMask(red, green, blue, alpha) - 用于后台缓冲区
  • glDepthMask(t/f) - 用于深度缓冲区
  • glStencilMask(value) - 用于模板缓冲区

对于深度和模板缓冲区,您可以通过以下方式专门启用/禁用:

  • gl启用/gl禁用(GL_DEPTH_TEST)
  • gl启用/gl禁用(GL_STENCIL_TEST)

渲染到屏幕上的任何三角形都将写入所有启用的缓冲区,除非某些操作功能阻止它。对于模板缓冲区,可以使用多个函数进行设置。请查找 OpenGL 参考页上的功能,但这里有一个简单的示例,遮盖屏幕的一部分,然后仅在屏幕的遮盖部分进行渲染,只是为了帮助您入门。

glClearColor(0, 0, 0, 1);
glClearStencil(0);
glStencilMask(0xFF);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Do not draw any pixels on the back buffer
glEnable(GL_STENCIL_TEST); // Enables testing AND writing functionalities
glStencilFunc(GL_ALWAYS, 1, 0xFF); // Do not test the current value in the stencil buffer, always accept any value on there for drawing
glStencilMask(0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); // Make every test succeed

// ... here you render the part of the scene you want masked, this may be a simple triangle or square, or for example a monitor on a computer in your spaceship ...

glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Make sure you will no longer (over)write stencil values, even if any test succeeds
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Make sure we draw on the backbuffer again.

glStencilFunc(GL_EQUAL, 1, 0xFF); // Now we will only draw pixels where the corresponding stencil buffer value equals 1

// ... here you render your image on the computer screen (or whatever) that should be limited by the previous geometry ...

glDisable(GL_STENCIL_TEST);

请注意,我故意省略了任何深度代码,以确保您看到它与模板绘制无关。如果渲染 3D 几何体,您可能需要启用它。如果深度测试失败,您甚至可能不需要编写模板值。

请注意,渲染遮罩几何体时,请将模板函数设置为 GL_ALWAYS,这一点很重要,因为否则,将根据上次使用的内容和遮罩来测试模板缓冲区中的当前值(在示例中已清除)甚至可能根本不会绘制几何图形。

因此没有特殊的函数可以写入模板缓冲区。我什至不确定它是否可以像直接将数据写入后台缓冲区和深度缓冲区视频内存一样写入,但这不是它应该做的方式(因为它非常慢)。模板缓冲区是与深度缓冲区共享的内存,因此可以通过更改写入函数的参数来实现。不过,我不指望它适用于所有视频驱动程序。


0
投票

您可以读取、写入值(字节、浮点数、双字...)并将其复制到帧和深度缓冲区,但不能复制到模板缓冲区。

所有三个缓冲区都位于 GPU 内存,问题是模板缓冲区使用了 24 位深度缓冲区中剩余的 8 位!

这就是为什么您必须渲染一些内容来设置或覆盖 8 位模板缓冲区(实际上是深度缓冲区中的区域)中的值

DJ

© www.soinside.com 2019 - 2024. All rights reserved.