图形学笔记——光栅化

Rasterization

一、总体过程以及思路

光栅化的本质是基于对象的渲染,这种渲染的思路以每个图元为出发点,根据图元来计算每个像素点的着色,与此相对光追是以像素点为出发点,每个像素独立计算其着色。光栅化的过程如下,这个过程也就是所谓的渲染管线:

  1. 顶点处理:其实就是投影(也就是Projection文件中所写的过程),在这个过程最终生成了要处理的图元作为下一步的输入。
  2. 光栅化:以图元和顶点为基础,通过变化来把图元的颜色和各种属性计算/插值到像素,形成片元,片元就是带有各种数学的像素点。
  3. 片元处理:这个过程就是shader工作的过程,此处不做详细解释,这个文件重点在光栅化,输出的结果也汇入片元的属性中。
  4. 混合:根据片元中的属性来进行绘画,只有这一步才会真的生成画在屏幕上的图形,z-buffer的处理在这一步。

二、直线的光栅化(中点算法)

对于直线来讲,其实只需要关系画出来的问题,三维的复杂场景一般不会出现纯直线的图形,就是在二维情况下的讨论。

只说斜率属于(0, + ∞ +\infty +)对于直线上一点(x,y),下一步要画的点一定是(x+1,y)和(x+1,y+1)的其中一个,至于怎么确定,方法如下:

  1. 计算直线方程f(x,y)
  2. 将(x+1,y+0.5)带入f(x,y)
  3. 如果直线在该点之上,则画(x+1,y+1),否则画(x+1,y)

很明显思路就是把看直线在两者终点上面还是下面,所以叫做中点算法。

三、三角形的光栅化

这一步其实就是光栅化的核心,因为三维的物体模型大多用三角形的面来组成。步骤如下:

  1. 在世界空间中对三角形中的像素点所有点进行插值
  2. 处理三角形边界颜色计算问题
  3. 根据上一步中的结果映射到纹理空间

这里面的世界空间就是摄像机所在的三维空间,纹理空间就是要映射到的二维平面,这和屏幕的二维空间不同,是指纹理分布的二维空间。这个过程只对三角形中间的插值点管用,因为三角形的顶点的纹理坐标一定是知道的。

3.1 对世界空间的三角形插值

基本思路是根据三角形三个顶点的属性,然后对三角形内部的所有点进行一个平滑的插值,这个属性现在以颜色为例。

3.1.1 barycentric 坐标系

这个坐标系的思路如下:把三角形的两条边作为基,便可以表示三角形内的任何一个点,而且坐标一定都属于(0,1)之内,凡是坐标中为1的点就是顶点,也就是坐标轴为其对边。

以这个思想,三角形内的任何一点,都可以表示为(a,b,c),如果三角形的顶点分别为1,2,3.则点1的坐标为(1,0,0),点2的坐标为(0,1,0),点3的坐标为(0,0,1)。点p的坐标(a,b,c)的计算如下:
a = f 23 ( p ) / f 23 ( p i o n t 1 ) ( 1 ) a = f_{23}(p)/f_{23}(piont1) \qquad\qquad (1) a=f23(p)/f23(piont1)(1)
其他两个值的计算和(1)式类似。

故对于三角形内的任意一点 p = ( a , b , c ) p =(a,b,c) p=(a,b,c),如果已知其顶点的颜色 c i c_i ci,则 p p p点的颜色可进行如下插值:
c p = a ⋅ c 1 + b ⋅ c 2 + c ⋅ c 3 c_p=a\cdot c_1 + b \cdot c_2 + c\cdot c_3 cp=ac1+bc2+cc3

3.1.2 对于边界问题的处理

如果两个三角形有相同的边,那这条边按照哪个三角形进行计算就成了问题,最糟糕的做法就是把这条边空出来不着色,因为这样会留下很多三角形之间的缝隙显示在屏幕上,所以可以按照其中某一个三角形进行着色,至于是哪个无所谓,只要选定就好了。

选定三角形的方法可以选择屏幕外固定一点,判断这一点和重叠边相对的顶点是否在重叠边的同一边,无论选择和相对顶点在同一遍的三角形,还是不在同一边的三角形都无所谓,关键是要选一个。

3.2 对于纹理空间的映射

为什么会有这一步呢?因为顶点处理输出的图元信息都是符合透视的近大远小,但是如果把世界空间的点 [ x y z w ] \left[\begin{matrix} x\\ y \\z \\w \end{matrix}\right] xyzw 的属性直接映射到纹理空间的点 [ x y ] \left[\begin{matrix} x\\y \end{matrix}\right] [xy]就会出现属性的扭曲,因为到纹理空间的这一步映射只是简单的正交投影,而没有符合近大远小的规定,相当于图形虽然近大远小,但是颜色变化却是均匀的不符合图形的变化。

为了解决这一问题,思路就是把到纹理空间的坐标 [ u v ] \left[\begin{matrix} u\\v \end{matrix}\right] [uv]这两个分量也作为三角形的属性进行插值,最后插值的结果才是点 [ x y z w ] \left[\begin{matrix} x\\ y \\z \\w \end{matrix}\right] xyzw 应该映射到的地方。具体的计算方法如下:

  1. 把点 [ x y z w ] \left[\begin{matrix} x\\ y \\z \\w \end{matrix}\right] xyzw 齐次化为 [ x / w y / w z / w 1 ] = [ x s y s z s 1 ] \left[\begin{matrix} x/w\\ y/w \\z/w \\1 \end{matrix}\right] = \left[\begin{matrix} x_s\\ y_s \\z_s \\1 \end{matrix}\right] x/wy/wz/w1 = xsyszs1 ,包括顶点也做类似处理

  2. 计算 ( u s , v s ) (u_s,v_s) (us,vs),如下
    u s = a ⋅ u 1 / w 1 + b ⋅ u 2 / w 2 + c ⋅ u 3 / w 3 v s = a ⋅ v 1 / w 1 + b ⋅ v 2 / w 2 + c ⋅ v 3 / w 3 u_s = a\cdot u_1/w_1 + b \cdot u_2/w_2 +c\cdot u_3/w_3 \\ v_s = a\cdot v_1/w_1 + b \cdot v_2/w_2 +c\cdot v_3/w_3 us=au1/w1+bu2/w2+cu3/w3vs=av1/w1+bv2/w2+cv3/w3
    其中 ( u i , v i ) (u_i,v_i) (ui,vi)为三角形的三个顶点的纹理坐标

  3. 计算 w w w,如下:

    $w = a\cdot w_1 + b \cdot w_2 +c\cdot w_3 $

  4. u = u S ⋅ w v = v S ⋅ w u = u_S \cdot w \\v = v_S \cdot w u=uSwv=vSw

    为什么要多出第三步和第四步呢,因为并不能确定纹理空间的坐标,也就是给了你纹理你不知道往物体哪里贴,给了你属性你也不知道加载在纹理的哪个地方,因为纹理空间的坐标是和 [ x y z w ] \left[\begin{matrix} x\\ y \\z \\w \end{matrix}\right] xyzw 带着w的那个缩放一致的,也就是说纹理空间的坐标如果作为 [ x y z w ] \left[\begin{matrix} x\\ y \\z \\w \end{matrix}\right] xyzw 的一个属性有这种形式: [ x y z w u v ] \left[\begin{matrix} x\\ y \\z \\w \\ u \\v \end{matrix}\right] xyzwuv ,而屏幕空间的坐标实际上是这种形式 [ x / w y / w z / w 1 u s v s ] \left[\begin{matrix} x/w\\ y/w \\z/w \\1 \\ u_s \\ v_s \end{matrix}\right] x/wy/wz/w1usvs ,所以必须把w乘回去才能得到纹理空间坐标。最后要把处理完成的 ( u , v ) (u,v) (u,v)画在 ( x s , y s ) (x_s,y_s) (xs,ys)上。

    不从数学角度,从实际的目的角度来说,纹理本身是贴在物体上,画在屏幕上的。所以纹理到底贴哪,只能根据物体的三角形面进行插值,但是贴完以后画在屏幕上哪,就需要把贴完纹理后的物体映射到屏幕上,这里就是简单的正交投影所以就是 ( x s , y s ) (x_s,y_s) (xs,ys)

    四、z-buffer

    关于shader的工作和其他片元处理的细节这里不做过多阐述,之说最后混合阶段的z-buffer。

    z-buffer的诞生来源于这么一个问题,那就是物体远近的问题,远处的物体会被近处的物体遮挡,从而在像素上所画的东西应该以近处的物体为准,那么,只需要把深度/远近作为片元的一个属性,遇到更小的深度就替换原有的片元就可以了,这个缓冲就叫做z-buffer。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值