Unity Shader 入门笔记(三)

发布时间:2024年01月19日

2079149a721b4e969216f56a4a8d2fc9.png

前言

在上一篇 Unity Shader 入门笔记(二)中,我们了解了关于Unity Shader中顶点着色器和片元着色器如何通信和渲染,本文中我们将继续学习和了解上文提及的Unity的语义和内置包含文件。

1. 内置包含文件

包含文件(include file),类似于C++中头文件的一种文件。

在Unity中,他们的文件后缀是.cgnic。在编写Shader时,我们可以使用#include指令把这些文件包含进来,我们就可以使用Unity为我们提供的变量和函数,写法如下所示:

CGPROGRAM
#include "UnityCG.cginc"
ENDCG

相关文件位置如下:

  • Windows
{unity 安装路径}/Data/CGIncludes/UnityCG.cginc
  • Mac?
/Applications/Unity/Unity.app/Contents/CGIncludes/UnityCG.cginc

Unity内置包含文件都在CGIncludes文件夹中,下面介绍比较常用的几个文件:

  • UnityCG.cginc:包含了最常使用的帮助函数、宏和结构体;
  • UnityShaderVariables.cgnic:编译UnityShader时会自动包含进来。包含了许多内置的全局变量,如UNITY_MATRIX_MVP。
  • Lighting.cginc:包含了各种内置光照模型,如果编写的时Surface Shader的话,会被自动包含进来。
  • HLSLSupport.cgnic:在编译Unity Shader时,会被自动包含进来。声明了很多用于跨平台编译的宏和定义。
  • AutoLight.cginc : 光照和阴影功能,例如表面着色器内部使用此文件。
  • TerrainEngine.cginc : 地形和植被着色器的帮助函数。

1.1. 介绍一些 UnityGC.cginc中一些常用结构

appdata_base

可用于顶点着色器输入

顶点位置、顶点法线、第一组纹理坐标

appdata_tan

可用于顶点着色器输入

顶点位置、顶点切线、顶点法线、第一组纹理坐标

appdata_full

可用于顶点着色器输入

顶点位置、顶点切线、顶点法线、四组(更多)组纹理坐标

appdata_img

可用于顶点着色器输入

顶点位置、第一组纹理坐标

v2f_img

可用于顶点着色器输出

裁剪空间中的位置、纹理坐标

1.2. 关于 UnityCG.cgnic 中常用的帮助函数

读者可查阅如下链接的官方文档,进行了解和学习:

内置着色器 helper 函数 - Unity 手册

1.3. 如何使用 UnityGC.cginc 的结构体和帮助函数?

上一篇文章中,我们写了一些简单的shader,并自己定义了顶点着色器输入结构,下面尝试使用#include "UnityCG.cginc",将a2v修改为appdata_base,如下所示:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "My Shader/SimpleShader03"
{
    Properties{
        _Color ("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0)
    }

    SubShader
    {
        Pass{
            CGPROGRAM
            //声明顶点着色函数 vert是顶点着色函数名字
            #pragma vertex vert
            //声明片元着色函数 frag是片元着色函数名字
            #pragma fragment frag

            #include "UnityCG.cginc"
    
            //在CG代码中,需要定义一个属性名称都和类型匹配的变量
            fixed4 _Color;

            //顶点着色器的输入
            // struct a2v {
            //     float4 vertex : POSITION; //用模型空间顶点填充vertex变量
            //     float3 normal : NORMAL;   //用模型空间法线填充normal变量
            //     float4 texcoord : TEXCOORD0; //用模型空间第一套纹理坐标填充texcoord变量
            // };

            //顶点着色器的输出 --> 输出到片元着色器
            struct v2f{
                float4 pos : SV_POSITION;
                fixed3 color : COLOR0;
            };

            // POSITION / SV_POSITION 是 CG/HLSL 的语义
            v2f vert (appdata_base v)
            {
                v2f o;
                //注意:MVP变换就是将模型空间转化到裁剪空间
                o.pos = UnityObjectToClipPos(v.vertex);
                //顶点法线的分量范围在[-1,1]之间
                o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                return o;
            }

            // SV_Target 是HLSL中的系统语义,
            //它等同于告诉渲染器,将用户输出的颜色存储到一个渲染目标上
            //这里输出到默认的帧缓存上
            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 c = i.color;
                c *= _Color.rgb;
                return fixed4(c,1.0);
            }
            ENDCG
        }
    }
}

?

?

2. Unity提供的CG/HLSL语义

2.1. 什么是语义

语义可以让Shader知道从哪里读取数据,并且把数据输出到哪里。

在DirectX 10以后,有了一种新的语义类型,就是系统数值语义(System-value semanties)。这类语义是以SV开头的,SV代表的含义就是系统数值(System-value)

使用SV_POSITION语义去修饰顶点着色器的输出变量pos,就表示pos包含了可用于光栅化的变换后的顶点坐标,用这里语义描述的变量是不可以随便赋值的,因为流水线需要使用它们来完成特定目的。

官方文档语义说明:着色器语义 - Unity 手册

2.2. Unity中的语义总结

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

?

c6a3680efa6931f4445410fa61febdd0.jpeg

2.2.2. 从顶点着色器传递数据给片元着色器时Unity使用的常用语义

?

74d9ff61c9537e77a91d2442d4688713.jpeg

?

?

?

2.3. 在程序中使用语义

struct v2f{
	float4 pos : SV_POSITION;
	fixed3 color0 : COLOR0;
	fixed4 color1 : COLOR1;
	half value0 :  TEXCOORD0;
	float2 value1 : TEXCOORD1;
}

2.4. Shader语义差异

在某些平台上SV_POSITIONPOSITION是等价的,但在某些平台上不等价。尽量使用下面的语义描述Shader的输入输出变量:

  • 使用SV_POSITION描述顶点着色器输出的顶点位置。
  • 使用SV_TARGET描述片元着色器的输出颜色。

?

3. 关于调试工具

3.1. 内部调试工具

  • Frame Debugger

具体使用参考官方链接:Frame Debugger window reference - Unity 手册

3.2. 其他调试工具

具体可以搜索一下相关工具名称和使用方法,本文不在赘述。

  • Graphics Debugger
  • Intel GPA
  • RenderDoc
  • NVIDIA NSight
  • AMD GPU PrefStudio

4. 总结

本文中我们了解了Unity的语义和内置包含文件,以及内置包含文件如何使用,并简单介绍了关于Unity的调试工具,接下来我们将开始学习Unity中的基本光照模型,学习如何在Unity中实现简单的局部光照效果。

最后,非常感谢您能看到这里,如果该文章对你有所帮助和启发,也欢迎您能点赞👍支持,如果有任何疑问和优化建议也非常欢迎各位大佬能够在评论区友好交流,一起学习进步。

?

文章来源:https://blog.csdn.net/qq_44261945/article/details/135686446
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。