惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
L
LangChain Blog
Y
Y Combinator Blog
Microsoft Security Blog
Microsoft Security Blog
宝玉的分享
宝玉的分享
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
Jina AI
Jina AI
D
Docker
B
Blog
Engineering at Meta
Engineering at Meta
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
I
InfoQ
G
Google Developers Blog
博客园 - Franky
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
大猫的无限游戏
大猫的无限游戏
阮一峰的网络日志
阮一峰的网络日志
U
Unit 42

音视频开发进阶

音视频教程-第三节 音视频教程-第二节 真的,AI 可能就是新时代的信息差 充值 Cursor 之后,工作有了哪些变化?🤔 个人'蒸馏'大模型能做哪些有意思的事情 DeepSeek 大模型在 Mac 上的部署和运行 音视频教程-第一节 【WebRTC 专栏】-- Android 开发集成 WebRTC 库的几种方式 【WebRTC 专栏】-- 在 Mac M1 等系列芯片编译和开发 WebRTC-Android 库 Meta Llama3 大模型在 Mac 上的部署和运行 iOS VideoToolBox 解码 HEVC Open-GOP 视频的问题排查 Flutter 状态管理之 InheritedWidget 使用和分析 用 ChatGPT 回答技术问题怎么样 ? 音视频开发系统入门大致路线 UE 4.27 添加自定义 ShadingModel 用 UE4 虚幻引擎做个捏脸小功能~~ UE4 材质练习 之 凹凸贴图偏移的使用 UE4 材质练习系列基础 OpenGL上下文创建以及共享机制 007 | 播放器系列专栏-解析 MP4 文件读取信息 006 | 播放器系列专栏-在 Mac 上查看 MP4 格式信息 干货 | 快速抽取缩略图是怎么练成的? 关于直播、WebRTC、FFmpeg 的那些事 005 | 播放器系列专栏-在 Windows 上查看 MP4 格式信息 将音视频中的花屏、绿屏、黑屏问题一网打尽 关于音视频里面的解码帧率和渲染帧率 004 | 播放器系列专栏-认识MP4视频(下) 003 | 播放器系列专栏-认识MP4视频(上) 入门或者转行音视频,应该要怎么做? H264视频文件如何缩放分辨率
Unity Shader 光照基础之 Half Lambert 光照模型
音视频开发进阶 · 2021-09-02 · via 音视频开发进阶

一个专注音视频领域的小圈子

Half Lambert 模型(也叫作半兰伯特模型)在 Lambert 模型的基础之上做了一些优化。 在 Lambert 模型中,光照无法到达的区域,比如模型的背面,模型外观通常是全黑的,没有任何明暗变化,而 Half Lambert 模型就是改善这一状况。 回顾 Lambert 模型的计算公式如下: $c_{diffuse} = (c_{light} \cdot m_{diffuse}) \cdot max (0,n \cdot I)$ 当光源和法向量夹角的余弦值为负数的时候,所得到的结果始终都是 0 了,所以就会有图中看到的一片黑。

Half Labmert 模型的计算公式如下:

$c_{diffuse} = (c_{light} \cdot m_{diffuse}) \cdot ( a (n \cdot I) + b)$

同样会计算余弦值,但是会把余弦值先缩放 a 倍,再偏移 b 大小,不再用 max 函数避免为负值。

绝大多数情况下,a 和 b 的值都是 0.5,所以也是为什么叫 half 了。

$c_{diffuse} = (c_{light} \cdot m_{diffuse}) \cdot ( 0.5 (n \cdot I) + 0.5)$

余弦值的取值范围是 [-1,1] ,经过缩放和偏移后就是 [0,1] 了,这样一来原本余弦值为负数导致直接取 0 的点,变成了取值结果在 [0,0.5] 了,从而就可以体现出明暗变化,不同的点积结果会映射到不同的值上。

对于 unity shader 的计算,也不会有太大的改变,主要如下:

fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);                
fixed halfLambert = dot(worldNormal,worldLight) * 0.5 + 0.5;

原本用 saturate 函数对点积结果做取值范围约束,现在直接通过映射来保证范围了。

具体的 shader 代码如下,以逐顶点着色为例:

Shader "Custom/HalfLambertShader"
{
   Properties
    {
        _Diffuse ("Diffuse",Color) = (1,1,1,1)
    }
    SubShader
    {
 
        Pass
        {
            Tags"LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            fixed4 _Diffuse;
            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            struct v2f
            {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR;
            };
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
                
                fixed halfLambert = dot(worldNormal,worldLight) * 0.5 + 0.5;
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert;
                o.color = ambient + diffuse;
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(i.color,1.0);
            }
            ENDCG
        }
    }
}

渲染效果如下:

可以看到 Half Lambert 模型在背面有了明显的亮暗变化。

同时 Half Lambert 模型在正面也会更加明亮一点。

小结

Half Lambert 模型在 Lambert 基础之上做了优化,而这正是应了图像渲染里面的那就话:如果看起来是对的,那么它就是对的

原创文章,转载请注明来源:    Unity Shader 光照基础之 Half Lambert 光照模型