Skip to content

作业3陆陆续续的做了一周,在透视投影矫正、interpolated_shadingcoords等地方卡了很久,不理解。参考网上一些博客文章,总结自己在做作业3的过程中的一些收获。 参考的一些博文: Games101:作业3(管线分析、深度插值、libpng warning、双线性插值等)矫正透视投影插值及属性插值详解

软光栅渲染流程

从Games101 shadeing部分介绍了图形渲染管线: graphics pipeline 那么如何用代码去实现这样一个图形渲染管线,作业3的代码中实现了一个基本的软光栅渲染器,我们从作业框架的代码中,总结软光栅渲染器渲染一个模型的流程:

  1. 读取模型坐标,通过模型矩阵、视图矩阵,转换为视图空间下的坐标。(main函数)
  2. 进行投影变换转换为投影空间下坐标。
  3. 进行视口变换,转换为屏幕空间下坐标。
  4. 在屏幕空间下,进行逐像素的着色:
    1. 判断像素是否着色
    2. 对像素进行插值,深度插值、颜色插值、法线插值等,这时因为是在屏幕空间上,经过了透视投影后物体发生了非线性变换,所以需要进行透视投影矫正插值(可参考)。
    3. 获取了像素的深度、颜色、法线等信息后,根据不同的着色模型(phong、texture、bump、dispacement、pbr等等),计算出该像素的颜色,赋值给该像素即可。注意这里不同的着色模型计算,是发生在视图空间的,也就是说我们要把当前着色像素点对应到视图空间中的某个点,在视图空间下计算该像素的颜色。(这也就是作业框架中出现的shading_coordinates)

问题

透视投影矫正

参考Games101:作业3(管线分析、深度插值、libpng warning、双线性插值等)_games101作业3_Q_pril的博客-CSDN博客


推导: 假设二维空间中小三角形三个顶点的深度值分别为,其内部一点的重心坐标为,对应深度值为;而三维空间三个顶点的深度值分别为重心坐标为,对应深度值为,可得出: 联立①⑤:
可知⑥+⑦+⑧ = 1,将各式右边相加,得: **这就是透视投影矫正的公式,**通过二维空间中一点的重心坐标,以及三维空间中三个点的Z值,可得到该点在三维空间中的Z值。 同理,对于任意的属性值,在三维空间中有: 深度值也是一个属性,这里的与①式中的是相同的,所以有: 也就是说对于任意的属性,我们都可以通过⑩式来求得。

公式⑨、⑩都很重要

对于作业框架代码,z值就是通过⑨式求值,zp是⑩式。

cpp
auto[alpha, beta, gamma] = computeBarycentric2D(i+0.5, j+0.5, t.v);
float Z = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
float zp = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
zp *= Z;

这里刚开始不理解,z值就是视图空间(未发生透视变换)的深度值,为什么还要在带入⑩式求出zp,其实我们用⑩式来计算深度插值,求出的结果就是⑨式,zzp是相等的。

interpolated_shadingcoords

注意这里不同的着色模型计算,是发生在视图空间的,也就是说我们要把当前着色像素点对应到视图空间中的某个点,在视图空间下计算该像素的颜色。(这也就是作业框架中出现的shading_coordinates) 参考: games论坛中关于interpolated_shadingcoords的解释