OpenGL GLSL:从着色器输出到内存

OpenGL GLSL: Output from shader to memory

我需要在图形内存中有一些 variable/object 可以在我的片段着色器和我的普通 C# 代码中访问。最好是 16Byte vec4

我想做的事情:

  1. [在 C# 中] 从图形内存读取变量到 cpu 内存
  2. [在 C# 中] 将变量设置为零
  3. [在 C# 中]执行我的场景的正常绘制
  4. [在着色器中] 一个 片段传递向变量写入一些内容 (UPDATE)
  5. 重新开始循环

(更新) 我将当前鼠标坐标传递给具有统一变量的片段着色器。然后片段着色器检查它是否是相应的像素。如果是,它会将某种颜色写入变量中以进行颜色选择。我不写入 FS 输出的原因是我根本没有在互联网上找到任何关于如何将此输出放入我的正常内存的解决方案。另外我会为每个像素而不是一个输出

我想要的基本上是一个着色器可以写入的统一变量。

是否有任何一种 variable/object 适合我的需要?如果有,它的性能如何?

您的着色器可以写入的 "uniform" 是错误的术语。统一意味着统一(就像到处都是相同的值)。如果特定着色器调用正在更改值,则它不再统一。

你可以用 atomic counters 来做这种事情;为每个通过的测试增加计数器,然后检查非零状态。这比设置通用着色器存储缓冲区对象然后担心对其进行内存访问要简单得多。

遮挡查询也可用于较旧的硬件。它们的工作方式与原子计数器惊人地相似,您可以(非常粗略地)计算通过深度测试的片段数量。不要指望它的准确性,在片段着色器中对任何未通过测试条件的像素使用 discard,然后在查询回读中测试非零片段计数。


至于性能,只要您可以在发出命令和稍后使用结果之间处理几帧的延迟,就应该没问题。

如果您尝试使用原子计数器或遮挡查询并在同一帧中回读结果,您将停止管道并消除 CPU/GPU 并行性。

我建议在命令流中插入一个栅栏同步对象,然后在尝试读回结果之前每帧检查一次栅栏的状态。这将防止停顿。