UnityShader入门精要笔记(4)——UnityShader结构

UnityShader结构

一、顶点/片元着色器的基本结构

Shader "Unlit/MyFirstShader"{   //Shader的路径跟名字
    SubShader{
        pass{
            CGPROGRAM

            #pragma vertex vert //这里是定义vert为顶点着色器的函数
            #pragma fragment frag //这里是定义frag为片元着色器的函数
            
            //下面的POSITION和SV_POSITION都是CG/HLSL中的语义。
            //它们是不可忽略的,这些语义将告诉系统用户,需要哪些输入值,以及输出是什么
            //以下说明:POSITION告诉Unity,把模型的顶点坐标填充到输入参数v中,SV_POSITION告诉Unity顶点着色器的输出是裁剪空间中的顶点坐标
            float4 vert(float4 v : POSITION):SV_POSITION{
                return mul(UNITY_MATRIX_MVP,v)
                //unity中有函数:UnityObjectToClipPos(v)跟上述公式有一样的效果;
            }
            //片元着色器输出的颜色的每个分量范围在[0,1]中
            fixed4 frag() :SV_TARGET{
                return fixed4(1.0,1.0,1.0,1.0)
             }
            ENDCG
        }
    }
}

二、增加顶点着色器的输入

Shader "Unlit/MyFirstShader"
{
   SubShader{
       pass{
           CGPROGRAM

           #pragma vertex vert 
           #pragma fragment frag
           //使用一个结构体来定义顶点着色器的输入
           struct a2v{
               //POSITION语义,用模型空间的顶点坐标填充vertex变量
               float4 vertex : POSITION;
               //NORMAL语义,用模型空间的法线方向填充normal变量
               float3 normal : NORMAL;
               //TEXCOORD0语义,用模型的第一套纹理坐标填充texcoord变量
               float4 texcoord:TEXCOORD0;
           };


           float4 vert(a2v v):SV_POSITION{
               return UnityObjectToClipPos(v.vertex);
           }
           fixed4 frag() :SV_TARGET{
               return fixed4(1.0,1.0,1.0,1.0);
           }
           ENDCG
       }
   }
}

顶点着色器的输入格式

struct StrictName{
    Type Name : Semantic;
    Type Name : Semantic;
}

对于顶点着色器的输出,Unity支持的语义

  • POSITION:顶点数据;
  • TANGENT:切线数据
  • NORMAL:法线数据
  • TEXCOORD0:第一套纹理数据
  • TEXCOORD1:第二套纹理数据
  • COLOR:颜色

三、顶点着色器和片元着色器之间的通信

Shader "Unlit/MyFirstShader"
{
   SubShader{
       pass{
           CGPROGRAM

           #pragma vertex vert 
           #pragma fragment frag
           struct a2v{
               float4 vertex : POSITION;
               float3 normal : NORMAL;
               float4 texcoord:TEXCOORD0;
           };
           

           //使用一个结构体来定义顶点着色器的输出
           struct v2f{
               //SV_POSITION语义告诉Unity,pos里包含了顶点在裁剪空间中的位置信息
               float4 pos : SV_POSITION;
               //COLOR0语义可以用于存储颜色信息
               fixed3 color : COLOR0;
           };

           v2f vert(a2v v){
               //声明输出结构
               v2f o;
               o.pos = UnityObjectToClipPos(v.vertex);
               //v.normal包含了顶点的法线方向,其分量范围在[-1.0,1.0]
               //下面的代码把分量范围映射到了[0.0,1.0]
               //存储到o.color中传递给片元着色器
               o.color = v.normal * 0.5 + fixed3(0.5,0.5,0.5);
               return o;
           }
           fixed4 frag(v2f i) :SV_TARGET{
               //将插值后的i.color显示到屏幕中
               return fixed4(i.color,1.0);
           }
           ENDCG
       }
   }
}

需要注意的地方:

  • 顶点着色器是逐顶点调用的,片元着色器是逐片元调用的。
  • 片元着色器的输入实际上是把顶点着色器的输出进行插值后得到的结果

四、使用属性

Shader "Unlit/MyFirstShader"
{
    //通过定义Properties模块的增加可以在材质面板中控制的属性
    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
       }
   }
}

ShaderLab中属性类型和CG中变量的类型之间的匹配的关系

ShaderLab属性类型CG变量类型
Color,Vectorfloat4,half4,fixed4
Range,Floatfloat,half,fixed
2Dsampler2D
CubesamplerCube
3Dsampler3D

uniform 关键字

  • 有时候CG变量前会有一个uniform关键字,例如:uniform fixed4 _Color;
  • uniform关键字是CG中修饰变量和参数的一种修饰词,仅仅用于提供一些关于该变量的初始值是如何指定和存储的相关信息。
  • 在UnityShader中,uniforme关键字可以省略。

五、Unity内置的包含文件

Unity中一些常用的包含文件

文件名描述
UnityCG.cginc包含了最常用的帮助函数、宏和结构体等
UnityShaderVariables.cgnic在编译Unity Shader时,会被自动包含进来。包含了许多内置的全局变量,如UNITY_MATRIX_MVP等
Lighting.cgnic包含了各种内置的光照模型,如果编写的是Surface Shader的话,会自动包含进来
HLSL.Support.cginc在编译Unity Shader时,会被自动包含进来。声明了很多用于跨平台编译的宏和定义

UnityCG.cgnic中一些常用的结构体

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

UnityCG.cgnic中一些常用的帮助函数

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

从应用阶段传递模型数据给顶点着色器时Unity支持的常用语义

语义描述
POSITION模型空间中的顶点位置,通常是float4类型
NORMAL顶点法线,通常是float3类型
TANGENT顶点切线,通常是float4类型
TEXCOORDn该顶点的纹理坐标,通常是float2或float4类型
COLOR顶点颜色,通常是fixed4或float4类型

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

语义描述
SV_Target输出值将会存储到渲染目标(render target)中。等同于DirectX9中的语义,但最好使用。

CG/HLSL中的3种精度的数值类型

类型精度
float最高精度的浮点值。通常使用32位来存储
half中等精度的浮点值。通常使用16位来存储,精度范围是-60000~+60000
fixed最低精度的浮点数。通常使用11位来存储,精度范围是-2.0~+2.0

注意事项

  • SV代表的含义是系统数值。
  • 一个语义可以使用的寄存器只能处理4个浮点值(float)。
  • 使用SV_POSITION来描述顶点着色器输出的顶点位置。
  • 使用SV_Tartet来描述片元着色器的输出颜色。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值