Shader中的光照模型(五)

【本系列文章系学习 唐福幸《Unity ShaderLab 新手宝典》的笔记,包含个人理解,如有错误欢迎批评指出

Shader中的光照模型


一句话总结
当场景中存在大量远处的物体需要光照渲染时(观察者和灯光离被照射物体非常远时),使用Blinn-Phong可以提高计算效率(待验证)

6.6 Blinn-Phong光照模型

在这里插入图片描述

在一些情况下,Phong模型要计算反射向量,计算效率会偏高,Jim Blinn对Phong光照模型进行改进:不再使用反射向量r计算,而是使用半角向量h代替r,视角方向v替换成法线向量n

计算公式为:
CSpecular = (Clight · MSpecular)saturate(n · h)M

  • CSpecular:物体的镜面反射颜色
  • Clight:灯光亮度
  • MSpecular:物体材质的镜面反射颜色
  • n:法线向量
  • h:半角向量:h=normalize(v+l)
  • M:物体材质的光泽度
Shader "Chapter6/BlinnPhong"
{
    Properties
    {
        _MainCol ("Main Color", Color) = (1,1,1,1)

        _SpecularColor("Specular Color",Color) = (0,0,0,0)
        _Shininess("Shininess",Range(1,100)) = 1
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityLightingCommon.cginc"

            struct v2f
            {
                float4 posi : SV_POSITION;//用于保存裁切空间位置信息
                float3 normal : TEXCOORD0;//传递法线向量信息
                float4 vertex : TEXCOORD1;//传递顶点信息
                //fixed4 diff : COLOR0;//也可以不要这个属性(会报警告),后面直接return,保留是因为便于理解改动
            };

            fixed4 _MainCol;
            fixed4 _SpecularColor;//控制高光颜色
            half _Shininess;//物体材质光泽度

            v2f vert (appdata_base v)
            {
                v2f o;
                o.posi = UnityObjectToClipPos(v.vertex);
                o.normal = v.normal;//获取世界空间法线向量需要的模型空间法线向量
                o.vertex = v.vertex;//后面计算反射需要用到的顶点信息
                return o;//将上面获取到的信息传递给逐像素光照
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //获取世界空间法线向量
                float3 n = UnityObjectToWorldNormal(i.normal);

                //世界空间灯光方向向量
                fixed3 L = normalize(_WorldSpaceLightPos0.xyz);

                //计算漫反射
                fixed ndotl = dot(n,L);
                fixed4 refCol = _LightColor0 * _MainCol * saturate(ndotl);

                //计算镜面反射
                视角方向
                fixed3 view = normalize(UnityWorldSpaceViewDir(i.vertex));
                光线反射方向,由于参数需要灯光指向顶点的方向,_WorldSpaceLightPos0得到顶点指向灯光方向,所以需要-1 * L
                float3 h = normalize(view + L);//修改部分
                公式
                fixed vr = saturate(dot(h,n));//修改部分
                fixed4 Cspe = _LightColor0 * _SpecularColor * pow(vr,_Shininess);

                return unity_AmbientSky + refCol + Cspe;
                //i.diff = unity_AmbientSky + refCol + Cspe;
                //return i.diff;
            }
            ENDCG
        }
    }
}

效果对比

在这里插入图片描述

在这里插入图片描述

当观察者和灯光离被照射物体非常远时,Blinn-Phong的计算效率要高于Phong,因为当两者很远的时候h可以被认为是常量,跟位置以及表面的曲率没关系,因此大大减少计算量。

在这里插入图片描述

### Shader 中支持的光照模型种类 #### 1. 兰伯特 (Lambert) 照明模型 Unity 提供了内置的兰伯特照明模型,该模型用于实现漫反射光照效果。当编写着色器并使用 `#pragma surface surf Lambert` 编译指令时,会调用 Unity 实现的标准兰伯特光照算法[^1]。此模型遵循兰伯特定律,即反射光线强度与表面法线和光源方向之间的夹角余弦值成正比[^4]。 #### 2. Blinn-Phong 照明模型 除了兰伯特模型外,Unity 还提供了 Blinn-Phong 模型作为另一种选择。这种模型不仅考虑了漫反射成分,还加入了镜面高光部分来模拟光滑表面上更集中的反光现象。通过调整参数可以控制高光区域大小及其亮度。 #### 3. 环境光遮蔽 (Ambient Occlusion, AO) 虽然严格意义上不属于传统意义上的光照模型,但在现代图形渲染管线中扮演重要角色。AO 是一种技术手段用来增强场景的真实感,特别是对于物体间接触处产生的暗影效果尤为显著。它能够有效模拟由于周围几何结构阻挡而导致局部光照减少的情况,在提升画质方面有着不可替代的作用[^2]。 ```cpp // 计算世界空间视图方向,并确保其为单位向量 float3 viewDir = normalize(WorldSpaceViewDir(i.worldPos)); ``` 上述代码展示了如何利用 Unity 内置函数 `WorldSpaceViewDir()` 来获得观察者相对于片段位置的世界坐标系下的视线方向向量;需要注意的是返回的结果并非总是标准化后的形式,因此建议显式执行一次规范化操作以保证后续计算准确性[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值