使用GLSL片段着色器为每个三角形/面绘制纯色的方法

6
我有包含每个三角形(面)的颜色数据和顶点数据,而不是每个顶点的颜色数据。也就是说,一个顶点被多个面共享,每个面可能有不同的颜色。
在GLSL中,我应该如何解决这个问题以获得每个正在渲染的面的单一颜色分配?计算和分配“顶点颜色”缓冲区通过平均邻近多边形的颜色很容易,但这当然会产生模糊的结果,在片段着色器中进行颜色插值。
我真正需要的不应该是任何插值的颜色值,一旦按预期工作,我将使用大约15种可能的纯色对大约40k个三角形进行着色。

请参见:https://dev59.com/yG025IYBdhLWcg3wW0oc - Ville Krumlinde
3个回答

8

虽然你可以在高端GLSL中完成这个操作,但正确的实心着色方式是为每个三角形创建唯一的顶点。这是一个微不足道的循环。对于每个顶点,计算共享它的三角形数量。这就是你必须复制它的次数。确保你的循环是O(n)。然后将每个顶点的颜色或法线设置为三角形的颜色或法线。再次进行直线循环。不要费心为共享颜色进行优化,这是不值得的。

编辑时间较晚,因为这是一个流行的答案:

要进行平面每面着色,可以在世界或视图空间中插值顶点位置。然后在片段着色器中计算此变量的ddx(dFdx)和ddy(dFdy)。取这两个向量的叉积并归一化 - 你得到了一个平面法线!完全不需要网格更改或每个顶点数据。


我关心性能问题,但如果所有几何体都在一个中,那么可能不是问题。得看看它的表现如何。另一个我没有提到的复杂情况是,我希望能够从这种“模式”切换到完全多纹理、混合模式。但我也可以只切换网格可见性。 - Manius
这是一段时间以前的事情了,但这就是我最终所需要的。只需复制所有顶点,没有三角形共享相同的顶点索引。 - Manius

4

OpenGL没有“每个面”属性。请参考:

如何在使用索引顶点数组时指定每个面的颜色?

我看到了几个可能的选项:

  1. 放弃索引数组,为每个面使用单独的顶点,就像starmole建议的那样。
  2. 为每种颜色创建一个索引数组。使用材料而不是顶点颜色,并在绘制每个颜色的索引数组三角形后更改材料。
  3. 如果几何图形允许,您可以确保由索引数组指定的最后一个顶点具有正确的面顶点颜色,然后使用GL_FLAT着色或片段着色器仅使用最后一个顶点颜色。

2
您能详细说明第三点吗?特别是在片元着色器中“使用最后一个顶点颜色”的能力-我们如何从frag shader访问片元的顶点? - Manius

4

除了其他答案外,您还可以使用gl_PrimitiveID变量,这是片段着色器的输入(不知道从哪个版本开始),并且对于每个三角形都会隐式递增。然后,您可以使用此变量查找颜色(可以从颜色缓冲区纹理或15种颜色颜色映射的颜色索引中查找,或者直接从原始id进行一些直接计算)。但是不要问我这种方法的性能。


如果我尝试这个,你知道那个ID变量是针对每个网格应用的,还是ID将递增以渲染每个三角形?我会担心ID是否一致,以及其他网格是否会使计数失误。 - Manius
@Crusader 对于每个glDraw...命令(以及每个glDrawMulti...命令的每个实例),ID都设置为零,并且在绘制原语(三角形)时每次都会增加,因此是的ID是一致的,只取决于当前的glDraw...命令。 - Christian Rau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接