找回密码
 立即注册
查看: 239|回复: 0

【Unity3D】顶点和片段着色器

[复制链接]
发表于 2023-1-5 12:10 | 显示全部楼层 |阅读模式
1 前言

    上文介绍了渲染管线、固定管线着色器和表面着色器,如下:

  • 渲染管线
  • 固定管线着色器一
  • 固定管线着色器二
  • 表面着色器
    固定管线着色器通过命令方式实现光照和贴图等效果,表面着色器通过给 SurfaceOutput 赋值实现光照、贴图和法线贴图等效果,它们都不用关注光照算法是如何实现的,只需要传值就行。
    顶点和片段着色器给用户提供了更灵活的用法,但使用也更困难。另外,顶点着色器可以通过控制 MVP 矩阵变换实现对模型位置和姿态的控制。
2 固定颜色

    在 Assets 窗口右键,依次选择【Create→Shader→Standard Surface Shader】创建 Shader 脚本,实现固定颜色 Shader 代码如下:
    VFShader.shader
Shader "MyShader/VFShaderTest" {
    Properties
    {
        // 属性名 ("面板显示名称", 类型) = 默认值
        _MainColor ("显示颜色", Color) = (1, 0, 0, 1)
    }

    SubShader
    {
        Pass
        {
            CGPROGRAM // CG语言的开始
            // 编译指令 着色器名称 函数名称
            #pragma vertex vert // 顶点着色器, 每个顶点执行一次
            #pragma fragment frag // 片段着色器, 每个像素执行一次
            // 导入头文件
            #include "UnityCG.cginc"

            // 声明属性变量, 必须与外部属性变量名称一致
            fixed4 _MainColor;

            // 顶点着色器, 输入模型坐标, 输出屏幕坐标
            half4 vert(half4 vertexPos: POSITION): SV_POSITION
            {
                // 将模型坐标转换为屏幕坐标
                return UnityObjectToClipPos(vertexPos); // 等价于: mul(UNITY_MATRIX_MVP vertexPos)
            }

            // 片段着色器, 输入模型坐标, 输出像素颜色
            fixed4 frag(): COLOR
            {
                return _MainColor;
            }

            ENDCG // CG语言的结束
        }
    }

    FallBack "Diffuse"
}
    创建一个 Material,并将 ShaderTest 绑定到该 Material 上,如下:


     将该 Material 拖拽到一个 Cube 和 Sphere 游戏对象上。选中绑定的 Material,在 Inspector 窗口调整 Shader 中固定颜色,显示效果如下:


3 光照

    VFShader.shader
Shader "MyShader/VFShaderTest" {
    Properties
    {
        // 属性名 ("面板显示名称", 类型) = 默认值
        _DiffuseColor ("漫反射颜色", Color) = (1, 0, 0, 1)
    }

    SubShader
    {
        Pass
        {
            Tags {"LightMode"="ForwardBase"}
            CGPROGRAM // CG语言的开始
            // 编译指令 着色器名称 函数名称
            #pragma vertex vert // 顶点着色器, 每个顶点执行一次
            #pragma fragment frag // 片段着色器, 每个像素执行一次

            // 导入头文件
            #include "UnityCG.cginc"

            // 声明属性变量, 必须与外部属性变量名称一致
            fixed4 _DiffuseColor;

            struct appdata // 顶点函数输入结构体
            {
                half4 vertexPos: POSITION; // 顶点坐标
                half3 vertexNormal: NORMAL; // 顶点法线向量
            };

            struct v2f // 顶点函数输出结构体
            {
                half4 screenPos: SV_POSITION; // 屏幕坐标
                half3 screenNormal: Normal; // 屏幕法线向量
            };

            // 顶点着色器, 输入模型坐标, 输出v2f
            v2f vert(appdata data)
            {
                v2f o;
                o.screenPos = UnityObjectToClipPos(data.vertexPos); // 等价于: mul(UNITY_MATRIX_MVP, data.vertexPos)
                o.screenNormal = mul(half4(data.vertexNormal, 1), unity_WorldToObject).xyz; // 将顶点法线转换为屏幕法线
                return o;
            }

            // 片段着色器, 输入模型坐标, 输出像素颜色
            fixed4 frag(v2f input): COLOR
            {
                half3 lightDir = normalize(_WorldSpaceLightPos0); <span class="c1">// 光源照射方向向量, 由顶点指向光源
                half3 normalDir = normalize(input.screenNormal);
                // return _DiffuseColor * saturate(dot(lightDir, normalDir)) + UNITY_LIGHTMODEL_AMBIENT; // Lambert光照模型
                return _DiffuseColor * (0.5 * dot(lightDir, normalDir) + 0.5) + UNITY_LIGHTMODEL_AMBIENT; // 半Lambert光照模型
            }

            ENDCG // CG语言的结束
        }
    }

    FallBack "Diffuse"
}
    选中绑定的 Material,在 Inspector 窗口调整 Shader 中光照颜色,显示效果如下:


4 贴图

    VFShader.shader
Shader "MyShader/VFShaderTest" {
    Properties
    {
        // 属性名 ("面板显示名称", 类型) = 默认值
        _MainTex ("2阶贴图", 2D) = "white" {}
    }

    SubShader
    {
        Pass
        {
            Tags {"LightMode"="ForwardBase"}
            CGPROGRAM // CG语言的开始
            // 编译指令 着色器名称 函数名称
            #pragma vertex vert // 顶点着色器, 每个顶点执行一次
            #pragma fragment frag // 片段着色器, 每个像素执行一次

            // 导入头文件
            #include "UnityCG.cginc"

            // 声明属性变量, 必须与外部属性变量名称一致
            sampler2D _MainTex;

            struct appdata // 顶点函数输入结构体
            {
                half4 vertexPos: POSITION; // 顶点坐标
                half2 uv_MainTex: TEXCOORD0; // 纹理uv坐标
            };

            struct v2f // 顶点函数输出结构体
            {
                half4 screenPos: SV_POSITION; // 屏幕坐标
                half2 uv_MainTex: TEXCOORD0; // 纹理uv坐标
            };

            // 顶点着色器, 输入模型坐标, 输出v2f
            v2f vert(appdata data)
            {
                v2f o;
                o.screenPos = UnityObjectToClipPos(data.vertexPos); // 等价于: mul(UNITY_MATRIX_MVP, data.vertexPos)
                o.uv_MainTex = data.uv_MainTex;
                return o;
            }

            // 片段着色器, 输入模型坐标, 输出像素颜色
            fixed4 frag(v2f input): COLOR
            {
                return tex2D(_MainTex, input.uv_MainTex);
            }

            ENDCG // CG语言的结束
        }
    }

    FallBack "Diffuse"
}
    选中绑定的 Material,在 Inspector 窗口选择贴图图片,显示效果如下:


        声明:本文转自【Unity3D】顶点和片段着色器

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-16 02:20 , Processed in 0.093389 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表