render pipe

图形渲染管道

给定一个虚拟相机,三维物体模型,光源,着色方程,纹理等,通过渲染管道产生或渲染一张二维图像。

粗略的划分实时渲染管道:

  • application stage
  • geometry stage
  • rasterizer stage

简述

  • The Application Stage

    此阶段开发者拥有完全的控制,负责产生渲染图元(rendering primitives)传递到几何管道阶段。以及其他控制,如碰撞检测,分层视锥剔除等

  • The Geometry Stage

    负责大部分每多边形或每顶点操作,同时分成许多其他功能阶段

    • 模视变换 (model and view transform)
    • 顶点着色 (vertex shading)
    • 投影 (projection)
    • 裁剪 (cliping)
    • 屏幕映射 (screen mapping)

    功能阶段简述

    • 模视变换

    模型处于自己的模型空间(model space),通过模型变换作用于顶点和法线(vertices,normals)可改变其位置、方向、大小、形状等。变换后模型处于世界空间(world space)。相机位于世界空间,为了方便投影和裁剪,相机和所有的模型都通过视变换变换到视空间(view space)。视变换的目的视将相机放置在坐标空间原点,使它看向-z方向,朝上方向为+y,朝右方向为+x。具体依赖于相应的API。

    • 顶点着色

    描述模型的外观,如材质、光照影响。光作用于材质被称为着色(shading)。顶点着色的结果被传入光栅阶段插值。

    • 投影

    将视空间变换为单位立方体,称为规范立方体(canonical view volume),坐标范围为(-1,-1,-1)到(1,1,1)。常用投影包括,正交投影和透视投影。正交投影后平行线保持平行。透视投影平行线将在远处交会,几何上将视空间称为视锥(frustum)。经过变换,模型处于标准设备坐标系(normalized device coordinates)。此过程中,模型将从三位变为二维,z轴信息不包含在图像中。

    • 裁剪

    当图元部分处于视体之外,需要将之裁剪,因为这部分不会显示在屏幕上,无需处理。

    • 屏幕映射

    图元的x,y坐标转化为屏幕坐标(screen space),屏幕坐标和z轴坐标被称为窗口坐标(window coordinates),OpenGL规定像素的中点为0.5,d 为像素的离散索引, c 为表示像素内的连续浮点值。OpenGL图像原点在左下角,DirectX通常在左上角

    
    d = floor(c), 
    
    c = d + 0.5,
    
  • The Rasterizer Stage

    计算和设置物体表面像素的颜色,称为光栅化(rasterization)或者扫描转换(scan conversion)。

    同时分成许多其他功能阶段

    • 三角形设置 (Triangle Setup)
    • 三角形遍历 (Triangle Traversal)
    • 像素着色 (Pixel Shading)
    • 合并 (Merging)

    功能阶段简述

    • 三角形设置

    计算三角形表面的差异以及其他数据。数据用来进行扫描转换,同时将几何阶段多种着色数据进行插值。

    • 三角形遍历

    检查每个像素的中心或者采样是否被三角形覆盖,并且为被覆盖的像素生成一个片段(fragment)。每个三角形的片段属性通过三个顶点插值产生,包括片段的深度,以及其他着色数据。

    • 像素着色

    使用经过插值的着色数据计算每像素着色。通常使用颜色或者纹理贴图(Texture)。

    • 合并

    每个像素的信息存储在颜色缓冲中(color buffer),是一个颜色数组,存储(R,G,B)值,此阶段将这些信息合并成片段颜色。同时此阶段会决定片段的可见性,通常使用深度缓冲Z-buffer(depth buffer)算法决定处于相机视体中可见场景的颜色,并把它们存储在颜色缓冲中。深度缓冲和颜色缓冲拥有相同的大小和形状,并且存储了距离相机最近图元相应像素的z值。如果某图元某像素z值小于存储于深度缓冲中的z值,则将深度缓冲的z值更新为此像素z值,同时更新颜色缓冲中相应像素的颜色为此像素的颜色。反之,深度缓冲和颜色缓冲保持不变。

    Z-buffer算法拥有线性时间复杂度,并且可以以任意顺序渲染大部分图元。但是,对于透明图元必须在不透明图元渲染完成之后渲染,并且透明图元之间必须从后往前渲染。

    透明通道(alpha channel)存储每个像素的不透明度。可选的透明度测试(alpha test)可以在深度测试之前先处理片段,如果测试失败可以丢弃相应的片段。它通常用来保证全透明片段不会影响Z-buffer。

    模板缓冲(stencil buffer),用来做模板测试(stencil test),是一个用来记录被渲染图元位置的离屏缓冲。通常每像素8位。可以将图元通过多种方法渲染到模板缓冲中,用它来控制如何渲染图元到颜色缓冲和深度缓冲,从而产生特殊的效果。这些方法被称为光栅操作(raster operations, ROP)或者混合操作(blend operations)。

    帧缓冲(frame buffer)包含系统中所有的缓冲,通常只使用颜色缓冲和深度缓冲。

    使用双缓冲(double buffering)技术,可以避免屏幕出现像素的绘制过程。在背景缓冲(back buffer)中渲染下一帧,渲染完成后将内容交换给前景缓冲(front buffer),交换发生在垂直消隐期间(vertical retrace)。

图形处理单元

综述

image
  • 可编程着色阶段

    shader virtual machine.png

    uniform(constant) inputs:在一个draw call中保持不变

    varying inputs:因为每个顶点或像素而不同

  • 顶点着色器

    处理三角网格(顶点和相关信息的集合),修改、创建或忽略顶点相关的值,比如颜色、法线、纹理坐标、位置等。通常将顶点从模型空间转换到齐次裁剪空间,或者仅仅输出位置。

    顶点着色器不可以创建或者删除顶点,以及一个顶点产生的结果不可以传给另一个顶点。顶点之间相互独立。

    通过顶点着色器产生特效:

    • 创建阴影视体 (shadow volume creation)
    • 运动关节的顶点混合 (vertex blending for animating joints)
    • 轮廓渲染 (silhouette rendering)
    • 透镜效果(lens effects),鱼眼视角畸变,水下物体畸变


      vertex shader effects.png
    • 物体定义,创建一次网格,通过变换获得其他物体
    • 物体扭曲(twist),混合(blend),锐化(taper)操作
    • 程序性变形(procedural deformations),旗、布料或水的运动
    • 页面卷曲(page curls)、热霾(heat haze)、水波(water ripples)等,通过将整个帧缓冲的内容作为纹理,对其施加程序性变形。
    • 顶点纹理拾取(vertex texture fetch),将纹理作用于顶点网格,是产生海洋表面和地形高度场的经济手段。
  • 几何着色器

    可选的。通常输入是单个物体和其相关联的顶点,比如三角形、线段、点等。


    geometry shader input.png

    处理输入图元,输出0个或多个新图元。输出点、多边形、三角形序列。一个顶点的数据可以施予另一个顶点。输出的每个顶点必须位于齐次裁剪空间。

    几何着色器保证图元的输出顺序和输入顺序一致。

    geometry shader using.png
  • 像素着色器

    遍历每个三角形,顶点各值在其覆盖的三角形区域插值,计算每个像素的颜色。OpenGL称之为片段着色器(fragment shader),材质是不透明的或者透明的三角形片段覆盖每个像素的全部或者部分区域。

    像素着色器只能影响其处理的片段,当着色程序执行后,不可将结果直接传给相邻像素,只可以通过顶点数据、相关常量、纹理数据插值来影响一个像素。然而,相邻像素可以通过图像处理技术来施加影响。

    其中一种情形是,像素着色器可以通过计算梯度或者微分信息,访问邻接像素的信息。像素着色器可以基于随屏幕坐标x或y变化的每个像素,获取任何值并计算其和,这可以用与多种计算和纹理寻址。梯度对于像素过滤操作有很重要作用。

    像素着色器设置片段的颜色,用于合并阶段进行颜色合并。光栅化阶段产生的深度值也可以在像素着色器中修改。模板缓冲的值是不可在此修改,而是直接传入到合并阶段。

    此着色器也可以丢弃一些片段的数据。如在烟雾计算和透明测试中,丢弃一些未通过测试的颜色。

    得益于可以在单个渲染阶段同时计算任何数目的值,产生了MRT(multiple render targets)。可以为每个片段产生多个矢量,并存到不同的缓冲中而不是仅仅把着色器渲染的结果存到但一个颜色缓冲中。这些缓冲必须具有同样的维数,一些架构需要相同的深度位数。但是这些缓冲具有一些限制,比如没有反锯齿处理。

  • 合并阶段

    此阶段将各片段深度和颜色组合成帧缓冲,模板缓冲和Z缓冲操作发生在此阶段。颜色混合操作亦发生在此。

    此阶段虽然不可编程,但具有高度可配置性。例如颜色混合的多种操作,加、乘、减、取最大、最小值、位运算等。

  • 特效

    通过组合不同的顶点、几何、像素着色器可以产生不同的渲染效果。

    一次pass通常包含一个顶点、几何、像素着色器,以及相关的状态设置。
    一个technique是一个或多个用来产生所需特效的pass集合。

变换

  • 线性变换:可加性,齐次性。缩放、旋转是线性变换

    f(x) + f(y) = f(x + y)
    
    kf(x) = f(kx)
    
  • 仿射变换:线性变换+平移变换

    • 矢量 $\vec{v} = (v_x \quad v_y \quad v_z \quad 0)^T$

    • $\vec{v} = (v_x \quad v_y \quad v_z \quad 1)^T$

    仿射矩阵保持平行性不变,但不保持长度和角度不变

    transform notation.png
  • 基本变换

    • 平移(刚体变换,rigid-body transform)

      Translation:
      
      T(\vec{t})=T(t_x,t_y,t_z)=
      \begin{pmatrix}
          1&0&0&t_x\\
          0&1&0&t_y\\
          0&0&1&t_z\\
          0&0&0&1
      \end{pmatrix}
      
      T^{-1}(\vec{t})=T(-\vec{t})
      
    • 旋转(刚体变换,rigid-body transform)

      变换保持点之间的距离,不改变点的相对关系。为单位正交矩阵。

      Rotaion:
      
      R_x(\phi)=
      \begin{pmatrix}
      1&0&0&0\\
      0&\cos\phi&-\sin\phi&0\\
      0&\sin\phi&\cos\phi&0\\
      0&0&0&1
      \end{pmatrix}
      
      R_y(\phi)=
      \begin{pmatrix}
      \cos\phi&0&\sin\phi&0\\
      0&1&0&0\\
      -\sin\phi&0&\cos\phi&0\\
      0&0&0&1
      \end{pmatrix}
      
      R_z(\phi)=
      \begin{pmatrix}
      \cos\phi&-\sin\phi&0&0\\
      \sin\phi&\cos\phi&0&0\\
      0&0&1&0\\
      0&0&0&1
      \end{pmatrix}
      
      tr(R_{3\times3})=1+2\cos\phi
      
      R_i^{-1}(\phi)=R_i(-\phi)
      
      \phi : \text{radians}
      
      x-,y-,z-:\text{coordinate axis}
      
      X=T(p)R_z(\phi)T(-p)
      
    • 缩放

      Scaling:
      
      S(\vec{s}) = \begin{pmatrix}
      s_x&0&0&0\\
      0&s_y&0&0\\
      0&0&s_z&0\\
      0&0&0&1
      \end{pmatrix}
      
      S^{-1}(\vec{s})=S(1/s_x,1/s_y,1/s_z)
      
      X=FS(\vec{s})F^T,\quad F=\begin{pmatrix}
      \vec{f}^x&\vec{f}^y&\vec{f}^z&\vec{0}\\
      0&0&0&1
      \end{pmatrix}
      
      \vec{f}^x,\quad\vec{f}^y,\quad\vec{f}^z\quad \text{标准正交}
      

      如果有一个或三个因子为负数,则成为反射矩阵(reflection matrix)或镜像矩阵(mirror matrix);如果有两个因子为-1,则旋转 $\pi$ 弧度。

      通过计算 $detS(S_{3\times3})$,如果为负则为反射矩阵。

    • 切变

      Shearing:
      
      H_{xz}(s)=\begin{pmatrix}
      1&0&s&0\\
      0&1&0&0\\
      0&0&1&0\\
      0&0&0&1
      \end{pmatrix}
      
      \text{在x,z平面处理切变}
      
      H^{-1}_{ij}(s)=H_{ij}(-s)
      
      \det{H}=1
      
      H_{ij}\text{随着j轴变换相应切变i轴}
      
    • 变换组合

      C=TRS=(TR)S
      
      TR \quad \text{称为刚体变换矩阵}
      
      \acute{p}=Cp
      
    • 刚体变换

    X=T(\vec{t})R=\begin{pmatrix}
    r_{00}&r_{01}&r_{02}&t_x\\
    r_{10}&r_{11}&r_{12}&t_y\\
    r_{20}&r_{21}&r_{22}&t_z\\
    0&0&0&1
    \end{pmatrix}
    
    \text{逆变换}
    X^{-1}=(T(\vec{t})R)^{-1}=R^{-1}T(\vec{t})^{-1}=R^TT(-\vec{t}),
    
    \text{或}
    R_{3\times3}=(\vec{r}_{,0}\quad\vec{r}_{,1}\quad\vec{r}_{,2})=\begin{pmatrix}
    r^T_{0,}\\
    r^T_{1,}\\
    r^T_{2,}
    \end{pmatrix},
    
    X=\begin{pmatrix}
    R_{3\times3}&\vec{t}\\
    \vec{0}^T&1
    \end{pmatrix}
    
    \text{则}X^{-1}=\begin{pmatrix}
    R_{3\times3}^T&-R_{3\times3}^T\vec{t}\\
    \vec{0}^T&1
    \end{pmatrix}
    
    =\begin{pmatrix}
    \vec{r_{0,}}&\vec{r_{1,}}&\vec{r_{2,}}&-R_{3\times3}^T\vec{t}\\0&0&0&1
    \end{pmatrix}
    
    • 法线变换

    the transpose of the matrix’s adjoint;平移变换不会影响,统一缩放会改变法线的长度

    \acute{A}=(A^*)^T
    
    • 计算矩阵的逆

      • 如果矩阵是由给定参数生成的单变换或者一系列单变换的组合,则只需将参数置为负,然后反序乘各个变换$M=T(\vec{t})R(\phi)$则,$M^{-1}=R(-\phi)T(-\vec{t})$
      • 如果矩阵正交,则$M^{-1}=M^T$,如旋转矩阵
      • 标准方法求逆
  • 欧拉变换

    image.png
    E(h,p,r)=R_z(r)R_x(p)R_y(h)
    
    • gimbal lock问题,旋转使得丢失了一个自由度;例如验证$p=\pi/2$时,E只与$(r+h)$有关。
    • 不同旋转可能得到相同结果
    • 不利于旋转组合,不利于插值
    E(h,p,r)=\begin{pmatrix}
    f_{00}&f_{01}&f_{02}\\
    f_{10}&f_{11}&f_{12}\\
    f_{20}&f_{21}&f_{22}
    \end{pmatrix}
    
    =\begin{pmatrix}
    \cos{r}\cos{h}-\sin{r}\sin{p}\sin{h}&
    -\sin{r}\cos{p}&\cos{r}\sin{h}+\sin{r}\sin{p}\cos{h}\\
    \sin{r}\cos{h}+\cos{r}\sin{p}\sin{h}&\cos{r}\cos{p}&
    \sin{r}\sin{h}-\cos{r}\sin{p}\cos{h}\\
    -\cos{p}\sin{h}&\sin{p}&\cos{p}\cos{h}
    \end{pmatrix}
    
    ==>h=atan2(-f_{20}, f_{22}),
    
    p=arcsin(f_{21}),{-\pi/2 \leq p \leq \pi/2}
    
    r=atan2(-f_{01}, f_{11}),
        
    \text{当} \cos{p}=0\text{时},f_{01}=f_{11}=0,\sin{p}=1\text{或}\sin{p}=-1,\text{则}
    
    E(h,p,r)=\begin{pmatrix}
    \cos{(r \pm h)}&0&\sin{(r \pm h)}\\
    \sin{(r \pm h)}&0&-\cos{(r \pm h)}\\
    0& \pm &0
    \end{pmatrix}
    
  • 矩阵解压

    • 获取缩放变换因子
    • 根据不同需要获取特定变换
    • 判断一个模型是否使用刚体变换
    • 对于物体动画关键帧的插值,要获取物体相关的变换矩阵
    • 从旋转矩阵中移除切变
  • 任意轴旋转


    image.png
    • 先将$(\vec{r}\quad\vec{s}\quad\vec{t})$变换到标准正交坐标系
    • 再绕x轴旋转$\alpha$
    • 再将坐标轴变换回去
    M=\begin{pmatrix}
    \vec{r}^T\\
    \vec{s}^T\\
    \vec{t}^T
    \end{pmatrix}
    
    X=M^TR_x(\alpha)M
    
    image.png
  • 四元数

  • 顶点混合(vertex blending,skinning,enveloping,skeleton-subspace deformation)

    例如手臂关节处,通过将相关上肢和下肢的顶点进行加权变换,是的关节处更符合实际。

    u(t)=\sum_{i=0}^{n-1}w_iB_i(t)M_i^{-1}p,where\quad\sum_{i=0}^{n-1}w_i=1,\quad w_i \geq0.
    
    • $p$是原始顶点,处于世界坐标系
    • $u(t)$是随时间变化的变换后的顶点
    • $n$表示有$n$个骨骼影响$p$
    • $M_i$是将初始骨骼变换到世界坐标系的矩阵
    • $B_i(t)$是第$i$个骨骼的随时间变化世界变换矩阵,用来表示骨骼运动
    • $w_i$是第$i$个骨骼施于点$p$的权重

    缺点是可能造成折叠、扭曲以及骨骼相互重叠,使用dual quaternions可以保持变换的刚体性,并且计算量小于线性混合的1.5倍。

  • Morphing

    一个物体在$t_0$的时候是一个样子,在$t_1$的时候是另一个样子,则可以通过使用某种插值,获得物体在$t_0 \to t_1$过程中连续的样子。而起始和结束的样子称为morph targets或者blend shapes

    morphing 一般包含两个问题

    • 顶点对应(vertex correspondence)
    • 如何插值(interpolation)
    image.png
    M=N+\sum_{i=1}^{k}w_iD_i
    
    • $M$为最终的样子
    • $N$为初始样子
    • $D_i$为不同的终变化样子
  • 正交投影

    投影后保持平行线的平行性


    image.png

你可能感兴趣的:(render pipe)