GLSL顶点着色器取消渲染

use*_*443 8 opengl glsl terminate vertex-shader

可以在顶点着色器中终止像素的渲染.例如,如果顶点不满足某个要求,则取消该顶点的渲染?

Nic*_*las 16

我假设你说" 终止渲染顶点 ".不,你不能; OpenGL对VS的输入顶点与输出的1:1比率非常严格.此外,它并不意味着你想要它,因为顶点不会被渲染.原语做的,原始的,可以由一个以上的顶点.例如,丢弃三角形条带中间的顶点意味着什么.

这就是几何着色器能够"剔除"原语的原因; 它们专门处理原语,而不仅仅是单个顶点.这是通过简单地不发射任何顶点来完成的; GS必须明确地发出它想要输出的顶点.


顶点着色器现在具有剔除基元的能力.这是使用OpenGL 4.5的"剔除距离"功能完成的.它就像gl_ClipDistance只有一个顶点越过阈值,而不是剪切,它会剔除整个基元.


And*_*man 11

理论上,您可以使用顶点着色器生成退化(零区域)基元.具有零区域的基元不应导致任何栅格化,因此不会渲染任何片段.但是,它并不是特别直观,特别是如果您使用共享顶点的基元.

但不,取消顶点几乎毫无意义.它是构建基元的基本单元.如果只删除单个顶点,则将以未定义的方式更改栅格化输出.

简而言之,顶点不是在屏幕上创建像素的原因.它是顶点之间的连接,它创建了最终导致像素的基元.几何着色器以原始为基础进行操作,因此它们通常以编程方式取消光栅化和片段着色.


更新:

我注意到你使用的GL_POINTS是原始类型.在这种特殊情况下,您需要做的就是防止顶点沿着管道向下移动,将其位置设置在摄像机查看量之外的某个位置.顶点将被剪裁,不会发生光栅化或片段着色.

这是一种更有效的解决方案,用于在片段着色器中测试某些条件然后丢弃,因为您跳过光栅化并且根本不必执行片段着色器.更不用说,discard通常最终作为后着色器执行标志工作,告诉GPU丢弃结果 - 无论您在着色器中发出discard指令的位置,GPU都经常被强制执行整个着色器.因此discard很少提供性能优势,并且在许多情况下,它可以禁用其他可能更有用的硬件优化.不幸的是,这是GPU调度着色器工作负载的方式的本质.

最便宜的片段是你永远不需要处理的片段:)


sho*_*ton 7

您无法终止顶点着色器中的像素渲染(它不处理像素),但您可以使用discard指令在片段着色器中进行渲染.

  • 这实际上只会丢弃像素的结果.在现代硬件(Shader Model 3.0+)上,像素以2x2块绘制,以使衍生指令工作......这些2x2块可以被调度到同时运行的着色器的warp(NV)或波前(AMD).提前片段着色的唯一方法是将warp/wavefront中的每个片段丢弃.否则,它将继续评估所有指令,但会在逐个像素的基础上抛出结果.经常`discard`或`kill`实际上并没有终止任何东西,它只是看起来像:) (5认同)

Ric*_*k77 6

我正在详细说明 Andon M. Coleman 的答案,恕我直言,这应该被标记为正确的答案。

尽管 OpenGL 规范坚持认为您不能跳过片段着色器步骤(除非您实际上删除了几何着色器中的整个图元,正如Nicol Bolas 正确指出的那样,这有点矫枉过正,恕我直言),您可以做到在实践中,通过让 OpenGL 剔除整个几何体,因为现代 GPU 具有早期的片段拒绝优化,这可能会产生相同的效果。

而且,对于记录,丢弃整个几何体真的很容易:只需将顶点写入 (-1, -1, -1),(1,1,1) 立方体之外,

gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
Run Code Online (Sandbox Code Playgroud)

……你走吧!

希望这可以帮助