Unity入门精要04(0)-更复杂的光照

这篇具有很好参考价值的文章主要介绍了Unity入门精要04(0)-更复杂的光照。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本书知识点是真的多(

Unity入门精要04(0)-更复杂的光照

1.渲染路径

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

   

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

Unity入门精要04(0)-更复杂的光照

Unity入门精要04(0)-更复杂的光照

1.1 前向渲染路径

   前向渲染的伪代码如下

Unity入门精要04(0)-更复杂的光照

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

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

当然也可以自己设置

Unity入门精要04(0)-更复杂的光照

 Unity入门精要04(0)-更复杂的光照

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

详细参考可见  ↓↓↓

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

1.2 前向渲染的两种Pass

  Unity入门精要04(0)-更复杂的光照

关于编译指令可参考

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入门精要》中的透明效果部分。

Unity入门精要04(0)-更复杂的光照

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

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

Unity入门精要04(0)-更复杂的光照

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

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

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

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

2.延迟渲染。

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

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

那么什么是延迟渲染?

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

Unity入门精要04(0)-更复杂的光照

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

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

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

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

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

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

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

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

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

Unity入门精要04(0)-更复杂的光照

Unity入门精要04(0)-更复杂的光照

Unity入门精要04(0)-更复杂的光照

 如图所示,更详细的可见

LearnOpenGL - Deferred Shading

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

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

Unity入门精要04(0)-更复杂的光照

 3.光源类型

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

点光源

聚光灯

面光源

4.光照衰减

  4.1光照衰减纹理

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

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

完整的光照衰减计算代码

#ifdef USING_DIRECTIONAL_LIGHT
    fixed 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;
	#else
		fixed 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 使用数学公式计算衰减

Unity入门精要04(0)-更复杂的光照

 文章来源地址https://www.toymoban.com/news/detail-411508.html

 

到了这里,关于Unity入门精要04(0)-更复杂的光照的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity入门精要03---透明效果

    本节知识架构      如果采用了透明度混合即要是实现半透明效果,那么就要关闭深度写入,那么此时渲染顺序就会变得非常非常重要,不然会出现不正确的遮挡效果。具体的分析可见书中解释 一句话概括就是因为没有写入深度,会导致之后读取的时候没有读取到深度,就可

    2024年02月04日
    浏览(61)
  • 《Unity Shader 入门精要》笔记07

    Unity中通常使用两种方法来实现透明效果:第一种是试用 透明度测试(Alpha Test) ,这种方法其实无法得到真正的半透明效果;另一种是 透明度混合(Alpha Blending) 。 由于深度缓冲的存在,可以让不透明物体不考虑他们渲染顺序也能得到正确的排序效果。但是实现透明效果需

    2024年02月07日
    浏览(38)
  • Unity Shader入门精要学习——透明效果

    要么完全透明,要么完全不透明。 实现简单,实质上是一种剔除机制,通过将不满足条件(通常使用小于某个阈值来判定,一般使用clip方法)的片元舍弃的方法来达到完全透明效果。这些被舍弃的片元不会再进行任何的处理,也不会对颜色缓冲产生任何影响,其余满足条件

    2024年02月17日
    浏览(47)
  • 《Unity 入门精要》第8章 透明效果

    在 Unity 中,我们通常使用两种方法来实现透明效果: 透明度测试(Alpha Test) 和 透明度混合(Alpha Blending) 。 当我们渲染不透明物体时,我们不需要特别考虑渲染顺序的问题,因为有 深度缓冲(depth buffer,也称 z-buffer) 的存在,它的基本思想是:根据深度缓存中的来判断

    2024年02月10日
    浏览(45)
  • Unity Shader入门精要 第八章——透明效果

    目录 前言 一、渲染顺序的重要性 二、Unity Shader的渲染顺序 三、透明度测试 1、什么是透明度测试 2、实践 四、透明度混合 1、什么是透明度混合 2、实践  五、开启深度写入的半透明效果 1、实现方法  2、实践 六、ShaderLab的混合命令 1、混合等式和参数 2、混合操作  3、常见

    2024年02月04日
    浏览(42)
  • [Unity Shader入门精要]初级篇 代码拆解

    简介: 介绍了Unity Shader入门精要中初级篇包含的所有代码, 通过详细拆解代码 ,一步一步揭晓Shader的原理。 5.2.1 顶点/片元着色器的基本结构 说人话: •第一行是着色器的名字,用大括号{} 包裹后续所有的Shader代码, Shader。 •紧接着是Shader的属性,用大括号{} 包裹

    2024年02月03日
    浏览(41)
  • Unity中的渲染优化技术 -- Shader入门精要学习(15)

    本章中,我们将阐述一些 Unity 中常见的优化技术。这些优化技术都是和渲染相关的,例如,使用批处理、LOD 技术等。 游戏优化不仅是程序员的工作,更需要美工人员在游戏的美术上进行一定的权衡。例如,避免使用全屏的屏幕特效,避免使用计算复杂的 Shader,减少透明混合

    2024年01月18日
    浏览(39)
  • 【UnityShader入门精要学习笔记】第三章(1)Unity Shader介绍

    本系列为作者学习UnityShader入门精要而作的笔记,内容将包括: 书本中句子照抄 + 个人批注 项目源码 一堆新手会犯的错误 潜在的太监断更,有始无终 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 从本章节开始我们要学习Shader相关的知识了,诸位看客可能有的

    2024年02月02日
    浏览(66)
  • 【UnityShader入门精要学习笔记】第三章(2)Unity Shader的形式,章节答疑

    本系列为作者学习UnityShader入门精要而作的笔记,内容将包括: 书本中句子照抄 + 个人批注 项目源码 一堆新手会犯的错误 潜在的太监断更,有始无终 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 (该系列笔记中大多数都会复习前文的知识,特别是前文知识非

    2024年02月02日
    浏览(50)
  • log4j2漏洞CVE-2021-44228复现笔记(纯步骤过程,没有复杂的知识点)

    前言: Apache Log4j 2 是对 Log4j 的升级,它比其前身 Log4j 1.x 提供了显着改进,并提供了 Logback 中可用的许多改进,同时修复了 Logback 架构中的一些固有问题。 2021 年 12 月,在 Apache Log4j2 中发现了一个 0-day 漏洞。Log4j 的 JNDI 支持并没有限制可以解析的名称。一些协议像rmi:和ld

    2024年02月12日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包