【问题标题】:Why passing parameter is OK between Vertex and Fragment shader为什么在顶点和片段着色器之间传递参数是可以的
【发布时间】:2015-06-13 08:50:52
【问题描述】:

一个典型的着色器是这样的:

struct vin_vct 
        {
            float4 vertex : POSITION;
            float4 color : COLOR;
            float2 texcoord : TEXCOORD0;
        };

        struct v2f_vct
        {
            float4 vertex : POSITION;
            fixed4 color : COLOR;
            float2 texcoord : TEXCOORD0;
        };

        v2f_vct vert_vct(vin_vct v)
        {
            v2f_vct o;
            o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
            o.color = v.color;
            o.texcoord = v.texcoord;
            return o;
        }

        fixed4 frag_mult(v2f_vct i) : COLOR
        {
            fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;
            return col;
        }

我感到困惑的是: vert_vct 被每个顶点调用; frag_mult 被称为每个片段(大多数情况下为像素);

所以基本上 frag_mult 会和 vert_vct 运行不同的时间,例如,frag mult 运行 10 次,而 vert_vct 运行 3 次三角形。那么每次frag_mult运行时都会接受一个vert_vct传递的参数,那么如果运行时间不同,如何在frag和vert之间进行映射,如何决定将哪个vert_vct传递给指定的frag_mult呢?

【问题讨论】:

  • 值(大部分时间)是线性插值的。对于每个片段,值是从周围的顶点插入的。例如,一个三角形的 3 个顶点中的每一个都有一种颜色会产生很多片段,这些片段的颜色将从顶点的颜色中插值。

标签: shader vertex cg


【解决方案1】:

顶点着色器和片段着色器执行的计数没有直接关系。

如果你有一个三角形,那么你是正确的,顶点着色器将运行 3 次,每个顶点运行一次。但随后它的结果被插值 - 即光栅化 - 到最终的投影屏幕三角形覆盖的许多片段上。对于一个巨大的三角形来说,它可能是屏幕上的每个像素,或者对于一个不在屏幕上的三角形来说,没有一个像素。如果有任何可见像素,则片段着色器会为每个像素运行一次(错误,片段,正如 GL 命名法所采用的那样)。

由于值是在顶点之间插值的,因此您可能会在大多数片段上获得不完全是任何单个顶点的值的值,除非您将相同的值传递给所有这三个顶点 - 例如,如果您拥有所有模型中的红色顶点为 v.color 然后将传递给 o.colori.color 将在任何地方出现不变。即便如此,这些值仍然被插值,但由于它们都是相同的,结果实际上是恒定的。

这对你有意义吗?

【讨论】: