BRDF

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

refer:
LearnOpenGL
《入门精要》
Adobe Part1
Adobe Part2
知乎王江荣
知乎实现代码
几种不同的DFG
代码参考 间接光部分
代码参考 直接光部分




0. 写在前面

如果想要更好的理解,可以先看这篇文章

  • 首先,BRDF其本意是一个函数,特指Cook-Torrance BRDF模型中计算反射的部分
  • 但一般所说的BRDF均指整个Cook-Torrance BRDF模型:
  • 本人由于习惯,BRDF均特指计算反射的函数
  • 本文不考虑透射(BTDF)情况

双向反射分布函数BRDF(Bidirectional Reflectance Distribution Function)



1. 简单理解

  • 先简单的理解BRDF干了些什么事情,后面的公式才看得懂

首先用文字描述来解释一下BRDF干了什么事情:
对于每一个点(片元)

  • (入射)先遍历其法向半球的中所有光源,累加得到辐照度(先理解为入射光)
  • (反射)根据BRDF,仅计算到摄像机方向的反射强度

就是非常简单的一件事,只不过这个函数有点复杂,想要真正的完全理解并不容易,按照常理本应先从计算辐照度(入射光强度)开始入手,但其含有非常多的光学名词和概念,先从这里来会被绕晕;本文选择先从更容易被理解(但更复杂)的反射部分开始。
现在坐稳了,发车!



2. Cook-Torrance BRDF模型


这是通常大家所说的的BRDF的全名,其包含完整的反射计算(BRDF),SSS计算(BSSRDF)

            f = k S S S f S S S + k r f r f= k_{SSS}f_{SSS}+k_{r}f_{r} f=kSSSfSSS+krfr
f f f包含两个部分:

  • k k k指各部分所占比率: k S S S + k s p e c < 1 k_{SSS}+k_{spec}<1 kSSS+kspec<1 (SSS被吸收的损失)
  • f S S S f_{SSS} fSSS被称为漫反射,实际为SSS
  • f r f_{r} fr被称为高光反射部分,实际上是真正的BRDF


2.1 BRDF

现在先只考虑BRDF的部分,让我们来看看一个点在真实的物理世界中,是怎么反射光线的吧!

  • 当前只考虑单个光源的情况(方向光)

  • 已知当前点的 入射方向 v i v_i vi法线n观察角度 v o v_o vo(出射方向)(均为从当前点出发的标准化向量)

    f r = D F G 4 ( v o ⋅ n ) ( v i ⋅ n ) f_{r}=\frac{DFG}{4(v_o\cdot n)(v_i\cdot n)} fr=4(von)(vin)DFG
  • DFG分别代表一个函数:(每个DFG都有非常多的版本,有的开销大效果好,有的效果一般性能好)
    D 法线分布函数:估算在受到表面粗糙度的影响下,朝向方向与半程向量一致的微平面的数量。这是用来估算微平面的主要函数。
    F 菲涅尔方程:菲涅尔方程描述的是在不同的表面角下表面所反射的光线所占的比率。
    G 几何函数:描述了微平面自成阴影的属性。当一个平面相对比较粗糙的时候,平面表面上的微平面有可能挡住其他的微平面从而减少表面所反射的光线。

  • 先将DFG视为常数,BRDF当前的作用:(还不明白)

这个函数用来衡量:一个点在收受指定方向的光照后,有多少比例的光会反射到 v o v_o vo方向

  • 其实一条光线无非就两个变量:方向,强度(颜色) ;既然方向已经指定,这时我们要考虑的仅仅是强度,这也是BRDF的输出:一个0到1的数字




D 法线分布函数

  • 选取的为 N D F G G X T R NDF_{GGXTR} NDFGGXTR

BRDF

D ( n , h , α ) = α 2 π ( ( n ⋅ h ) 2 ( α 2 − 1 ) + 1 ) 2 D(n,h,\alpha)=\frac{\alpha^2}{\pi((n\cdot h)^2(\alpha^2-1)+1)^2} D(n,h,α)=π((nh)2(α21)+1)2α2
  • α \alpha α:粗糙度; n n n法线向量; h h h半程向量(与blinn一致,入射和出射的中间向量)




F 菲涅尔

  • 选取的为 F S c h l i c k F_{Schlick} FSchlick
    BRDF
    菲涅尔的作用是:计算光线反射部分所占的比例

真实的菲涅尔方程是一个相当复杂的函数,因此Fresnel-Schlick近似在实时渲染中是比较常用的函数:

F ( h , v , F 0 ) = F 0 + ( 1 − F 0 ) ( 1 − ( n ⋅ v ) ) 5 F(h,v, F_0)=F_0+(1-F_0)(1-(n\cdot v))^5 F(h,v,F0)=F0+(1F0)(1(nv))5
(opengl这里的公式错了,应该是n不是h)



G 几何函数

BRDF

G S c h l i c k G G X ( n , v , k ) = n ⋅ v ( n ⋅ v ) ( 1 − k ) + k G_{SchlickGGX}(n,v,k)=\frac{n\cdot v}{(n\cdot v)(1-k) + k} GSchlickGGX(n,v,k)=(nv)(1k)+knv
k d i r e c t = ( α + 1 ) 2 8 k_{direct}=\frac{(\alpha+1)^2}{8} kdirect=8(α+1)2 k I B L = α 2 2 k_{IBL}=\frac{\alpha^2}{2} kIBL=2α2
G ( n , v , l , k ) = G s u b ( n , v , k ) G ( n , l , k ) G(n,v,l,k)=G_{sub}(n,v,k)G(n,l,k) G(n,v,l,k)=Gsub(n,v,k)G(n,l,k)





1.1.3 L i ( p , ω i ) L_i(p,\omega_i) Li(p,ωi)

  • 立体角: ω \omega ω顾名思义,注意,仅角所对应的面积有关,与角所对应的形状无关

  • 辐射通量(Radiant flux): Φ \Phi Φ 表示的是一个光源的功率(光源单位时间内所输出的能量),以瓦特为单位

  • 辐射强度(Radiant Intensity): I = d ϕ d ω I = \frac{d\phi}{d\omega} I=dωdϕ 表示的是在单位球面上,一个光源向每单位立体角所投送的辐射通量。

  • 辐射率(Radiance): L = d ϕ d A ⋅ I c o s θ L = \frac{d\phi}{dA}\cdot\frac{I}{cos\theta} L=dAdϕcosθI 平面光源的每单位面积,所投射的辐射强度(因为是平面,要计算角度衰减)(描述出射光, θ \theta θ为光源平面和出射方向夹角)

  • 辐照度(Irradiance):(入射)平面单位面积所受L的总和



















\

首先,这个模型计算的对象仅是Object上的一个点(即上文所述的摄像机方向):

L o ( p , ω o ) = ∫ Ω f r ( p , ω i , ω o ) × L i ( p , ω i ) × ( n ⋅ ω i ) d ω i L_o(p,\omega_o) = \int_\Omega f_r(p,\omega_i,\omega_o)\times L_i(p,\omega_i)\times(n\cdot\omega_i)\mathrm{d}\omega_i Lo(p,ωo)=Ωfr(p,ωi,ωo)×Li(p,ωi)×(nωi)dωi


1.1.1 积分框架

            ∫ Ω A   d ω i \int_\Omega A\ \mathrm{d}\omega_i ΩA dωi

  • Ω \Omega Ω代表该点法线所面对的整个半球面
  • ω i \omega_i ωi代表每一单位立体角

1.1.2 f r ( p , ω i , ω o ) f_r(p,\omega_i,\omega_o) fr(p,ωi,ωo):




个人疑惑及解答

1.漫反射在物理中到底是什么?真实存在吗?


学习过PBR的同学可能知道,BRDF模型的光照其实也包含漫反射部分和镜面反射部分;但是我们学过微平面表面模型,所有的PBR都是基于此,有这样的理论:

  • 物体表面其实是无数镜面的,只会发生镜面反射和折射
  • 反射的光自然是specular
  • 折射的部分变为了次表面散射、透射和被吸收掉

也就是说,基于物理的真实世界的光照中,并没有漫反射这种东西!

那BRDF模型怎么大言不惭的说自己是PBR呢?

  • 首先事实是:BRDF模型是对的,没有错
  • 实际上BRDF中所谓的漫反射,其实是SSS部分
  • BRDF并没有考虑SSS远距离的情况,而是认为其SSS出射在入射光附近(同一像素)(大部分物质都可以这样近似,因为其散射距离确实很近)

如果你对上述的解释还不理解,可能是你还不了解BSSRDF模型,可以看我的这篇文章文章来源地址https://www.toymoban.com/news/detail-434714.html

到了这里,关于BRDF的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • SwiftUI 布局协议 - Part1

    SwiftUI 布局协议 - Part1

    今年 SwiftUI 新增最好的功能之一必须是布局协议。它不但让我们参与到布局过程中,而且也给了我们一个很好的机会去更好的理解布局在 SwiftUI 中的作用。 早在2019年,我写了一篇文章 SwiftUI 中 frame 的表现 ,其中,我阐述了父视图和子视图如何协调形成最终视图效果。那里描

    2024年02月05日
    浏览(7)
  • C/C++文件操作(细节满满,part1)

    C/C++文件操作(细节满满,part1)

    个人主页: 仍有未知等待探索_C语言疑难,数据结构,PTA-CSDN博客 专题分栏: C语言疑难_仍有未知等待探索的博客-CSDN博客 目录 一、引言  二、什么是文件  1、程序文件 2、数据文件 3、文件名  4、文件路径  1.相对路径 2.绝对路径 三、文件的打开和关闭  1、文件操作的大体流

    2024年02月08日
    浏览(7)
  • Python八股文:基础知识Part1

    Python八股文:基础知识Part1

    1. 不用中间变量交换 a 和 b 这是python非常方便的一个功能可以这样直接交换两个值  2. 可变数据类型字典在for 循环中进行修改 这道题在这里就是让我们去回答输出的内容,这里看似我们是在for循环中每一次加入了都在list中加入了一个字典,然后字典的键值对的value每次都加

    2024年04月12日
    浏览(10)
  • 当代软件工程师技术面试准备Part1

    当代软件工程师技术面试准备Part1

    当代软件工程师技术面试准备Part1 一. 编码 - Leetcode     LeetCode 是一个在线的编程练习平台,专注于帮助程序员提升他们的编程技能。该平台提供了大量的算法和数据结构问题,涵盖了各种难度级别,从简单到困难。LeetCode的主要目标是帮助程序员准备技术面试,特别是在软

    2024年02月03日
    浏览(11)
  • NzN的数据结构--二叉树part1

    NzN的数据结构--二叉树part1

            你叉叉,让你学数据结构你不学;你叉叉,让你看二叉树你不看。 今天我们来一起学习二叉树部分, 先赞后看是好习惯 。           树是一种 非线性 的数据结构,它是由n(n=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂

    2024年04月13日
    浏览(24)
  • Leetcode with Golang 滑动窗口 Part1

    Leetcode with Golang 滑动窗口 Part1

    滑动窗口的定义: 滑动窗口这一个技巧主要运用于处理数组问题上,一般用于“子串”问题。精髓是,维护一个里面装着元素的“窗口”,在将新元素装进“窗口”的同时,根据题意,把不符合题意的元素踢出“窗口”。 滑动窗口的模板: 接下来看几道题目: Leetcode 209.长

    2024年01月19日
    浏览(9)
  • 使用go语言构建区块链 Part1.基础原型

    英文源地址 区块链技术是21世纪最具变革型的技术之一,它仍处于成长阶段, 其潜力尚未完全实现.从本质上说, 区块链是一个分布式的记账数据库.但它的独特之处在于它不是一个私有数据库,而是一个公共数据库, 也就是说, 每个使用它的人都有它的完整或部分副本.而且,只有在

    2024年02月07日
    浏览(10)
  • D47|动态规划-子序列part2

    D47|动态规划-子序列part2

                     左为判断公共子序列,右为判断子序列,感觉代码完全可以套用,如果公共子序列的长度是较短的字符串的长度的话即输出true,如果不是即输出false。         完全不一样的思路,一个新的操纵方法: 编辑距离! 动态规划五部曲: 1)确定dp数组(

    2024年02月02日
    浏览(11)
  • python文件处理之open()功能的使用part1

    什么是文件? 文件是操作系统提供给用户或者是应用程序用于操作硬盘的虚拟概念或者说接口。 为什么要有文件? 用户通过应用程序可以通过文件,将数据永久保存到硬盘中。 详细的说:用户和应用程序操作的是文件,对文件的所有操作,都是向操作系统发送系统调用,然

    2023年04月08日
    浏览(8)
  • C/C++文件操作(细节满满,part2)

    C/C++文件操作(细节满满,part2)

    该文章上一篇:C/C++文件操作(细节满满,part1)_仍有未知等待探索的博客-CSDN博客 个人主页:仍有未知等待探索_C语言疑难,数据结构,小项目-CSDN博客 专题分栏:C语言疑难_仍有未知等待探索的博客-CSDN博客 目录   一、引言 二、文件的顺序 1、输入流和输出流 2、fputc 1.功能

    2024年02月08日
    浏览(15)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包