是否可以在间接绘制调用中清除模板缓冲区?

问题描述

我想实现模板阴影,而不必在 CPU 端使用单独的灯光(记录为每个灯光交替管道的缓冲区) - 我想一次性完成所有灯光。我认为使用计算着色器是可能的;但是我无法访问它们的 ROP,虽然使用原子应该是可能的,但感觉不对(将 R32UINT 图像转换为 B8G8R8A8UNORMvkGetPhysicalDeviceSurfaceFormatsKHR 可能输出的任何内容) .必须对阴影体积进行软件光栅化也感觉不对。简单地使用模板,并在绘制阴影体积时输出 0 颜色,然后做一个四边形的实际光很好,但是我没有看到任何方法可以在绘制之间清除它。我也考虑过使用混合和 alpha 值,但我能想到的唯一方法需要特殊的钳位行为:不钳位混合输入,但钳位输出。据我所知,不可能在同一个绘制调用中从被绘制到的帧缓冲区中读取像素。

解决方法

我打算一个接一个地绘制灯光:用绘制填充模板缓冲区,在第二次绘制时使用相同的绘制 inderect 命令绘制一个光四边形,以某种方式清除它,然后继续。

您在“以某种方式清除它”部分之前遇到了问题。也就是说,绘制“轻四边形”需要将模板参数从写入模板值更改为测试。这当然不能在绘图命令中进行。

虽然将几何图形捆绑到几个绘制命令中总是好的,但重要的是要记住 Vulkan 不是 OpenGL。状态更改不是免费的,完整的管道更改也不是特别便宜,但它们不像在 OpenGL 下那样昂贵。因此,您不必为必须以这种方式分解绘图命令而感到难过。

,

在绘制命令中清除模板缓冲区是不可能的;但是,我能够通过特殊的模板状态、后期深度模板测试、discard 和着色器中的一些额外工作来实现所需的结果,代价是做这些事情和灵活性。

在我的情况下它是如何工作的(深度失败阴影):

  1. 为了区分通行证,我将 GL_ARB_shader_draw_parameters 用于 gl_DrawID,但应该可以通过其他方式实现
  2. 暗影传递:
    1. 在片段着色器中,如果要传递深度,则丢弃 // 因此,永远不会对其进行颜色写入
    2. 在模板状态下,正面失败(深度和模板)-> 增量;背面失败 -> 递减; // 有计算量
  3. 光通:
    1. 如果光三角形是背面,输出零;模板状态,背面通过 -> 替换为参考; // 清除模板
    2. 否则,计算颜色;模板状态,正面传递 -> 无关紧要。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...