UnityShader入门精要-系统语义与函数体

系统语义与函数体

系统语义标记,指该类型将返回给流水线GPU做处理。

结构体做返回值时,不需要在函数头标记系统语义。结构体外部和内部的标记会产生二义性,所以新版本只能在内部声明

原版错误

Shader "Unity Shaders Book/Chapter 5/Simple Shader" {
    Properties {
        // 声明一个Color类型的属性
        _Color ("Color Tint", Color) = (1.0,1.0,1.0,1.0)
    }
    SubShader {
        Pass {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            // 在Cg代码中,我们需要定义一个与属性名称和类型都匹配的变量
            fixed4 _Color;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR0;
            };

            v2f vert(a2v v) : SV_POSITION {  // 错误,不能在外面声明,不再可以自动解构
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed3 c = i.color;
                // 使用_Color属性来控制输出颜色
                c *= _Color.rgb;
                return fixed4(c, 1.0);
            }

            ENDCG
        }
    }
}

​- 不再容忍模糊或错误的语义使用​
​- 不允许给结构体整体标记语义(如 struct v2f : SV_POSITION)

mul 被遗弃,会自动转换为UnityObjectToClipPos

改正后

Shader "Unity Shaders Book/Chapter 5/Simple Shader" {
    Properties {
        // 声明一个Color类型的属性
        _Color ("Color Tint", Color) = (1.0,1.0,1.0,1.0)
    }
    SubShader {
        Pass {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            // 在Cg代码中,我们需要定义一个与属性名称和类型都匹配的变量
            fixed4 _Color;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR0;
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed3 c = i.color;
                // 使用_Color属性来控制输出颜色
                c *= _Color.rgb;
                return fixed4(c, 1.0);
            }

            ENDCG
        }
    }
}

传入的结构体系统语义会被GPU捕捉赋值,返回的结构体的系统语义会被自动解构获取

也就是说,两种函数头

结构体内部标记系统语义,函数头不再声明

struct a2v {
	float4 vertex : POSITION;
	float3 normal : NORMAL;
	float4 texcoord : TEXCOORD0;
};

struct v2f {
	float4 pos : SV_POSITION;
	fixed3 color : COLOR0;
};

v2f vert(a2v v) {
	v2f o;
	o.pos = UnityObjectToClipPos(v.vertex);
	o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
	return o;
}

或者基本类型系统语义在函数头标记

fixed4 frag(v2f i) : SV_Target {
	fixed3 c = i.color;
	// 使用_Color属性来控制输出颜色
	c *= _Color.rgb;
	return fixed4(c, 1.0);
}
posted @ 2025-10-05 15:19  丘狸尾  阅读(10)  评论(0)    收藏  举报