延迟着色法

延迟着色法基于我们延迟(Defer)或推迟(Postpone)大部分计算量非常大的渲染(像是光照)到后期进行处理的想法。它包含两个处理阶段(Pass):在第一个几何处理阶段(Geometry Pass)中,我们先渲染场景一次,之后获取对象的各种几何信息,并储存在一系列叫做G缓冲(G-buffer)的纹理中;想想位置向量(Position Vector)、颜色向量(Color Vector)、法向量(Normal Vector)和/或镜面值(Specular Value)。场景中这些储存在G缓冲中的几何信息将会在之后用来做(更复杂的)光照计算。下面是一帧中G缓冲的内容:


我们会在第二个光照处理阶段(Lighting Pass)中使用G缓冲内的纹理数据。在光照处理阶段中,我们渲染一个屏幕大小的方形,并使用G缓冲中的几何数据对每一个片段计算场景的光照;在每个像素中我们都会对G缓冲进行迭代。我们对于渲染过程进行解耦,将它高级的片段处理挪到后期进行,而不是直接将每个对象从顶点着色器带到片段着色器。光照计算过程还是和我们以前一样,但是现在我们需要从对应的G缓冲而不是顶点着色器(和一些uniform变量)那里获取输入变量了。

下面这幅图片很好地展示了延迟着色法的整个过程:

这种渲染方法一个很大的好处就是能保证在G缓冲中的片段和在屏幕上呈现的像素所包含的片段信息是一样的,因为深度测试已经最终将这里的片段信息作为最顶层的片段。这样保证了对于在光照处理阶段中处理的每一个像素都只处理一次,所以我们能够省下很多无用的渲染调用。除此之外,延迟渲染还允许我们做更多的优化,从而渲染更多的光源。

在几何处理阶段中填充G缓冲非常高效,因为我们直接储存像素位置、颜色、法线等对象信息到帧缓冲中,而这几乎不会消耗处理时间。在此基础上使用多渲染目标(Multiple Render Targets, MRT)技术,我们甚至可以在一个渲染处理之内完成这所有的工作。

G缓冲

G缓冲(G-buffer)是对所有用来储存光照相关的数据,并在最后的光照处理阶段中使用的所有纹理的总称,主要包括Position、Color、Normal、Specular等。

坐标系统

为了将坐标从一个坐标系转换到另一个坐标系,我们需要用到几个转换矩阵,最重要的几个分别是模型(Model)、视图(View)、投影(Projection)三个矩阵。首先,顶点坐标开始于局部空间(Local Space),称为局部坐标(Local Coordinate),然后经过世界坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Coordinate)结束。下面的图示显示了整个流程及各个转换过程做了什么:

OpenGL Projection Matrix

HDR(High Dynamic Range高动态范围)

HDR原本只是被运用在摄影上,摄影师对同一个场景采取不同曝光拍多张照片,捕捉大范围的色彩值。这些图片被合成为HDR图片,从而综合不同的曝光等级使得大范围的细节可见。看下面这个例子,左边这张图片在被光照亮的区域充满细节,但是在黑暗的区域就什么都看不见了;但是右边这张图的高曝光却可以让之前看不出来的黑暗区域显现出来。

深度冲突

防止深度冲突

  • 第一个也是最重要的技巧是让物体之间不要离得太近,以至于他们的三角形重叠。通过在物体之间制造一点用户无法察觉到的偏移,可以完全解决深度冲突。在容器和平面的条件下,我们可以把容器像+y方向上略微移动。这微小的改变可能完全不被注意但是可以有效地减少或者完全解决深度冲突。然而这需要人工的干预每个物体,并进行彻底地测试,以确保这个场景的物体之间没有深度冲突。
  • 另一个技巧是尽可能把近平面设置得远一些。前面我们讨论过越靠近近平面的位置精度越高。所以我们移动近平面远离观察者,我们可以在椎体内很有效的提高精度。然而把近平面移动的太远会导致近处的物体被裁剪掉。所以不断调整测试近平面的值,为你的场景找出最好的近平面的距离。
  • 另外一个技巧是放弃一些性能来得到更高的深度值的精度。大多数的深度缓冲区都是24位。但现在显卡支持32位深度值,这让深度缓冲区的精度提高了一大节。所以牺牲一些性能你会得到更精确的深度测试,减少深度冲突。

光照模型

1967年,wylie等人第一次在显示物体时加进光照效果。wylie认为,物体表面上一点的光强,与该点到光源的距离成反比。
1970年,Bouknight提出第一个光反射模型,指出物体表面朝向是确定物体表面上一点光强的主要因素,用Lambert漫反射定律计算物体表面上各多边形的光强,对光照射不到的地方,用环境光代替。
1971年Gourand提出的基于“漫反射模型与插值”思想的Gourand模型。对多面体模型,用漫反射模型计算多边形顶点的光亮度,再用增量法插值计算。
1975年,phong提出图形学中第一个有影响的简单光照明模型。模型虽然只是一个经验模型,但是其真实度已达到可以接受的程度。在phong光照模型的基础之上,相继出现了Goud明暗处理和phong明暗处理两个增量式光照模型。
1980年,whitted提出了一个光透射模型:whitted模型,并第一次给出光线跟踪算法的范例,实现了模型它综合考虑了光的反射、折射透射、阴影等。从本质上来说,whitted模型也只是一种经验模型,它仅考虑特定方向上的环境入射光对被照射点的光亮度共线,因而它仅能模拟理想的镜面反射和规则的投射效果。
1982年,Cook和Torrance为了克服Phong模型的缺点,提出了一个基于物理光学的表面反射模型—Cook-Torrance模型“使得模型中反射光的位置和分布与实际情况非常接近,因而用它绘制的图形具有很好的质感。
1983年,Hall和Greenbert在whitted基础上此进一步给出Hall光透射模型,考虑了漫透射和规则透射光。改进了whitted中投射高光效果,并再环境光中加入距离衰减因子,使之能够更好的模拟物体表面的透射特性。
1986年,Kajiya统一了以前所有的光照模型.Kajiya首先提出使类似于随机采样的蒙特卡罗(Monte Carlo)方法求解绘制方程的光线追踪算法(Raytracing), 通过对到达图像平面上的光线路径进行采样,然后估计它们对最终图像的贡献来生成图像.

  • 漫反射Lambert

环境光:
Iambdiff = Kd*I a
其中Ia表示环境光强度,Kd(0<K<1)为材质对环境光的反射系数,Iambdiff是漫反射体与环境光交互反射的光强。
方向光:
Ildiff = Kd * Il * Cos(θ)
其中Il是点光源强度,θ是入射光方向与顶点法线的夹角,称入射角(0<=A<=90°),Ildiff是漫反射体与方向光交互反射的光强,若 N为顶点单位法向量,L表示从顶点指向光源的单位向量(注意顶点指向光源),则Cos(θ)等价于dot(N,L),故又有:
Ildiff = Kd * Il * dot(N,L)
最后综合环境光和方向光源,Lambert光照模型可以写成:
Idiff = Iambdiff + Ildiff = Kd * Ia + Kd * Il * dot(N,L)

  • 冯氏镜面光照模型Phong

Phong模型认为镜面反射的光强与反射光线和视线的夹角相关:
Ispec = Ks * Il*(dot(V,R)) Ns
其中Ks 为镜面反射系数,Ns是高光指数,V表示从顶点到视点的观察方向,R代表反射光方向。由于反射光的方向R可以通过入射光方向L(从顶点指向光源)和物体的法向量求出,
R + L = 2 * dot(N, L) * N 即 R = 2 * dot(N,L) * N - L
所以最终的计算式为:
Ispec = Ks * Il * ( dot(V, (2 * dot(N,L) * N – L ) )Ns

  • 布冯修正镜面光照模型Blinn-Phong

Blinn-Phong是一个基于Phong模型修正的模型,其公式为:
Ispec = Ks * Il * (dot(N,H) )Ns
其中N是入射点的单位法向量,H是光入射方向L和视点方向V的中间向量,通常也称之为半角向量(半角向量被广泛用于各类光照模型,原因不但在于半角向量蕴含的信息价值,也在于半角向量是很简单的计算:H = (L + V) / |L + V| )。

  • 全局光照模型Rendering Equation

Rendering Equation 是Kajia在1986年提出的,
Lo(X, Wo) = Le(X, Wo) + ∫fr(X, Wi, Wo) Li(X, Wi) dot(N, Wi) dWi
其中X表示入射点,Lo(X, Wo)即从物体表面X点,沿方向Wo反射的光强,Le(X, Wo)表示从物体表面X以方向Wo 发射出去的光强,该值仅对自发光体有效,fr(X, Wi, Wo)为,入射光线方向为Wi, 照射到点X上,然后从Wo方向发射出去的BRDF值,Li(X, Wi)为入射方向为Wi照射到点X上的入射光强,N表示点X处的法向量,然后对入射方向进行积分(因为光线入射的方向是四面八方的,积分的意义是对每个方向进行一遍计算后相加),计算的结果就是全局光照的辐射率。
对于单个点光源照射到不会自发光的物体上,公式可以简化成:
Lo(X, Wo) = fr(X, Wi, Wo) Li(X, Wi) dot(N, Wi)
这个公式非常有用,通常会将该公式分解为漫反射表达式和镜面表达式之和。对于漫反射表面,BRDF可以忽略不计,因为它总是返回某个恒定值,所以可以写成如下形式:
Lo(X, Wo) = Idiff + frs(X, Wi, Wo) Li(X, Wi) dot(N, Wi)
其中Idiff表示漫反射分量,使用公式的计算方法,frs(X, Wi, Wo)表示镜面反射的BRDF函数,前面的Phong高光模型,其实是rendering equation在单一光源下针对理想镜面反射的特定推导,对于Phong高光而言:
frs(X, Wi, Wo) = Ks (dot(N, H)Ns / dot(N, Wi)

几种光照模型的比较
Lambert 模型能够较好地表现粗糙表面上的光照现象,如石灰墙,纸张等等,但是在渲染金属材质制成的物体时,则会显得呆板,表现不出光泽,主要原因是其没有考虑到镜面反射效果,所以Phong模型对其进行了很好的补充。
由于Blinn-phng光照模型混合了Lambert的漫射部分和标准的高光,渲染效果有时会比 Phong高光更柔和,有些人认为phong光照模型比blinn-phong更加真实,实际上也是如此,Blinn-phong渲染效果要更加柔和一些,但是由于Blinn-phong的光照模型省去了计算反射光线方向向量的两个乘法运算,速度更快,因此成为许多CG软件中默认的光照渲染方法,此外它也继承在了大多数图形芯片中,用以产生实时的快速渲染。在OpenGL和Direct3D渲染管线中,Blinn-Phong就是默认的渲染模型。
Rendering Equation是基于物理光学的模型,其对于观察方向上的辐射率进行了本质上的量化,Phong模型只是其特定BRDF的推导。

图形杂记--基础概念补充相关推荐

  1. UnrealEngine5实操--基础概念(持续补充)

    UnrealEngine5实操--基础概念 Unreal 术语 UE5 上手指南 关卡快速搭建 视口标准按键操作 Editor 视角移动速度调节 Unreal Editor 快速测距 Actor 操作 ...

  2. ROS wiki系列|ROS入门基础概念讲解

    上一期我们对ROS wiki中ROS部分进行了着重讲解,回顾戳这 这一期我们主要介绍ROS-getting started部分的一些基本概念 相关wiki页面:http://wiki.ros.org/ ...

  3. 机器学习/深度学习-学习笔记:概念补充(上)

    学习时间:2022.05.09~2022.05.11 概念补充(上) 在进行学习机器学习和深度学习的过程中,对于部分概念会比较陌生(可能是因为没有系统深入学习过统计学.运筹学和概率统计的相关知识:也可 ...

  4. 【Linux开发】linux设备驱动归纳总结(一):内核的相关基础概念

    linux设备驱动归纳总结(一):内核的相关基础概念 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  5. OpenCASCADE:可视化之基础概念

    OpenCASCADE:可视化之基础概念 介绍 演示文稿的结构 演示包 基本示例:如何显示 3D 对象 选择 术语和概念 算法 包和类 使用示例 介绍 在 Open CASCADE 技术中,表示服务与 ...

  6. SQL基础操作_8_基础概念

    目录 3 基础概念 3.1 数据库基础概念 3.2 集合相关概念 3.3 常见数据库对象 3.3.1 表 3.3.2 模式 3.3.3 视图 3.3.4 触发器 3.3.5 函数 3.3.6 存储过程 ...

  7. 【Alljoyn】Alljoyn学习笔记五 AllJoyn开源技术基础概念解析

    AllJoyn开源技术基础概念解析 摘要: 总线(Bus) 实现P2P通信的基础 AllJoyn 的底层协议类似于D-Bus,相当于是跨设备分布式的 D-Bus 总线附件(Bus Attachment ...

  8. linux驱动内核哪个文件夹,linux设备驱动归纳总结(一):内核的相关基础概念...

    linux设备驱动归纳总结(一):内核的相关基础概念 1. 内核与 linux 设备驱动的作用与关系 内核:用于管理软硬件资源,并提供运行环境.如分配 4G 虚拟空间等. linux 设备驱动:是连接 ...

  9. opencv:卷积涉及的基础概念,Sobel边缘检测代码实现及卷积填充模式

    具体参考我的另一篇文章: opencv:卷积涉及的基础概念,Sobel边缘检测代码实现及Same(相同)填充与Vaild(有效)填充 这里是对这一篇文章的补充! 卷积-三种填充模式 橙色部分为imag ...

最新文章

  1. 3.Linux文件与目录管理
  2. 单击事件开启线程时,再次单击就会出现 java.lang.IllegalThreadStateException: Thread already started. 错误
  3. 如何测试一个空的JavaScript对象?
  4. mysql conflicts with_安装MYSQL错误“conflicts with file from package mysql-libs-*” 解决方法...
  5. vue使用echarts可视化图形插件
  6. 马斯克“够狂”!发布“全世界最好的芯片”、推出自动驾驶Taxi,特斯拉鸣锣新战场...
  7. 独角访谈 | 去中心化交易所领军人物–Loi Luu
  8. SAS︱数据索引、数据集常用操作(set、where、merge、append)
  9. arduino声音传感器与二极管_Arduino声音传感器
  10. 行列式键盘+共阴极数码管显示
  11. 职业学校计算机教学,职业学校计算机专业教学初探
  12. C-CCSK云计算安全知识认证
  13. Agisoft Photoscan/Mateshape 相机参数XML解读
  14. 如何成为一名研发主管--关于个人、过程、工具和团队之一
  15. 从还珠格格到延禧攻略,不变的是什么?
  16. PS更改图片的背景颜色
  17. 爱普生Epson TM-T88III 打印机驱动
  18. CGB2111-Day13-用户模块管理
  19. 经典PID控制器的缺陷
  20. 一种高效自然光供电的6LoWPAN无线传感节点

热门文章

  1. 免费生成ios证书,利用Hbuilder打包ipa
  2. 关于拼多多开店售后服务的话术
  3. 用VMware Infrastructure 3进行服务器整合
  4. 【数学建模】2018数学建模国赛B题 --python实现情况1
  5. C#:数据结构queue队列源码:循环使用数组头标,尾标,防止不停扩容数组
  6. Dreamweave CS4 粘贴功能无效的解决方法
  7. unity后处理Bloom与HDR和ColorGrade,ToneMapping
  8. python实现闭合导线平差与坐标计算(改进)
  9. python电影评价分析.dat_python读DAT - IT屋-程序员软件开发技术分享社区
  10. 好奇!滴滴在 GitHub 开源了哪些有意思的项目?