US3S1L6-1——Blinn-Phong式高光反射光照模型的逐顶点光照

知识回顾

公式:

高光反射光照颜色=光源的颜色×材质高光反射颜色×max(0, 标准化后顶点法线方向标准化后半角向量方向)光泽度高光反射光照颜色 = 光源的颜色 \times 材质高光反射颜色 \times \max(0,\ \overrightarrow{标准化后顶点法线方向} \cdot \overrightarrow{标准化后半角向量方向})^{光泽度}

  1. 标准化后顶点法线方向标准化后半角向量方向\overrightarrow{标准化后顶点法线方向} \cdot \overrightarrow{标准化后半角向量方向} 得到的结果就是 cosθ\cos\theta
  2. 半角向量方向=视角单位向量+入射光单位向量\overrightarrow{半角向量方向} = \overrightarrow{视角单位向量} + \overrightarrow{入射光单位向量}
  3. 光泽度是幂运算,假设光泽度为 nn ,相当于:(max(0,cosθ))n(max(0,\cos\theta))^n

利用Blinn-Phong式高光反射模型实现光照效果(逐顶点光照)

关键步骤

  1. 属性声明(材质高光反射颜色、光泽度)

    1
    2
    3
    4
    5
    Properties
    {
    _SpecularColor("SpecularColor", Color) = (1, 1, 1, 1) //材质高光反射颜色
    _SpecularNum("SpecularNum", Range(0, 20)) = 5 //光泽度
    }
  2. 渲染标签 Tags​ 设置将 LightMode​ 光照模式设置为 ForwardBase​ 向前渲染(通常用于不透明物体的基本渲染)

    1
    Tags { "LightMode" = "ForwardBase" }
  3. 引用内置文件 UnityCG.cginc​ 和 Lighting.cginc​

    1
    2
    #include "UnityCG.cginc"
    #include "Lighting.cginc"
  4. 结构体声明

    1
    2
    3
    4
    5
    struct v2f
    {
    float4 svPos : SV_POSITION;
    fixed3 color : COLOR;
    };
  5. 基本公式实现逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    fixed4 _SpecularColor;  //材质高光反射颜色
    float _SpecularNum; //光泽度

    v2f vert (appdata_base v)
    {
    v2f v2fData;
    v2fData.svPos = UnityObjectToClipPos(v.vertex); //首先将模型空间下的顶点转换到裁剪空间下

    float3 wNormal = UnityObjectToWorldNormal(v.normal); //得到世界空间下的法线向量
    float3 wPos = mul(unity_ObjectToWorld, v.vertex); //使用unity_ObjectToWorld矩阵,将模型空间下的顶点转换到世界空间下
    float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - wPos); //将摄像机坐标和顶点坐标通过相减,得到观察方向向量,并标准化
    float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); //得到世界空间下的指向光源方向的标准化向量
    float3 halfA = normalize(viewDir + lightDir); //将光源方向和观察方向相加得到其半角向量,并标准化
    //Blinn-Phong高光反射模型的实现,这里的颜色计算只取rgb,不考虑透明度的情况
    v2fData.color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(wNormal, halfA)), _SpecularNum);
    return v2fData;
    }

    fixed4 frag (v2f i) : SV_Target
    {
    return fixed4(i.color.rgb, 1); //因为传递过来的颜色变量不包括透明度,因此这里需要手动指定透明度
    }

显示效果(光泽度统一为5,左边为Blinn-Phong式高光反射模型的效果,右边为Phong式高光反射模型的效果):

image

可见,Blinn-Phong式高光反射模型比Phong式高光反射模型的高光效果更加均匀,面积也更大