计算机图形学十五菲涅尔方程

news2024/9/23 16:19:41

菲涅尔效应

菲涅尔效应在我们的日常生活中无处不在,下面来个例子三连:
我们去公园的池塘喂鲤鱼,当爆米花丢的比较近的时候,我们可以看见水底下成群的鲤鱼在抢吃的。但是当我们把爆米花丢的很远时,却看不见水底下那些如狼似虎的鲤鱼,只能看见水面上的倒影。
即近处可以看清水底细节,远处只能看清倒影。
我们在坐公交车的时候,从身边的窗户往外看,可以清晰的看清楚车外的世界,但是当我们去看离得比较远的玻璃的时候,往往会看见很多车内的倒影,例如司机和别的乘客。
即较近的玻璃可以很清楚的看清后面的东西,远处的玻璃出现了路面的倒影。
对于放置在桌面上的物体,当我们从不同的角度去观察它时,也会发现很神奇的现象,如下:
水平看时,可以看见物体的倒影
从上往下看时,几乎看不见物体的倒影。

上面这些生活中常见的现象就是菲涅尔效应。
那么我们怎么用更科学的术语来描述这个它们呢?我们能够看见水底下或者玻璃后的东西,那肯定是光线发生了折射所导致的。而对于水面上的倒影或者是玻璃变得像镜子一样这些都是因为光线发生了反射所导致的。通过前面的现象,我们可以发现,当我们人眼离物体表面(玻璃,水,或者桌子等)比较近时,此时我们的视线几乎与表面垂直,我们可以看见更多折射过来的光(水底的鱼,玻璃外的东西)。而当人们眼睛离物体表面比较远时,此时我们的视线几乎与表面平行,我们可以看见更多反射过来的光(倒影)。
我们知道当光线打向一个物体表面(介质)时,会发生反射与折射。其中反射光的方向以及入射光的方向我们可以通过反射定律折射定律来计算出。
在这里插入图片描述
但是到底是反射光更强还是折射光更强呢?了解过辐射度量学应该知道这里比较的是辐射率(Radiance)的大小,通过菲涅尔效应我们不难发现,当入射光方向接近垂直表面时,大部分的能量会被折射,所以我们能看清水底的东西。而当入射光方向接近平行表面时,大部分的能量会被反射,所以我们会看见远处的倒影。
那么在我们渲染的时候,自然要把这个现象给考虑进去,才能够达到以假乱真的目的。因此我们自然需要一个公式,能够描述出在不同入射光的情况下,反射光与折射光所占的比例,这个公式就是菲涅尔方程。

菲涅尔方程

当光线碰撞到一个表面的时候,菲涅尔方程会根据观察角度告诉我们被反射的光线所占的百分比。利用这个反射比率和能量守恒原则,我们可以直接得出光线被折射的部分以及光线剩余的能量。将其应用在BRDF中,我们就可以更加精准的计算出渲染方程中在这里插入图片描述的值。
我们假设入射光与法线的夹角为在这里插入图片描述,折射光与法线的夹角为在这里插入图片描述。由于折射还和介质的折射率有关,例如空气中的光射入水中,我们需要知道空气和水分别对应的折射率,我们再假设入射光所在的介质的折射率为n1,物体的折射率为n2.由于**光的偏振(极化)**现象,我们可以得到S偏振光和P偏振光分别对应的菲涅尔方程,如下:
在这里插入图片描述
根据折射定律:
在这里插入图片描述
可以推导出:
在这里插入图片描述
因此上面的菲涅尔方程可以写成没有在这里插入图片描述的形式:
在这里插入图片描述
如果我们不考虑偏振的情况,那么菲涅尔方程即是上面两者的平均值:
在这里插入图片描述
利用菲涅尔方程,我们就可以根据不同的反射率画出R与在这里插入图片描述的对应关系图,如下:
在这里插入图片描述
图中代表的是折射率为1.5的绝缘体(例如某种玻璃)的反射情况。可以发现当夹角为0时,即入射光垂直于表面,反射光的比例只有4%左右,而当夹角为90度时,即入射光平行于表面,反射比例将近100%,符合我们前面所说的菲涅尔效应。
我们再来看一个导体(比如铜镜)的关系图,如下:
在这里插入图片描述
可以发现即使光线垂直于导体表面,但是依旧有90%的光被反射。这也证实了为什么我们可以用铜来做镜子,却没法使用玻璃来做镜子。

Schlick近似法

很明显,前面的式子实在太复杂了,计算量会非常的多,那么有没有什么近似的方法来求得菲涅尔方程的值呢?
从上面两个关系图中,我们可以发现,反射比例和夹角的关系,基本上都是由基础反射率在这里插入图片描述的值,假设为R0)以某种类似的曲线增长到1。
其中基础反射率的值我们很好求得,因此此时在这里插入图片描述,带入前面的公式可得:
在这里插入图片描述
例如水的折射率为1.333,对应的R0即为(0.333/2.333)²=0.02。接下来的问题就是怎么用一个简单的函数使得反射率能随着在这里插入图片描述的增长以类似某种指数增长的方式从基础反射率变为1,这里Schlick为我们提供了一种近似方程:
在这里插入图片描述
上面的方程就是我们在渲染时常用的菲涅尔方程,用代码可以表示为:

vec3 fresnelSchlick(float cosTheta, vec3 R0)
{
    return R0 + (1.0 - R0) * pow(1.0 - cosTheta, 5.0);
}

其中一个问题是它仅仅对电介质或者说非金属表面有定义,而对于导体表面,使用它们的折射率(导体的折射率为负数)计算并不能得出正确的结果,这样我们就需要使用一种不同的菲涅尔方程来对导体表面进行计算,但是这样很不方便。所以我们预先计算出导体的基础反射率,然后用Schlick方法来对其进行插值估算,这样我们就能对金属和非金属材质使用同一个公式了。

下面是一些常见材质的基础反射率:
在这里插入图片描述
从中可以发现大多数电介质(绝缘体)的基础反射率要低于0.17,而导体(金属)的往往在0.5-1之间,对于导体而言它们的反射率一般都是带有颜色的,这也是为什么要用RGB三原色来表示。
金属表面的这个特性也引出了所谓的金属工作流概念,也就是我们需要额外使用一个被称为**金属度(Metalness)的参数来参与编写表面材质。金属度用来描述一个材质表面时金属还是非金属的。理论上莱索,一个表面的金属度应该是个布尔值,即要么是金属要么不是金属,不能两者皆是,但是,大多数的渲染管线都允许在0.0至1.0之间线性的调配金属度。**这主要是由于材质纹理精度不足以描述一个拥有诸如细沙/沙状粒子/刮痕的金属表面。因此我们需要一个可调整的金属度模拟这些效果,来获得非常好看的视觉效果。

通过预先计算物体的基础反射率的值,我们可以对两种类型的表面使用相同的Fresnel-Schlick近似,但是如果四金属表面的话就需要对基础反射率添加色彩。我么一般是按下面这个样子来实现的:

vec3 R0 = vec3(0.04);
R0 = mix(R0, surfaceColor.rgb, metalness);//根据金属度作插值

外发光

根绝菲涅尔效应我们可以知道,当物体表面的法线平行于屏幕的时候,也就是Camera基本水平看向这个平面的时候,此时的反射光应该是最强的,示意图如下:
在这里插入图片描述
因此我们就可以使用这个性质在shader中制作外发光的效果,视频教程如下:
https://www.bilibili.com/video/BV1Fb411p7hN
下面是效果图。
在这里插入图片描述

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

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

相关文章

多线程面试题--使用场景

目录 线程池使用场景 多线程使用场景一( es数据批量导入) 多线程使用场景二(数据汇总) 多线程使用场景三(异步调用) 总结 如何控制某个方法允许并发访问线程的数量 总结​编辑 对ThreadLocal的理解 实现…

1200*A. Cheap Travel

#include<bits/stdc.h> using namespace std; typedef long long ll; int n,m,a,b,res; int main(){cin>>n>>m>>a>>b;if(a*m<b) resa*n;else{if(n%m0) resn/m*b;else{resn/m*b;resmin(n%m*a,b);}}cout<<res;return 0; }

「动态规划dp」

文章目录 0 概览1 步骤1.1 框架 2 刷题2.1 斐波那契数列2.1.1 题解2.1.2 Code2.1.3 结果 2.2 零钱兑换2.2.1 题解2.2.2 Code2.2.3 结果 0 概览 动态规划的题型&#xff0c;一定是要求解最值的&#xff0c;比如最短编辑距离&#xff0c;最长递增子序列&#xff0c;最长公共子序…

删除每行中的最大值

给你一个 m x n 大小的矩阵 grid &#xff0c;由若干正整数组成。 执行下述操作&#xff0c;直到 grid 变为空矩阵&#xff1a; 从每一行删除值最大的元素。如果存在多个这样的值&#xff0c;删除其中任何一个。 将删除元素中的最大值与答案相加。 注意 每执行一次操作&…

Python - OpenCV识别条形码、二维码(已封装,拿来即用)

此代码可识别条形码和二维码&#xff0c;已封装好&#xff0c;拿来即用&#xff1a; import cv2 import pyzbar.pyzbar as pyzbar import numpy from PIL import Image, ImageDraw, ImageFontclass CodeScan():def __init__(self):super(CodeScan, self).__init__()def decode…

uniapp checkbox radio 样式修改

文章目录 通过查看代码&#xff0c;发现 before部分是设置样式的主要属性 我们要设置的话&#xff0c;就要设置checkbox::before的属性。 其中的content表示内容&#xff0c;比如内部的对勾 那么我们设置的时候&#xff0c;比如设置disabletrue的时候或者checkedtrue的时候&…

Redis(三)—— Redis基本的事务操作、Redis实现乐观锁

一、Redis基本的事务操作 首先声明&#xff1a; redis的单条命令是保证原子性的&#xff08;回想一下setnx k1 v1 k5 v5命令如果k1已经存在&#xff0c;那么k5也会设置失败&#xff09;但是redis的事务不保证原子性&#xff01;见下面“1.2 某条命令有错怎么办&#xff1f;”…

产品经理:如何做好项目需求管理

产品经理每天都要接触各种不同的需求&#xff0c;只有对这些需求进行分析&#xff0c;才能更好地了解问题&#xff0c;从而制定相应的解决方案。那么&#xff0c;怎么做需求分析呢&#xff1f; 一、需求确定 选择需求是很重要的&#xff0c;先做出选择&#xff0c;才会有对应的…

Item2连接SSH

在MocOS系统上&#xff0c;没有xshell&#xff0c;而一些类似xshell的工具中&#xff0c;好用的要收费&#xff0c;免费的不好用&#xff0c;于是决定使用iTerm2打造一个好用的ssh神器。 一、新建一个Profile 在配置管理页面切换到Profiles管理页面&#xff1a; 二、配置ssh连接…

五、控制流(1)

本章概要 true 和 falseif-else迭代语句 whiledo-whilefor 逗号操作符 for-in 语法 程序必须在执行过程中控制它的世界并做出选择。 在 Java 中&#xff0c;你需要执行控制语句来做出选择。 Java 使用了 C 的所有执行控制语句&#xff0c;因此对于熟悉 C/C 编程的人来说&…

KNN模型进行分类和回归任务

KNN工作原理 “近朱者赤&#xff0c;近墨者黑”可以说是KNN的工作原理。整个计算过程分为三步&#xff1a;1:计算待分类物体与其他物体之间的距离&#xff1b;2:统计距离最近的K个邻居&#xff1b;3:对于K个最近的邻居&#xff0c;它们属于哪个分类最多&#xff0c;待分类物体就…

【Nginx12】Nginx学习:HTTP核心模块(九)浏览器缓存与try_files

Nginx学习&#xff1a;HTTP核心模块&#xff08;九&#xff09;浏览器缓存与try_files 浏览器缓存在 Nginx 的 HTTP 核心模块中其实只有两个简单的配置&#xff0c;这一块也是 HTTP 的基础知识。之前我们就一直在强调&#xff0c;学习 Nginx 需要的就是各种网络相关的基础知识&…

前端程序员入门:先学Vue3还是Vue2?

一、前言 对于新手来说&#xff0c;学习Vue.js框架时往往会有这样一个疑问&#xff1a;应该先学习Vue2还是直接学习Vue3&#xff1f;在回答这个问题之前&#xff0c;我们先简单介绍一下Vue.js框架。 Vue.js是一个轻量级的MVVM(Model-View-ViewModel)框架&#xff0c;它以数据驱…

数字世界未来十年面貌展望

2023年&#xff0c;数字技术已经深刻改变了我们的生活和社会&#xff0c;而未来十年数字世界的面貌将会更加令人瞩目。从人工智能到区块链&#xff0c;从虚拟现实到5G&#xff0c;各种科技将继续发展演进&#xff0c;给我们带来更多令人兴奋的可能性。以下是对数字世界未来十年…

交换机之HOL拥塞

队首阻塞(Head of Line Blocking, HOL)是一种出现在缓存式通信网络交换中的一种现象&#xff0c;其交换结构通常由缓存式FIFO输入端、交换结构(Switch Fabric)、FIFO输出端构成。 HOL阻塞用一个现实生活中的例子说明&#xff0c;就如同你在一条单车道的马路上右转&#xff0c;…

人机交互与人机混合智能的区别

人机交互和人机融合智能是两个相关但不完全相同的概念&#xff1a; 人机交互是指人与计算机之间的信息交流和互动过程。它关注的是如何设计和实现用户友好的界面&#xff0c;以便人们能够方便、高效地与计算机进行沟通和操作。人机交互通常强调用户体验和界面设计&#xff0c;旨…

如何找回删除的文件?文件恢复,3招就行!

“昨天不小心把我的毕业资料删除了&#xff0c;因为改了很多版&#xff0c;删除的时候没想到把正确的版本删除了&#xff0c;错误的版本还在&#xff01;这种情况应该怎么办呢&#xff1f;怎样才能找回我删除的文件呀&#xff1f;” 对于一些比较重要的文件&#xff0c;不小心删…

【C++初阶】C++基础(上)——C++关键字、命名空间、C++输入输出、缺省参数、函数重载

目录 1. C关键字 2. 命名空间 2.1 命名空间的定义 2.2 命名空间的使用 3. C输入&输出 4. 缺省参数 4.1 缺省参数概念 4.2 缺省参数分类 5. 函数重载 5.1 函数重载概念 5.2 C支持函数重载的原理——名字修饰&#xff08;name Mingling&#xff09; 5.3 extern &…

围棋基础知识

1、气 1.1星位位置 1.2天元位置 1.3 气的位置 2、禁入点 白棋里面的位置就是禁入点&#xff0c;也可以称为没有气的位置可以称为禁入点 破解之法&#xff1a; 在于将白棋全部围住&#xff0c;下一步为围住之策&#xff0c;即可。 3、死棋和活棋 3.1活棋 3.2 死棋 白棋的样…

探寻数据服务的本质:API之外的可能性

数据服务在数据建设中发挥着重要的作用。数据服务到底啥样&#xff1f; 是不是只对外提供一个API&#xff1f; 这么简单&#xff1f; 而我希望你能在学完这部分内容之后&#xff0c;真正掌握数据服务的产品功能设计和系统架构设计。因为这会对你设计一个数据服务&#xff0c;或…