1
0
mirror of https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git synced 2025-08-23 04:35:28 +08:00

更新“模板测试”原文

This commit is contained in:
1i9h7_b1u3
2025-01-17 18:21:09 +08:00
parent 0256023f8f
commit 0499b92877

View File

@@ -20,7 +20,7 @@
模板缓冲首先会被清除为0之后在模板缓冲中使用1填充了一个空心矩形。场景中的片段将会只在片段的模板值为1的时候会被渲染其它的都被丢弃了 模板缓冲首先会被清除为0之后在模板缓冲中使用1填充了一个空心矩形。场景中的片段将会只在片段的模板值为1的时候会被渲染其它的都被丢弃了
模板缓冲操作允许我们在渲染片段时将模板缓冲设定为一个特定的值。通过在渲染时修改模板缓冲的内容,我们**写入**了模板缓冲。在同一个(或者接下来的)渲染迭代中,我们可以**读取**这些值,来决定丢弃还是保留某个片段。使用模板缓冲的时候你可以尽情发挥,但大体的步骤如下: 模板缓冲操作允许我们在渲染片段时将模板缓冲设定为一个特定的值。通过在渲染时修改模板缓冲的内容,我们**写入**了模板缓冲。在同一个(或者接下来的)中,我们可以**读取**这些值,来决定丢弃还是保留某个片段。使用模板缓冲的时候你可以尽情发挥,但大体的步骤如下:
- 启用模板缓冲的写入。 - 启用模板缓冲的写入。
- 渲染物体,更新模板缓冲的内容。 - 渲染物体,更新模板缓冲的内容。
@@ -101,13 +101,14 @@ GL_INVERT | 按位翻转当前的模板缓冲值
物体轮廓所能做的事情正如它名字所描述的那样。我们将会为每个(或者一个)物体在它的周围创建一个很小的有色边框。当你想要在策略游戏中选中一个单位进行操作的,想要告诉玩家选中的是哪个单位的时候,这个效果就非常有用了。为物体创建轮廓的步骤如下: 物体轮廓所能做的事情正如它名字所描述的那样。我们将会为每个(或者一个)物体在它的周围创建一个很小的有色边框。当你想要在策略游戏中选中一个单位进行操作的,想要告诉玩家选中的是哪个单位的时候,这个效果就非常有用了。为物体创建轮廓的步骤如下:
1. 在绘制(需要添加轮廓的)物体之前,将模板函数设置为<var>GL_ALWAYS</var>每当物体的片段被渲染时将模板缓冲更新为1 1. 启用模板写入
2. 渲染物体 2. 在绘制(需要添加轮廓的)物体之前,将模板函数设置为<var>GL_ALWAYS</var>每当物体的片段被渲染时将模板缓冲更新为1
3. 禁用模板写入以及深度测试 3. 渲染物体
4. 将每个物体缩放一点点 4. 禁用模板写入以及深度测试
5. 使用一个不同的片段着色器,输出一个单独的(边框)颜色 5. 将每个物体缩放一点点
6. 再次绘制物体但只在它们片段的模板值不等于1时才绘制 6. 使用一个不同的片段着色器,输出一个单独的(边框)颜色
7. 再次启用模板写入和深度测试 7. 再次绘制物体但只在它们片段的模板值不等于1时才绘制
8. 再次启用模板写入和深度测试。
这个过程将每个物体的片段的模板缓冲设置为1当我们想要绘制边框的时候我们主要绘制放大版本的物体中模板测试通过的部分也就是物体的边框的位置。我们主要使用模板缓冲丢弃了放大版本中属于原物体片段的部分。 这个过程将每个物体的片段的模板缓冲设置为1当我们想要绘制边框的时候我们主要绘制放大版本的物体中模板测试通过的部分也就是物体的边框的位置。我们主要使用模板缓冲丢弃了放大版本中属于原物体片段的部分。
@@ -122,10 +123,15 @@ void main()
我们只想给那两个箱子加上边框,所以我们让地板不参与这个过程。我们希望首先绘制地板,再绘制两个箱子(并写入模板缓冲),之后绘制放大的箱子(并丢弃覆盖了之前绘制的箱子片段的那些片段)。 我们只想给那两个箱子加上边框,所以我们让地板不参与这个过程。我们希望首先绘制地板,再绘制两个箱子(并写入模板缓冲),之后绘制放大的箱子(并丢弃覆盖了之前绘制的箱子片段的那些片段)。
我们首先启用模板测试,并设置测试通过或失败时的行为 我们首先启用模板测试:
```c++ ```c++
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
```
并设置在每一帧中模板测试通过或失败时,需要执行的操作:
```c++
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
``` ```
@@ -134,13 +140,14 @@ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
我们将模板缓冲清除为0对箱子中所有绘制的片段将模板值更新为1 我们将模板缓冲清除为0对箱子中所有绘制的片段将模板值更新为1
```c++ ```c++
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, 0xFF); // 所有的片段都应该更新模板缓冲 glStencilFunc(GL_ALWAYS, 1, 0xFF); // 所有的片段都应该更新模板缓冲
glStencilMask(0xFF); // 启用模板缓冲写入 glStencilMask(0xFF); // 启用模板缓冲写入
normalShader.use(); normalShader.use();
DrawTwoContainers(); DrawTwoContainers();
``` ```
通过使用<var>GL_ALWAYS</var>模板测试函数我们保证了箱子的每个片段都会将模板缓冲的模板值更新为1。因为片段永远会通过模板测试在绘制片段的地方模板缓冲会被更新为参考值。 通过使用<var>GL_REPLACE</var>模板测试函数我们保证了箱子的每个片段都会将模板缓冲的模板值更新为1。因为片段永远会通过模板测试在绘制片段的地方模板缓冲会被更新为参考值。
现在模板缓冲在箱子被绘制的地方都更新为1了我们将要绘制放大的箱子但这次要禁用模板缓冲的写入 现在模板缓冲在箱子被绘制的地方都更新为1了我们将要绘制放大的箱子但这次要禁用模板缓冲的写入