【光照】[漫反射]UnityURP兰伯特有光照衰减吗?

news/2025/9/20 4:51:15/文章来源:https://www.cnblogs.com/SmalBox/p/19101944

【从UnityURP开始探索游戏渲染】专栏-直达

光照衰减的基本原理

在物理正确的光照模型中,衰减需要遵循两个基本定律:

  • 平方反比定律‌:光强与距离平方成反比 (I ∝ 1/r²)
  • 余弦定律‌:表面接收的光强与入射角余弦成正比 (I ∝ cosθ)

经典兰伯特模型的衰减处理

标准兰伯特公式

$漫反射 = 表面颜色 * 表面反照率 * max(0, N·L)$

衰减实现分析

  • 角度衰减‌:
    • ✅ 正确实现余弦定律
    • 通过 N·L 点积计算入射角衰减
    • 符合物理规律:光线入射角越大,光照强度越小
  • 距离衰减‌:
    • ⚠️ ‌完全缺失距离衰减计算
    • 公式中没有包含光源距离(r)相关项
    • 光强不会随距离增加而减弱
    • 导致物理不准确性

Unity URP中的实现方案

距离衰减补偿机制

URP通过额外计算衰减因子来弥补兰伯特的不足:

hlsl
// URP光源获取函数 (Lighting.hlsl)
Light GetMainLight()
{Light light;light.direction = _MainLightPosition.xyz;// 距离衰减计算float distance = length(_WorldSpaceCameraPos - positionWS);light.distanceAttenuation = 1.0 / max(distance * distance, 0.01);light.color = _MainLightColor.rgb;return light;
}// 主光源 漫反射计算
lightingData.mainLightColor += CalculateBlinnPhong(mainLight, inputData, surfaceData);half3 CalculateBlinnPhong(Light light, InputData inputData, SurfaceData surfaceData)
{
// 这里通过颜色计算了光线衰减half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);half3 lightDiffuseColor = LightingLambert(attenuatedLightColor, light.direction, inputData.normalWS);half3 lightSpecularColor = half3(0,0,0);#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)half smoothness = exp2(10 * surfaceData.smoothness + 1);lightSpecularColor += LightingSpecular(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, half4(surfaceData.specular, 1), smoothness);#endif#if _ALPHAPREMULTIPLY_ONreturn lightDiffuseColor * surfaceData.albedo * surfaceData.alpha + lightSpecularColor;
#elsereturn lightDiffuseColor * surfaceData.albedo + lightSpecularColor;
#endif
}

URP衰减系统组成

光源类型处理‌:

  • 平行光:无距离衰减 (1.0)
  • 点光源:平方反比衰减 (1/r²)
  • 聚光灯:角度衰减 × 距离衰减

优化策略‌:

  • 使用预计算的衰减纹理
  • 最大距离截断(light.range)
  • 平滑过渡边缘处理
graph TDA[光源类型] --> B{平行光?}B -->|是| C[衰减=1.0]B -->|否| D{点光源?}D -->|是| E[1/r²计算]D -->|否| F[聚光灯衰减曲线]E --> G[距离截断]F --> GG --> H[平滑过渡]

为什么经典兰伯特缺乏距离衰减

  • 历史设计局限‌:
    • 早期计算机图形学简化模型
    • 源自环境固定的CAD渲染需求
    • 仅考虑局部表面光照
  • 数学简化考量‌:
    • 减少每像素计算量
    • 避免昂贵的距离计算
    • 保持公式简洁性
  • 艺术导向设计‌:
    • 允许美术师手动控制光照范围
    • 避免距离导致的过度变暗
    • 更适合风格化渲染

URP的实用解决方案

衰减校正技术

  • 物理混合方案‌:

    hlsl
    half3 ApplyAttenuation(Light light, float3 positionWS)
    {// 基础平方反比衰减float dist = distance(light.position, positionWS);float atten = 1.0 / (dist * dist);// 范围平滑过渡float fade = saturate(1.0 - (dist / light.range));atten *= fade * fade;// 聚光灯角度衰减if(light.type == SPOT){float3 toLight = normalize(light.position - positionWS);float spotFactor = dot(toLight, light.direction);atten *= smoothstep(light.outerAngle, light.innerAngle, spotFactor);}return saturate(atten * light.intensity);
    }
    
  • 移动端优化版‌:

    hlsl
    half3 SimpleAttenuation(Light light, float3 positionWS)
    {// 使用预计算的衰减纹理float dist = distance(light.position, positionWS);float t = saturate(dist / light.range);half atten = SAMPLE_TEXTURE2D(_LightAttenuationTex, sampler_LinearClamp, float2(t, 0.5)).r;return atten * light.intensity;
    }
    

Unity编辑器中配置

csharp
// 光源组件属性设置
Light light = gameObject.AddComponent<Light>();
light.type = LightType.Point;
light.range = 10.0f;// 控制衰减范围
light.intensity = 1.0f;// 控制最大强度
light.color = Color.white;

结论与建议

核心结论

  • 经典兰伯特模型自身不包含距离衰减‌,仅有角度衰减
  • URP通过外部衰减系统提供完整衰减支持‌,使经验模型实用化
  • 现代实现已接近物理正确‌,但仍有可控的艺术化调整空间

开发实践建议

  • 性能敏感场景‌:

    hls
    // 使用简化距离衰减
    float atten = saturate(1.0 - distance/range);
    
  • 高品质渲染‌:

    hlsl
    // 物理精确衰减
    float atten = 1.0 / (distance * distance + 1e-5);
    
  • 风格化渲染‌:

    hlsl
    // 自定义衰减曲线
    float atten = exp(-_Falloff * distance);
    

在URP中,虽然经典兰伯特模型本身不具备完整的物理衰减特性,但通过引擎层的光照系统补偿,开发者可以轻松实现物理正确的衰减效果,同时保留艺术控制自由度。这种分层设计正是现代渲染管线的实用智慧体现。


【从UnityURP开始探索游戏渲染】专栏-直达

(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/908177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手把手带你从零开始实现一个编译器

手把手带你从零开始实现一个编译器https://www.cnblogs.com/abinzhao/p/18748462其实我之前写过关于编译器方面的文章,昨天写了一篇关于通过自制适合自己的JavaScript语法的文章,但是被某个掘友说不懂编译,误人子弟…

prenotami.esteri.it 意大利签证预约error

可以尝试重新登录一下账号,可能会好

绯闻女孩不只会八卦:从“验明正身”到“抓内鬼”,Gossip的进阶玩法

绯闻女孩不只会八卦:从“验明正身”到“抓内鬼”,Gossip的进阶玩法默克尔树 默克尔树(Merkle Tree)是由计算机科学家Ralph Merkle多年前提出,并以他本人的名字来命名,也叫哈希树。默克尔树是一种树形数据结构,通…

reLeetCode 热题 100- 15. 三数之和 - MKT

reLeetCode 热题 100- 15. 三数之和1 排序 2 双指针 位置卡死逐步对着移动 左右2个指针 3 while 跳过重复的数 双指针class Solution { public:vector<vector<int>> my_test1(vector<int>& nums…

US$94 T300 Key Programmer Spanish Blue 2016 V16.8 Full

T300 Key Programmer Spanish 2016 V16.8 Full BlueNotice: 1. It Cant Do Ford, GM and Holden2. In order to make the pacakge easy to pass through customs, we dont take the case into the package to make the…

US$99 VVDI MB NEC Key Adaptor

VVDI MB NEC Key AdaptorNEC Key Adaptor Support Versions:(Without soldering/ Without wire jumper/ Not need other adaptor)Updating support more versionsSupport v51 v57 get password directlySupport normal…

testuserpython

import json import boto3 import flask import psycopg2 from flask import request app = flask.Flask(name) @app.route(/) def route_root(): return flask.jsonify(OK) dynamodb = boto3.client(dynamodb) @app.r…

Python-Pathlib库

Pathlib 是 Python 3.4+ 中引入的面向对象的文件系统路径处理库,提供了比传统 os.path 更直观、更 Pythonic 的方式来处理文件路径和文件系统操作。Python Pathlib 库指南 Pathlib 是 Python 3.4+ 中引入的面向对象的…

反省

我大抵是废了、累了。

US$34 Bluetooth Adapter for Yanhua Mini ACDP

Bluetooth Adapter for Yanhua Mini ACDPPackage List:1pc x Bluetooth Adapter for Yanhua Mini ACDP Pictures of Bluetooth Adapter for Yanhua Mini ACDPBluetooth Adapter for Yanhua Mini ACDP, now only need U…

global 设置内核源码在线浏览

global 设置内核源码在线浏览获取内核源码放到http家目录 /var/www/html/linux-5.10.0-136.12.0.86.x86_64 下载编译global wget https://ftp.gnu.org/gnu/global/global-6.6.tar.gz tar xf global-6.6.tar.gz cd glob…

[Nacos/Docker/MCP] Nacos 3.x : 为 AI MCP 而生

0 序言 : Nacos 3.x 的发布2025年4月28日,Nacos 3.0 正式发布:MCP Registry、安全零信任、链接更多生态升级 MCP Registry,围绕着 MCP 服务管理,MCP 多种类型注册,包含 MCP Server 注册、编排、动态调试和管理,…

牛客周赛 Round 108 CDEF题解

C、小苯的数字合并 题意: 小苯有一个长度为 $ n $ 的数组 $ a_1, a_2, \ldots, a_n $,他可以对 $ a $ 进行任意次“数字合并”操作,具体地,一次数字合并操作描述为:选择一个下标 $ i $ ($ 1 \leq i < |a| $),…

[LeetCode] 3484. Design Spreadsheet

A spreadsheet is a grid with 26 columns (labeled from A to Z) and a given number of rows. Each cell in the spreadsheet can hold an integer value between 0 and 105. Implement the Spreadsheet class: Spre…

Redis的使用问题

1:穿透,访问缓存中没有,数据库中也没有的数据,直接忽略缓存层,直达数据库 解决方案:方案一,查一个不存在的数据时,给一个设置一定过期间的key的数据,存入缓存,方案二:布隆过滤器,在将数据存入Redis时,会同…

AIGC拾遗:Flash Attention

前言 对于attention操作,其计算复杂度随着序列长度的增加呈平方倍的增长。因此,出现了诸多尝试将计算复杂度降低为\(O(n)\)的注意力机制。然而,这些方法忽略了计算时的IO复杂度的影响,频繁的内存交换也在长序列计算…

深度好文-风雨飘摇信竞路

风雨飘摇信竞路 写作时间:2025.9.19夜 1. 引子 夜深了,我捣鼓好了博客园,长舒了一口气。 明天就是 CSP-S 的初赛了,上周老师说可能这次我们没有初赛直升的名额了,把我们搞得都很慌,做了不少卷子。明天早上我还要…

Python-CSV库

CSV (Comma Separated Values) 是电子表格和数据库中最常见的数据交换格式。Python 的 csv 模块提供了读写 CSV 文件的功能,支持多种 CSV 变体和自定义格式。Python CSV 库 1. 库概述 1.1 简介 CSV (Comma Separated …

C++小白修仙记_LeetCode刷题_位运算

位运算 (难度:easy) 231. 2 的幂 给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。 如果存在一个整数 x 使得 n == 2x ,则认为 n 是 2 的幂次方。 示例: 输入:n = 1 …

C++小白修仙记_LeetCode刷题_双指针

双指针(easy) 345. 反转字符串中的元音字母 给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。 元音字母包括 a、e、i、o、u,且可能以大小写两种形式出现不止一次。 示例: 输入:s = "Ic…