8.半兰伯特漫反射逐片元光照

8.光照模型-漫反射光照模型-半兰伯特光照模型-逐片元光照


8.1 知识点

利用半兰伯特光照模型实现光照效果(逐片元光照)

我们将实现半兰伯特光照模型的逐片元效果。该模型与兰伯特光照模型类似,唯一的区别在于计算颜色的公式。漫反射光照颜色的计算公式为:

漫反射光照颜色 = 光源的颜色 * 材质的漫反射颜色 * ((标准化后物体表面法线向量· 标准化后光源方向向量) * 0.5 + 0.5)

在片元函数中将计算颜色的公式修改为半兰伯特的实现即可

fixed4 frag(v2f i) : SV_Target
{
    //_WorldSpaceLightPos0.xyz 世界坐标系下光源方向 _WorldSpaceLightPos0是四维向量 只需要xyz即可
    //normalize 把向量归一化
    //lightDir 得到光源单位向量
    float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

    //_LightColor0光 照颜色
    //.rgb 代表只使用颜色进行计算 透明度不考虑 
    //color 计算出了半兰伯特光照的漫反射颜色
    fixed3 color = _LightColor0.rgb * _MainColor.rgb * (dot(i.normal, lightDir) * 0.5 + 0.5);

    //UNITY_LIGHTMODEL_AMBIENT.rgb 半兰伯特光照模型环境光变量
    //为了让背光的地方不至于是黑色 所以加上自带的漫反射颜色 看起来更加真实
    color = UNITY_LIGHTMODEL_AMBIENT.rgb + color;

    //返回color中的颜色 透明度传1
    return fixed4(color.rgb, 1);
}

进行对比

将完成的半兰伯特光照模型的着色器与之前的兰伯特光照模型进行对比,可以观察到两者在视觉效果上的细微差异。逐片元更光滑一些。


8.2 知识点代码

Lesson08_光照模型_漫反射光照模型_兰半伯特光照模型_逐片元光照

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

public class Lesson08_光照模型_漫反射光照模型_兰半伯特光照模型_逐片元光照 : MonoBehaviour
{
    void Start()
    {
        #region 知识点 利用半兰伯特光照模型实现光照效果(逐片元光照)

        //半兰伯特光照模型的逐片元实现
        //和兰伯特一模一样
        //唯一的区别就是公式
        //漫反射光照颜色 = 光源的颜色 * 材质的漫反射颜色 *((标准化后物体表面法线向量· 标准化后光源方向向量)* 0.5 + 0.5)

        #endregion
    }
}

Lesson08_Half_Lambert_Pixel.shader

Shader "Unlit/Lesson08_Half_Lambert_Pixel"
{
    Properties
    {
        //材质的漫反射光照颜色
        _MainColor("MainColor", Color) = (1,1,1,1)
    }
    SubShader
    {
        //设置我们的光照模式 ForwardBase这种向前渲染模式 主要是用来处理 不透明物体的 光照渲染的
        Tags
        {
            "LightMode"="ForwardBase"
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            //引用对应的内置文件 
            //主要是为了之后 的 比如内置结构体使用,内置变量使用
            #include "UnityCG.cginc"
            #include "Lighting.cginc"


            //材质漫反射颜色
            fixed4 _MainColor;

            //顶点着色器返回出去的内容
            struct v2f
            {
                //裁剪空间下的顶点位置
                float4 pos:SV_POSITION;
                //世界空间下的法线位置
                float3 normal:NORMAL;
            };


            v2f vert(appdata_base appdata_base)
            {
                //声明v2f 要传递给片元函数的
                v2f v2f;

                //UnityObjectToClipPos 把模型空间下的顶点转换到裁剪空间下
                v2f.pos = UnityObjectToClipPos(appdata_base.vertex);

                //appdata_base.normal 获取到在模型空间下的法线  
                //UnityObjectToWorldNormal 将法线从模型空间转换成世界空间 获取到相对于世界坐标系下的法线信息 
                v2f.normal = UnityObjectToWorldNormal(appdata_base.normal);
                return v2f;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                //_WorldSpaceLightPos0.xyz 世界坐标系下光源方向 _WorldSpaceLightPos0是四维向量 只需要xyz即可
                //normalize 把向量归一化
                //lightDir 得到光源单位向量
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

                //_LightColor0光 照颜色
                //.rgb 代表只使用颜色进行计算 透明度不考虑 
                //color 计算出了兰伯特光照的漫反射颜色
                fixed3 color = _LightColor0.rgb * _MainColor.rgb * (dot(i.normal, lightDir) * 0.5 + 0.5);

                //UNITY_LIGHTMODEL_AMBIENT.rgb 兰伯特光照模型环境光变量
                //为了让背光的地方不至于是黑色 所以加上自带的漫反射颜色 看起来更加真实
                color = UNITY_LIGHTMODEL_AMBIENT.rgb + color;

                //返回color中的颜色 透明度传1
                return fixed4(color.rgb, 1);
            }
            ENDCG
        }
    }
}


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

×

喜欢就点赞,疼爱就打赏