Posted on 2009-03-10 22:40
林森(L.S.Winson) 阅读(1914)
评论(6) 编辑 收藏 引用
呵呵,既然都说了,是“我的第一个”。那自然就不会有太好的效率和表现,不过实现了基本功能,值得鼓励一下~。
PS:这属于扫盲帖,同时邀请牛们来点评下。
首先,介绍背景。。。
目前在一个游戏公司实习,培训的时候,有一个扩展练习,就是写一个3D渲染管线。
之前没写过这种东西,仅仅小用了一下OPENGL,搞了个旋转立方体以后,就因为自己混乱的坐标变换概念无法深入了。
现在算是基本实现出来了,马上就发觉了这东西的锻炼价值了,首先是包含的数学多,尤其线性代数,不理解的话很多东西都不能懂。其次,是计算量潜力很大,图形计算,随便一算就几百万几千万的,真要做得好,要优化效率,然后各种东西都来了,汇编啊,显卡啊之类的。
何为3D渲染管线呢,就是一个能把3D世界模型,转换成屏幕显示的这个东西。说“管线”,就是因为它一般是一种类似过滤器的实现方法,经过N步的转换过程,最终输出了屏幕像素信息。
OK,直入主题。
最基本的渲染过程一般包含这样几个步骤。 世界坐标变换、摄像机变换、透视变换、剪切、行扫描输出。
世界坐标变换:就是把3D世界中的各种物体,通过 缩放、旋转、平移 放置到一个指定的位置,这个过程一般都可以记录成文本或二进制格式,从而渲染管线可以方便地初始化好整个世界信息。
摄像机变换: 这个比较好理解,3D世界生成好了,那么人在哪里呢? 我们总要有一个眼睛来看这个3D世界。这个眼睛的位置不同,所看到的东西也就不同。 这个摄像机变换,就把3D世界的物体坐标转换为眼睛看到的坐标。 例子:有个点在(1,1,1) 处,我的眼睛在(1,1,0)处,看着那个点。 那么这个时候,这个点就在我的正前方,它在我眼中的坐标就是(0,0,1)。
透视变换: 一般情况下,我们看东西都有一种近大远小的感觉,那么这个变换,就是为了制造出这种效果。比如说,我眼睛看到了两个点 (-1,0,0) 和(1,0,0) ,假如我们把这两个点都垂直于我们拿远一点,那么他们的摄像机坐标本来是变成(-1,0,1) (1,0,1),但是由于透视效果,近大远小,我们实际看到的坐标会变成(-a,0,1) (a,0,1) ,这里 a < 1。
剪切: 这个也很好理解,我们看不到我们身后的东西,所以我们就不要去管它了,这样可以节省很多计算量,也可以使得计算的结果有一个确定的范围。实际的剪切变换中,还有近平面,远平面等参数,就是最近能看到多近,最远能看多远。
行扫描输出: 我们现在已经得到了一堆坐标,表示我们看到的世界是什么样子,现在就是要把这个坐标转换成图片了,3D世界中的所有东西都是由三角形组成,所以我们把这些三角型的每一个点的坐标都计算出来(在之前的处理中始终只保留其顶点)。然后根据X,Y坐标画到屏幕上,画的过程中还要判断哪个点在前面,哪个点在后面,在后面的点不能遮住前面的点。这里使用的一个技术叫Z-Buffer,用来记录某个X,Y坐标上离屏幕最近的点的Z坐标值。
大概就这么多先,发觉原来想把东西表达清楚还真不容易,代码过两天再贴,等把纹理和比较方便的世界模型定义脚本做好再说。而且,讲到具体的东西,需要比较透彻的线性代数理解,要表达好不容易,自己还要先理解理解。