8.光照模型(兰伯特光照模型)

什么是光照模型?

光照模型就是一个公式,使用这个公式来计算在某个点的光照效果。

 

标准光照模型

在标准光照模型里,我们把进入摄像机的光分为下面几个部分

  1. 自发光(Self-luminous)(如萤火虫)
  2. 高光反射(Specular)
  3. 漫反射(Diffuse)
  • Diffuse = 直射光颜色 * max(0,cosθ(光和法线夹角))     这个max 后面的0其实就是夹角大于90度的时候当做90度来处理。
  • cosθ = 光的向量 · 顶点的法线 (向量的点乘)

向量点乘和叉乘

点乘:(标量)代表a在b上的投影和b的乘积

a · b = |a| |b| cosθ

叉乘:   (矢量)  a和b为邻边的平行四边形的面积

a × b = |a| |b| sinθ

Tags { "LightMode"="ForwardBase" }    只有定义正确的LightMode才能得到一些Unity的内置光照变量

#include “Lighting.cginc”   包含Unity内置的文件,这样才可以使用unity内置的一些变量

 

 

模拟漫反射:

1. 逐顶点光照(在shader顶点函数中使用漫反射公式)

片元函数里传进的color值后在顶点函数后进行差值运算传进来

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
Shader "Custom/MyDiffuseShader-Vert"
{
    Properties
    {
        _Diffuse("Diffuse color",Color) = (1,1,1,1)
    }  
    SubShader
    {      
        pass
        {
            Tags { "LightMode"="ForwardBase" }
            //_LightColor0 取得第一个直射光的颜色
            //_WorldSpaceLightPos0 第一个直射光的位置
            CGPROGRAM
            #include "Lighting.cginc"
            #pragma vertex vert
            #pragma fragment frag
            fixed4 _Diffuse;
            struct a2v
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
            };
            struct v2f
            {
                float4 pos:SV_POSITION;
                fixed3 color:color;
            };
            v2f vert(a2v i)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(i.vertex);
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//获取环境光
                fixed3 normalDir = normalize(mul(i.normal,(float3x3)unity_WorldToObject));  //这个矩阵把一个方向从世界空间转换到模型空间  这样放在后面就是模型到世界了
                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说光的位置就是光的方向,因为光是平行的。
                fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir,lightDir),0) * _Diffuse;//取得漫反射的颜色
                o.color = diffuse + ambient;
                return o;
            }
            float4 frag(v2f i):SV_TARGET
            {
                return fixed4(i.color,1);
            }
            ENDCG
        }
    }
}

这里有一点是漫反射时候计算的diffuse是物体的颜色和漫反射光的颜色相乘,而最后的环境光却是相加的

可能环境光的影响更大点把。且可能盖过主体色,漫反射光则是和主体色相互融合。

 

2. 逐片元光照(片元函数中使用漫反射公式)

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
Shader "Custom/MyDiffuseShader-Frag"
{
    Properties
    {
        _Diffuse("Diffuse color",Color) = (1,1,1,1)
    }  
    SubShader
    {      
        pass
        {
            Tags { "LightMode"="ForwardBase" }
            //_LightColor0 取得第一个直射光的颜色
            //_WorldSpaceLightPos0 第一个直射光的位置
            CGPROGRAM
            #include "Lighting.cginc"
            #pragma vertex vert
            #pragma fragment frag
            fixed4 _Diffuse;
            struct a2v
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
            };
            struct v2f
            {
                float4 pos:SV_POSITION;
                fixed3 worldNormalDir:color;
            };
            v2f vert(a2v i)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(i.vertex);
                o.worldNormalDir = mul(i.normal,(float3x3)unity_WorldToObject);
                return o;
            }
            float4 frag(v2f i):SV_TARGET
            {
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//获取环境光
                fixed3 normalDir = normalize(i.worldNormalDir);  //这个矩阵把一个方向从世界空间转换到模型空间  这样放在后面就是模型到世界了
                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说光的位置就是光的方向,因为光是平行的。
                fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir,lightDir),0) * _Diffuse;//取得漫反射的颜色
                fixed3 tempColor = diffuse + ambient;
                return fixed4(tempColor,1);
            }
            ENDCG
        }
    }
}

 

  1. 相比两种方式逐片元的方式表现效果更好
  • 因为像素个数比顶点来的要多,逐顶点方式的像素颜色是由顶点颜色进行差值得来的。
  1. 性能方面肯定是逐顶点的要好的。

 

对比如下

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值