NEKOPARTY STUDIO

Godot 4.5 中的Stencil

字数统计: 970阅读时长: 3 min
2025/07/06
loading

概述

在渲染Depth Buffer时,一般使用D32S8的类似格式。在Godot中,原本Depth Buffer就只渲染了Depth,因此S8的通道没有被使用。Stencil即特定材质可以向这个通道里写入内容,本文先称为Stencil通道,在后续过程中被其他材质读取使用。

Godot自带的Spatial Shader提供了几种快捷的默认设置让你体验这个功能,只要去材质里打开开关就能用。

自带的Xray

这个就是自带的Xray效果。材质设置界面目前如下

设置界面

Stencil Mode里面能够选择Disable,Outline,Xray以及Custome。其中,选择Outline和Xray后会自动创建一个Next Pass去帮助实现这两种效果。这两个选项无需说明且实用价值有限(当然如果你不使用高级功能,只想一键完成描边或者透视你就点这个),所以就不多介绍。我们重点说一下Custom的内容。

Godot中的Stencil

Custom选项的设置界面如下

Custom设置界面

首先可以看到Flags选项。我们先说两个Write选项。如果选择Write,则会在屏幕上出现该物体且通过了深度测试的像素上,向Stencil通道中写入这个Reference的值。

所谓通过深度测试,可以理解为:物体原本会覆盖一块屏幕上的区域,但是物体前面有可能会被别的物体挡住;如果没有被挡住正常露了出来,则称为通过了深度测试;反之本应渲染但是由于被挡住实际看不见的部分,称为深度测试失败。

回到原来的内容,如果你选择Write Depth Fail,那么意思就是当深度测试失败的时候向Stencil通道写入这个Reference的值。两个Write选项都勾选则不论什么情况都会写入。

现在我们能够向Stencil通道写入值,那我们来看一下Read选项。勾选Read选项会读取Stencil通道里的内容进行比较。Compare选项中可以选择如何比较,可以是更大更小相等等情况。当这个材质设置的Reference与从Stencil通道里读取的数值相比,满足条件的时候,则成为通过Stencil测试。只有通过Stencil测试的像素能够被绘制出来。

(注:Write选项也能Compare,同样也是指的在满足Compare条件的情况下进行Write)

这样我们就很好理解预设的Outline和Xray选项了。我们看这个示例Demo

Demo

实际上,我们只要在物体本身的材质里打开Stencil,选择Write Depth Failed,这样物体就会把自己没能显示出来的部分写进Stencil通道。然后在物体的Next Pass里,我们去检查Stencil,如果读取到的值就是上面写进Stencil通道的值,说明这块就是物体没能显示的部分,那就在Next Pass通道把这一块显示出来就行。

至于Outline,即把物体显示出来的部分写进Stencil,在Next Pass里对这部分进行比较处理。图中的Custom则是演示的则是讲两个Write选项都打开的情景。

在Shader中使用Stencil

至于如何在Shader中使用,gdshader中的写法如下,只需要在shader开头(render_mode相同的地方)加上

1
stencil_mode (Write or Read Mode), (Compare Mode), (Reference);

均可直接对应上文中Custom的几个选项。如可这么写

1
stencil_mode write_depth_fail, compare_always, 2;

当然我们知道Write or Read Mode是可以选择选择多个的。你也可以写

1
stencil_mode write, write_depth_fail, compare_always, 2;

然后在这之后正常的完成Shader内容即可。

最后

这个刘海阴影就是拿Stencil完成的。在之前的版本里几乎不可能高效的完成这个工作。Stencil确实是Godot渲染的一大进步,要是能进步的快点就更好了。

结果

CATALOG
  1. 1. 概述
  2. 2. Godot中的Stencil
  3. 3. 在Shader中使用Stencil
  4. 4. 最后