3D渲染流水线

来源:互联网 发布:投资影视行业 知乎 编辑:程序博客网 时间:2024/04/29 23:44

1、模型坐标系到世界坐标系:模型的每个顶点经旋转和缩放之后平移到世界坐标的位置。

2、隐藏面消除(可选):通常执行的测试为背面消除和包围球测试,在世界空间中进行。

      2.1、包围球测试原理:对于世界空间中的每个物体,创建一个包围球,只对球心执行世界坐标到相机坐标的变换,并判断整个球体是否位于视截体内,如果不在,则丢弃它包围的物体。如果球体的一部分在视截体内,需要在将整个模型变换到相机坐标后做其他测试。
               2.1.1、包围球:定义6个点,它们与变换到像极坐标后的球心之间的连线分别平行于三个轴, 到球心的距离都等于顶点列表中距离球心最远的点到球心的距离。为了更加精确,可选择包围盒等其他几何体代替包围球。
              2.1.2、判断点(x, y, z)是否在视野为90度的视截体外部:(z > far_z) || (z < near z) ||  (fabs(x) < z) || (fabs(y) < z)

      2.2、背面测试的工作原理:以统一的方式(顺时针或逆时针)对构成每个物体的所有多边形进行标记,然后计算每个多边形的面法线,并根据观察向量对这条法线进行测试。如果面法线和观察向量之间的夹角不超过90度,也就是点积大于0时,多边形对于观察者而言是可见的。夹角刚好为90度时的多边形宽度通常为1个像素,渲染时可能带来问题,因此排除它。

3、世界坐标系到相机坐标系:对所有世界坐标进行平移,平移量为负的相机的世界坐标再对世界坐标针对三个轴进行三次旋转,旋转角度为相机对应角度的负值。若要反求世界坐标,则先旋转再平移。平移矩阵为以相机世界坐标为平移量的矩阵的逆矩阵,旋转矩阵为以相机相对于对应轴旋转矩阵的转置矩阵。对于每一帧,只需手工计算变换矩阵一次。

4(可选)、3D裁剪:对于不完全位于视截体内部的几何体(直线或多边形)用视截体进行裁剪。可对视截体应用投影变换,使它变为长方体。若不执行这一步,则执行第六步。如果愿意对所有几何体都进行投影变换,可以在投影变换之后再进行3D裁剪。

5、相机坐标系到投影坐标系:设视平面为z = d(视距,视点到视平面的距离),视点为(0,0,0),则根据相似三角形的比例关系,点(x,y,z)投影点(xp,yp)为:xp = d * x / z,yp = d * y / z。当z = 0时,投影点的坐标为无穷大,另外z为负时物体被倒转,但能够投影,这是为什么需要指定近裁剪面的理由之一。投影变换编码时必须使用其次坐标。

      5.1、4D其次坐标投影变换矩阵:

               | 1 0 0 0    |

               | 0 1 0 0    |

               | 0 0 1 1/d |

               | 0 0 0 0    |

               用点(x,y,z,1)验证,结果为(x,y,z,z / d),将x,y,z分别除以齐次坐标,得到3D坐标:

             (x * d / z,y * d / z,z * d / z),忽略z坐标,x,y为投影点。

      5.2、非正方形视口d值的确定:

               d = 0.5 * 宽度 * tan(fov / 2), tan(fov / 2)= 视距 / (宽度 / 2)

               xp = d * x / z          yp = d * y * ar(宽高比) / z

               4D其次坐标投影变换矩阵:

               | d    0  0 0 |

               | 0 d*ar 0 0 |

               | 0    0  1 1 |

               | 0    0  0 0 |

6、图像空间裁剪(若第四步不执行,则执行该步):所有要被渲染的物体被转换为屏幕坐标后,再使用屏幕空间或视口对它们进行裁剪

7、投影坐标系到屏幕坐标系:

     7.1、当视野为90度,视距为1:在投影空间中视平面坐标在每个轴上被归一化为-1到1(方形投影),投影面为方形时,投影变换将所有几何体投影到一个2 * 2的虚拟视平面上(xp和yp的范围都是 [-1,+1]);投影面不是方形时,虚拟视平面大小为2 *(2 / ar),xp范围为[-1,+1],yp范围为[-1 / ar,+1 / ar]。

             7.1.1、将上述x,y的范围映射到屏幕:

                         xp -> xs @ [0,SCREEN_WIDTH - 1]

                         yp -> ys @ [0,SCREEN_HEIGHT - 1]

                         注意y轴被反转,屏幕坐标是以左上角为原点,y轴正方向向下。

             7.1.2、设a = 0.5 * SCREEN_WIDTH - 0.5,b = 0.5 * SCREEN_HEIGHT - 0.5

                         xs = (xp + 1)* a = xp * a + a

                         ys = 2 * b -(yp + 1)* b = b - yp * b 

                         对应的4D变换矩阵:

                         | a 0  0 0 |

                         | 0 -b 0 0 |

                         | 0 0  1 0 |

                         | a b  0 1 |

                         对应的3D变换矩阵:

                         | a 0  0 |

                         | 0 -b 0 |

                         | a b  1 |

     7.2、视野和视距为任何值:

             7.2.1、d值计算:d = 0.5 * viewplane_width(height) * tan(fov / 2)

                         设视平面与视口(屏幕)大小相同:d = 0.5 * (SCREEN_WIDTH(HEIGHT)- 1)* tan(fov / 2)

              7.2.2、一次性将相机坐标变换为屏幕坐标:

                          xs = xp + a = d * x / z + a 

                          ys = b - yp = -d * y  * ar/ z + b

                          变换矩阵:

                          | d  0 0 0 |

                          | 0 -d 0 0 |

                          | a  b 1 1 |

                          | 0  0 0 0 |

                          7.2.2.1、对于使用矩阵来执行投影变换和屏幕变换,需要注意投影变换得到的是齐次坐标,必须将其转换为3D坐

                                        标。

                          7.2.2.2、将投影变换和屏幕变换合并后,宽高比被消除了。

8、其他:

     8.1、在坐标变换时,不要更改坐标,而应使用另一个数组来存储结果。

     8.2、水平、垂直视野都是90度的视截体上下左右平面方程:|x| = z  |y| = z / ar。

     8.3、在得到世界坐标之后和得到屏幕坐标之前,必须对多边形进行光照计算和纹理映射,本文只讨论坐标变换,所以忽略。

原创粉丝点击