【UnityShader入门精要学习笔记】第六章(1)Unity中的基础光照

本文主要是介绍【UnityShader入门精要学习笔记】第六章(1)Unity中的基础光照,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述
本系列为作者学习UnityShader入门精要而作的笔记,内容将包括:

  • 书本中句子照抄 + 个人批注
  • 项目源码
  • 一堆新手会犯的错误
  • 潜在的太监断更,有始无终

总之适用于同样开始学习Shader的同学们进行有取舍的参考。


文章目录

  • 光照的原理
    • 光源
    • 吸收和散射
    • 着色
    • BRDF光照模型
  • 标准光照模型
    • 自发光
    • 环境光
    • 漫反射
    • 高光反射
    • 逐像素还是逐顶点
    • 总结


光照的原理

一个物体为什么看起来是红色的?从物理上解释是因为这个物体能够反射更多的红色波长而吸收了其他波长。

因此想要实现光照渲染,我们就需要模拟光照环境下的物理现象:

  • 首先,光线要从光源(Light Source)中被发射出来
  • 然后,光线和场景中的一些物体相交:一些光线被物体吸收了,而另一些光线被散射到其他方向
  • 最后,摄像机吸收了一些光,产生了一张图像

光源

光是从光源发射出来的。在光学里,我们量化光的标准是辐照度(irradiance),对于平行光而言,辐照度可以通过计算光线方向 l l l(光源照射方向)垂直于单位面积上单位时间穿过的能量来得到。

而在计算光照模型时,若要计算物体表面的辐照度。而物体表面往往和光线方向 l l l是不垂直的,那么我们就会计算光源方向 l l l和表面法线n之间夹角的余弦值来得到。

在这里插入图片描述
(通过上图不难知道为什么 c o s θ cos\theta cosθ可以计算辐照度,假设左图单位面积的长度为8d,那么辐照度就是8d/d = 8 = 单位辐照度。如右图所示,若光线与法线入射角为 θ \theta θ,则两条光线间入射点间距则为 d / c o s θ d/cos\theta d/cosθ,则辐照度 = 8 d / ( d / c o s θ ) = 8 c o s θ = 单位辐照度 ∗ c o s θ = 8d / (d/cos\theta)= 8cos\theta = 单位辐照度 * cos\theta =8d/(d/cosθ)=8cosθ=单位辐照度cosθ

因此 c o s θ cos\theta cosθ就可以使用光源向量 l l l和表面法线向量 n n n的点积来计算得到( l ⋅ n ∣ l ∣ ∣ n ∣ \frac{l \cdot n}{|l||n|} l∣∣nln),因此我们可以通过点积来计算辐照度。(点积也可以理解为光线l在法线n向量方向上的投影与法线n的乘积)

吸收和散射

光线由光源发射出来后,就会与一些物体相交,通常相交的结果只有两个:散射(scattering)和吸收(absorption)

散射只能改变光线的方向,但不改变光线的密度和颜色。吸收改变光线密度和颜色但不改变方向。

光线在物体表面产生散射通常有两种方向,如果散射到物体内部,被称为折射(refraction)。而另一种方向是散射到物体外部,被称为反射(reflection)
在这里插入图片描述

为了区分这两种不同的散射方向,我们在光照模型中使用了不同的部分来计算它们:高光反射/镜面反射(specular) 表示物体表面是如何反射光线的,而漫反射(diffuse) 则表示有多少光线会被折射、吸收和散射出表面。根据入射光线的数量和方向,我们也可以计算出出射光线的数量和方向,我们用出射度(exitance) 来描述它。

辐照度和出射度是满足线性关系的,而它们之间的比值就是材质的漫反射和高光反射属性

而且漫反射是没有方向性的,所以我们可以假设它在各个方向上是平均分布的。因此我们只会考虑某一特定方向上的高光反射。

着色

着色(Shading) 指的是,根据材质属性(如漫反射属性等),光源信息(如光源方向,辐照度等),使用一个等式去计算沿某个观察方向的出射度的过程。我们也把这个等式称为光照模型(Lighing Model) 。不同的光照模型由不同的目的,例如一些用于描述粗糙的物体表面,一些用于描述金属表面等等。


BRDF光照模型

BRDF是一种光照模型,通过给定入射光线的方向和辐照度后,BRDF可以给出在某个出射方向上的光照能量分布。


标准光照模型

标准光照模型是游戏引擎中早期使用的光照模型,原理比较简单,它只关心直接光照。从光源发射出来照射到物体表面的光,经过表面的一次反射直接进入摄像机的光线。

它的基本方法是,把进入到摄像机内部的光线分为4个部分。每个部分使用一种方法来计算它的贡献度:

  • 自发光(emissive) ,在本书中用 C e m i s s i v e C_{emissive} Cemissive来表示。这个部分用于描述当给定一个方向时,一个表面本身会向该方向发射多少辐射度。需要注意的是,如果没有使用全局光照(global illumination)技术,这些自发光的表面并不会真的照亮周围的物体。而是它本身看起来更亮了
  • 高光反射(specular) 部分,本书用 C s p e c u l a r C_{specular} Cspecular来表示,这个部分用于描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。
  • 漫反射(diffuse) 部分,本书使用 C d i f f u s e C_{diffuse} Cdiffuse来表示,漫反射用于描述,当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。
  • 环境光(ambient) 部分,本书使用 C a m b i e n t C_{ambient} Cambient来表示,用于描述其他所有的间接光照。

自发光

自发光光线会从光源本身直接进入摄像机,无需任何物体表面的反射。自发光的值等于材质本身的自发光颜色值:

C e m i s s i v e = m e m i s s i v e C_{emissive} = m_{emissive} Cemissive=memissive

环境光

虽然标准光照模型通常用于描述直接光照,但是现实中的物体也可以被间接光照所照亮,间接光照指的是,光线通常会在多个物体之间反射,最后进入相机。

例如在红地毯上放置一个灰色的沙发,那么沙发的底部也会反射出由红地毯反射的一部分红光。

我们通过环境光来近似模拟间接光照,环境光就是一个全局变量,场景中的所有物体都使用这个变量:

C a m b i e n t = g a m b i e n t C_{ambient} = g_{ambient} Cambient=gambient

漫反射

漫反射光照的方向是完全随机的,因此我们可以认为在任意反射方向上光照的分布都是一样的,但是入射光线的角度很重要。

漫反射光照符合兰伯特定律 :反射光线的强度与表面法线和光源方向之间的夹角的余弦值成正比,因此,漫反射部分的计算如下:

在这里插入图片描述

高光反射

此处的高光反射也是经验模型,并不完全符合现实中的高光反射现象。它可用于计算那些沿着镜面方向被反射的光线,从而让物体看起来有光泽,例如金属材质

计算高光反射需要知道的信息比较多,如表面法线,视角方向,光源方向,反射方向等。

在这四个向量中,我们只需要知道其中的表面法线,视角方向和光源方向即可。反射方向可以通过其他信息计算:

在这里插入图片描述

其中, m g l o s s m_{gloss} mgloss是材质的光泽度,也被称为反光度。它用于控制高光区域的大小, m g l o s s m_{gloss} mgloss越大,高光区域呈现的亮点越小。 m s p s c u l a r m_{spscular} mspscular是材质的高光反射颜色,用于控制该材质对于高光反射的强度和颜色。

除了上述的Phong模型,还有一个类似的Blinn模型:
在这里插入图片描述
Blinn模型引入了一个归一化矢量h,并使用n和h的夹角进行计算。通常来说,若v和I向量是定值时Blinn模型更快。反之是Phong模型更快。


逐像素还是逐顶点

这些光照模型是在着色器中进行计算的。若在片元着色器中进行计算,就被称为逐像素光照,而在顶点着色器中计算,则被称为逐顶点光照

在逐像素光照中,我们以每个像素为基础,得到它的法线(可以是对顶点法线进行插值得到的,也可以从法线纹理中采样得到)。并进行光照模型的计算。这种在片元着色器中,在面片之间对顶点法线插值的技术被称为Phong着色 ,也被称为Phong插值或者法线插值着色技术。注意,此处的Phong着色不同于我们说的Phong光照模型。

与之相对的是逐顶点光照,被称为高洛德着色(Gouraud shading) 。在逐顶点光照中,我们在每个顶点上计算光照,然后会在渲染图元内部进行线性插值,最后输出成像素颜色。

由于顶点数远远少于像素点数,因此逐顶点光照的计算量少于逐像素光照。但是,由于逐顶点光照依赖于通过顶点的线性插值输出像素颜色,因此若光照模型中有非线性计算的时候(例如计算高光反射时),逐顶点光照就会出现问题。

总结

在上文中我们了解了,光照我们通常用辐照度来描述其强度,并可以用光源方向l和法线向量n的夹角余弦值 c o s θ cos\theta cosθ来描述光的辐照度。

在光线发射过程中会发生吸收和散射两种现象。为了模拟光照,我们通常用光照模型对光线进行计算着色。

在标准光照模型中,通常存在四类光线:
自发光——材质自身的发光值,
环境光——反射光照的间接光照,通常用全局变量来表示,
漫反射——与辐照度类似,反射光线的强度与表面法线和光源方向之间的夹角的余弦值成正比;
高光反射——一个非线性的经验模型,一般有Phong模型和Blinn模型两种。

在对着色器进行光照计算的时候,通常有逐像素和逐顶点两种模式。如果使用片元着色器进行光照渲染,则是逐像素光照,逐像素光照以每个像素为单位进行光照颜色计算,其中每个像素点的法线可以通过顶点进行插值计算获取,或者直接从法线纹理中获取。

若使用顶点着色器进行渲染则为逐顶点光照。逐顶点光照只计算片元顶点上的光照,并直接通过顶点间的线性插值来计算其中每个像素的颜色。

显然逐顶点计算的计算量远小于逐像素计算。但是逐顶点计算的缺陷在于依赖对顶点的线性插值。若光照模型中包含非线性的计算时(例如计算高光反射),逐顶点计算就会出问题。

标准光照模型我们也称为Blinn-Phong光照模型。但这种模型也存在很多局限性,首先很多重要的物理线性无法通过Blinn-Phong模型来表现出来,例如菲涅尔反射

其次,Blinn-Phong模型是各向同性的 ,即当我们旋转物体表面时,光照反射不会发生任何改变。但是有些表面材质是需要各向异性的,例如金属,毛发等。后文中,我们将学习基于物理的光照模型,这些模型将会更加复杂。

这篇关于【UnityShader入门精要学习笔记】第六章(1)Unity中的基础光照的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/750417

相关文章

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

Spring的基础事务注解@Transactional作用解读

《Spring的基础事务注解@Transactional作用解读》文章介绍了Spring框架中的事务管理,核心注解@Transactional用于声明事务,支持传播机制、隔离级别等配置,结合@Tran... 目录一、事务管理基础1.1 Spring事务的核心注解1.2 注解属性详解1.3 实现原理二、事务事

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Java List 使用举例(从入门到精通)

《JavaList使用举例(从入门到精通)》本文系统讲解JavaList,涵盖基础概念、核心特性、常用实现(如ArrayList、LinkedList)及性能对比,介绍创建、操作、遍历方法,结合实... 目录一、List 基础概念1.1 什么是 List?1.2 List 的核心特性1.3 List 家族成