UnityShader7:内置包含文件UnityCG.cginc与GG/HLSL语义

 

一、包含文件 .cginc

类似于头文件,cginc 可以理解为 GC include,用 #include 指令包括进来后,就可以使用其中的变量和帮助函数,在上一章:UnityShader6:最简单的顶点/片元着色器中,我们直接通过 UnityObjectToClipPos(v) 这个方法来得到顶点在裁剪空间中的坐标,这个 UnityObjectToClipPos() 方法就实现在对应的 .cginc 文件里

Unity 自带一些非常基础的 .cginc 文件,例如 UnityCG.cginc,在 Windows 系统中,它们在 Unity安装路径/Data/CGIncludes

CGIncludes 中几个基本的 .cginc 文件如下:

  • UnityCG.cginc:包含了最常使用的帮助函数、 宏和结构体等
  • UnityShaderVariables.cginc:包含了许多内置的全局变量, 例如 UNITY_MATRIX_MVP 等
  • Lighting.cginc:包含了各种内置的光照模型,对于表面着色器会自动包含进来
  • HLSLSupport.cginc:内部声明了很多用于跨平台编译的宏和定义
  • UnityStandardBRDF.cginc/UnityStandardCore.cginc:物理库,暂时可以不用考虑
  • ……

中间三个 .cginc 文件的特点是,无需使用 #include 指令就会被自动包含,这也是为什么前一章中没有看到类似的代码

也可以自己编写 .cginc 文件,不过要讲究一些格式

 

二、UnityCG.cginc 主要结构体和函数

可以直接打开 UnityCG.cginc 参考其代码以及函数的具体内部实现,UnityCG.cginc 需要主动包含

常用的结构体套餐:

  • appdata_img:用于顶点着色器的输入,位置+第1组纹理坐标
  • v2f_img:用于顶点着色器的输出,裁剪空间的位置+纹理坐标
  • appdata_base:用于顶点着色器的输入,位置+法线+第1组纹理坐标
  • appdata_tan:用于顶点着色器的输入,位置+法线+切线+第1组纹理坐标
  • appdata_full:用于顶点着色器的输入,位置+法线+切线+前4组纹理坐标

常用的帮助函数:

  • float3 WorldSpaceViewDir(float4 localPos):输入一个模型空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向
  • float3 UnityWorldSpaceViewDir(float3 worldPos):输入一个世界空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向
  • float3 ObjSpaceViewDir(float4 v):输入一个模型空间中的顶点位置,返回模型空间中从该点到摄像机的观察方向
  • float3 WorldSpaceLightDir(float4 localPos):输入一个模型空间中的顶点位置,返回世界空间中从该点到光源的光照方向,没有被归一化,仅可用于前向渲染(非延迟渲染)
  • float3 UnityWorldSpaceLightDir(float4 localPos):输入一个世界空间中的顶点位置,返回世界空间中从该点到光源的光照方向,没有被归一化,仅可用于前向渲染(非延迟渲染)
  • float3 ObjSpaceLightDir(float4 v):输入一个模型空间中的顶点位置,返回模型空间中从该点到光源的光照方向,没有被归一化,仅可用于前向渲染(非延迟渲染)
  • float3 UnityObjectToWorldNormal(float3 norm):把法线方向从模型空间转换到世界空间中
  • float3 UnityObjectToWorldDir(float3 dir):把方向矢量从模型空间变换到世界空间中
  • float3 UnityWorldToObjectDir(float3 dir):把方向矢量从世界空间变换到模型空间中
  • float3 UnityObjectToViewPos(float3/float4 pos):把模型空间中的顶点位置变换到观察空间中
  • float3 UnityWorldToViewPos(float3 pos):把世界空间中的顶点位置变换到观察空间中
  • UnityWorldToClipPos/UnityViewToClipPos/UnityObjectToClipPos:把XX空间中的顶点位置变换到裁剪空间中
  • ……

因此,可以将上一章的代码改造如下:

Shader "Jaihk662/NewSurfaceShader"
{
    Properties
    {
        _Color ("Color", Color) = (0.0, 0.0, 1.0, 1.0)
    }
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 200
        PASS 
        {
            CGPROGRAM
            #pragma vertex vert             //声明顶点着色器的函数
            #pragma fragment frag           //声明片段着色器的函数
            #include "UnityCG.cginc"
 
            fixed4 _Color;
            struct vert2frag {
                float4 pos: SV_POSITION;
                fixed4 color: COLOR0;
            };
 
            vert2frag vert(appdata_base v) {
                vert2frag o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color = _Color;
                return o;
            }
            fixed4 frag(vert2frag i): SV_Target {
                return i.color; 
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

 

三、Unity 提供的 CG/HLSL 语义

上一章已经介绍了一些常用语义了,语义本质上是让Shader知道从哪里读取数据,并把数据输出到哪里,根据语义的数据传递分类:

  • 从应用阶段传递模型数据给顶点着色器时 Unity 支持的常用语义有:POSITION / NORMAL / TANGENT / TEXCOORD0~9 / COLOR,这里的 COLOR 往往为顶点颜色
  • 从顶点着色器传递数据给片元着色器时 Unity 使用的常用语义有:SV_POSITION / COLOR0~1 / TEXCOORD0~9
  • 片元着色器输出时 Unity 支持的常用语义:SV_Target

关于语义需要注意的是:

  1. Unity为了方便对模型数据的传输,对某些语义进行了特别的含义规定,例如若在顶点着色器的输入结构体中用 TEXCOORDO 来描述 texcoord,Unity 就会自动把第一组纹理坐标填充到 texcoord 中
  2. 同样的语义名称可以出现在多个位置中(例如TEXCOORD0~9),但是他们本质上是不同的

系统数值语义(system-value semantics):DirectX10 后新增,这类语义以 SV_ 开头,SV 代表系统数值,往往带有特殊的含义。例如渲染引擎会把用 SV_POSITION 修饰的变量经过光栅化后显示在屏幕上,不可更改其使用目的也不能随意赋值

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值