Shader5-简单的Shader & Unity内置文件和变量 & CG语义

本文详细介绍Unity Shader的基础知识,包括Shader的结构、内置函数、变量和数据结构,以及如何使用CG/HLSL语言进行顶点和片元着色器的编写。通过实例解析,帮助读者理解Shader的工作原理和数据流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最简单的Shader:

Shader "Chan/Shader_5_All" {
    Properties
    {
        //面板定义属性
        _Color("Color Tint",Color) = (1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            //定义了顶点着色器函数
            //pragma vertex name 一般顶点着色器函数名用vert
            #pragma vertex vert
            
            //定义了片元着色器函数
            //pragma vertex name 一般顶点着色器函数名用frag
            #pragma fragment frag

            //在CG代码中,定义一个属性名称和类型都匹配的变量
            fixed4 _Color;

            //1.为了访问模型数据,定义一个数据结构,然后用语义告诉系统,每个值需要用什么数据填充
            //2.这个数据结构作为顶点着色器的输入(下边的a2v v)
            //3.语义中的数据由使用了该材质的Mesh Render提供 每帧调用Draw Call时候,Mesh Render会把需要渲染的模型数据发送给Shader
            struct a2v
            {
                //语义获取模型空间下的顶点
                float4 vertex:POSITION;
                //语义获取模型空间下的法线
                float3 normal:NORMAL;
                //语义获取模型的第一套纹理坐标
                float4 texcoord:TEXCOORD0;
            };

            //定义一个数据结构,用于从顶点着色器传数据给片元着色器
            struct v2f
            {
                //1.通过语义,知道pos是裁剪空间下的顶点坐标数据
                //2.必须有SV_POSITION,否则片元着色器得不到顶点坐标,无法渲染
                float4 pos:SV_POSITION;
                //通过语义,知道color变量用于存储颜色信息
                float3 color:COLOR0;
            };

            //顶点着色器函数名
            v2f vert(a2v v)
            {
                //申明结构(顶点着色器像片元着色器传递数据的数据结构)
                v2f o;
                //Shader内置函数 将顶点坐标从模型空间变换到裁剪空间下
                o.pos = UnityObjectToClipPos(v.vertex);
                //随便计算一个颜色值,赋值给color
                o.color = v.normal * fixed3(0.5,0.5,0.5);
                //返回赋值后数据结构,供片元着色器使用
                return o;
            }

            //片元着色器函数名
            //SV_Target告诉渲染器,把用户输出的颜色存储到渲染目标中,这里将输出到默认的帧缓存中
            fixed4 frag(v2f i):SV_Target
            {
                fixed3 c = i.color;
                c *= _Color.rgb;
                return fixed4(c,1.0);
            }

            ENDCG
        }
    }
}


Unity内置包含文件:

路径 = Unity安装路劲下的CGIncludes文件夹下。

.cginc文件中定义了一些常用变量和帮助函数。使用#include指令可包含文件,方便使用。

常用包含文件:

文件名描述
UnityCG.cginc包含了最常用的帮助函数,宏和结构体等
UnityShaderVariables.cginc

在编译Unity_Shader时,会被自动包含进来,包含了许多内置的全局变量,如

UNITY_MATIRX_MVP等

Lighting.cginc包含了各种内置的光照模型,如果编写的是Surface Shader,会自动包含进来
HLSLSupport.cginc在编译Unity Shader时,会被自动包含进来,声明了很多用于跨平台编译的宏和定义

UnityCG.cginc中常用的结构体

名称描述包含的变量
appdata_base可用于顶点着色器的输入顶点位置,顶点法线,第一组纹理坐标
appdata_tan可用于顶点着色器的输入顶点位置,顶点切线,顶点法线,第一组纹理坐标
appdata_full可用于顶点着色器的输入顶点位置,顶点切线,顶点法线,四组(或更多)纹理坐标
appdata_img可用于顶点着色器的输入顶点位置,第一组纹理坐标
v2f_img可用于顶点着色器的输出裁剪空间中的位置,纹理坐标

UnityCG.cginc中常用的帮助函数

函数名描述
float3 WorldSpaceViewDir(float4 v)输入模型空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向
float3 ObjectSpaceViewDir(float4 v)输入模型空间中的顶点位置,返回模型空间中从该点到摄像机的观察方向
float3 WorldSpaceLightDir(float4 v)仅可用于前向渲染中,输入一个模型空间中的顶点位置,返回世界空间中从该点到光源的光照方向,没有被归一化
float3 ObjSpaceLightDir(float4 v)仅可用于前向渲染中,输入一个模型空间中的顶点位置,返回模型空间中从该点到光源的光照方向,没有被归一化
float3 UnityObjectToWorldNormal(float3 norm)把法线方向从模型空间转换到世界空间中
float3 UnityObjectToWorldDir(in float3 dir)把方向矢量从模型空间变换到世界空间中
float3 UnityWorldToObjectDir(float3 dir)把方向矢量从世界空间变换到模型空间中

CG/HLSL提供的语义:

这些语义告诉Shader该怎么读取数据,并把数据输出到哪。同一个语义在不同的着色器中,含义不尽相同。

例如:在传递给顶点着色器的结构体中TEXCOORD0来描述texcoord,Unity会识别TEXCOORD0语义,以把模型的第一组纹理坐标填充到texcoord中。如果在顶点着色器传递给片元着色器的数据结构体中TEXCOORD0修饰的变量由我们随便赋值。

DirectX10以后,有了SV开头的系统数值语义(system value)。SV开头的语义修饰的变量不能随便赋值,因为渲染流水线需要用它们完成特定的目的。

应用阶段传递模型数据给顶点着色器时,Unity内部赋予某些语义特殊含义:

语义描述
POSITION模型空间中的顶点位置,通常是float4类型
NORMAL顶点法线,通常是float3类型
TANGENT顶点切线,通常是float4类型
TEXCOORDn,如TEXCOORD0,TEXCOORD1该顶点的纹理坐标,TEXCOORD0表示第一组纹理坐标,以此类推,通常是float2或float4类型
COLOR顶点颜色,通常是fixed4 或 float4类型

从顶点着色器传递模型数据给片元着色器时,Unity支持的语义

语义描述
SV_POSITION齐次裁剪空间中的顶点坐标,结构体中必须要包含一个用于该语义修饰的变量,等同于DirectX9中的POSITION,但最好使用SV_POSITION(为了通用性)
COLOR0通常用于输出第一组顶点颜色,但不是必需的
COLOR1通常用于输出第二组顶点颜色,但不是必需的
TEXCOORD0~TEXCOORD7通常用于输出纹理坐标,但不是必需的

除了SV_POSITION,其他都可以任意赋值,比如需要把自定义数据从顶点着色器传递给片元着色器,一般选用TEXCOORD0.

片元着色器输出时,Unity支持的常用语义

语义描述
SV_Target输出值将会存储到渲染目标中(render target),等同于DirectX 9中的COLOR语义,但最好使用SV_Target
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值