|
前言
从毕业一直摆烂到到12月份.......接触TA的知识也有一段时间了,作为一个坚定走白嫖路线的菜鸡,在各位老师的慷慨分享下,也笨拙的学了(抄了)一些东西。
借着整理面试思路的机会,今天就总结一下《TA百人计划》图形部分的一小块知识结构(其他教程的知识结构就先不总结了,有兴趣的可以去我笔记库翻翻)
老规矩,又是喜闻乐见的贴Reference环节:
首先要感谢霜狼May,May佬的这个视频也是我梦开始的地方:
所以,这篇思路总结的结构也是按照《TA百人计划》中一些目录标题来划分的。
在整理的过程中可能还穿插着一些其他地方提到过的知识,包括但不限于:闫令琪老师的GAME101&202、Youtube的Ben Cloward和 Freya Holmér两位老师的频道等等。
最后,因为是简单的思路总结,难免有不详细、不准确的地方,和很多没能涉及的知识,还请大佬们指出错误与不足
接下来进入正题:
0.渲染管线
管线单独整理了出来:
0.5MVP变换
- M矩阵
- V矩阵
- 观察空间是以Camera为中心的坐标系
- V矩阵代表的变换过程可以这样理解:观察空间变换到世界空间的逆过程
- 观察空间→世界空间 可以这样理解:让观察空间的坐标系原点和世界空间重合即可
- 过程:先旋转,再平移
- 求V矩阵 = 逆过程
- 过程:平移 → 旋转 →z取反(Unity为左手坐标系)
- P矩阵
- 不是真正的投影,而是为投影做准备(投影操作在后续)
- 有正交和透视投影两种
- 本质上对xyz分量进行了不同程度的缩放,方便裁剪
- w是z分量取反,用来进行视锥体内的裁剪(如果在视锥体内,必定满足-w≤x≤w)
- 应用了P矩阵之后的结果是转换到裁剪空间
1.线代知识
- 向量
- 是矢量,有方向,有大小
- 向量的运算
- 点乘
- 计算方式
- 普遍情况: 点乘 = 两向量模长乘积 * cosθ
- 单位向量情况: 点乘 = cosθ
- 点乘的应用
- ①找两向量夹角,点乘 = cosθ
- ②找投影:b向量投影到a向量上 = b的模长*cosθ
- ③判断“前后”和“接近程度”:根据cosθ的正负和大小
- 叉乘
- 计算方式
- 右手定则:食指向向量a,中指向向量b,大拇指就是叉乘的结果(normalize之后,忽略了长度)
- 叉乘的应用
- ①右手坐标系:x轴和y轴叉乘得到z轴
- ②判断“左右”:a叉乘b结果为正 → b在a的左侧
- ③判断“内外”:给定三角形ABC,在忽略ABC点命名顺序的情况下:将三个顶点依次连成向量,如果点P都在这三个向量的左侧or右侧 → 点P在三角形内部
- 矩阵
- 这里用《线代的本质》中的一句话理解:矩阵包含 着“线性变换”信息
- 矩阵左乘的来源
- 同来来自《线代的本质》,矩阵在此处和“函数”意义相同,接收输入,进行输出
- 函数是f(x),f放在变量x左边的
- 矩阵的乘法:
- m×n 和 n×p 的矩阵才可以乘,结果为m×p的矩阵
- 计算方法:
- 矩阵A * 矩阵B ,结果的第a行第b列的数 = 矩阵A的第a行 · 矩阵B的第b列
- 仿射变换
- 齐次空间
- 3×3矩阵并不能表示仿射变换,所以我们扩充了一维,这样就能表示了
2.纹理知识
- 纹理过大过小出现的问题及解决:
- 纹理过小:
- 问题:这个简单,因为精度不够,会失真
- 解决:
- 过滤机制(Filter Mode)
- 将浮点型的像素坐标转换为整型
- 最邻近、双线性插值、立方体卷积插值(双向三次插值)、Q光滑曲线插值
- 纹理过大:
- 问题:近处锯齿(走样),远处摩尔纹
- 解决:
- ①超采样:把每个像素细分成多个采样点(太耗)
- ②Mipmap:对纹理进行预处理,预先生成一系列以2为倍数缩小的纹理序列,在采样纹理时根据图形的大小自动选择相近等级的Mipmap进行采样。
- Mipmap总共有多少层:log2n层
- Mipmap的存储量:比原来多1/3(整体的4/3)
- Mipmap层级的计算方法:
- 计算纹理坐标横向和纵向的偏导数(ddx,ddy),并取做大值delata
- 最后来计算层数 = 0.5 * log2delta
- Mipmap看这位大佬的文章:Clawko:图形学底层探秘 - 纹理采样、环绕、过滤与Mipmap的那些事
- 补充:不使用Mipmap会出现的一个问题
- 远处的精度比较高,会出现一种Pixel Shimmer/Sizzle的情况
- 是因为贴图的像素比屏幕的像素更多
- 纹理的优化手段
- CPU优化手段-降低DrawCall
- 纹理图集:一堆小纹理合成一个大的纹理
- 纹理数组(Texture Array)
- GPU优化手段-带宽入手
3.色彩空间
- 人眼的感光细胞、锥形细胞
- 感光细胞:用来感知光强度(灰度图)
- 锥形细胞:有三种大小,s(小波长/高频)、m、l(低频)
- 不同人的眼睛的锥形细胞分布是不同的,颜色实际上是人眼的感知
- 色彩空间的定义?
- 定义色彩空间的三个指标
- 色域:三基色的坐标
- Gamma:是色彩空间对颜色进行采样的一种方式(1=线性 2.2=Gamma)
- 白点:色域三角形的中间点,色彩空间中最亮的点
- 增色系统/减色系统:
- 人眼的可见范围是多少?
4.模型和材质
- 模型包含数据:
- BRDF、反射方程、渲染方程、全局光照?
- BRDF = Bidirectional Reflectance Distribution Function = 双向分布反射函数
- 反射方程、渲染方程
- 在渲染方程中哪一项与材质有关?
- BRDF项和材质有关,也就是说 BRDF -> 材质
- 漫反射:光射向四面八方,物体表面入射的Radiance和出射得Radiance相等。其中Lambert模型认为各个方向是均匀的
- 镜面反射-BRDF
- 折射-BSDF
- BSDF = BRDF + BTDF
- 不只是会出射,还会有折射发生
- 次表面散射-BSSRDF
- 可以理解为皮肤和光的作用(手电筒透过手出来的效果)
- 微表面BRDF
- D项:法线分布
- F项:菲涅尔
- G项:几何项(自遮挡,投影)
- 各向异性BRDF:
- 各向异性:法线分布有明确的方向性(而不是均匀)
- 常见于:拉丝金属、尼龙、天鹅绒
- 顶点色的作用
5.传统经验光照
- Lambert
- Phong
- Pow(dot(v,r) , _gloss)
- v = normalize(_WorldSpaceCameraPos.xyz - WorldPos.xyz)
- r = normalize(reflect(-l , n))
- 高光
- Blinn-Phong
- 引入半程向量/半角向量 h = bisector(v,l) = (v + l) /(||v+l||)
- Pow(dot(n,h) , _gloss)
- h = normalize(l + v)
- Blinn-Phong的一个问题
- 当视线来到背面时,会有一个类似“聚光源”的漏光现象
- 解决:给高光乘上Lambert>0(因为是在背面,Lambert<0代表背面,这时乘上的bool值返回0,这样就裁掉了背面的部分)
- IBL
- Image-based lighting
- 用一张图来代替环境光照,增加环境光的细节
- Mipmap导致的“接隙线”
- 代码中可以用Tex2Dlod指定mip级别
- UE4连连看可以把Sampler节点的MipValueMode改为Derivative
6.Bump映射
- 法线映射
- 将法线信息存在一张Texture中,一般是高模烘焙得到的,在实际使用中,将它给低模使用
- 在使用中涉及到的一些知识
- 切线空间
- 切线空间的好处
- 自由度高
- 模型空间的法线是绝对法线信息,仅能用在创建它时的模型
- 可以重用
- 可以压缩
- TBN中,B可以由T和N叉乘得到,也就是说只用存两个信息
- 解压法线
- 法线贴图蓝紫色的原因:
- 法线信息是在切线空间的
- 如果一个点的法线方向不变,那么它切线空间中新法线的方向就是Z轴方向(0,0,1)
- 经过*2-1Remap之后就是(0.5,0.5,1)
- TBN矩阵
- 由T切线,B副切线,N法线构成的3×3矩阵
- TBN矩阵式切线空间转换到世界空间的矩阵
- 反过来就是TBN的逆矩阵,是世界空间转换到切线空间的矩阵
- 法线混合(NormalBlending)相关知识
- 这篇笔记有整理:https://www.yuque.com/sugelameiyoudi-jadcc/okgm7e/cuq5g1
- UE混合法线的节点:BlendAngleCOrrectedNormal
- Unity混合法线的节点:Normal Blend
- 默认:Whiteout
- Reoriented:RNM
- 视差映射(Parallax Mapping)
- 引入了高度图
- 利用模型表面高度信息来对纹理进行偏移
- 法线贴图和高度图
- 法线贴图中存的是:每个纹素的不同方向
- 高度图中存的是:每个点的高度信息
- 顶点沿着法线方向偏移时,出现“断面”或者把面挤出来的情况
- 陡峭视察映射(Steep Parallax Mapping)
- 将物体表面分为若干层,从顶端开始采样,每次都沿着视角方向偏移一定的值,如果当前采样的层数,大于实际采样的层数,就停止采样。
- 浮雕映射(Relief Mapping)
- 在视差映射基础上进行了改进,一般用射线步进和二分查找来决定uv偏移量
- 视差闭塞(POM,Parallax Occlusion Mapping)
- 在上一步基础又做了改进,将最后一步的二分查找改为了对两端uv进行采样,再插值计算作为最终的偏移值
7.伽马校正
- 传递函数
- 传递函数就是用来做转换的,颜色的颜色值,要在电子设备上显示,就要把它转换为视频信号,
- OETF,光转电:线性光信息转到非线性视频信号信息
- EOTF,电转光:把非线性视频信号值转到显示光亮度
- 什么是Gamma校正
- Vout = Vingamma
- Gamma是指对线性三色值和非线性视频信号之间进行编码和解码的操作
- 线性空间(相机捕捉到的真实世界光信号) + gamma编码 + 显示器显示 = 结果
- Gamma编码曲线:人眼看到的中灰颜色(美术0.5),实际上是物理上的0.2左右
- 美术灰阶、线性灰阶
- 美术灰阶是视觉上的均匀分布,但视觉上的“中灰”并非真正的中间,而是实际物理中间偏左的
- 线性灰阶是指物理上的均匀分布
- Gamma校正就可以对这两种灰阶进行转换
- 为什么要使用Gamma校正?/ 为什么不用线性的方式存储,而是要线性和Gamma来回转换
- ①人眼对暗部的变化更敏感,非线性的存储可以合理利用8bit,给暗部更多的精度
- ②历史原因:CRT(阴极射线显像管)设备的亮度和电压的关系不是线性的,而是类似Gamma2.2次幂的关系
- CRT的物理特性,刚好可以把线性(物理)的亮度压低,对亮度进行校正
- 什么是线性工作流?
- 在shader中做计算的,需要是线性数据
- 如果贴图中是Gamma空间的,传入shader时要将它转换到线性空间再做计算
- 不在线性空间下计算可能出现的问题:
- 为什么要使用线性工作流?
- ①一个正确的工作流是非常重要的,我们在实际工作中需要有一个规范,这样可以提升所有人的效率
- ②线性工作流可以保证计算不会出错
- 简述整个图片数据存储过程
- 原始的图片数据是物理数据,存储到硬盘时,我们用一个gamma小于1(0.454)的曲线对它进行处理,进行存储(此时是Gamma≈2.2的色彩空间,sRGB)
- 在我们查看电脑中的图片时,再进行一个gamma大于1(2.2)的曲线进行处理,这样又被还原回去了
- 勾选sRGB?
- 如果是Gamma空间的贴图,需要勾选sRGB,这样采样时硬件特性会将它转换到线性空间
- 如果是线性空间的贴图,就不需要勾选sRGB
8.LDR和HDR
- 什么是DR、LDR、HDR
- DR = Dynamic Range(动态范围)=最高亮度/最低亮度
- L和H分别代表Low 和 High,也就是高动态范围和低动态范围
- LDR:
- 8位精度,单通道为0~1
- 常用格式:jpg、png
- 使用场景:常用的DCC工具、拾色器、电脑屏幕等都是LDR
- HDR
- 远高于8位的精度,单通道可以大于1
- 常用格式:hdr/tif/exr/raw等(多为相机常用格式)
- 使用场景:真实的物理世界,HDRI( 高动态范围图像)
- 为什么需要HDR
- HDR有更好的色彩,更高的动态范围,更丰富的细节,增加了亮部细节
- 可以表现出超过1的亮度
- 超过1才有bloom效果
- ToneMapping
- 将HDR内容显示到LDR设备,所做的映射,就叫做ToneMapping
- 几种算法:直接贴大佬发过的文章:https://zhuanlan.zhihu.com/p/21983679
- LUT
- Look Up Table
- 可以理解为一个滤镜,对LDR信息进行做处理
9.flowmap
- Flowmap是什么
- 本质上是一张记录着向量场信息的纹理,通过两个通道记录着向量的信息
- flowmap的原理?
- flowmap的实现?
- ①解压,*2-1,把(0,1)remap到(-1,1)
- ②用读取到的信息对uv进行偏移
- 其他:
- 无缝衔接:用两个差一个周期的偏移,进行lerp
- flowmap更改法线:用偏移后的uv采样法线
10.深度测试、模板测试
- 深度测试和模板测试位于管线的什么位置
- 模板测试和深度测试位于光栅化阶段的逐片元操作中
- 都是可配置但不可编程的
- 如何理解模板测试
- 三个重要参数:
- 通过比较操作,对当前片元和模板缓冲区中的值做比较,最后决定这个片元是否保留
- Unity默认模板缓冲区的值为0
- 如何理解深度测试
- 和模板测试差不多,也是三个参数
- Z Write
- Zwrite决定是否写入深度缓冲区
- ZWrite on:如果Ztest通过就写入深度缓冲区
- ZWrite off:不写入深度缓冲区
- Z Test
- ZTest通过,如果同时Z Write On,就写入深度缓冲区;否则只写入颜色缓冲区
- 深度缓冲一开始默认值为无限大
- 从各个空间理解深度值
- 模型空间下是没有深度值的
- 经过M矩阵变换到世界空间后,此时坐标变换到了齐次坐标(x,y,z,w),此时深度值存在z值
- 经过V矩阵变换到观察空间后,深度存在z值(还是线性的)
- 通过P矩阵变换到裁剪空间后,深度值存在z/w中(此时是非线性的)
- 最后经过投影和屏幕映射,变换到屏幕空间
- 为什么深度缓冲区要存储非线性的深度值
- ①可以给近处更高的精度(类比gamma校正,给暗部更高的精度)
- ②Z-Fight,深度冲突(两个片元太近,无法判断前后时出现的闪烁情况)
- 如何避免Z-Fight
- 物体别放太近/重叠
- 尽可能把近平面放远点
- 放弃一些性能来换取更高精度的深度值
11.曲面细分着色器、几何着色器
- 两个着色器位于渲染管线的什么位置
- 曲线细分着色器的流程
- 输入Patch(顶点数据的集合),然后进行细分
- 最常见的就是增加mesh复杂程度,配合一些效果使用(经典的:搭配置换贴图displacement)
- 流程:
- Hull shader
- Tessellation Primitive Generator
- Domain shader
- 几何着色器的流程
- 输入图元,定义输出最大顶点数,重点是:需要自己构建图元
- 流程:
12.前向渲染/延迟渲染
- 什么是渲染路径
- 什么是前向渲染
- 会计算所有顶点光照,片元处理阶段每个物体都直接计算光照,直接把东西渲染出来
- 比如:
- m个mesh,n个light,最后的复杂度就是m*n
- 什么是延迟渲染
- pass1:几何处理通路:
- 不直接计算光照,而是将mesh的几何信息存在G-Buffer中(比如位置、颜色、深度、法线等)
- pass2:光照处理通路:
- 比如:
- m个mesh,n个light,最后的复杂度就是m+n
- 前向渲染的优缺点
- 几何和着色在同一个pass,计算光照比较方便
- 适用于光源少的情况
- MSAA possible
- 半透明渲染较好支持
- 延迟渲染的优缺点
- 只能用一种光照模型
- 对多光源有良好的支持
- 对后处理有良好支持(直接拿GBuffer里的数据)
- 不支持MSAA,但是可以TAA
- 带宽占用大(移动端一般为前向)
13.Early Z , PreZ,透明物体相关
- 什么是Early z
- 管线位置:
- 内容:
- 在计算片元之前,做一次深度测试,如果不通过就直接丢弃,避免一些重复的计算
- Early-Z是基于硬件的优化,满足条件会自动开启
- 为什么要做Early-Z
- 传统的深度测试在计算片元之后,这样就会产生一个问题:
- 有些片元计算了之后并没有通过深度测试,被直接抛弃了
- 这就等于白计算了,非常浪费
- 所以区分于传统的深度测试(ZTest),硬件自动做了一步提前的深度测试(ZCull),叫作early-z
- Early-Z失效的情况?
- 开启AlphaTest、手动丢弃片元、手动修改GPU插值得到的深度
- early z 不止会进行深度测试,通常还会开启深度写入
- 前面渲染的片元被丢弃,但是写入了深度,后续的像素就无法正常渲染了
- 开启Alpha Blend
- 开启Alhpa Blend需要关闭深度写入,所以就无法进行early z
- 关闭深度测试
- Unity的渲染顺序
- 不透明度物体:从前往后
- 半透明物体:从后往前(OverDraw)
- 透明物体相关问题
- 在渲染不透明物体时不怎么提渲染顺序,是因为有深度缓冲的存在(开启深度写入)
- 深度缓冲帮我们解决了可见性的问题(visibility)
- 当涉及到半透明物体渲染时,就要考虑的更周全一点了
- 并且是从后往前的渲染方式(OverDraw)
- Unity的渲染队列
- 队列越小渲染越早
- Background 1000
- Geometry 2000
- AlphaTest 2450
- Transparent 3000
- Overlay 4000
- AlphaTest
- AlphaTest不需要关闭深度写入
- 透明度测试并不能实现半透明效果,而是设置一个透明度的阈值,进行clip
- Dither效果
- 可以用AlphaTest结合屏幕坐标点阵效果来实现一些半透明
- 同时不用开启透明度混合,避免一些坑
- 还可以结合PreZ使用
- 在任天堂的游戏中常见
- 可以看看这位大佬的文章:Stipple Transparency - 点阵像素剔除半透明
- AlphaBlend
- 透明度混合能够实现真正半透明
- 需要关闭深度写入(并没有关闭深度测试)
- 混合模式:
- 公式:Orgb = SrcFactor × Srgb + DstFactor × Drgb
- 可以通过控制两个“混合因子”和“混合操作符”改变混合模式
- 什么是Pre-Z/Zprepass?(开启深度写入的AlphaBlend)
- 当物体本身模型比较复杂时,会因为关闭了深度写入而产生的错误的自身遮挡关系
- 这时就需要pre z 来解决
- Pre-Z:
- 做法1:双pass做法
- pass1:开启深度写入,但是不输出颜色,只是把深度信息写入缓冲区
- pass2:关闭深度写入,进行透明度混合
- 做法1的问题:
- 增加DrawCall
- 多pass shader无法进行动态批处理
- 做法2:提前分离的Zprepass
- Pre-Z的适用情况?
- 当场景的OverDraw很多的时候,可以考虑使用PreZ进行优化
- 注意,PreZ会增加DrawCall,如果用错了可能是负优化
- 双面渲染/背面剔除
- Unity默认是Cull back的
- 我们可以自己配置剔除
- cull back 剔除背面
- cull front 剔除正面
- cull off 关闭剔除
14.TBDR、IMR
- 关于GPU架构的一些名词
- Soc(System on Chip)
- Soc是把cpu、gpu、内存、通信基带、GPS模块等整合到一起的芯片
- 常见的:a系、m系、骁龙、麒麟、联发科
- System Memory
- 就是手机内存,Soc中cpu和gpu共用的一块物理内存
- On-Chip Memory
- CPU和GPU还分别有自己的高速SRAM的Cache缓存,读取速度要比System Memory快几倍到几十倍
- 但是很小
- IMR
- Immediate Mode Rendering,立即渲染架构
- 内容&特点:
- 整个渲染管线中的读写操作都是直接和显存交互的
- 是PC端的解决方案,相比TBR,效率更高,功耗也更高(每一次渲染完的Color和Depth数据写回到Frame Buffer和 Depth Buffer)
- TBR
- Tile-Based Rendering,基于块元的渲染(将屏幕分块渲染)
- 内容&特点:
- 是主流移动端的GPU架构
- 将屏幕划分块渲染,每个块就是一个tile(因为分块了,所以能够在on chip memory上进行计算)
- Tilling操作是在顶点处理,剔除、裁剪、投影之后进行的
- 流程:
- ①执行几何相关处理计算(计算数据时不用访问system memory,而是在on chip memory上完成的)
- ②进行光栅化和后续的处理,完成后从Tile Buffer写回到System Memory(Frame Buffer)
- TBR:VS -> Defer -> RS -> PS
- TBR的本质:将光栅化片元着色器的操作延迟到所有顶点着色器处理完之后再进行
- Defer的理解
- TBDR
- TBDR是PowerVR公司提出的在TBR基础上进行的硬件优化
- 在TBR的基础上又加了一个Derfer(光栅化到片元着色器中间),避免执行不必要的PS计算与相关资源调用的带宽开销,以达到最少的性能消耗和最高的渲染效率
- TBDR:VS -> Defer -> RS -> Defer -> PS
- PowerVR家第二步Defer叫作“HSR技术”,能够通过硬件层面解决OverDraw
15.纹理压缩
- 什么是纹理压缩?
- 为了解决内存占用、带宽问题,专门为了存储纹理而使用的图像压缩技术
- 纹理压缩格式和图片格式的区别?
- 图片压缩是基于整张图片进行压缩,不能发挥显卡的并行优点
- 纹理压缩是基于块进行压缩,支持快速访问,是GPU能直接进行采样的格式
- 常见的非压缩格式?
- RGBA32(8888)
- RGBA16(4444)
- RGB24(888)
- RGB16(565)
- 常见的压缩格式?
- DXT系列
- DirectX的标准压缩格式
- DXT1(BC1)
- 将4×4的像素块压缩成64位数据块
- 分别为:32位分给两个极端颜色值,32位分配给16个像素的颜色索引值(每个2)
- 主要用于没有Alpha信息
- DXT2/3(BC2)
- 128位数据块,比DXT1多64位给Alpha信息用,每一个像素多给4位信息,用来记录Alpha信息
- DXT2和3的区别:
- DXT2:已经完成了颜色与Alpha的混合,当透明度发生改变时,直接改变整体颜色值,不再单独进行复合
- DXT3:Alpha信息相对独立(分开压缩)
- DXT4/5(BC3)
- 128位数据块,多出的64位:2个8位的极端值(2*8),每个像素3位的索引值(16*3)
- Alpha信息是用过线性插值得来的
- Unity将贴图类型选为法线时,会采用DXTnm格式(基于DXT5)
- ATI1/2(BC4、BC5)
- ATI1(BC4)
- 64位数据块,每一个数据块中存储的是单个颜色通道的数据
- 主要用于存储高度图等单通道信息
- ATI2(BC5)
- BC6/7
- BC6和BC7仅在D3D11及以上图形硬件中受到支持
- 每个块16位
- BC6:
- 针对HDR的压缩算法,针对RGB半精度浮点数数据进行压缩
- BC7:
- 针对LDR的压缩算法,针对8位RGB或RGBA的图像进行压缩
- ETC
- OpenGL选择了爱立信研发的ETC格式
- 64位,将4×4的像素块编码为两个2×4或4×2的块
- 2*12位基础颜色信息(RGB444*2 或者RGB333+RGB555)
- 2*16位像素索引信息
- 2*3 位亮度索引信息
- 2*1 位filp信息(控制竖直还是水平划分)
- ETC2在1的基础上支持了Alpha通道
- ASTC
- ASTC是由ARM和AMD联合开发的纹理压缩格式
- 压缩算法和BC7类似,固定128位数据块,块中的像素从4×4到12×12都有
- 同时支持HDR和LDR
- 图片长宽可以不是2的次幂
- 可以根据不同图片选择不同压缩率的算法
- PVRTC
- PowerVR显卡的专用格式
- 不是基于块的算法,而是将图像分为了低频和高频信号
- 各自的压缩比是多少?
- DXT1 6:1
- DXT2/3 4:1
- DXT4/5 4:1
- ATI1 4:1
- ATI2 4:1
- BC6 6:1
- BC7 3:1
- ETC1 6:1
- PVRTC 6:1
- ASTC 4:1~35.95:1
- 画质:
- RGBA > ASTC 4×4> ASTC6×6 > TEC2 ≈ ETC1
- 实际应用中的选择?
- 手机端比较常用ASTC(安卓ios通用)
- IOS端
- 低质量可以用PVRTC2(支持Iphone6以下版本)
- PC端
16.阴影
- shadowmap
- 本质上是基于图像空间的做法(生成shadow这一步不需要这个场景的几何信息)
- 只能做硬阴影
- 理解原理:
- 我们能看到 + 光能看到 = 渲染
- 我们能看到 + 光看不到 = 阴影
- 做法:
- 双pass做法:
- 从光源看场景记录深度
- 从相机看场景记录深度
- 比较深度:
- 深度一致:我们和光都能看到 ->正常渲染
- 深度不一致:我们能看到,光看不到 ->阴影
- Unity中屏幕空间阴影步骤:
- 渲染屏幕空间深度图
- 从光源方向渲染shadowmap
- 屏幕空间做一次阴影收集计算(比较前两张图的深度),得到一张屏幕空间的shadowmap
- 绘制物体时,用屏幕坐标uv采样shadowmap
- shadowmap问题:
- 问题1:自遮挡
- 因为分辨率有限,会造成自遮挡现象(实际是红色,被自身的橙色部分遮挡了)
- 解决:
- 深度偏移、法线偏移(偏移单位为shadowmap的纹素)
- 问题2:走样
- 解决方法:级联阴影映射:给shadowmap不同位置不同的分辨率
- 硬阴影和软阴影的区别:
- 硬阴影没有一个明显的从有阴影到没有的过度/界限(因为绝大多数的生活中的光源是面光源)
- 软阴影做法
- PCSS和PCF
- PCF最早是用来做阴影反走样的
- 用PCF作软阴影就是PCSS
- 太菜了,具体做法就省略了,没有完全搞明白
- PCSS的缺点:
- 开销恐怖(第一步和第三步要每个texel走一遍)
- 优化方案:稀疏采样再降噪
- VSSM
- Moment Shadowmapping
- 因为VSSM做了大量的近似,所以会有分布描述不准的问题
- Moment Shadowmapping解决了分布不准的问题
17.抗锯齿/反走样
- 只做了简单了解,GAMES101中提过一些
- 反走样思路:
- 一些抗锯齿方式:
- MSAA(Multisample)
- 只是在光栅化阶段,判断一个三角形是否被像素覆盖的时候会计算多个覆盖样本(片元着色阶段还是每个像素计算一次)
- 缺点:不兼容延迟渲染
- SSAA(Super Sample)
- 模糊的一个近似做法,通过增加采样点实现
- 每个采样点扩大到四个,再做平均
- TAA-时间抗锯齿
- FXAA(Fast Approximate)
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|