Unity入门精要04(0)-更复杂的光照
创始人
2025-05-29 17:38:33
0

本书知识点是真的多(

1.渲染路径

Unity中的渲染路径有如下选项 

   

对某一Pass指定了渲染路径后,Unity会在过程中自动填充系统的变量,便于使用。

1.1 前向渲染路径

   前向渲染的伪代码如下

一句话概括前向渲染就是:对于每个光源在其范围能影响物体的都计算一次所有的Pass(除了Base Pass以外),计算完光照后再把计算结果叠加起来。

但这如果在多光源的情况下会造成极大的性能消耗。因此Unity通常会自动进行光照质量的限制,

当然也可以自己设置

 

 在Render Mode处如果设置为Important,那么该光源就是逐像素光源。

详细参考可见  ↓↓↓

Forward rendering path - Unity 手册 (unity3d.com)

1.2 前向渲染的两种Pass

  

关于编译指令可参考

Declaring and using shader keywords in HLSL - Unity 手册 (unity3d.com)

使用这些编译指令可以产生Shader变种

 Base Pass 最基础的Pass,一个Base Pass只会进行一次平行光和其它所有的逐顶点和SH光

使用方法:在第一个Pass中加入

Tags { "LightMode"="ForwardBase" }
#pragma multi_compile_fwdbase//加入此编译命令,可以使之后光照衰减所使用的变量可以被正确赋值
//即能在BasePass中访问到正确的光照变量

 在第二个Pass中写下

Tags { "LightMode"="ForwardAdd" }
Blend One One//多光源叠加要开启混合,具体的混合操作可以看透明效果实现的那篇文章
#pragma multi_compile_fwdadd//此编译命令表示该Pass是用来进行多光源叠加的
//效果同上

Additional Pass,会计算影响该物体的所有逐像素光源,每个光源都进行一次Pass.

为了使Additional Pass 能和Base Pass进行混合,我们开启了混合命令,具体的混合命令请看《Unity入门精要》中的透明效果部分。

效果如下,我们设置绿色的为平行光,红色的为点光源

在帧调试器的时候,渲染顺序是调用Base先渲染平行光,然后调用Additional点光源远近依次渲染 

1.3 逐像素,SH光源和顶点照明(已经被抛弃)

  逐像素比较简单,略过,着重记录一下SH光源(魔方工作室的面试考到过)

球谐函数就是一组分布在球上的函数,这恰好可以描述光照在一个物体上的光照。 

详细参考:球谐光照——球谐函数 - 知乎 (zhihu.com)

2.延迟渲染。

如果游戏中有大量的实时光照,那么用前向渲染消耗会非常大,因为每个光照都会计算所有的Additional Pass,出大问题(

延迟渲染似乎只能在URP和SRP中使用?(不太清楚)

那么什么是延迟渲染?

延迟渲染分为两个Pass,第一个Pass通道用来将信息存储在G缓冲区(实际上就是输出到一张渲染纹理上)中

然后再第二个Pass进行计算光照和进行合成

可以把延迟渲染想象成一个拼图游戏。首先,你需要把所有的拼图碎片(物体)按照一定的规则(投影)放到一个大的画板(缓冲区)上,每个碎片都有自己的颜色、形状、质感等信息。这个过程叫做几何渲染(geometry rendering)。

然后,你需要把一些灯泡(光源)放到画板上,每个灯泡都有自己的颜色、亮度、方向等信息。这个过程叫做光照渲染(light rendering)。

最后,你需要把画板上的所有碎片和灯泡的信息混合起来,形成一个完整的拼图(图像)。这个过程叫做合成渲染(composition rendering)。

因此在实时光照和大量光照中延迟渲染性能更优。但延迟渲染也是有缺点的,例如

·不能支持真正的抗锯齿(因为延迟渲染使用了非常多的缓冲区来储存信息,而缓冲区的分辨率一般是和屏幕空间不同的,如果相同的话,缓冲区会占用非常多的带宽)

·不能处理半透明(因为延迟渲染相比于前向渲染是将光照计算放在三维物体投影到二维纹理之后进行光照计算。而我们在进行延迟渲染过程中是需要G-buffer,而G-buffer只能处理最前面的混合后的像素,不能记录半透明物体后面的像素)

·对显卡有一定要求,显卡必须支持MRT

延迟渲染的具体操作方法:使用两个Pass,第一个Pass用于渲染G_Buffer,用来储存漫反射颜色,高光反射颜色,自发光,平滑度,法线,深度,金属度等信息渲染到基于屏幕空间下的G缓冲区

 如图所示,更详细的可见

LearnOpenGL - Deferred Shading

 第二个Pass来计算光照,默认情况下只能用Standard 光照模型,如果要用其它的,就要替换掉原有的Internal-DeferredShaing.shader文件

延迟渲染可以访问的内置变量和函数

 3.光源类型

平行光,只有方向没有位置

点光源

聚光灯

面光源

4.光照衰减

  4.1光照衰减纹理

Unity内部使用了一张名为_LightTexture0的纹理来计算光源衰减。如果对光源使用了Cookie,那么衰减查找纹理是_LightTextureB0。

通俗来讲,这个纹理就是将光照衰减映射到纹理上,然后从(0,0)(离光源最近)依次查询到(1,1)(离光源最远)。为了知道物体上的某一点受到光照后的颜色究竟是什么?我们把物体上的所有顶点转换到光源空间下(这里就体现了Shader中的编程核心思想,要知道物体的样子,就是知道物体的颜色,要知道物体的颜色,就要根据光照模型计算,要获取光照模型中的相应参数,就应转换到相应的空间下去计算),在光源空间下查询光照衰减纹理

完整的光照衰减计算代码

#ifdef USING_DIRECTIONAL_LIGHTfixed atten = 1.0;
#else#if defined (POINT)//点光源float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;fixed atten = tex2D(_LightTexture0, dot(lightCoord,lightCoord).rr).UNITY_ATTEN_CHANNEL;//利用顶点在光源空间的中的距离的平方进行采样(避免开方)//利用宏UNITY_ATTEN_CHANNEL获取衰减纹理中(_LightTexture0)衰减值所在的分量#elif defined (SPOT)//聚光灯float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;#elsefixed atten = 1.0;#endif
#endif

重点说明一下聚光灯(比较复杂) 

在聚光灯下_LightTextureB0是阴影纹理,_LightTexture0是储存光照强度和聚光灯颜色

1.

(lightCoord.z > 0) 这里的代码其实有歧义,因为在计算聚光灯光照的时候,我们通常采用的是锥形视锥,而不是平截头视锥,因为锥形视锥更适合表示聚光灯的光照区域。在锥形视锥中,视锥的顶点在 z 轴的负半轴上,因此 z 坐标始终是负数。而这里可能重新定义了朝向也说不定。所以这里开头是判断是否在视锥中(关于这个知识,可以去看Games101中的透视投影,每次投影的时候都需要将物体平移到原点,然后旋转相机为正(或者说是光源视锥)然后投影,然后再平移旋转返回原来的样子)

2. 

tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w

第一个tex2D函数采样聚光灯的光强和颜色信息,lightCoord.xy / lightCoord.w 这里的含义是为了将其变为非齐次坐标变为齐次坐标,我们将物体的顶点从世界空间转换到光源的视锥空间的时候,因为矩阵乘法会给w赋上一定的权重,离视点越远,x,y,z越小,投影出来就会越小(这里需要理解齐次坐标的含义,我们将(x,y,z,w)叫做齐次坐标,它实际上表示的点应该为(x/w, y/w, z/w) 就是非齐次坐标,w中储存的是顶点的逆深度(1/z)),我们使用了转换矩阵转换到光源的视锥空间,然后又使用投影矩阵投影到二维上(因为纹理是二维的,可以形象的理解压缩成二维,贴在纹理上一个一个找),但是此时的x,y仍是齐次坐标,因此要除以w,消除w所带来的透视效果,变成原本的非齐次坐标。得到真正的二维坐标,而加上0.5则是保证映射到[0,1]上(纹理的范围)

那么为什么只取w分量呢?因为tex2D函数返回RGBA四个通道,我们取第4个通道,即透明度来表示光照衰减系数。

3. 

tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL

这个阴影贴图是根据光源空间中的深度信息计算得到的,因此需要将光源空间中的坐标进行 dot 运算得到深度值,然后取两个 R 分量构成 UV 坐标,用于采样阴影贴图纹理。这样做是因为阴影贴图可能采用不同的投影方式,如果不用 dot 运算来获取深度值并计算 UV 坐标,可能会导致阴影贴图采样出现错误。

最后使用宏UNITY_ATTEN_CHANNEL获取我们生产的衰减纹理中衰减值所在的分量

4.2 使用数学公式计算衰减

 

 

相关内容

热门资讯

现货黄金直线跳水,跌破5200... 新闻荐读 1月29日晚,现货黄金白银快速走低,回吐盘中全部涨幅。23:15左右,现货黄金跌破5300...
加拿大拟与多国联合设立国防银行 新华社北京1月31日电 加拿大财政部长商鹏飞1月30日说,加拿大将在未来数月与国际伙伴密切合作,推进...
马斯克大消息!SpaceX申请... 据券商中国,美东时间1月30日,路透社报道,据两位知情人士透露,马斯克旗下SpaceX公司2025年...
澳网:雷巴金娜2-1萨巴伦卡女... 北京时间1月31日,2026赛季网球大满贯澳大利亚公开赛继续进行,在女单决赛中,5号种子雷巴金娜6-...
春节前白酒促销热:“扫码抽黄金... 春节临近,白酒市场再现价格异动。 近日,飞天茅台批价拉升,有酒商直言“年前要冲2000元关口”,引发...
新安县人民医院让专业护理走进千... 由211名专业人员组成的服务团队,提供60项全维度服务,累计完成上门服务3217人次;实现“入院—出...
跨国企业负责人高度肯定中国经济... 本文转自【中国经济网-《经济日报》】; 参观者在第八届中国国际进口博览会美敦力公司一款超硬导丝产品...
中药配方颗粒标准化浪潮:数商云... 在中医药现代化与国际化加速推进的背景下,中药配方颗粒行业正经历一场以标准化为核心的深刻变革。截至20...
长江能科迪拜孙公司完成注册 拓... 来源:新浪财经-鹰眼工作室 【财经网讯】长江三星能源科技股份有限公司(证券代码:920158,证券简...
银行职工因贪污罪获刑后留任,在... 新京报记者 刘锦涵 制作 礼牧周 ▲新京报我们视频出品(ID:wevideo) 近日,农发行福建福鼎...
黄金创40年来最大单日跌幅!金... (来源:劳动报) 转自:劳动报 1月31日,国际金银价格同步大跌,创40余年来最大跌幅。国内金饰价...
“一人公司”近来何以兴起? 2026年开年,“一人公司”发展备受关注。这种新型创业模式正在上海、北京、江苏等地悄然兴起,凭借低成...
寒武纪预计 2025 年净利润... 消息,AI 芯片企业寒武纪今日发布 2025 年年度业绩预告: 经财务部门初步测算,公司预计 2...
和讯投顾徐剑波:ETF买入法! 这轮牛市是机构主导的ETF牛市,选对ETF往往比选股更加赚钱。那么如何投资ETF?今天教给大家一个非...
君乐宝上市申请已递交,国内乳品... 2026年 1月19日,中国领先的综合乳制品企业君乐宝乳业集团股份有限公司正式向香港联交所递交主板上...
大涨!马斯克,突传大消息!重磅... SpaceX的“赚钱能力”曝光。 据最新消息,世界首富埃隆·马斯克旗下的商业航天公司SpaceX去年...
原创 顶... 2025年微博之夜定档于2026年2月5日北京线上直播,这场已经走过二十多年风雨的互联网年度盛典,因...
体检查出肺结节?3个日常行为正... 太原龙城中医医院科普:如今越来越多人在体检中发现肺结节,看到报告上的“阴影”便忧心忡忡。其实研究表明...
记者观察丨美联储下任主席提名揭... 在经过长达一年反复挑选后,美国总统唐纳德·特朗普终于做出决定,提名凯文·沃什为下一任美联储主席,接替...
首饰金,一夜大跌上百元!金价暴... 【导读】多家首饰品牌金价出现大幅下跌 中国基金报记者 忆山 随着国际金价急速下跌,国内首饰金价也迎来...