我有一些编程几何和计算着色器的经验-但从未真正玩过片段着色器。目前,我试图更好地了解它们的工作方式和潜力。我在多个地方都读过的一件事是,片段(即屏幕像素)不能在片段着色器中超出自身。这意味着,要迭代的给定片段只能影响自身。

因此,为了学习起见,我想知道以下内容是否可行(以及如果可行,通常线,可以实现)。为了简单起见,假设我们有一个仅由两个顶点组成的点网格(位于3D世界空间中)。我们能否以一种方式对着色器进行编程,以使这两个顶点中的每个顶点都可以在其确切的WorldToViewport位置上绘制在屏幕上,而且还可以围绕它们周围的每个像素绘制一个半径为R的圆,即使它们延伸了是否超出了着色器所连接的原始网格?如下图所示(圆圈中心的红色正方形表示在屏幕上绘制的顶点):



如果可能的话,是否也可以使用着色器以这样的方式进行编程,使得这些超出顶点的圆会彼此影响颜色(RGBA)?如下图所示:



正如我所说,如果这些都是可能的话,我很想听听如何实现这样的目标-无论是在概念或实际术语。它是在片段着色器中完成的,还是必须在顶点或几何着色器之前进行计算?如何计算并传递超出网格物体所占据的那些碎片的“其他碎片”?

评论

几何着色器可能会添加比原始网格中更多的图元。这样对您有用吗?

#1 楼

当您使用线宽或线抗锯齿或点宽或pointsprites时,OpenGL会为您创建一个带有纹理坐标的小矩形而不是线或点。如今,您甚至可以使用几何着色器甚至是镶嵌器自己进行编程。

一种完全不同的方法是使用延迟着色,使用一次几何传递仅将信息存储在RGBAZ缓冲区中,然后进行第二次传递比您在屏幕上所有像素上运行都要进行的处理。 (要作用于所有像素,只需绘制一个全屏矩形即可。)
现在,您甚至可以将一个或多个“渲染为纹理”进行第一遍,然后对这些纹理进行MIPmap处理,以便最终遍历可以轻松实现访问较少的本地值。

评论


$ \ begingroup $
谢谢!一开始,我一直在做您所说的事情,使用几何体着色器在点周围创建几何体,从而可以在点周围绘制像素。当然,它可以工作,但是它的解决方案比较麻烦。我对您所说的最后一点特别感兴趣:如果我对您的理解正确,那么您所说的就是可以渲染整个场景,然后使用针对感兴趣区域的屏幕着色器,然后在渲染的帧以便工作在中心点周围需要多少像素?
$ \ endgroup $
– AndrewSteer
16年5月20日在0:06

$ \ begingroup $
您可以在纹理中渲染第一遍。然后在第二次全屏显示中,可以检查每个像素中每个像素周围的纹理内容,然后执行所需的操作(例如,根据最接近的填充像素进行颜色显示,或者仅当距离低于某个阈值时才涂白色) 。当然,对于仅绘制磁盘而言,这并不是最有效的方法;-)
$ \ endgroup $
–Fabrice NEYRET
16年5月20日在7:12



$ \ begingroup $
当然,我只是给出了我能想到的简单示例。但是,是的,我认为您的发言与我一直在考虑的想法是一致的,即一次渲染为纹理,然后在其他阶段中,我们获得了有关其他像素的信息,以相对于周围像素中的像素进行更改。非常感谢。
$ \ endgroup $
– AndrewSteer
16年5月20日在9:04

#2 楼

可以为网格中的每个顶点安排一个圆形(或其他形状)的一种好方法是使用几何体实例化。这是一项GPU功能,它允许一次绘制网格的多个实例(副本),网格的顶点/索引由一组缓冲区提供,而另一个顶点缓冲区可以按实例提供附加数据。顶点着色器可用于以您选择的任何方式组合来自两个缓冲区的数据。

具体来说,您可以创建一个代表所需半径的圆及其顶点的网格直接在屏幕空间坐标中指定,并以原点为中心。然后,您将使用实例化使GPU为原始点网格的每个顶点渲染一个新的圆形网格副本。在顶点着色器中,您将计算该点的屏幕空间位置(照常使用world-view-projection变换),然后平移圆形网格使其居中于该位置。

至于问题的第二部分,关于圆如何影响彼此的颜色:具体取决于您要执行的操作。硬件混合可用于处理简单的情况,例如增加或增加颜色或alpha混合。如果您想要比这更复杂的东西,则可能可以使用多遍算法或(在最新的GPU上)可编程混合来实现。