我的表面着色器中需要三角形信息吗?

Do I need triangle information in my surface shader?

更新

主要问题是:如何将三角形的世界 space 顶点位置传递给 Unity 着色器中的表面着色器。 如评论中所述,可能可以从几何着色器传递它们。但我在某处读到,实现自定义几何着色器会覆盖 Unity 的逻辑来计算阴影等。 我会在输入结构中添加三角形信息。但在我改变我的网格生成逻辑之前,我想知道这是否可行。对于此解决方案,三角形的顶点位置对于三角形中的每个像素都必须保持不变,并且不能进行插值。

这是原题:

我正在为三角形网格编写表面着色器。我为每个顶点设置了一个带有纹理 ID 的自定义顶点属性。现在我希望表面着色器应用纹理,如下图所示。 (注意每种颜色代表一种纹理)

在表面着色器中,我需要定义三角形的 3 个顶点及其纹理 ID。此外,我需要定位我正在绘制的像素。

  1. 如果所有纹理 ID 都相同,我会为所有像素选择此纹理。
  2. 如果一个或两个纹理 ID 不同,我会计算到三角形顶点的像素距离并选择纹理,如下图所示:

表面着色器需要知道像素三角形。按照这个逻辑,我应该得到我正在寻找的阴影。我正在以编程方式创建我的网格,因此我可以将三角形顶点及其纹理 ID 添加为顶点属性并将其传递给表面着色器。

但我不确定 surface/vertex 着色器的工作方式是否可行。从中获取自定义三角形信息的顶点和像素之间是否存在关系?有更好的方法吗?

我正在为我的着色器使用 Unitys ShaderLab。

不,您不应该(也无权访问)在片段着色器中使用顶点数据。在片段着色器中,您只能访问有关该给定像素的数据,您不能返回并查看形成它的网格(这是构建管道的方式)。

您可以做的(也是一种常见做法)是将数据烘焙到顶点着色器中顶点的可用通道之一(即其他 UV 贴图通道)。这样片段着色器将可以通过插值器访问值

好的,我想我找到了解决办法。感谢您的评论,它们在有用的地方。

首先,我将网格拓扑更改为不使用共享顶点。有了这个,我可以使用顶点颜色通道来设置纹理 ID。

vertexColor.r = vertexTextureId0; // Texture to use for vertex 0
vertexColor.g = vertexTextureId1; // Texture to use for vertex 1
vertexColor.b = vertexTextureId2; // Texture to use for vertex 2

我不必担心插值,因为三角形的所有顶点都具有相同的颜色信息。 现在我创建一个纹理来查找我的像素属于哪个顶点。该纹理看起来与我在问题中发布的图像相似。我必须根据两种或三种情况转置 UV 坐标。此解决方案使我可以自由地轻松更改边缘并使其更加粗糙。