《Unity Shader入门精要》笔记:初级篇(1)

2022-09-21 14:44:00 浏览数 (1)

  • 本篇博客主要为个人学习所编写读书笔记,不用于任何商业用途,以及不允许任何人以任何形式进行转载。

  • 本篇博客会补充一些扩展内容(例如其他博客链接)
  • 本篇博客还会提供一些边读边做的效果截图。文章内所有数学公式都由Latex在线编辑器生成。
  • 本篇博客主要提供一个“glance”,知识点的总结。如有需要请到书店购买正版。
  • 博客提及所有官方文档基于2022.2版本,博客会更新一些书中的旧的知识点到2022.2版本。
  • 如有不对之处欢迎指正。
  • 我创建了一个游戏制作交流群:637959304 进群密码:(CSGO的拆包密码)欢迎各位大佬一起学习交流,不限于任何平台(U3D、UE、COCO2dx、GamesMaker等),以及欢迎编程,美术,音乐等游戏相关的任何人员一起进群学习交流。

  • 初级篇内容主要讲述关于基础的光照模型、纹理和透视等的初级渲染效果。(这部分也可以同时阅读我的HLSL博客内容进行学习)

UnityShader入门

  • 最简单的顶点/片元着色器:
代码语言:javascript复制
Shader "name"
{
        Properties
        {
                //属性
        }

        SubShader
        {
                Pass
                {
                        //设置渲染状态和标签
                        //开始CG代码片段
                        CGPROGRAM
                        //编译指令
                        #pragma vertex vert
                        #pragma fragment frag

                        //CG代码

                        ENDCG
                        //其他设置
                }
                //其他pass
        }
        //其他的SubShader

        //如果SubShader都失败了
        Fallback “VertexLit”
}
  • 第一个代码
  • 关于’:’语法,可以理解为一种限制,或条件。例如: SV_POSITION是限制函数只能输出裁剪空间的坐标,也可以换一种角度理解,限制->通知,告知Unity要输出的是裁剪空间坐标。
代码语言:javascript复制
shader "Example/Shader01"
{
        SubShader
        {
                Pass
                {
//CG代码片段
                        CGPROGRAM
//告诉Unity哪个函数包含了顶点着色器代码,哪个函数包含片元着色器代码
                        #pragma vertex vert
                        #pragma fragment frag
//POSITION把顶点坐标填入到V中,SV_POSITION顶点着色器输出的是裁剪空间中的坐标
                        float4 vert(float 4 v : POSITION) : SV_POSITION
                        {
                                return mul (UNITY_MATRIX_MVP,v);
                        
                        }

                        fixed4 frag() : SV_Target
                        {
                                return fixed4(1.0,1.0,1.0,1.0);
                        }
                        ENDCG
                }
        }
 }

材质,Shader

游戏内物体(CUBE)

效果

  • 活学活用: return fixed4(1.0,1.0,0.5,1.0);时的效果。有时候要刷新一下材质才能显示出效果。
  • 注意有一条语句语法进行了更新:Upgrade NOTE: replaced ‘mul(UNITY_MATRIX_MVP,*)’ with ‘UnityObjectToClipPos(*)’
  • 我们利用结构体来存储模型的法线,纹理坐标等信息。
代码语言:javascript复制
Pass
{
        CGPROGRAM

        #pragma vertex vert
        #pragma fragment frag
//输入结构体
        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.xyz);
//根据法线向量v.normal来改变颜色
                o.color = v.normal * 0.5   fixed3(0.5,0.5,0.5);
                 return o;
        }

        fixed4 frag(v2f i) : SV_Target
        {
                return fixed4(i.color,1.0);
                }
        ENDCG
}

你别说还蛮好看的

  • 属性设置:设置一个颜色的properties让用户自定义颜色。
代码语言:javascript复制
shader "Example/Shader01"
{
//自定义用户面板
    Properties
    {
        _Color ("Color Tint",Color) = (1.0,1.0,1.0,1.0)
    }

    SubShader
    {
        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            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.xyz);
                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;
//让用户面板中的颜色来决定顶点输出的颜色
                c *= _Color.rgb;
                return fixed4(c,1.0);
            }
            ENDCG
        }
    }
}
  • ShaderLab属性类型和CG变量类型的匹配关系

ShaderLab属性类型

CG变量类型

Color,Vector

float4,half4,fixed4

Range,Float

float,half,fixed

2D

sampler2D

Cube

samplerCube

3D

sampler3D

  • 数值类型:精度范围在不同平台可能会略有不同

类型

精度

float

32位

half

16位,范围: -60 000

fixed

11位,范围: -2.0

  • Unity内置文件和变量:传送门,UnityShader提供了一些内置文件(具体见官方手册),可以不适用include进行头文件包含,Unity会自动加安策处理。
  • 内置着色器变量:传送门
  • CG/HLSL语义:语义可以让Shader知道从哪里读取数据(例如:COLOR0)。即使语义相同,位置不同表达的意思也会不同。DirectX10以后新的语义类型:系统数值语义(system-value semantics),以SV为开头,代表系统数值。有些时候(例如POSITION和SV_POSITION)语义可以不加SV开头,但如果考虑跨平台的工程,那么最好在能加SV的地方把SV加上去。
  • 从应用阶段传递模型数据给顶点着色器时的常用语义:

语义

描述

POSITION

模型空间顶点位置,float4

NORAML

顶点法线,float3

TANGENT

顶点切线,float4

TEXCOORD0-7

寄存器类似于,存放坐标等。float2或float4

COLOR

顶点颜色,fixed4或float4

  • 从顶点着色器传递数据给片元着色器时的常用语义:

语义

描述

SV_POSITION

裁剪空间中的顶点坐标,必要语义

COLOR0、COLOR1

通常用于输出第一、二组顶点颜色

TEXCOORD0-7

通常用语输出纹理坐标

  • 片元着色器输出时的常用语义

语义

描述

SV_Target

输出值存储到渲染目标中,等同于DirectX9中的COLOR

  • 调试:Unity中自带UnityShader的调试,在Windows->Analysis->Frame Debugger中(与书中当时的位置稍有不同)。如果想要看到更多的信息,可以在VS等IDE中寻找相关插件。

  • 额外补充-代码数学规范: 1、规范化语法 2、避免不必要的计算 3、慎用分支和循环语句(因为开销大) 4、不要除以0

0 人点赞