《Cg Tutorial》的第四章介绍了场景转换的一些基本概念,并就此给出了一个程序例子,演示了在Cg顶点程序中执行从模型空间到剪切空间的转换。由于顶点程序的模型视点投影距阵参数是uniform类型,因此是通过在应用程序中先手动计算各矩阵(包括平移、旋转、视点以及投影距阵),然后按照转换空间的顺序相乘,最后在传递给顶点程序的顺序来完成的。程序实现时,完全是通过传递参数,然后自己来构造相应的矩阵,这种办法虽然可行,但必须要对各种矩阵的构造原理十分的了解。考虑到OpenGL中,可以使用状态函数glGetFloatv来获取指定的矩阵,因此可以先执行相应的操作,让OpenGL来计算最终的合成矩阵,而我们则可以直接通过状态获取函数来得到最终的矩阵。下面就是基于这种方法的实现:
void getModelViewProjMatrix(float outModelViewProjMatix[16],
float fovy,float aspect,float zNear,float ZFar, /* The Projection Parameter*/
double eyex,double eyey,double eyez, /* The Eye Position */
double centerx,double centery,double centerz, /* The Center Position*/
double upx,double upy,double upz, /* The Up Vector*/
void (*transformOp)(void) /* The transform Operation*/)
{
float projMatrix[16];
// Get the projection matrix
getProjectMatrix(projMatrix,fovy,aspect,zNear,ZFar);
// ModelMatrix = Translate * Rotation * ...
// ModelViewMatrix = ViewMatrix * ModelMatrix
// ModelViewProjectionMatrix = ProjectionMatrix * ModelViewMatrix
// In OpenGL,the order of matrix multiplication is REVERSE to the order of function call
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
// Multiple the modelview matrix by projection matrix
glMultMatrixf(projMatrix);
//do the transformation operation and camera setting
gluLookAt(eyex,eyey,eyez,centerx,centery,centerz,upx,upy,upz);
transformOp();
//get the modelview matrix
glGetFloatv(GL_MODELVIEW_MATRIX,outModelViewProjMatix);
glPopMatrix();
}
此函数用来获取模型视点矩阵与投影矩阵相乘的结果,这个结果就是传递给顶点程序的值。其中(fovy,aspect,zNear,ZFar)调用gluPerspectiv()函数,获取投影矩阵;(eyex, eyey,eyez
centerx,centery,centerz, upx,upy,upz)则用来调用gluLookAt()函数,设置视点矩阵。由于平移、旋转的操作顺序和次数不定,因此在这里是通过函数指针的形式指定。在这个函数中指定的具体的平移和旋转操作。
使用这种方法时,需要考虑到两个问题:
1、 从模型空间到剪切空间的转换顺序:
2、 在OpenGL中,矩阵相乘的顺序与函数调用的顺序相反:
例如:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMultMatrixf(N);
glMultMatrixf(M);
glMultMatrixf(L);
glBegin(GL_POINTs);
glVertex3f(v);
glEnd();
在上述代码中,当前矩阵依次为I、N、NM、NML。变换后的顶点为NMLv。
3、 在OpenGL中,使用一维数组存储矩阵时,默认的方式是按列存储的,因此在使用Cg程序时,需要使用cgSetMatrixParameter{f,d}c来传递矩阵参数。
在所有参数设置相同时,试验的结果与书上的结果有一些出入,主要体现在物体在空间的位置不同。为了验证真实的情况,我在只使用OpenGL,不是用Cg程序的条件下绘制,绘制结果同我的一样。下面是在这三种方法下的最终结果:从左到右依次为使用上面方法渲染结果、使用纯OpenGL渲染结果以及书中自带结果
不知道这是我的方法有问题,还是书上程序有问题。