13.表面着色器法线贴图

13.表面着色器-实例分析-法线贴图


13.1 知识点

在表面着色器中使用法线贴图

主要步骤

  • 新建表面着色器
  • 删除无关代码
  • 声明相关属性
  • 检查编译指令
  • 编写相关逻辑

创建表面着色器,删除无关代码

Shader "Custom/Lesson13"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        Tags
        {
            "RenderType"="Opaque"
        }

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        fixed4 _Color;


        void surf(Input IN, inout SurfaceOutputStandard o)
        {
        }
        ENDCG
    }
    FallBack "Diffuse"
}

声明法线贴图属性,并进行映射

// 定义材质属性,在 Inspector 面板中显示
Properties
{
    //...
    _BumpMap("BumpMap", 2D) = ""{}                // 法线贴图
}
sampler2D _BumpMap;

检查编译指令

#pragma surface surf Standard fullforwardshadows  // 使用标准光照模型和全前向阴影
#pragma target 3.0                                  // 指定 Shader 模型 3.0

在输入结构体中添加反映纹理 UV:

// 输入结构体:包含顶点传来的 UV 坐标
struct Input
{
    float2 uv_MainTex;
    float2 uv_BumpMap;
};

编写表面函数,设置基础颜色、漫反射颜色、透明度及切线空间下的法线

// 表面函数:计算最终材质效果
void surf(Input IN, inout SurfaceOutputStandard o)
{
    // 从主纹理采样基础颜色
    fixed4 texColor = tex2D(_MainTex, IN.uv_MainTex);
    
    // 漫反射颜色(纹理颜色 × 基础颜色)
    o.Albedo = texColor.rgb * _Color.rgb;
    
    // 透明度计算(纹理颜色 × 基础颜色)
    o.Alpha = texColor.a * _Color.a;
    
    // 从法线贴图解包法线,得到切线空间下的法线
    o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}

可以看到效果

输出结构体相关参数的使用

我们可以用 SurfaceOutputStandard 的发光程度、金属度和平滑度来举例。

设置发光属性并添加映射

Properties
{
    _Color ("Color", Color) = (1,1,1,1)                   // 基础颜色
    _MainTex ("Albedo (RGB)", 2D) = "white" {}              // 颜色纹理
    _BumpMap("BumpMap", 2D) = "{}"                          // 法线贴图
    _Emission("Emission", Color) = (1,1,1,1)                // 发光
    _Metallic("Metallic", Range(0,1)) = 0                   // 金属度
    _Smoothness("Smoothness", Range(0,1)) = 0               // 平滑度
}
fixed4 _Emission;
fixed _Metallic;
fixed _Smoothness;

修改表面函数,设置发光效果、金属度和平滑度

// 表面函数:计算最终材质效果
void surf(Input IN, inout SurfaceOutputStandard o)
{
    // 从主纹理采样基础颜色
    fixed4 texColor = tex2D(_MainTex, IN.uv_MainTex);
    
    // 漫反射颜色(纹理颜色 × 基础颜色)
    o.Albedo = texColor.rgb * _Color.rgb;
    
    // 透明度计算(纹理颜色 × 基础颜色)
    o.Alpha = texColor.a * _Color.a;
    
    // 从法线贴图解包法线,得到切线空间下的法线
    o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    
    // 设置发光效果、金属度和平滑度
    o.Emission = _Emission.rgb;
    o.Metallic = _Metallic;
    o.Smoothness = _Smoothness;
}

查看效果



13.2 知识点代码

Lesson13.shader

Shader "Custom/Lesson13"
{
    // 定义材质属性,在Inspector面板中显示
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1) // 基础颜色
        _MainTex ("Albedo (RGB)", 2D) = "white" {} // 颜色纹理
        _BumpMap("BumpMap", 2D) = ""{} // 法线贴图

        _Emission("Emission", Color) = (1,1,1,1) // 发光
        _Metallic("Metallic", Range(0,1)) = 0 // 金属度
        _Smoothness("Smoothness", Range(0,1)) = 0 // 平滑度
    }
    SubShader
    {
        Tags
        {
            "RenderType"="Opaque"
        } // 设置为不透明材质

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows  // 使用标准光照模型和全前向阴影
        #pragma target 3.0                                 // 指定Shader模型3.0

        // 声明属性变量
        fixed4 _Color;
        sampler2D _MainTex;
        sampler2D _BumpMap;

        fixed4 _Emission;
        fixed _Metallic;
        fixed _Smoothness;

        // 输入结构体:包含顶点传来的UV坐标
        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpMap;
        };

        // 表面函数:计算最终材质效果
        void surf(Input IN, inout SurfaceOutputStandard o)
        {
            // 从主纹理采样基础颜色
            fixed4 texColor = tex2D(_MainTex, IN.uv_MainTex);

            // 漫反射颜色(纹理颜色×基础颜色)
            o.Albedo = texColor.rgb * _Color.rgb;

            // 透明度计算 (纹理颜色×基础颜色)
            o.Alpha = texColor.a * _Color.a;

            // 从法线贴图解包法线 得到切线空间下的法线
            o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));

            // 设置 发光效果 金属度和平滑度
            o.Emission = _Emission.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Smoothness;
        }
        ENDCG
    }
    FallBack "Diffuse" // 当该Shader无法使用时采用Diffuse Shader
}

Lesson13_表面着色器_实例分析_法线贴图.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson13_表面着色器_实例分析_法线贴图 : MonoBehaviour
{
    void Start()
    {
        #region 知识点一 在表面着色器中使用法线贴图

        //1.新建表面着色器
        //2.删除无关代码
        //3.声明相关属性
        //4.检查编译指令
        //5.编写相关逻辑

        #endregion

        #region 知识点二 输出结构体相关参数的使用

        //我们可以用SurfaceOutputStandard来举例

        #endregion
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏