Unity Shader - Providing vertex data to vertex programs 给顶点着色器提供顶点数据

目录:Unity Shader - 知识点目录(先占位,后续持续更新)
原文:Providing vertex data to vertex programs
版本:2019.1

Providing vertex data to vertex programs

给顶点着色器提供顶点数据

对于 Cg/HLSL 的顶点程序来说,网格的顶点数据需要传入到顶点着色器函数。每个输入的数据都需要指定 semantic (语义) :如,POSITION 代表输入顶点的坐标,NORMAL 代表顶点法线。

通常来说,顶点的输入数据定义在一个结构体,而不是一个一个的在函数里头声明定义。一些常用的顶点结构都定义在 UnityCG.cginc include file,大多数情况下这些结构都够用。这些结构体是:

  • appdata_base:坐标,法线和一个纹理坐标。
  • appdata_tan:坐标,切线,法线和一个纹理坐标。
  • appdata_full:坐标,切线,法线,四个纹理坐标和一个颜色。

例如:下面的shader中,网格的颜色是基于法线来定,且使用 appdata_base 作为顶点程序的输入结构:

Shader "VertexInputSimple" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
         
            struct v2f {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };
            
            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color.xyz = v.normal * 0.5 + 0.5;
                o.color.w = 1.0;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target { return i.color; }
            ENDCG
        }
    } 
}

访问不同的顶点数据,你需要定义顶点数据结构体,或是给顶点着色器函数添加参数的方式。顶点数据都是以 Cg/HLSL semantics(语义)来识别的,必须是一下这些语义:

  • POSITION 是顶点的坐标,通常是 float3 或是 float4
  • NORMAL 是顶点的法线,通常是 float3
  • TEXCOORD0 是第一个UV坐标,通常是 float2float3 或是 float4
  • TEXCOORD1TEXCOORD2TEXCOORD3 分别是第二,第三和第四个UV坐标。
  • TANGENT 是切向量(用于法线映射),通常是 float4
  • COLOR 是顶点的颜色,通常是 float4

当网格数据分量数的比顶点着色器输入指定类型的数据分量数少时,那么其余的都用0填充,只有.w分量默认值为1。如,网格的纹理坐标通常是2D向量,有x和y分量。如果顶点着色器定义为一个 float4 类型,并使用 TEXCOORD0 语义,那么在顶点着色器接收该 float4 数据实际值就是:(x,y,0,1)。

Examples

例子

Visualizing UVs

可视化UV

接下来着色器的例子将使用顶点坐标和第一个纹理坐标作为顶点着色器输入数据结构(定义于 appdata 结构体)。这个 shader 用于调试网格的UV坐标是很有用的。

Shader "Debug/UV 1" {
SubShader {
    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

        // 顶点输入:坐标,UV
        struct appdata {
            float4 vertex : POSITION;
            float4 texcoord : TEXCOORD0;
        };

        struct v2f {
            float4 pos : SV_POSITION;
            float4 uv : TEXCOORD0;
        };
        
        v2f vert (appdata v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex );
            o.uv = float4( v.texcoord.xy, 0, 0 );
            return o;
        }
        
        half4 frag( v2f i ) : SV_Target {
            half4 c = frac( i.uv );
            if (any(saturate(i.uv) - i.uv))
                c.b = 0.5;
            return c;
        }
        ENDCG
    }
}
}

这里的UV坐标被可视化为红和绿颜色,当UV坐标唱过0-1范围的都显示为蓝色:
Debug UV1 shader applied to a torus knot model
调试UV1着色器应用在圆环结(麻花结)的模型上

类似的,着色器可视化模型的第二个UV:

Shader "Debug/UV 2" {
SubShader {
    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

        // 顶点输入:坐标,第二个UV
        struct appdata {
            float4 vertex : POSITION;
            float4 texcoord1 : TEXCOORD1;
        };

        struct v2f {
            float4 pos : SV_POSITION;
            float4 uv : TEXCOORD0;
        };
        
        v2f vert (appdata v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex );
            o.uv = float4( v.texcoord1.xy, 0, 0 );
            return o;
        }
        
        half4 frag( v2f i ) : SV_Target {
            half4 c = frac( i.uv );
            if (any(saturate(i.uv) - i.uv))
                c.b = 0.5;
            return c;
        }
        ENDCG
    }
}
}

Visualizing vertex colors

可视化顶点颜色

接下来的shader使用顶点的坐标和顶点颜色作为顶点输入的数据结构(定义在 appdata 结构体)。

Shader "Debug/Vertex color" {
SubShader {
    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

        // 顶点输入:坐标,颜色
        struct appdata {
            float4 vertex : POSITION;
            fixed4 color : COLOR;
        };

        struct v2f {
            float4 pos : SV_POSITION;
            fixed4 color : COLOR;
        };
        
        v2f vert (appdata v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex );
            o.color = v.color;
            return o;
        }
        
        fixed4 frag (v2f i) : SV_Target { return i.color; }
        ENDCG
    }
}
}

Debug Colors shader applied to a torus knot model that has illumination baked into colors
调试颜色着色器应用于带有烘焙光照颜色的圆环结模型

Visualizing normals

可视化法线

下面的shader使用顶点坐标和法线作为顶点着色器的输入结构(定义在 appdata 结构体)。法线的 X,Y,Z分量可视化为RGB颜色。因为法线分量的数据范围是-1 ~ 1的,我们需要缩放和偏移它们,以便它们能用于显示颜色的数据范围: 0 ~ 1。

Shader "Debug/Normals" {
SubShader {
    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

        // 顶点输入:坐标,法线
        struct appdata {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
        };

        struct v2f {
            float4 pos : SV_POSITION;
            fixed4 color : COLOR;
        };
        
        v2f vert (appdata v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex );
            o.color.xyz = v.normal * 0.5 + 0.5;
            o.color.w = 1.0;
            return o;
        }
        
        fixed4 frag (v2f i) : SV_Target { return i.color; }
        ENDCG
    }
}
}

Debug Normals shader applied to a torus knot model. You can see that the model has hard shading edges.
调试法线着色器应用于圆环结模型。你可以看到模型的着色带有硬边缘。

Visualizing tangents and bitangent

可视化切线与副切线

切线与副切线向量用于法线映射。在Unity仅有切线向量存在顶点在,而副切线是从法线与切线推导出来的。

下面的shader使用顶点的坐标和切线作为顶点着色器的输入(定于在 appdata 结构体)。切线的x,y,z分量可视化为RGB颜色。因为法线的分量都是 -1 ~ 1的范围,我们缩放和偏移它们以便于输出到显示颜色的范围:0 ~ 1。

Shader "Debug/Tangents" {
SubShader {
    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

        // 顶点输入:坐标,切线
        struct appdata {
            float4 vertex : POSITION;
            float4 tangent : TANGENT;
        };

        struct v2f {
            float4 pos : SV_POSITION;
            fixed4 color : COLOR;
        };
        
        v2f vert (appdata v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex );
            o.color = v.tangent * 0.5 + 0.5;
            return o;
        }
        
        fixed4 frag (v2f i) : SV_Target { return i.color; }
        ENDCG
    }
}
}

Debug Tangents shader applied to a torus knot model.
调试切线着色器应用于圆环结模型。

下面的shader可视化副切线。使用顶点的坐标,法线和切线作为顶点的输入。副切线(某些情况也叫副法线)是从法线和切线计算得来的。它需要被缩放和偏移到显示颜色的范围:0 ~ 1。

Shader "Debug/Bitangents" {
SubShader {
    Pass {
        Fog { Mode Off }
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

        // 顶点输入:坐标,法线,切线
        struct appdata {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
            float4 tangent : TANGENT;
        };

        struct v2f {
            float4 pos : SV_POSITION;
            float4 color : COLOR;
        };
        
        v2f vert (appdata v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex );
            // 计算副切线
            float3 bitangent = cross( v.normal, v.tangent.xyz ) * v.tangent.w;
            o.color.xyz = bitangent * 0.5 + 0.5;
            o.color.w = 1.0;
            return o;
        }
        
        fixed4 frag (v2f i) : SV_Target { return i.color; }
        ENDCG
    }
}
}

Debug Bitangents shader applied to a torus knot model.
调试副切线着色器应用于圆环结模型。

Further Reading

延伸阅读

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值