posts - 4, comments - 12, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

        上次说到渲染管线的一般组成,接下来就要说说各部分的转换怎么做了。
     
        在这之前,本着扫盲的态度,先介绍一点矩阵的基础知识。

        大学一年级一般都会上一门叫做“线性代数”的课,这个课上就会讲很多关于线性方程组(可以先不管“线性”两个字,初等数学里的东西基本都是线性的),关于矩阵的东西。
        首先,什么是线性方程组?
        ax + by + c = 0                                                                            a  b  c
        dx + ey + f  = 0            这个就是一个线性方程组,                d  e  f
        gx + hy + i  = 0             我们可以把它表示成矩阵                   g  h   i

        再来,什么是向量?一个1 x N 的矩阵,就是一个向量,例如
        a
        b       一般可以记成(a,b,c)
        c

        线性代数对矩阵定义了一系列的运算方法,比如乘法,加法等。具体的定义最好找本线性代数来看看,另外推荐一个《理解矩阵》,是个短小精悍的文章,对于理解矩阵,坐标系,向量比较有好处。
        
        现在就先说明几个问题。
        1、一个N维向量,可以表示一个N维空间的点。比如说(1,2)在平面直角坐标系表示x=1,y=2的点
        2、可以同时存在多个坐标系。例如,有两个坐标系,重叠在一起,但是坐标系A的单位长度是坐标系B单位长度的2倍。那么在A坐标系中的 (1,0)点,在B坐标系中就是 (2,0)点
        3、坐标系原点位置可以不同。比如,坐标系A原点在坐标系B的 (1,1)处,那么坐标系A的(1,0)点就是坐标系B的(2,1)点。
        4、坐标系可以表示成矩阵。 比如   2  0   就表示一个x轴缩小一半的坐标系。这个坐标系实际上是由
                                                                       0  1

两个向量 2   和  0  放在一起组成的,没错,也就是坐标轴的单位向量值的倒数组成了坐标系。所以很显
                  0         1                                                                                                                                             
然,1  0就是一个我们平常使用的坐标系。至于另外那两个数要是不为0会发生什么情况,可以自己想
        0  1
想,我后面也会解释。
        5、三维空间的坐标系可以表示成3x3矩阵。(这个不用解释了吧)
        6、坐标系矩阵与对应维数的向量相乘,将得到该向量在这个坐标系下的表示。这个是最关键的一个点,能理解,后面就都好办了。一个向量 (2,2,2) ,一个矩阵(坐标系)2  0  0  ,用矩阵乘以这个向量,
                                                                                                                              0  2  0
                                                                                                                              0  0  2
根据矩阵乘法,我们将得到向量(4,4,4) 。关于这一点,大家可以看看《理解矩阵》,它的描述比我说得更透彻,其实矩阵还表达了一种映射关系,或者表达了一种变换。
        7、坐标系矩阵还可以扩展,用来表示坐标系原点的位置。这种扩展的坐标系矩阵看起来就像这个样子1  0  0  1   这是就是所谓的“三维空间的齐次坐标系”。为什么叫“齐次”,我还没理解透,以后理解
    0  1  0  1
    0  0  1  0
    0  0  0  1
了再补上。这个矩阵描述的坐标系是这样的: 坐标系的x,y,z轴的单位向量都与我们最常见的那种坐标系一样,原点在(-1,-1,0)处。也就是,最右边一列多出来的,就是表达原点位置的向量。那么这个矩阵怎么做乘法呢,因为根据矩阵乘法,这个矩阵需要乘以一个4维向量。假设有一个点(1,1,1),那么我们就在这个向量后面再增加一个数,变成 (1,1,1,1),然后就可以去乘这个矩阵了(关于这个硬加上的数,见下一点)。
        8、上面说到齐次坐标系,还说到了一个三维向量增加一维变成4维,那么这个第四维是什么含义呢?当一个向量表达齐次坐标时,它的最后一维有特殊的含义。一个4维向量V (a,b,c,h),当h = 0 时,V表示一个三维空间中的向量。当h 不为 0 时,V表示一个三维空间中的点。这个点的坐标是 (a/h,b/h,c/h)。在进行矩阵运算时,第四维正常的参与运算,我们可以得到简单的推论:
        向量加向量得到向量。 向量得到点。 点加点得到中点。
        在此补充一点,在空间中,“点”和“向量”其实是不同的概念,向量有方向,但没位置,点有位置但没方向。所以在齐次坐标系矩阵中,第四列第四行是1,因为原点是一个点,不是向量。
        9、在计算机图形学中,一般就是用矩阵来做各种物体的坐标变换,方法很简单,就是用一个矩阵去乘以表示坐标的向量。
        10、矩阵的表示方法还有一种,就是向量按行表示,线性方程组矩阵就是这样。也就是一行表示一个向量。所以看其它资料的时候要注意一下。


         说了一这么些数学,估计也看烦了,那么就先讲一个实例:世界坐标变换。
         世界坐标变换是渲染管线生成世界模型时的必备操作。
         比如说,我有一个正方体,顶点坐标为(1,1,1),(1,1,-1),(1,-1,1),(1,-1,-1),(-1,1,1),(-1,1,-1),(-1,-1,1),(-1,-1,-1)。  然后我需要在这个世界模型中放置很多个正方体,怎么办呢?总不能手工的去输入那么多的坐标吧。我只能对这个正方体作一些变换,比如:放大缩小,旋转,移动。通过这样一些操作,我就可以把这个正方体放到任何地方了。那么现在简单说怎么实现。

        这个正方体,我们存储的时候就存下8个点就够了,这8个点都各自是一个4维齐次向量,可以用静态数组来实现。然后构造一个矩阵,依次乘以这8个点,那么一次变换就算做完了。
        放大缩小,我们就构造这样的矩阵 2  0  0  0 ,这样就把正方体放大一倍
                                                                      0  2  0  0
                                                                      0  0  2  0
                                                                      0  0  0  1

        旋转: 这个相对比较复杂一点,在这里的旋转我们会说 绕x轴旋转 a 弧度(角度),相应的矩阵为
1   0       0    0
0 cosa  sina  0
0 -sina  cosa 0
0   0       0    1
        平移: 把正方体中心移动到(1,2,3),矩阵为 1  0  0  1
                                                                                      0  1  0  2
                                                                                      0  0  1  3
                                                                                      0  0  0  1
        
        一般情况下我们应该按照这样的顺序来做这三种变换:  缩放、旋转、平移。  如果改变顺序,那么转换出来的效果也将不一样,有兴趣的可以自己计算一下。

        暂时就这么多吧,下次继续说~


Feedback

# re: 我的第一个3D渲染管线(2)[未登录]  回复  更多评论   

2009-03-12 11:53 by cppexplore
顶下!

# re: 我的第一个3D渲染管线(2)  回复  更多评论   

2009-03-15 21:26 by Jymstart
师兄在哪公司实习呢

# re: 我的第一个3D渲染管线(2)  回复  更多评论   

2009-03-16 00:29 by 林森(L.S.Winson)
@Jymstart
额。。你是哪位来着~?

# re: 我的第一个3D渲染管线(2)  回复  更多评论   

2009-07-02 17:12 by waterpg
怎么不更新了啊~~

# re: 我的第一个3D渲染管线(2)  回复  更多评论   

2012-06-07 10:40 by 吼吼

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理