第七章实时图形渲染管道 学习打卡
渲染方程
- 从二维/三维模型生成图像,数学上可用渲染方程(The Rendering Equation)表示
参数说明如下:
L
o
(
x
,
w
⃗
)
表
示
x
点
朝
w
方
向
射
出
的
辐
射
(
r
a
d
i
a
n
c
e
)
L
e
(
x
,
w
⃗
)
表
示
物
体
在
x
点
自
身
朝
w
方
向
射
出
的
r
a
d
i
a
n
c
e
∫
O
m
e
g
a
⋅
⋅
⋅
d
w
′
⃗
半
球
上
所
有
入
射
光
方
向
的
积
分
L
i
(
x
,
w
′
⃗
)
w
′
方
向
入
射
光
的
r
a
d
i
a
n
c
e
c
o
s
θ
光
照
递
减
L_o(x,\vec{w})表示x点朝w方向射出的辐射(radiance) \\ L_e(x,\vec{w})表示物体在x点自身朝w方向射出的radiance \\ \int_{Omega}···d\vec{w^{'}}半球上所有入射光方向的积分 \\ L_i(x,\vec{w^{'}})w'方向入射光的radiance \\ cosθ光照递减
Lo(x,w)表示x点朝w方向射出的辐射(radiance)Le(x,w)表示物体在x点自身朝w方向射出的radiance∫Omega⋅⋅⋅dw′半球上所有入射光方向的积分Li(x,w′)w′方向入射光的radiancecosθ光照递减
渲染方程如下:
- 从x’到x的光 = 从x’自发出的光 + 全部从四面八方射到x’然后再散射到x方向的光(x‘为光线入射到物体的某一点)
L o ( x , w o ) = L e ( x , w o ) + ∫ Ω L i ( x , w ′ ⃗ ) f r ( w ⃗ , x , w ′ ⃗ ) c o s θ d w ′ ⃗ L_o(x,w_o)=L_e(x,w_o)+\int_Ω^{}L_i(x,\vec{w^{'}})f_r(\vec{w},x,\vec{w^{'}}) cosθd\vec{w^{'}} Lo(x,wo)=Le(x,wo)+∫ΩLi(x,w′)fr(w,x,w′)cosθdw′
深度缓冲
- 深度缓冲可看作是一个记录颜色的纸,后的图像与之前的深度缓冲比较结果,如下图黄色的三角形,小于等于5的就画,大于5的不画,其余的∞(未填充的)也画,后可得出右下角的这个结果图
空间分割技术
- 使用空间分割技术加速场景查询
- 二元空间分割(BSP)
- 八叉树(octree)
- 入口(portal)、反入口(anti-portal)
可见性检测
- 找出摄像机可看的渲染物体
- 平截头体剔除(view frustum culling)
- 摄像机外的物体不会渲染
- 遮挡剔除(occlusion culling)
- 被遮挡的物体不会渲染
- 细节层次剔除(level-of-detail/LOD culling)
分组和排序
- 通常按照渲染层(layer)分组
- 不透明物体由近到远进行绘制
- 半透明物体不能用z-buffer(深度缓冲)排序
- 先绘制不透明物体
- 之后对于半透明物体用画家算法从后往前排序
- 但是两个物体不一定有全序关系
- 如需要解决这一问题,需要使用次序无关透明技术(Order Independent Transparency,OIT)
- 查看渲染顺序的工具:RenderDoc(记录CPU提交GPU的指令)
提交图元
- 提交图元(primitive)就是所谓的drawcall(unity中也有该专有名词)
- 由应用阶段输出数据给接下来的阶段
- 提交前需要设置图元数据和渲染状态
图元:顶点数据与索引数据
- 顶点数据通常储存在顶点缓冲区(vertex buffer,vb)
- 索引通常储存在索引缓冲区(index buffer,ib)
顶点着色可以实现的效果
- 在顶点着色器(vertex shader)中可以实现顶点位移相关的效果,如顶点动画,骨骼蒙皮动画,平面阴影效果
- 计算每个顶点,可以实现纹理的坐标动画和顶点光照的计算
一些可选的着色器
- 几何着色器
- 几何着色器以一个或多个表示为一个单独基本图形的顶点作为输入,比如可以是一个点或者三角形。几何着色器在将这些顶点发送到下一个着色阶段之前,可以将这些顶点转变为它认为合适的内容
- Tessellation相关的Hull Shader和Domain Shader(用作曲面细分等)
朝向剔除
- 缠绕顺序(winding order)决定面的正反面
- 朝向提出时可以选择剔除屏幕空间中的cw(clockwise即顺时针)的面或者ccw(counter-clockwise即逆时针)的面,即不对物体的背面进行渲染
- 朝向提出时可以选择剔除屏幕空间中的cw(clockwise即顺时针)的面或者ccw(counter-clockwise即逆时针)的面,即不对物体的背面进行渲染
- Unity默认将CW设为正面,CCW设为反面
- OpenGL默认将CCW设为正面(glFrontFace(GL_CCW);)
输出合并
- 深度测试(前后遮挡关系挡住一部分)
- 模板测试(UI、逻辑操作手动设置的遮挡关系)
前向管线
- Forward Rendering是一种被大多数引擎所使用的比较传统的渲染技术,显卡(GPU)通过将应用程序阶段(CPU)所传递给它的Geometry拆解成顶点,并将其变换(transformed)和分解成为片段(fragment)或者像素,从而进入显示到屏幕前的最后的渲染操作阶段(final rendering treatment)。前向渲染的一个典型特征是一个几何体(Geometry)从传入显卡进行处理到最后屏幕显示图形的整个过程是不间断的,它是一个线性的处理过程。
- 在前向管线中,如果有m个物体,n个光源,则最终需要计算m*n次
- 上图的四个Geometry,对应了四个Drawcall,VS(Vertex Shader)、GS(Geometry Shader)、FS(Fragment Shader),最后到达RenderTarget的阶段的过程是不会被终端的,RenderPipe(渲染管道)一次处理一个Geometry
- 这就是常说的Forward Rendering
延时管线
- 不在顶点着色器中计算光照,先将几何物体放入RT缓冲(buffer)中,RT记录物体颜色和它的法线等,全部记录完后再用N个光源对RT进行计算
- 在延时管线中,如果有m个物体,n个光源,则最终需要计算m+n次
Drawcall
- 发送方为CPU,接收方为GPU,即CPU发送命令给GPU,命令指向需要被渲染的图元列表等数据
场景管理
特别适合大规模的广阔室外场景管理。
一般来说如果游戏场景是基于地形的(甚至没有高度)(如城市、平原、2D场景),那么适合用四叉树来管理。
而如果游戏场景在高度轴上也有大量物体需要管理(如太空、高山),那么适合用八叉树来管理。
顶点着色:模型变换
模型(如网格)通常定义于模型空间
为了把一个模型渲染成多个实例,会把模型的顶点位置V_model变换到世界空间
V
w
o
r
l
d
=
M
m
o
d
e
l
−
>
w
o
r
l
d
V
M
m
o
d
e
l
V_{world}=M_{model->worldV}M_{model}
Vworld=Mmodel−>worldVMmodel
M
m
o
d
e
l
−
>
v
i
e
w
又
称
为
世
界
矩
阵
M_{model->view}又称为世界矩阵
Mmodel−>view又称为世界矩阵
裁剪计算
齐次裁切空间的坐标在[-1,+1]的范围,规定w>0,那么不在下面范围的三角形部分将被裁掉
−
1
<
x
w
<
1
−
1
<
y
w
<
1
−
1
<
z
w
<
1
−
w
<
x
<
w
−
w
<
y
<
w
−
w
<
z
<
w
-1<\frac{x}{w}<1 \;\;\;\;\;-1<\frac{y}{w}<1 \;\;\;\;\;\;-1<\frac{z}{w}<1 \\ -w<x<w \;\;\;\;\; -w<y<w \;\;\;\;\;-w<z<w
−1<wx<1−1<wy<1−1<wz<1−w<x<w−w<y<w−w<z<w
渲染管线阶段说明:
- 应用阶段:找出场景中需要渲染的物体,将这些物体的图元提交到GPU
- 几何阶段:处理和变换几何图元
- 光栅化阶段:把几何形状光栅化,计算每个像素的输出颜色
本博文参考资料:
八叉树/BVH树/四叉树
前向管线和延时管线
渲染方程