当前位置: 首页 > news >正文

2.4 传统经验光照模型详解

一、光照模型

光照模型(illumination model),也称为明暗模型,用于计算物体某点处的光强(颜色值)。从算法理论基础而言,光照模型分为两类:一种是基于物理理论的,另一种是基于经验模型的。

基于物理理论的光照模型:偏重于使用武力的度量和统计方法,效果非常真实,但是计算复杂,实现起来也较为困难。

经验模型:是对光照的一种模拟,通过实践总结出简化的方法,简化了真实光照计算,并能达到不错的效果。

 

1.1 为什么需要光照模型

现实世界的光照是极其复杂的,而且会受到诸多因素影响,有限的计算能力无法完全模拟。使用简化的光照模型对现实的情况进行近似,使得计算处理起来会更容易,并且零效果更符合需求。这些光照模型就是基于我们对光的特性的理解。

1.2 光照模型的发展

二、局部光照模型的组成

定义:局部光照模型只关心直接光照部分,即直接从光源发出并照射到物体表面并反射至摄像头的光线。

组成:

    • 漫反射
    • 高光反射
    • 环境光
    • 自发光

漫反射

定义:在光照模型的定义中,当光线从光源照射到模型表面时,光线均匀被反射到各个方向,这种现象就是漫反射。在漫反射的过程中,光线发生额了吸收和散射,而因此改变颜色方向。

如何计算:漫反射光照符合Lambert定律,反射光强与法线和光源方向之间的夹角余弦值成正比。

基础理论:在光学中通常使用辐射度来量化光。

其中光源每秒发出的能量为辐射通量P

单位面积接受的光量为辐射密度(辐照度)P/A

当光源垂直照射的单位面积的辐照度为E1 = P/A1

将光束以某个角度照射到更大的平面上的辐射度为E2 = P/A2

简洁的来说:反射光线的强度与表面法线和光源方向之间的夹角的余弦成正比。

高光/镜面反射

定义:当光线到达物体表面并发生了反射,观察室现在反射光线的附近时,便能够观察到高光反射。高光反射描述了光线与物体表面发生的反射(光强不变,方向改变)。

高光反射的反射率水根据一种菲尼尔效应的物理现象决定的,通常使用对应的反射贴图描述物体表面的反射率,并且使用光泽度(粗糙度,反光度)描述高光范围的大小。

环境光

定义:在局部光照模型中,由于没有考虑间接光照影响,因此为了处理这种间接光照,从而引入环境光。

计算:

通常使用漫反射的反照率来只是环境光找的反射量,个模型假定场景中发生多次散射和反射,并在所有方向上均等的射向目标物体。

渲染结果:

自发光

定义:顾名思义,物体自身发射的光线,通常作为单独的一项加入光照模型,一般使用一张发光贴图描述物体的自放光。

局部光照模型的整体效果

三、着色模型

1、Gourand模型(逐顶点着色)

定义:以顶点为单位计算光量在通过差值得到每个像素点的光亮度。

在表现物体光滑性上有较好的表现,但值不再是线性变化的时候,比如镜面高光,由于线性差值导致内插值不可能大于顶点值。因此高光只能出现在顶点。

由于使用的颜色差值,会导致镜面高高蔓延到周边。

代码部分:

  • 是在定点着色器中计算的(因为是逐顶点)
  • 顶点颜色使用的是Phong模型的结果
  • 高光部分用的是观察方向和反射方向的余弦值
  • 计算完之后将它座位顶点所携带的颜色
  • 在片元/像素着色器中,直接将顶点携带的颜色赋值给了返回颜色

最终效果:

左边是Gourand模型

2、Flat模型

平面着色模型,计算多边形的单个强度,每个三角形只有一个法线方向。以相同的光强度值显示多边形的所有点。适用于lowpoly风格的场景。

四、经典光照模型

1、Lambert模型

光照公式:

n:表面法线

l:指向光源的单位矢量

mdiffuse:材质的漫反射颜色

clight:光源颜色

防止法线和光源方向点乘的结果为负值,为此使用取最大值的函数来将其截取到0,这样可以防止物体被从后面来的光源照亮。

漫反射效果与观察者位置无关,于光源位置有关。

代码部分:

主光源入射光 * 漫反射材质的颜色 * 法线方向与光照方向的点积

渲染效果:

可以看出漫反射至于光源和表面法线有关,与观察者无关。

2、Phong模型

如何计算:

在这四个矢量中,我们实际上只需要知道其中3个矢量即可,而第四个矢量——反射方向,可以通过其他信息计算得到:

r计算过程参考:几何向量:计算光线反射reflect向量_空间几何中怎么求入射光的反射向量_羊羊2035的博客-CSDN博客

mgloss:材质的光泽度(反光度),它用于控制高光区域的“亮点”有多宽,数值越大,亮点越小。

mspecular:材质的高光反射颜色,它用于控制该材质对于高光反射的强度和颜色。

Clight:光源的颜色和强度

r:反射光线

v:视线向量

反应了光泽度与高光反射的关系

光泽度渲染效果:

最终计算公式:

代码部分:

unity的环境光宏 * 漫反射材质

最终渲染结果:

3、Blinn-Phong模型

在Phong的基础上引入了一个新的矢量h,他是通过vl取平均后在归一化得到的。

然后使用nh之间的夹角进行计算,而非vr之间的夹角。

计算公式:

最终计算公式:

代码部分:

最终渲染结果:

4、Phong和Blinn-Phong模型的区别

通过对Phong模型和Blinn-Phong模型公式对比,可以知道公式的不同之处在于使用了半角向量与发现的点积结果。

半角向量的使用带来的变化:

    • 计算更加简洁,半角向量的计算更加简洁
    • 当光源与视线都在表面之上时,半角向量与发现的角度永远不大于90度

设想一种情况,当材质的反光度非常低时,因此物体被光线照射的大部分区域都会发生高光反射。这些去榆中的一部分高光部分的反射向量与视线的夹角超过了90度。此时,如果使用Phong模型就会导致高光区域一部分发生缺失。这是由于Phong模型只会考虑实现与光照分布在法线两侧的情况。当时视线与光照在发现同侧时且高光反射对亮度有较大影响时,就会发生断层。

五、光照模型展示

作业

说出能量守恒的理念在基础光照模型中的作用

我理解的在光照模型中的能量守恒理念就是:光源所发出的能量(光线)经过物体多次表面反弹、散射、射入等后,其能量总和不会发生变化。

能量守恒是PBR的一个重要概念。它可以保证美术合适的设置材质的反射率和albedo值,而不破坏物理规则。虽然在着色系统中强制能量守恒的物理限制并不等价于最后好看的着色效果,但起码可以使得渲染效果不至于背离物理规则太远,保证在不同光照条件下物体的光照表现一致性。

基于能量守恒的理念,自己写一套完整的光照模型,需要包含环境光照

Shader "Lpk/Blinn-Phong"
{Properties{_Diffuse          ("Diffuse", Color)         = (1,1,1,1)_MainTex          ("Texture", 2D)            = "white"{}_NormalMap        ("Normal", 2D)             = "pink"{}_LocalNormalScale ("LocalNormal",Range(0,1)) = 0_Specular         ("SpecularColor", Color)   = (1,1,1,1)_Gloss            ("Gloss", Range(1.0,255))  = 20_CubeMap          ("Env map",CUBE)           = ""{}_EnvScale         ("Env Scale",Range(0,1))   = 1}SubShader{Tags { "RenderType"="Opaque" }Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag//引入头文件#include "UnityCG.cginc"#include "Lighting.cginc"struct appdata{float4 vertex : POSITION;float2 uv0 : TEXCOORD0;float2 uv1 : TEXCOORD1;float3 normal : NORMAL;float4 tangent : TANGENT;};struct v2f{float2 uv0 : TEXCOORD0;float2 uv1 : TEXCOORD1;float4 vertex : SV_POSITION;float3 worldNormal : TEXCOORD2;float3 tangentNormal : TEXCOORD3;float3 bitangentNormal : TEXCOORD4;float3 worldPos : TEXCOORD5;};sampler2D   _MainTex;float4      _MainTex_ST;sampler2D   _NormalMap;float4      _NormalMap_ST;fixed4      _Diffuse;fixed4      _Specular;float       _Gloss;float       _LocalNormalScale;samplerCUBE _CubeMap;float       _EnvScale;v2f vert (appdata v){v2f o;               //将顶点从模型空间转换到裁剪空间o.vertex = UnityObjectToClipPos(v.vertex);//把发现转换到世界空间//o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);(旧写法)o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;//计算UV Offset与Tilingo.uv0 = TRANSFORM_TEX(v.uv0,_MainTex);o.uv1 = TRANSFORM_TEX(v.uv1,_NormalMap);//计算法线切线、副切线o.tangentNormal = normalize(mul(unity_ObjectToWorld,float4(v.tangent.xyz,0.0)).xyz);o.bitangentNormal = normalize(cross(o.worldNormal,o.tangentNormal) * v.tangent.w);return o;}fixed4 frag (v2f i) : SV_Target{//--基础的计算//纹理采样fixed4 mainTex = tex2D(_MainTex,i.uv0);//环境光fixed3 amibent = UNITY_LIGHTMODEL_AMBIENT.xyz * _Diffuse.rgb * mainTex.rgb;//归一化光方向fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);//归一化法线,即使在vert归一化也不行,从vert到frag阶段有差值处理,传入的法线方向并不是vertex shader直接传出的fixed3 worldNormal = normalize(i.worldNormal);//--计算法线贴图fixed3x3 tangentRotation = fixed3x3(i.tangentNormal,i.bitangentNormal,worldNormal);fixed3 normalTangent = UnpackNormal(tex2D(_NormalMap, i.uv1));//将法线从切线空间转换到世界空间fixed3 normalWorld = normalize(mul(normalTangent.rgb,tangentRotation));fixed3 finalNormal = lerp(worldNormal,normalWorld,_LocalNormalScale);//--Lambert//计算法线与入射光的点积sfixed3 NdotL= max(0, dot(finalNormal, worldLightDir));//Lambert颜色(漫反射)fixed3 lambertColor = mainTex.rgb * _Diffuse.rgb * _LightColor0.rgb * NdotL;//--Phong//计算反射方向R,worldLight表示光源方向(指向光源),入射光线方向为-worldLightDirfixed3 reflectDir = normalize(reflect(-worldLightDir, finalNormal));//计算该视角方向fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);//计算VdotR,视角与反射光线的点积 fixed3 VdotR = max(0,dot(viewDir, reflectDir));//计算phong颜色fixed3 phong = pow(VdotR,_Gloss)* _Specular.rgb;//--Blinn-Phong//计算半角向量fixed3 halfDir = normalize(worldLightDir + viewDir);//计算NdotHfixed3 NdotH = saturate(dot(finalNormal,halfDir));//计算Blinn-Phongfixed3 blinnphong = pow(NdotH,_Gloss) * _Specular.rgb;//漫反射与高光有个过渡fixed3 specular = lerp(lambertColor * blinnphong, blinnphong,_Gloss / 255);//环境贴图fixed3 worldRef = normalize(reflect(-viewDir, finalNormal));fixed4 reflectColor = texCUBElod(_CubeMap, fixed4(worldRef.rgb,(255 - _Gloss) * 8/(255))) * _EnvScale;//环境贴图与漫反射有个过渡reflectColor.rgb = lerp(reflectColor * lambertColor.rgb,reflectColor,_Gloss/255);//--最终颜色fixed4 finalColor = fixed4(lambertColor + amibent + reflectColor.rgb + specular ,1.0);//fixed4 finalColor = fixed4( reflectColor.rgb,1.0);return finalColor; }ENDCG}}
}

兰伯特光照模型 Phong光照模型 Blinn-Phong光照模型

环境光贴图 环境光贴图=0.2 环境光贴图=1

相关文章:

2.4 传统经验光照模型详解

一、光照模型 光照模型(illumination model),也称为明暗模型,用于计算物体某点处的光强(颜色值)。从算法理论基础而言,光照模型分为两类:一种是基于物理理论的,另一种是…...

基于高通QCC5171的对讲机音频数据传输系统设计

一 研发资料准备 二 设计方法 蓝牙连接与配对:使用QCC5171的蓝牙功能,实现设备之间的蓝牙连接和配对。确保设备能够相互识别并建立起稳定的蓝牙连接。 音频采集与处理:将麦克风采集到的音频数据通过QCC5171的ADC(模数转换器&…...

【题解】判断链表中是否有环、链表中环的入口结点

文章目录 判断链表中是否有环链表中环的入口结点 判断链表中是否有环 题目链接:判断链表中是否有环 解题思路1:快慢指针 代码如下: bool hasCycle(ListNode *head) {if(head nullptr) return false;ListNode* fast head;ListNode* slow …...

Pytorch 最全入门介绍,Pytorch入门看这一篇就够了

本文通过详细且实践性的方式介绍了 PyTorch 的使用,包括环境安装、基础知识、张量操作、自动求导机制、神经网络创建、数据处理、模型训练、测试以及模型的保存和加载。 1. Pytorch简介 在这一部分,我们将会对Pytorch做一个简单的介绍,包括它…...

Lambda 表达式的作用域

在Lambda表达式中访问外层作用域和旧版本的匿名对象中的方式类似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。 Lambda表达式不会从超类(supertype)中继承任何变量名,也不会引入一个新的作用域。Lambd…...

【portswigger】第二专题-XSS(二)

portswigger 靶场(第二章节)XSS 视频同步更新至bilibili bibi地址 【【portswigger】第二专题-XSS(一前置知识)】 https://www.bilibili.com/video/BV1mp4y157xA/?share_sourcecopy_web 【【portswigger】第二专题-XSS&#xff…...

【计算机视觉|人脸建模】3D人脸重建基础知识(入门)

本系列博文为深度学习/计算机视觉论文笔记,转载请注明出处 一、三维重建基础 三维重建(3D Reconstruction)是指根据单视图或者多视图的图像重建三维信息的过程。 1. 常见三维重建技术 人工几何模型仪器采集基于图像的建模描述基于几何建模…...

使用Jetpack Glance创建Android Widget

使用Jetpack Glance创建Android Widget Jetpack Glance发布,让我们使用Google提供的Jetpack Glance创建一个联系人列表小部件。 https://developer.android.com/jetpack/compose/glance 什么是Glance? Jetpack Glance是一个使用Kotlin API创建小型、轻…...

【MyBatis 学习三】子段不一致问题 多表查询 动态SQL

目录 一、解决Java实体类属性与数据库表字段不一致问题 🌷现象1:显示字段不对应:使用ResultType查询结果为null; 🌷解决办法:字段不对应:使用ResultMap解决。 二、数据库的多表查询 &#…...

15. Spring AOP 的实现原理 代理模式

目录 1. 代理模式 2. 静态代理 3. 动态代理 3.1 JDK 动态代理 3.2 CGLIB 动态代理 4. JDK 动态代理和 CGLIB 动态代理对比 5. Spring代理选择 6. Spring AOP 实现原理 6.1 织入 7. JDK 动态代理实现 8. CGLIB 动态代理实现 9. 总结 1. 代理模式 代理模式&#xf…...

死锁产生的原因以及解决方案

一.原因: 1.使用互斥锁. 2.除非主动释放,负责不能被抢占. 3.占用一把锁不释放,等待其它锁资源(保持现状). 4.锁形成环路. 二.解决方案: 给锁编号,上锁的时候从小到大依次上锁,譬如如果一个线程要上1号和2号两把锁,如果1号锁被占用,不能上2号锁,等其它线程释放1号锁资源后…...

【构造】CF1758 D

Problem - D - Codeforces 题意: 思路: 如果需要构造一个和为定值的序列,那么考虑n-d,n-d1,.....nd-1,nd这种形式 如果要保证不能重复,那么先考虑一个排列,然后在排列上操作 如果根据小数据构造出了一些简单情形&a…...

【腾讯云 Cloud Studio 实战训练营】永不宕机的IDE,Coding Everywhere

【腾讯云 Cloud Studio 实战训练营】永不宕机的IDE,随时随地写代码! 写在最前视频讲解:Cloud Studio活动简介何为腾讯云 Cloud Studio?Cloud Studio简介免费试用,上手无忧Cloud Studio 特点及优势云端开发多种预制环境可选metawo…...

JavaScript将一层级对象数组转为children嵌套的三层级树状对象数组(多级树状分类)

有时候后端返回的数据不适合前端,我们就需要进行转换,比如我想用elementUI的级联选择器,而这个组件对数据格式有要求,本篇文章将介绍如何将一层级对象数组数据格式转为三层级嵌套children数组,JavaScript、Vue、小程序等都适用,使用情景为多级分类,嵌套数据 情况1:原数…...

Windows脚本启动Redis、Java和Nginx服务指南

文章目录 1. 完整的批处理脚本2. Redis服务3. Java服务4. Nginx服务 1. 完整的批处理脚本 echo offcd C:\path\to\redis tasklist /FI "IMAGENAME eq redis-server.exe" 2>NUL | find /I /N "redis-server.exe">NUL if "%ERRORLEVEL%"&qu…...

【宝藏系列】STM32之C语言基础知识

【宝藏系列】STM32之C语言基础知识 文章目录 【宝藏系列】STM32之C语言基础知识1️⃣位操作2️⃣define宏定义3️⃣ifdef条件编译4️⃣extern变量声明5️⃣typedef类型别名 C语言是单片机开发中的必备基础知识,本文列举了部分 STM32 学习中比较常见的一些C语言基础知…...

探索自除数:发现区间内的神奇数字

本篇博客会讲解力扣“728. 自除数”的解题思路,这是题目链接。 对于给定的正整数num,我们如何判断它是不是自除数呢?根据定义,我们只需要把num的每一位数字都取出来,判断能不能整除num,如果发现num的某一位…...

打卡力扣题目四

#左耳听风 ARST 打卡活动重启# 目录 一、题目 二、解题代码 三、解题思路 关于 ARTS 的释义 —— 每周完成一个 ARTS: ● Algorithm: 每周至少做一个 LeetCode 的算法题 ● Review: 阅读并点评至少一篇英文技术文章 ● Tips: 学习至少一个技术技巧 ● Share: 分享…...

npm yarn nrm

npm 和 yarn npm和yarn都是包管理器,yarn是在2016年发布的,那时npm还处于V3时期,那时候还没有package-lock.json文件,不稳定性、安装速度慢等缺点经常会受到广大开发者吐槽。此时,yarn 诞生了。yarn 的优点&#xff0c…...

关于我对刚开始学Java的小白想分享的内容:

编程是很有魅力的,让很多人为之痴迷 如果你是初学者,俗称小白,不妨看看下述内容: 文章目录 1. Java 简介 Java 是一门编程语言,发展至今已经成为一门真正意义上的语言标准。 Java是一个完整的平台,有一个…...

Redis学习路线(5)—— Redis生成唯一ID

一、全局唯一ID (一)在用户抢购时,就会生成订单并保存到数据库中,而订单表如果使用自增ID就会存在以下几种情况: 自增ID规律性太强受单表数据量的限制 (二)全局ID生成器,是一种在…...

django后台系统Tyadmin

无意之间发现个django的后台管理框架,仔细与xadmin对比了一下,无论是功能上还是便携性上都与xadmin特别相似,但个人感觉Tyadmin略胜一筹,因为外观上要比xadmin要美观,而且相比起来速度也快,部署甚至也和简单…...

设计模式适合用于解决特定的软件设计问题呢

当我们在开发软件时,经常会遇到各种各样的问题和挑战,例如如何处理对象之间的关系、如何实现复杂的业务逻辑、如何处理并发访问等。这些问题都是软件设计中经常遇到的问题,而设计模式就是为了解决这些问题而诞生的。 以下是一些常见的软件设…...

测试|测试分类

测试|测试分类 文章目录 测试|测试分类1.按照测试对象分类(部分掌握)2.是否查看代码:黑盒、白盒灰盒测试3.按开发阶段分:单元、集成、系统及验收测试4.按实施组织分:α、β、第三方测试5.按是否运行代码:静…...

矩阵中的路径(JS)

矩阵中的路径 题目 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是…...

Linux时间体系与LinuxPTP

Linux时间体系 Linux 需要提供“知道当前时间、计算时间长度、定时提醒”这三种功能。 其中知道当前时间和计算时间长度在某种程度上可以互相转换。即以UNIX Epoch计时开始可以知道当前时间。 一般硬件可以提供下列的硬件时钟: RTC 【真实时钟】 对于PC而言&…...

最优除法(力扣)数学 JAVA

给定一正整数数组 nums,nums 中的相邻整数将进行浮点除法。例如, [2,3,4] -> 2 / 3 / 4 。 例如,nums [2,3,4],我们将求表达式的值 “2/3/4”。 但是,你可以在任意位置添加任意数目的括号,来改变算数的…...

Git代码管理

目录: git环境配置 git工作流程git常用命令gitlab实战gitlog分析与检索分支管理策略git合并与冲突 1.git环境配置 Git 简介: Git 是目前世界上最先进的分布式版本控制系统。Git 优点: 适合分布式开发,强调个体…...

使用vscode进行远程开发服务器配置

1.下载vscode 2.给vscode 安装python 和 remote ssh插件 remote—SSH扩展允许您使用任何具有SSH服务器的远程机器作为您的开发环境。 3.安装remote-SSH插件之后,vscode左侧出现电脑图标,即为远程服务,按图依次点击,进行服务器配置…...

北斗gps卫星授时服务器(NTP)应用于防火墙场景

北斗gps卫星授时服务器(NTP)应用于防火墙场景 北斗gps卫星授时服务器(NTP)应用于防火墙场景 作为网络建设中不可或缺的两方面,在保证网络安全稳定以及时间同步精确性方面,防火墙和NTP服务器都极为重要。而防…...