美文网首页Unity开发《Unity Shader 入门精要》
Unity Shader 入门精要 | 第五章 开始 Unity

Unity Shader 入门精要 | 第五章 开始 Unity

作者: KomalZheng | 来源:发表于2019-11-18 18:53 被阅读0次

    欢迎前往个人博客 驽马点滴 和视频空间 哔哩哔哩-《挨踢日志》

    5.1 本书使用的软件和环境

    介绍 Unity Shader 的学习环境,开发平台、Unity 版本等信息。

    5.2 一个最简单的顶点/片元着色器

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

    Shader "Unity Shaders Book/Chapter 5/ Simple Shader" {
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                float4 vert(v: POSITION): SV_POSITION {
                    // return mul(UNITY_MATRIX_MVP, v);
                    // Unity Upgrade NOTE: replace 'mul(UNITY_MATRIX_MVP, *)' with 'UnityObjectToClipPos(*)'
                    return UnityObjectToClipPos(v);
                }
                fixed4 frag(): SV_Target {
                    return fixed4(1.0, 1.0, 1.0, 1.0);
                }
                ENDCG
            }
        }
    }
    

    几个点:

    1. Properties 属性不是必须的(方便材质面板中友好的用户显示);
    2. 顶点/片元着色器的 CGPROGRAM 和 ENDCG 写在 Pass 中;
    3. '#pragma vertex' 和 '#pragma fragment frag' 属于编译指令,告诉 Unity 顶点着色器和片元着色器的代码包含在哪个函数中;
    4. POSITION 是 Cg/HLSL 中的语义,用来指明顶点坐标;
    5. SV_POSITION 也是 Cg/HLSL 中的语义,用来指明顶点着色器的输出是裁剪空间中顶点坐标;
    6. mul(UNITY_MATRIX_MVP, v) 将顶点坐标变换到裁剪空间中(在第四章数学基础中已知),该使用方法,在新版本的 Unity 中,已替换成 UnityObjectToClipPos(v);
    7. SV_Target 是 HLSL 中的语义,它告诉渲染器把用户的输出颜色存储到一个渲染目标(Render Target)中;
    8. 片元着色器返回 fixed4 类型的变量,每个分量在 [0, 1] 中取值,[0, 0, 0] 表示黑色,[1, 1, 1] 表示白色;

    上述 Shader 中,传入顶点着色器的只有顶点的位置 POSITION,而我们知道,顶点还记录了其他的信息,比如 法线、纹理坐标、颜色等等。为了获得这些的数据,该如何做呢?因此引出下一节的内容,定义一个结构体,给顶点着色器传入更多的数据。

    5.2.2 模型数据从哪里来

    我们想获取顶点的法线和纹理坐标信息,因此将 Shader 改写如下:

    Shader "Unity Shaders Book/Chapter 5/ Simple Shader" {
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert 
                #pragma fragment frag 
    
                struct a2v {
                    float4 vertex : POSITION;
                    float3 normal : NORMAL;
                    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
            }
        }
    }
    

    其中:

    1. struct 书写格式需要注意,结构体的定义在末尾需要加分号;
    2. a2v 的意思是应用程序数据转为顶点数据(application data to vertex data);
    3. 结构体中,声明 float4 vertex : POSITION ,那么 Unity 会将顶点数据自动填充到 vertex 变量中;声明 float3 normal: NORMAL,那么 Unity 会将法线数据自动填充到 normal 变量中;声明 float4 texcoord: TEXCOORD0, Unity 会将第一个纹理坐标填充到 texcoord 变量中;

    5.2.3 顶点着色器和片元着色器之间如何通信

    1. 定义从顶点着色器输出的数据结构 v2f;
    2. 片元着色器中,将 v2f 对象作为参数传入;
    Shader "Unity Shaders Book/Chapter 5/ Simple Shader" {
        SubShader {
            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);
                   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
            }
        }
    }
    

    注意点:

    1. 顶点着色器输出结构中,必须包含一个变量,其语义为 SV_POSITION ;
    2. COLOR0 语义中的数据可以由用户自己定义,一般存储颜色(如漫反射颜色或者高光反射颜色);
    3. 片元着色器中的输入,实际是将顶点着色器中的顶点数据进行插值后得到的结果;

    5.2.4 如何使用属性

    1. 在 Shader 的 Properties 中添加变量 _Color("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0);
    2. 在 CGPROGRAM 中定义同名变量 fixed4 _Color;
      3.在 frag 中使用该变量;
    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    Shader "Unity Shaders Book/Chapter 5/ Simple Shader" {
        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);
                    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
            }
        }
    }
    

    5.3 强大的援手:Unity 提供的内置文件和变量

    官方网站(http://unity3d.com/cn/get-unity/download/archive)上下载 Unity 的包含文件。

    Unity 中常用的包含文件:
    UnityCG.cginc ——包含了常用的帮助函数、宏和结构体;
    HLSLSupport.cginc ——声明了很多用于跨平台编译的宏和定义,编译 Unity Shader 时,会自动包含;
    UnityShaderVariables.cginc——包含了许多内置的全局变量,如 UNITY_MATRIX_MVP 等,编译 Unity Shader 时,会自动包含;
    Lighting.cginc ——包含各种内置光照,如果是 Surface Shader ,会自动包含进来。

    UnityCG.cginc 中包含的常用结构体:
    appdata_base:可用于顶点着色器的输入,包含顶点位置、顶点法线、第一组纹理坐标;
    appdata_tan: 可用于顶点着色器的输入,包含顶点位置、顶点法线、顶点切线、第一组纹理坐标;
    appdata_full: 可用于顶点着色器的输入,包含顶点位置、顶点法线、顶点切线、四组(或更多组)纹理坐标;
    appdata_img: 可用于顶点着色器的输入,包含顶点位置、第一组纹理坐标;
    v2f_img: 可用于顶点着色器的输出,包含裁剪空间中的位置、纹理坐标;

    一些帮助函数:(略)

    5.5 程序员的烦恼:Debug

    (略)主要通过输出颜色来调试,比较原始。

    欢迎前往个人博客 驽马点滴 和视频空间 哔哩哔哩-《挨踢日志》

    相关文章

      网友评论

        本文标题:Unity Shader 入门精要 | 第五章 开始 Unity

        本文链接:https://www.haomeiwen.com/subject/shdvictx.html