一个半月的时间实现了一个软件光栅器,这个是导入茶壶obj文件后的效果,主要难点在于:
1、Cohen-SutherLand CVV裁剪(两周工作量)
2、法线贴图(一周工作量)
3、OBJ,MTL文件解析和加载(三天工作量)
该系列博文主要介绍软光栅的实现思路,设计到的诸如裁剪、切空间计算和光照模型等公示不是本文重点,此类信息可以查阅相关文献。本节先对软件光栅器定义进行介绍,并介绍光栅器的实现过程,这对程序的实现是算是一个宏观的概括和总结。转载请注明出处。
什么是软件光栅器?它和硬件光栅器有何区别?
在计算机上实现一个光栅器,无论如何也绕不开硬件,所有软件都是在硬件上跑的,但是我们所说的软件光栅器,一般是指运行在CPU上的光栅器程序。而硬件光栅器专指依赖于GPU的光栅器,例如OpenGL、Vulkan之类的图形库大都是依赖于显卡。但是软件光栅器可以根据用户需要,基于复杂的渲染公式,跑出更加复杂的渲染效果。软件光栅器由于不借助任何图形库和显卡硬件,仅调用了Windows底层的显示缓存句柄。通过PS(像素着色器)算出的颜色值存到一个数组,并由通过CreateDIBSection方法传给该句柄,实现颜色缓冲区的写入,从而实现渲染,故不需要配置各种VisualStudio的属性表。
一、软件光栅器管线概览
光栅器的管线就是把一堆表示模型的数据通过各种转化,最终写入到显示缓冲区中并在屏幕上渲染出来的过程。
模型的数据可以由用户自己定义,比如要渲染一个立方体,用户可以用数组设定好立方体8个点的模型空间坐标,进一步地,还可以设置每个点的颜色值、法线坐标和纹理坐标。如果用法线贴图,还需要准备与纹理贴图对应的法线贴图。当然,复杂的模型,比如游戏里的各种怪物、载具和武器,这些一般都是由美工从3Dsmax里制作的,如obj或者max格式的模型,这些格式数据以一定规律和索引包含有顶点、纹理、法线、颜色、材质等信息,不用用户自己手动一个一个点或者一个一个面定义了。
在设置好模型的顶点信息后,需要进行一系列坐标变换,最终变换到用户屏幕的坐标系上。最初的顶点坐标视模型空间下的坐标,以立方体来讲,这些点的坐标的相对位置都是类似的,比如一个1x1x1的立方体,各个点的模型空间坐标就是(0.5f,0.5f,0.5f)、(0.5f,0.5f,-0.5f)等,分别表示立方体前方右上角和后方右上角两个顶点(右手坐标系,大拇指x轴,食指y轴,中指z轴)。
模型空间坐标下一步需要转换到世界空间中,因为一个场景肯定不止一个模型,所以需要有一个世界空间坐标来统一地管理场景中所有的模型,所以每个模型的顶点都还要转换到世界空间中,其实就相当于给每个顶点多添加了一个新的身份,一个在世界环境下被承认、被认可的身份。
把所有顶点转换到世界中后,就需要摆上相机或者摄像机给模型们拍照了,所以在将相机摆到一个特定位置后(可能会实时变化),就需要把顶点们的世界坐标转成相机坐标,这相当于给每个顶点又添加一个在相机中被承认的身份证明。
在用相机给顶点们拍照时,肯定会出现一种情况:就是模型的部分或者全部顶点在相机的视口之外,而把这些相机视野之外的顶点也囊括进后续程序进行计算的话,很可能会加重计算机运行的负担,所以此时需要进行一个裁剪的步骤,将相机照不到的点儿滤掉,这个过程一般是在一个立方体的裁剪空间中进行。
在裁剪时,先进行透视除法,这样可以方便裁剪算法编码和求交时的计算(以后详细介绍)。裁剪后,就可以将顶点儿们转换到屏幕坐标了,屏幕坐标点都是相对于用户屏幕的像素分辨率对应起来的,你屏幕越大,屏幕空间的坐标点值一般也就越大。
上述坐标变换过程就是常说的几何阶段,这个过程一般放在顶点着色器(VS)中实现。如果考虑使用法线映射时,几何阶段一般就不是按上面所说的过程来了,包括模型、光线、视线等坐标信息都会转换到一个叫顶点空间的坐标系(或者叫切空间,一个比模型空间更小的空间,它以每个顶点为原点,有多少个顶点,就有多少个切空间)下进行计算,这个以后详细介绍。
但现在顶点还是顶点,我们还需要将点儿们变成面。我们需要根据一些三角形索引,将点连成线,再连成三角形。三角形又分为平顶三角形和平底三角形(底边是与屏幕水平线平行的三角形),以及一般三角形(可以切割成一个平顶三角形和一个平底三角形)。得到平x三角形后,就可以一行一行地扫描三角形的每一条与底边平行的线,扫面就是一个画线的过程,它将一个平行线左右两个点的信息进行插值,最终把每个三角形内点的坐标、纹理、颜色和法线等信息插值得到。得到这些信息后,就可以进入到像素着色器(PS)中进行对每一个点的绘制了。
PS会根据光照等信息计算出每个顶点的最终颜色(以后详细介绍),最终传到一个Windows维护的显示缓冲数组中,由Windows的图形渲染底层方法渲染到屏幕中,由此完成从模型顶点到屏幕渲染的过程。
下一节(二、VS和PS的输入、输出和运作,切空间的计算):