这是一个用C#+winform实现的软件光栅化渲染器,今天拿出来与大家分享一下,希望能起到抛砖引玉的作用,给新人一点启发(结构比较简单,注释比较详细^_^),也欢迎司机们拍砖指点和交流~
目的:
巩固图形编程知识,理解渲染流水线所做的事情。
实现功能:
1、将顶点数据进行一系列处理显示到屏幕上(废话。。。(¬_¬))
2、线框渲染模式、纹理渲染模式、顶点色模式
3、纹理uv坐标和顶点色等的透视校正插值
4、纹理双线性过滤采样
5、背面消隐
6、Cvv简单裁剪
7、“基础光照模型”(相当于D3D、OpenGL中的固定管线顶点光照)
截图:
光照
顶点色
线框模式:
代码放在Github上面: https://github.com/aceyan/SimpleSoftwareRenderer
下面我会将一些完成这个渲染器所需要的知识点以及相关资料的链接(多是博文)罗列一下,方便查阅。
零、准备阶段
想要实现渲染器首先我们得知道“给定视点、三维物体、光源、照明模式,和纹理等元素,如何绘制一幅二维图像”,这就必须提到一个词“图像绘制管线”(也称绘制流水线),我们得渲染器正是要以软件的形式来模拟这条流水线的运作。
流水线:http://www.cnblogs.com/wonderKK/p/5022226.html
理解了绘制管线,我们发现其中充满对矩阵向量等数学工具的运用,那么再实现流水线之前,我们必须先实现这些数学工具,这些数学类网上已经有很多的资料了,但是有几点需要特别说明:
1、本程序中使用行矩阵与行向量
相关资料:D3d和openGl矩阵区别
http://blog.csdn.net/Nightmare/article/details/3983724
2、本程序使用左手坐标系
3、实现了color类来方便进行颜色的运算,因为进行光照的时候要使用颜色乘以颜色的计算方法,它跟向量的乘法不同,应该称为“Modulate(调制)”,注意不能用向量乘法的计算公式哦。
相关资料:
https://www.zhihu.com/question/24026277/answer/26433842
@Milo Yip 大神的博文里面有一段讲颜色计算的:
http://www.cnblogs.com/miloyip/archive/2010/03/29/1698953.html#1794025
4、矩阵求逆
由于要进行光照,我们需要变换顶点法线,那么就需要矩阵求逆和求转置的运算。(为什么需要逆转置呢?请看:https://www.zhihu.com/question/27739027)
其中矩阵求逆比较复杂,本程序使用的是伴随矩阵的方法求矩阵的逆, 必须先求出矩阵的行列式和伴随矩阵,这部分需要一定的线性代数基础知识。
4.1矩阵求逆重要定理:
http://wenku.baidu.com/link?url=dga27GT5oSK8SDwHaeqPGL_raHnMLNP54oad7q8wJnMOqEpuT4_UAC-BHAeTsL8vGpYkRuphnXng99TLfHOx8_Nn7WMVycFRlUiMgSS-2Ve
4.2求矩阵行列式
本程序使用递归算法求行列式,请查看矩阵行列式的递归定义:
http://wenku.baidu.com/link?url=9TSCuxJdfypmsqZLYegHNuKYP1TABFwGT22v-cJut5wenWM-Ll2Bp6zqgDEeIvd9ChV3Laj3czAbdWtjSwaulHHSkUZtrLNcgLqNw2xrjb7,
4.3伴随矩阵:
http://wenku.baidu.com/link?url=BVbtO30v7eygbZUloybJtpFkCrpAwypYNyIx7XGX-OItxdWz0w4Y2hpzux729bq4MLKnx0sWwS4mJwm8Nrnf_3zxG9RqzD7LND3mklrwyDe
实现了数学类,就可以正式进入流水线了:
一、几何阶段
1、顶点从模型空间----->世界空间
这一步要生成世界矩阵(简称m),m是一系列平移、选择等变换的组合
如果开启了光照,我们还需要把模型空间的法线信息变换到世界空间,对顶点进行光照计算并保存光照结果颜色,以便在光栅化的时候进行差值和颜色调制(Modulate)
这里实现的“简单光照模型”可以参见《Cg教程_可编程实时图形权威指南》第五章光照
2、世界空间----->相机空间
这一步需要生成视矩阵(简称v)
推导过程:@zdd的博客 http://www.cnblogs.com/graphics/archive/2012/07/12/2476413.html
上面的推导中写错了
应该是
rxry rz
[ ux uy uz ]
dx dy dz
但是推导结果是对的
3、相机空间--->齐次剪裁空间
这里要生成投影矩阵,简称p
Dx风格的投影矩阵推导:
http://www.cnblogs.com/graphics/archive/2012/07/25/2582119.html
本程序使用的投影矩阵:
视空间的顶点乘以这个矩阵之后被变换到齐次剪裁空间,并且w分量保存着视空间的z信息。
在齐次剪裁空间我们可以对顶点进行简单的裁剪,既将不在
-w <= x <= w
-w<= y <= w
0 <= z <= w
这个范围的顶点剔除掉,不进行渲染。
这里采用的是最简单粗暴的剪裁方法,更加复杂的剪裁还需要生成新的顶点,有很多可以深入挖掘的地方:)
Ps:为了方便后续的透视校正插值,程序中还将1/z 保存在顶点数据中。
4、进行图元装配,也就是将顶点以一定的顺序组装成三角形(Primitive Assembly && Trianglesetup )
本程序中使用了顶点索引的方式来组织顶点数据,并且约定以逆时针顺序组织的三角形的法线朝向屏幕外,换句话说就是逆时针顺序组织的三角形看起来是正面。
有了这个约定就可以进行背面消隐:
http://blog.csdn.net/cppyin/article/details/6207206
5、透视除法
对透视变换得到的含有深度信息(z)的齐次坐标做透视除法。所谓透视除法,就是把透视变换后的齐次坐标除以(z)。由于透视变换矩阵已经构造好了,当
视锥体内部点经透视处理后的齐次坐标除以(z)后,使得顶点进入
-1<= x <= 1
-1<= y <= 1
0 <= z <= 1 (CVV正方体中)。
6、映射到视口
将cvv正方体的顶点根据屏幕大小或者视口大小转换为屏幕坐标
二、光栅化阶段
1、Rasterization光栅化
光栅化决定哪些像素被几何图元覆盖的过程
1.1 如果选择线框模式,本程序使用的画线方法是Bresenham快速画直线算法
相关资料:http://www.cnblogs.com/gamesky/archive/2012/08/21/2648623.html
1.2顶点色模式和纹理模式
三角形光栅化算法:http://blog.csdn.net/cppyin/article/details/6232453
扫描线填充算法:http://blog.csdn.net/cppyin/article/details/6172211
光栅化过程当中,我们要对uv坐标,顶点颜色、我们保存在顶点信息中的1/z等信息进行透视校正插值:
http://blog.csdn.net/popy007/article/details/5570803
文章中的重要结论:
我们发现s/z、t/z和x’、y’也是线性关系。而我们之前知道1/z和x’、y’是线性关系。则我们得出新的思路:对1/z关于x’、y’插值得到1/z’,然后对s/z、t/z关于x’、y’进行插值得到s’/z’、t’/z’,然后用s’/z’和t’/z’分别除以1/z’,就得到了s’和t’。
这就是为什么我们要保存1/z的原因。
2、Pixel Operation 像素操作
2.1消除遮挡面
根据zbuff 使用1/z来进行ztest,这样就不用给zbuff初始化一个很大的值了。
2.2 Texture operation 纹理操作,也就是根据像素的纹理坐标,查询对应的纹理值
纹理坐标的透视校正: http://blog.csdn.net/popy007/article/details/5556639
纹理采样,双线性纹理过滤:http://dev.gameres.com/Program/Visual/3D/Bilinear.htm
http://blog.csdn.net/i_dovelemon/article/details/27839279
2.3 Blending
本程序暂时没有对alpha的处理,后面应该会更新
2.4:Filtering
相当于后处理,就是对即将写入framebuff(帧缓冲)的像素进行一些处理,本程序暂时没有添加。
经历了上面的步骤,把要渲染的像素写到framebuff中,再将framebuff渲染到屏幕上就完成了所有步骤(本程序简单的生成了一个bitmap来作为framebuff),这时你应该可以在屏幕上看到你所渲染的东西。如果看起来不太对,那么进入debug吧。一开始也许会觉得调试这样一个绘制流水线会无从下手,因为其中任何一步的偏差都会使最后的渲染发生错误。
请假了一些大神后找到了不错的调试方法,下面给出一些tips:
1、调试数学库,用笔算来验证结果的正确性
2、调试流水线,可以建立一个简单多边形,比如一个quad,用笔算来验证m、v、p三个矩阵的正确性。光栅化的阶段由于要进行插值,计算量比较大,建议使用心算和单步跟踪的方式来进行调试。
笔算的过程能让你更加了解背后的数学奥秘:)
最后要感谢一下@cppyin,@zdd,@Milo Yip,@韦易笑等大神的文章,给我很大帮助。
特别要推荐@韦易笑老师写的mini3D:http://www.skywind.me/blog/archives/1498,让我受益匪浅。
最后
以上就是悦耳宝马最近收集整理的关于用C#实现一个简易的软件光栅化渲染器零、准备阶段一、几何阶段二、光栅化阶段的全部内容,更多相关用C#实现一个简易内容请搜索靠谱客的其他文章。
发表评论 取消回复