??xml version="1.0" encoding="utf-8" standalone="yes"?> glLoadIdentity() glTranslatef(x, y, z) 沿着 X, Y ?Z 轴移动?/p>
注意在glTranslatef(x, y, z)?当您Ud的时候,您ƈ不是相对屏幕中心UdQ而是相对与当前所在的屏幕位置。其作用是你l点坐标的原点在当前原点的基上^UM?x,y,z)向量?br> ///////////////////////////////////////////////////////////////////////////////////////////////////////////// glLoadIdentity(); glTranslatef(-1.5f,0.0f,-6.0f); glLoadIdentity(); ///////////////////////////////////////////////////////////////////////////////////// E序的运行结果如下: 左边的三角Ş是第一步绘制的Q可以看到该三角形绘制的坐标p,实际上是?-1.5f,0.0f,-6.0f)为原点的?/p>
W二个三角Şl制的时候,׃使用glLoadIdentity()使原炚w新回到屏q中心来Q因此其原点位于屏幕的中心?/p>
glRotatef(angle, x, y, z) //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// OpenGL实用工具?GLUT)介绍Q?/span>
]]>
当前的用户坐标pȝ原点Ud了屏q中心:cM于一个复位操?br>1.X坐标轴从左至叻IY坐标轴从下至上,Z坐标轴从里至外?br>2.OpenGL屏幕中心的坐标值是X和Y轴上?.0f炏V?br>3.中心左面的坐标值是负|右面是正倹{?br> Ud屏幕端是正|Ud屏幕底端是负倹{?br> Ud屏幕深处是负|Ud屏幕则是正倹{?/p>
M角Ş之前调用的glTranslatef(x, y, z) 是ؓ了让你所有的场景在可视区内?br>
因ؓopengl默认的摄像机位置在坐标原点(没有调用gluLookAt改变视图坐标p)Q?方向?Z负向。如果不把物体画?-z 的区间上Q?在此摄像机可视区内是看不到的?br>
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();
与glTranslatef(x, y, z)cMQglRotatef(angle, x, y, z)也是对坐标系q行操作?br>旋{轴经q原点,方向?x,y,z),旋{角度为angleQ方向满_手定则?br>////////////////////////////////////////////////////////////////
glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();
////////////////////////////////////////////////////////////////
在未旋{的情况下如图所C:
glLoadIdentity();
glRotatef(45,0.0f,0.0f,1.0f);
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();
////////////////////////////////////////////////////////////////
lZ轴正向旋?5度角Q因为Z轴正方向由屏q内指向屏幕外,由右手定则可知方向ؓ逆时针{动?br>׃直角点即ؓ原点Q因此将围绕直角逆时针旋转?/p>
glLoadIdentity();
glRotatef(45,0.0f,0.0f,1.0f);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();
////////////////////////////////////////////////////////////////
在旋转之后加了一个复位的指oQ图形就不会旋{了?br>
l于搞明白gluPerspective和gluLookAt的关pM
函数原型
gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);
gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)
一个一个来,首先得设|gluPerspective,来看看它的参数都表示什么意?br>fovy,q个最隄?我的理解?眼睛睁开的角??视角的大?如果讄?,相当你闭上眼睛了,所以什么也看不?如果?80,那么可以认ؓ你的视界很广?
aspect,q个好理?是实际H口的纵横比,即x/y
zNear,q个?表示你近?的裁?
zFar表示q处的裁?
如果q没有理解就l箋?
我们知道,q处的东西看h要小一?q处的东西看h会大一?q就是透视原理
如下图所C?br>
假设那两条线表示公\,理论上讲,它们的两条边是^行的,
但现实情况中,它们在远?可以无限q?总要怺于一?
实际U段AB的长?CD的长?只是在此例中使用了透视?故会有如上的效果,是不是很接近现实的情?
l合我们刚才q两个函?br>zNear,眼睛距离q处的距?假设?0c,请不要设|ؓ负?OpenGl傻?不知道怎么了,
zFar表示q处的裁?假设?000c,
是q两个参数的意义?
再解释下那个"眼睛睁开的角?是什么意?
首先假设我们现在距离物体?0个单位距远的位|?
在眼睛睁开角度讄?5?L大屏q?
我们可以看到,在远处一个球,,很好玩哈,
现在我们眼睛再张开点看,?眼睛睁开的角?讄?78
(180度表C^?那时候我们将什么也看不?眼睛睁太大了,眼大无神)
我们只看C个点,,,,,,,,,,,,,,,,,,,,,,,,,,,
因ؓ我们看的范围太大?q个球本w大没有改?但是它在我们?视界"内太了,
反之,我们眼睛闭些,改ؓ1度看看会出现什么情况呢?
在我们距该物体3000距离q?"眼睛睁开的角???我们g走进了这个球?q个是不是类g相机的焦?
当我们将"透视?讄??我们相当于闭上双?q个世界清静?
我们什么也看不?,,,,,,,,
现在来看gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);
它共接受三对坐标,
分别为eye,center,up
故名思义,eye表示我们眼睛?世界坐标p?中的位置,
center表示眼睛"?的那个点的坐?
最后那个up坐标表示观察者本w的方向,如果观察点比喻成我们的眼睛,那么q个up则表C我们是正立q是倒立异或某一个角度在?所看的影像大不相同,故此旉要指明我们现在正?那么X,Z轴ؓ0,Y轴ؓ正即?通常其讄?,只要表示一个向上的向量(方向)卛_
球是d世界坐标pȝ原点上的,即O(0,0,0)坐标?我们的眼睛位于观察点A(0,0,100),Z轴向屏幕里看ȝ方向,屏幕外我们的位置,Z轴ؓ正?其实很好理解,x们距d点的距离,讄100,观察到如下图所C的影像
如果我们向前或向后移?则相应的囑փ会变大或变小,q里其实是q用了透视原理,q处的物体大,q处的物体小,实际物体的大是不变?
同理改变center坐标(眼睛看去的那个点,可简单理解ؓ视线的终?也会影响球的大小,同样可以认ؓ是改变了物体与观察点的距L?
最后那个up坐标表示观察者本w的方向,如果观察点比喻成我们的眼睛,那么q个up则表C我们是正立q是倒立异或某一个角度在?所看的影像大不相同,故此旉要指明我们现在正?那么X,Z轴ؓ0,Y轴ؓ正即?通常其讄?,只要表示一个向上的向量(方向)卛_,我们指定0.1f?.00001f异或1000.0f,效果是一L,只要能表C方向即?
以上理解了之?来做一个测?br>透视图不?最q处仍ؓ3000,q处?.1
gluPerspective // 讄透视?br> (45, // 透视角设|ؓ 45 ?在Y方向上以角度为单位的视野
(GLfloat)x/(GLfloat)y, // H口的宽与高?br> 0.1f, // 视野透视深度:q点1.0f
3000.0f // 视野透视深度:始点0.1fq点1000.0f
);
我们的观察点置于A(0,10,0),
观察位|?视线l点)坐标|于(0,0,0)
然后在原点开始绘?M个V字Ş,q将Z轴的g-1000递增加到+1000,增量?0,
代码如下
glColor3f(0.5f, 0.7f, 1.0f);
glBegin(GL_LINES);
for(int i=-1000;i<=1000;i+=10)
{
glVertex3f(0,0,i);
glVertex3f(10,10,i);
glVertex3f(0,0,i);
glVertex3f(-10,10,i);
}
glEnd();
F5q行效果如下?br>
上图证实了我们的推测
//---------------------------------------------
//生成|络
glColor3f(0.5f, 0.7f, 1.0f);
int x=(int)(40*2);
glBegin(GL_LINES);
for(int i=-x;i<=x;i+=4)
{
glVertex3i(-x,0,i);
glVertex3i(x,0,i);
glVertex3i(i,0,x);
glVertex3i(i,0,-x);
}
glEnd();
//生成球体
GLUquadricObj * pObj;
pObj = gluNewQuadric();
gluQuadricDrawStyle(pObj,GLU_LINE);
gluQuadricNormals(pObj,GLU_SMOOTH);
gluSphere(pObj,16,16,16);
glTranslatef(0.0f,-20.0f,-40.0f)表示当前图形向x轴^U?Q向y轴^U?20Q向z轴^U?40
glScaled(10.0f,10.0f,10.0f)表示当前图形沿x,y,z轴分别放大ؓ原来?0?br>glRotatef(-80.0f,10.0f,1.0f,0.0f)表示当前图形沿方向向量(-10,1,0)时针旋?0
]]>
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glRotatef(rtri,0.0f,1.0f,0.0f); // Rotate The Triangle On The Y axis ( NEW )
glBegin(GL_TRIANGLES); // Start Drawing A Triangle
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Left Of Triangle (Front)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Right Of Triangle (Front)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)
glEnd();
]]>
http://www.videotutorialsrock.com/
]]>
一、基本图元的描述及定?/strong>
OpenGL囑օ是抽象的几何概念Q不是真实世界中的物体,因此ȝ相关的数学模型来描述。所有的囑օ都是׃pd有顺序的点集合来描q的。OpenGL中绘制几何图元,必须使用glBegain()和glEnd()q一对函敎ͼ传递给glBegain()函数的参数唯一定了要l制何种几何囑օQ同Ӟ在该函数对中l出了几何图元的定义Q函数glEnd()标志点列表的结束。例如,下面的代码绘制了一个多边ŞQ?br>
glBegin(GL_POLYGON);
glVertex2f(0.0,0.0);
glVertex2f(0.0,3.0);
glVertex2f(3.0,3.0);
glVertex2f(4.0,1.5);
glVertex2f(3.0,0.0);
glEnd();
函数glBegin(GLenum mode)标志描述一个几何图元的点列表的开始,其参数mode表示几何囑օ的描q类型,具体cd见表一Q?br>
表一、几何图元类型说?br>
cd
说明
GL_POINTS
单个点?/td>
GL_LINES
多组双顶点线D?/td>
GL_POLYGON
单个单填充凸多边?/td>
GL_TRAINGLES
多组独立填充三角?/td>
GL_QUADS
多组独立填充四边?/td>
GL_LINE_STRIP
不闭合折U?/td>
GL_LINE_LOOP
闭合折线
GL_TRAINGLE_STRIP
U型q箋填充三角形串
GL_TRAINGLE_FAN
扇Şq箋填充三角形串
GL_QUAD_STRIP
q箋填充四边形串
部分几何囑օ的示意图Q?br>
图一、部分几何图元示意图
在glBegin()和glEnd()之间最重要的信息就是由函数glVertex*()定义的顶点,必要时也可ؓ每个点指定颜色Q只对当前点或后l点有效Q、法向、纹理坐标或其他Q即调用相关的函敎ͼ
表二、在glBegin()和glEnd()之间可调用的函数
函数
函数意义
glColor*()
讄当前颜色
glIndex*()
讄当前颜色?/td>
glNormal*()
讄法向坐标
glEvalCoord*()
产生坐标
glCallList(),glCallLists()
昄列表
glTexCoord*()
讄U理坐标
glEdgeFlag*()
控制边界l制
glMaterial*()
讄材质
需要指出的是:OpenGL所定义的点、线、多边Ş{图元与一般数学定义不太一P存在一定的差别。一U差别源于基于计机计算的限制。OpenGL中所有Q点计精度有限,故点、线 、多边Ş的坐标值存在一定的误差。另一U差别源于位图显C的限制。以q种方式昄囑ŞQ最的昄囑օ是一个象素,管每个象素宽度很小Q但它们仍然比数学上所定义的点或线宽要大得多。当用OpenGLq行计算Ӟ虽然是用一pd点值定义点Ԍ但每个点仍然是用单个象素昄Q只是近似拟合?br>
二、点(Point)
用Q点DC的点称为顶?Vertex)。所有顶点在OpenGL内部计算旉使用三维坐标Qx,y,zQ来处理Q用二维坐标(x,y)定义的点在OpenGL中默认zgؓ0。顶点坐标也可以用齐ơ坐?x,y,z,w)来表C,如果w不ؓ0.0Q这些齐ơ坐标表C的点即ؓ三维I间?x/w,y/w,z/w),一般来_w~省?.0?br>
可以用glVertex{234}{sifd}[V](TYPE cords)函数来定义一个顶炏V例如:
glVertex2f(2.0f,3.0f);//二维坐标定义点Q?/td>
OpenGL中定义的点可以有不同的尺寸,其函数Ş式ؓQ?br>
void glPointSize(GLfloat size);
参数size讄点的宽度Q以象素为单位),必须大于0.0Q缺省时?.0?br>
三、线(Line)
在OpenGL中,U代表线D?Line Segment)Q它׃pd点次q结而成。具体的ԌU有独立U段、条带、封闭条带三U,如图二所C:
图二、线D늚三种q结方式
OpenGL能指定线的宽度ƈl制不同的虚点线Q如点线、虚U等。相应的函数形式如下Q?br>
1、void glLineWidth(GLfloat width);
讄U宽Q以象素为单位)。参数width必须大于0.0Q缺省时?.0?br>
2、void glLineStipple(GLint factor,GLushort pattern);
讄当前Uؓ虚点模式。参数pattern是一pd?6位二q制敎ͼ0?Q,它重复地赋给所指定的线Q从低位开始,每一个二q制位代表一个象素, 1表示用当前颜色绘制一个象素(或比例因子指定的个数Q,0表示当前不绘Ӟ只移动一个象素位Q或比例因子指定的个敎ͼ。参数factor是个比例因子Q它用来拉pattern中的元素Q即重复l制1或移?Q比如,factor?Q则到1时就q箋l制2ơ,到0时连l移?个单元。factor的大范围限制在1?55之间?br>
在绘制虚点线之前必须先启动虚Ҏ式,卌用函数glEnable(GL_LINE_STIPPLE);l束Ӟ调用glDisable(GL_LINE_STIPPLE)关闭。下面代码绘制了一个点U:
void line2i(GLint x1,GLint y1,GLint x2,GLint y2)
{
glBegin(GL_LINES);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glEnd();
}
glLineStipple (1, 0x1C47); /* 虚点U?*/
glEnable(GL_LINE_STIPPLE)Q?br>glColor3f(0.0,1.0,0.0);
line2i (450 , 250 , 600 , 250 );
Q一Q凸、凹多边形?br>
OpenGL定义的多边Ş是由一pdU段依次q结而成的封闭区域,多边形可以是q面多边形,x有顶点在一个^面上Q也可以是空间多边Ş。OpenGL规定多边形中的线D不能交叉,区域内不能有I洞Q也卛_边Ş必须是凸多边形(指多边ŞL非相ȝ两点的连U位于多边Ş的内部)Q不能是凹多边ŞQ否则不能被OpenGL函数接受。凸多边形和凹多边Ş见图三?br>
图三、凸凹多边Ş
Q二Q边界标志问题?br>
实际应用中,往往需要绘制一些凹多边形,通常解决的办法是对它们进行分Ԍ用多个三角Ş来替代。显Ӟl制q些三角形时Q有些边不应该进行绘Ӟ否则Q多边Ş内部׃出现多余的线框。OpenGL提供的解军_法是通过讄Ҏ志命令glEdgeFlagQ)来控制某些边产生l制Q而另外一些边不生绘Ӟq也UCؓ边界标志U或非边界线。这个命令的定义如下Q?br>
void glEdgeFlag(GLboolean flag);
void glEdgeFlag(PGLboolean pflag);
Q三Q多边Şl制模式?br>
多边形的l制模式包含有:全填充式、轮廓点式、轮廓线式、图案填充式及指定正反面{。下面分别介l相应的OpenGL函数形式?br>
1Q多边Ş模式讄。其函数为:
void glPolygonMode(GLenum face,GLenum mode);
参数face为GL_FRONT、GL_BACK或GL_FRONT_AND_BACKQ参数mode为GL_POINT、GL_LINE或GL_FILLQ分别表C绘制轮廓点式多边Ş、轮廓线式多边Ş或全填充式多边Ş。在OpenGL中,多边形分为正面和反面Q对q两个面都可以进行操作,在缺省状况下QOpenGL对多边Ş正反面是以相同的方式l制的,要改变绘制状态,必须调用PolygonModeQ)函数Q?br>
2Q设|图案填充式多边形。其函数为:
void glPolygonStipple(const GLubyte *mask);
参数mask是一个指?2x32位图的指针。与虚点U绘制的道理一P某位?时绘Ӟ?时什么也不绘。注意,在调用这个函数前Q必d启动glEnable(GL_POLYGON_STIPPLE)Q不用时用glDisable(GL_POLYGON_STIPPLE)关闭。下面DZ个多边Ş扩展l制实例Q?br>
void CALLBACK display(void)
{
/* 填充模式定义 Q?2x32Q?*/
GLubyte pattern[]= {
0x00, 0x01, 0x80, 0x00,
0x00, 0x03, 0xc0, 0x00,
0x00, 0x07, 0xe0, 0x00,
0x00, 0x0f, 0xf0, 0x00,
0x00, 0x1f, 0xf8, 0x00,
0x00, 0x3f, 0xfc, 0x00,
0x00, 0x7f, 0xfe, 0x00,
0x00, 0xff, 0xff, 0x00,
0x01, 0xff, 0xff, 0x80,
0x03, 0xff, 0xff, 0xc0,
0x07, 0xff, 0xff, 0xe0,
0x0f, 0xff, 0xff, 0xf0,
0x1f, 0xff, 0xff, 0xf8,
0x3f, 0xff, 0xff, 0xfc,
0x7f, 0xff, 0xff, 0xfe,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xfe,
0x3f, 0xff, 0xff, 0xfc,
0x1f, 0xff, 0xff, 0xf8,
0x0f, 0xff, 0xff, 0xf0,
0x07, 0xff, 0xff, 0xe0,
0x03, 0xff, 0xff, 0xc0,
0x01, 0xff, 0xff, 0x80,
0x00, 0xff, 0xff, 0x00,
0x00, 0x7f, 0xfe, 0x00,
0x00, 0x3f, 0xfc, 0x00,
0x00, 0x1f, 0xf8, 0x00,
0x00, 0x0f, 0xf0, 0x00,
0x00, 0x07, 0xe0, 0x00,
0x00, 0x03, 0xc0, 0x00,
0x00, 0x01, 0x80, 0x00
};
glClear (GL_COLOR_BUFFER_BIT);
/* l制一个指定图案填充的三角?*/
glColor3f(0.9,0.86,0.4);
glPolygonStipple (pattern);
glBegin(GL_TRIANGLES);
glVertex2i(310,310);
glVertex2i(220,80);
glVertex2i(405,80);
glEnd();
glDisable (GL_POLYGON_STIPPLE);
glFlush ();
}
Q三Q指定多边Ş的正反面?
其函CؓQ?br>
void glFrontFace(GLenum mode);
在正常情况下QOpenGL中的多边形的正面和反面是q制的多边形的点序军_的,逆时针绘制的面是多边形的正面Q但是,在OpenGL中用该函数可以自定义多边Ş的正面。该函数的参数mode指定了正面的方向。它可以是CL_CCW和CL_CWQ分别指定逆时针和时针方向ؓ多边形的正方向?br>四、法向量的计及指定
法向量是几何囑օ的重要属性之一。几何对象的法向量是垂直与曲面切面的单位向量Q它定义了几何对象的I间方向Q特别定义了它相对于光源的方向,军_了在该点上可接受多少光照?br>
OpenGL本n没有提供计算法向量的函数Q计法向量的Q务由E序员自己去完成Q,但它提供了赋予当前顶Ҏ向的函数?br>
Q一Q^面法向的计算Ҏ?br>
在一个^面内Q有两条怺的线D,假设其中一条ؓ矢量WQ另一条ؓ矢量VQ^面法向ؓNQ则q面法向q于两个矢量的叉积Q遵循右手定则)Q即NQWxV。例如:一个三角Şq面三个点分别为P0、P1、P2Q相应两个向量ؓW、VQ则三角q面法向的计方式如下列代码所C:
void getNormal(GLfloat gx[3],GLfloat gy[3],
GLfloat gz[3],GLfloat *ddnv)
{
GLfloat w0,w1,w2,v0,v1,v2,nr,nx,ny,nz;
w0=gx[0]-gx[1]; w1=gy[0]-gy[1];w2=gz[0]-gz[1];
v0=gx[2]-gx[1]; v1=gy[2]-gy[1];v2=gz[2]-gz[1];
nx=(w1*v2-w2*v1);ny=(w2*v0-w0*v2);nz=(w0*v1-w1*v0);
nr=sqrt(nx*nx+ny*ny+nz*nz); //向量单位化?br> ddnv[0]=nx/nr; ddnv[1]=ny/nr;ddnv[2]=nz/nr;
}
以上函数的输出参Cؓ指针ddnvQ它指向法向的三个分量,q且E序中已l将法向单位化(或归一化)了?br>
Q二Q曲面法向量的计?br>
对于曲面各顶点的法向计算有很多种Q如Ҏ函数表达式求偏导的方法等。但是,在大多数情况QOpenGL中的多边形ƈ不是由曲面方E徏立v来的Q而是由模型数l构成,q时候求取法向量的办法是曲面细分成多个多边ŞQ然后选取多边Ş上相ȝ三个点v1、v2、v3Q当然三个点不能在同一直线上)Q按照^面法向量的求取方法就可以了?br>
Q三Q法向量的定义?br>
OpenGL法向量定义函CؓQ?br>
void glNormal3{bsifd}(TYPE nx,TYPE ny,TYPE nz);
void glNormal3{bsifd}v(const TYPE *v);
非向量Ş式定义法向采用第一U方式,卛_函数中分别给出法向三个分量值nx、ny和nzQ向量Ş式定义采用第二种Q即v讄Z个指向拥有三个元素的指针Q例如v[3]={nx,ny,nz}?br>
五、显C列?/strong>
Q一Q定义显C列表?br>
前面所丑և的例子都是瞬时给出函数命令,OpenGL瞬时执行相应的命令,q种l图方式叫做立即或瞬时方式(immediate modeQ。OpenGL昄列表QDisplay ListQ是׃l预先存储v来的留待以后调用的OpenGL函数语句l成的,当调用显C列表时׃ơ执行表中所列出的函数语句。显C列表可以用在以下场合:
1Q矩阉|?br>
大部分矩阉|作需要OpenGL计算逆矩阵,矩阵及其逆矩阵都可以保存在显C列表中?br>
2Q光栅位囑֒囑փ
E序定义的光栅数据不一定是适合g处理的理x式。当~译l织一个显C列表时QOpenGL可能把数据{换成g能够接受的数据,q可以有效地提高M囄速度?br>
3Q光、材质和光照模型
当用一个比较复杂的光照环境l制场景Ӟ因ؓ材质计算可能比较慢。若把材质定义放在显C列表中Q则每次Ҏ材质时就不必重新计算了,因此能更快地l制光照场景?br>
4Q纹?br>
因ؓg的纹理格式可能与OpenGL格式不一_若把U理定义攑֜昄列表中,则在~译昄列表时就能对格式q行转换Q而不是在执行中进行,q样p大大提高效率?br>
5Q多边Ş的图案填充模式,卛_定义的图案攑֜昄列表中?
OpenGL提供cM于绘制图元的l构即类gglBegin()与glEnd()的Ş式创建显C列表,其相应的函数为:
void glNewList(GLuint list,GLenum mode);
void glEndList(void);
glNewListQ)函数说明一个显C列表的开始,其后的OpenGL函数存入昄列表中,直至调用l束表的函数glEndList(void)。glNewListQ)函数中的参数list是一个正整数Q它标志唯一的显C列表;参数mode的可能值有GL_COMPILE和GL_COMPILE_AND_EXECUTEQ若要列表中函数语句只存入而不执行Q则用GL_COMPILEQ若要列表中的函数语句存入表中且按瞬时方式执行一ơ,则用GL_COMPILE_AND_EXECUTE?br>
注意Qƈ不是所有的OpenGL函数都可以在昄列表中存储且通过昄列表执行。一般来_用于传递参数或q回数值的函数语句不能存入昄列表Q因张表有可能在参数的作用域之外被调用;如果在定义显C列表时调用了这L函数Q则它们按瞬时方式执行q且不保存在昄列表中,有时在调用执行显C列表函数时会生错误。以下列出的是不能存入显C列表的OpenGL函数Q?br>
glDeleteLists() glIsEnable()
glFeedbackBuffer() glIsList()
glFinish() glPixelStore()
glGenLists() glRenderMode()
glGet*() glSelectBuffer()
在徏立显C列表以后就可以调用执行昄列表的函数来执行它,q且允许在程序中多次执行同一昄列表Q同时也可以与其它函数的瞬时方式混合使用。显C列表执行的函数形式如下Q?br>
void glCallList(GLuint list);
参数list指定被执行的昄列表。显C列表中的函数语句按它们被存攄序依次执行Q若list没有定义Q则不会产生M事情?br>
Q二Q管理显C列?br>
在实际应用中Q一般调用函数glGenList()来创建多个显C列表,q样可以避免意外删除Q生一个没有用q的昄列表。此外,在管理显C列表的q程中,q可调用函数glDeleteLists()来删除一个或一个范围内的显C列表?br>
1QGLuint glGenList(GLsizei range)
该函数分配range个相ȝ未被占用的显C列表烦引。这个函数返回的是一个正整数索引|它是一l连l空索引的第一个倹{返回的索引都标志ؓIZ已被占用Q以后再调用q个函数时不再返回这些烦引。若甌索引的指定数目不能满xrange?则函数返??br>
2QGLboolean glIsList(GLuint list)
该函数询问显C列表是否已被占用的情况Q若索引list已被占用Q则函数q回TUREQ反之,q回FAULSE?br>
3Qvoid glDeleteLists(GLuint list,GLsizei range)
该函数删除一l连l的昄列表Q即从参数list所指示的显C列表开始,删除range个显C列表,q且删除后的q些索引重新有效?br>
Q三Q多U显C列?br>
多昄列表的徏立就是在一个显C列表中调用另一个显C列表,也就是说Q在函数glNewList()与glEndList()之间调用glCallList()。多U显C列表对于构造由多个元gl成的物体十分有用,其是某些元仉要重复用的情况。但Z避免无穷递归Q显C列表的嵌套深度最大ؓ64Q也许更高些Q这依赖于不同的OpenGL实现Q,当然也可调用函数glGetIntegerv()来获得这个最大嵌套深度倹{OpenGL也允许用一个显C列表包含几个低U的昄列表来模拟徏立一个可~辑的显C列表?br>
下面的一D代码用了列表嵌套来显CZ个三角ŞQ?br>
glNewList(1,GL_COMPILE);
glVertex3fv(v1);
glEndList();
glNewList(2,GL_COMPILE);
glVertex3fv(v2);
glEndList();
glNewList(3,GL_COMPILE);
glVertex3fv(v3);
glEndList();
glNewList(4,GL_COMPILE);
glBegin(GL_POLYGON);
glCallList(1);
glCallList(2);
glCallList(3);
glEnd();
glEndList();
]]>
1?span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">核心?115个库函数Q每个函数都以gl开_q些函数是最基本的,它们可以在Q何OpenGL的工作^C应用?/span>q些函数用于建立各种各样的Ş体,产生光照效果,q行反走样以及进行纹理映,q行投媄变换{等。由于这些核心函数有许多UŞ式ƈ能够接受不同cd的参敎ͼ实际上这些函数可以派生出300多个函数?br>2、实用库Q?3个函敎ͼ每个函数以glu开_是比OpenGL核心函数更高一层的函数Q这些函数是通过调用核心函数来v作用的。它们可以在MOpenGL的工作^C应用?/span>q些函数提供了十分简单的用法Q从而减M开发者的~程负担。OpenGL的实用函数包括纹理映、坐标变换、多边Ş分化、绘制一些如椭球、圆柱、茶壶等单多边Ş实体{。这部分函数象核心函C样在MOpenGLq_都可以应用?br>3?span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">辅助库:31个函敎ͼ每个函数以aux开_q些函数本来是用于初学者做单的l习之用Q因此这些函C能在所有的OpenGLq_上用,在Windows NT环境下可以用这些函数。这些函C用简单,它们可以用于H口理、输入输出处理以及绘制一些简单的三维形体。ؓ了OpenGL的应用程序具有良好的UL性,在用OpenGL辅助库的时候应谨慎?br>4?span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">专用库函敎ͼ每种H口都有一个用于扩展窗口系l功能,以支持OpenGL渲染的函数库。在使用XH口pȝ的计机中,提供了XH口pȝ的OpenGL扩展QGLXQ,作ؓOpenGL的附加。GLX库函数的名称中包含前~"glX"。在windowspȝ上,6个以wgl开头的函数提供了额windows和OpenGL之间的接口?br>5?span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">OpenGL实用工具包(GLUT,OpenGL Utility ToolkitQ?/span>是Mark Kilgard开发的一个独立于H口pȝ的工具包Q用于绕开H口pȝAPI的复杂性。GLUT函数名中包含前缀"glut"?br>6?span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">Win32 API函数Q?个函敎ͼ函数前面没有专用前缀Q用于处理象素存储格式和双缓冲区Q显然这些函C仅能够用于Win32pȝ而不能用于其他OpenGLq_?/p>
OpenGL包含渲染函数Q但被涉及成独立于Q何窗口系l和操作pȝ。因此,OpenGLq没用用于打开H口以及键盘或鼠标事g的函数。GLUT库被用来化这些相关Q务,此外q提供了一些用于创建复杂三位物体(如球体、圆环和茶壶{)的函数?/span>
H口理函数
glutInit(int *argc, char **argv)Q初始化GLUTq处理命令行参数Q应在调用其他GLUT函数前调用glutInit()?br> glutInitDisplayMode(unsigned int mode),指定使用RGBA模式q是颜色索引模式。还可以指定使用单缓存还是双~存{?br> glutInitWindowPosition(int x, int y),指定H口左上角在屏幕上的位置?br> glutInitWindowSize(int width, int size),指定H口的大,单位素?br> int glutCreateWindow(char *string)Q用一个OpenGL场景创徏一个窗口,该函数返回一个标识符Q唯一的标识新建的H口Q注意,在调用glutMainLoop()之前Q窗口不会被昄出来?br> 昄回调函数
glutDisplayFunc(void(*func)(void))是最重要的时间回调函数。每当GLUT认ؓ需要重新显C窗口的内容Ӟ都将执行函数glutDisplayFunc()函数注册的回调函敎ͼ因此Q应ؓ重新l制场景需要调用的函数都放到显C回调函C。如果程序修改了H口的内容,可能需要调用函数glutPostRedisplay(void)Q它提醒函数glutMainLoop调用注册的显C回调函数?br> q行E序
glutMainLoop(void)Q显C创建的所有窗口,被渲染到q些H口中的内容也将昄出来。程序开始事件处理,q册的显C回调函数被触发Q进入该循环Q便不会退出?br> 处理输入事g
glutReshapeFunc(void(*func)(int w, int h))Q指定窗口大发生改变时应采取的措施Q?br> glutKeyboardFunc(void(*func)(unsigned char key, int x, int y))和glutMouseFunc(void(*func)(int button,int state,int x,int y))Q指定当特定的键和鼠标按钮被按下或者松开时应调用的回调函数?br> glutMotionFunc(void(*func)(int x, int y))Q这册了当用h下鼠标按钮ƈUd鼠标时应调用的回调函数?br> 理后台处理
glutIdleFunc(void(*func)(void))指定一个在没有其他事g需要处理时Q如事g循环I闲Q执行的函数?br> l制三维物体
glutWireCube(GLdouble size)、glutSolidCube(GLdouble size)、glutWireSphere(GLdouble radius, GLint slices,GLint statcks)、glutSolidSphere(GLdouble radius, GLint slices, GLint stacks){?/p>
]]>
glOrtho是创Z个正交^行的视景体?一般用于物体不会因为离屏幕的远q而生大的变换的情c比如,常用的工E中的制囄。需要比较精的昄?而作为它的对立情? glFrustum则生一个透视投媄。这是一U模拟真是生zMQh们视野观物体的真实情况。例如:观察两条q的火车到Q在q了很远之后Q这两条铁轨是会怺于一处的。还有,ȝ睛近的物体看h大一些,q的物体看v来小一些?br>glOrtho(left, right, bottom, top, near, far)Q?left表示视景体左面的坐标Qright表示右面的坐标,bottom表示下面的,top表示上面的。这个函数简单理解v来,是一个物体摆在那里,你怎么L取他。这里,我们先抛开glViewport函数不看。先单独理解glOrtho的功能?假设有一个球体,半径?Q圆心在(0, 0, 0)Q那么,我们讑֮glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);pC用一个宽高都?的框框把q个球体整个都装了进来?nbsp; 如果讑֮glOrtho(0.0, 1.5, -1.5, 1.5, -10, 10);pC用一个宽?.5Q?高是3的框框把整个球体的右面装q来;如果讑֮glOrtho(0.0, 1.5, 0.0, 1.5, -10, 10)Q就表示用一个宽和高都是1.5的框框把球体的右上角装了q来。上qCU情况可以见图:
从上qCU情况,我们可以大致了解glOrtho函数的用法?/p>
---glViewport():
glOrtho函数只是负责使用什么样的视景体来截取图像,q不负责使用某种规则把图像呈现在屏幕上?br>glViewport主要完成q样的功能。它负责把视景体截取的图像按照怎样的高和宽昄到屏q上?br>比如Q如果我们用glut库徏立一个窗?glutInitWindowSize(500, 500); 然后使用glutReshapeFunc(reshape); reshape代码如下Q?/p>
void reshape(int width, int height)
{
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
glMatrixModel(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);
....
}
q样是可以看C个正常的球体的。但是,如果我们创徏H体时glutInitWindowSize(800, 500),那么看到的图像就是变形的。上q情况见图?/p>
因ؓ我们是用一个正方Ş截面的视景体截取的图像,但是拉到屏q上昄的时候,变成了glViewport(0, 0, 800, 500);也就是显C屏变宽了, 倒是昄的时候把一个正方Ş的图?#8220;zȝ生的l拉宽了”。就会生变形。这P需要我们调整我们的OpenGL昄屏了。我们可以不?00那么宽,因ؓ我们是用的正方Ş的视景体Q所以虽然窗体是800宽,但是我们只用其中?00够了。修改一下程序?br>void reshape(int width, int height)
{
int dis = width < height ? width : height;
glViewport(0, 0, dis, dis); /*q里dis应该?00*/
glMatrixModel(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);
.....
}
OK. 如果你能看明白我写的内容。你可能对glViewport函数有个大致的了解?/p>
不过Q我们采用上面的办法Q就是只使用了原来屏q的一部分Q宽度从501?00 我们没有用来昄囑փQ。如果我们想用整个OpenGL屏幕昄囑փQ但是又不囑փ变Ş怎么办?
那就只能修改glOrtho函数了。也是_我们使用一个和H体一h例的视景体(而不再是正方形的视景体)来截取图像。例如,对于(800, 500)的窗体,我们使用glOrtho(-1.5 * 800/500, 1.5 * 800/500, -1.5, 1.5, -10, 10)Q就是截取的时候,我们׃用一?#8220;扁扁”的视景体截取Q那么,昄的到OpenGL屏幕?800, 500)Q我们只要正常把q个扁扁的截取图像显C(扁扁的截取图像是指整个截取的囑փQ包括球形四周的黑色部分?球Şq是正常圆Ş的)Q就可以了。如Q?br>void reshape(int width , int height)
{
glViewport(width, height); //按照H体大小制作OpenGL屏幕
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (width <= height)
glOrtho(-1.5, 1.5, -1.5 * (GLfloat)height/(GLfloat)width, 1.5 * (GLfloat)height/(GLfloat)width, -10.0, 10.0);
else
glOrtho(-1.5*(GLfloat)width/(GLfloat)height, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
....
}
另外Q关于glViewport()函数Q我们还可以用来调整囑փ的分辨率。例如,保持目前的窗体大不变,我们如果用这个size来只昄整个物体的一部分Q那么图像的分L率就必然会增大。例如:
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(0, 1.5, 0, 1.5 * (GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho(0, 1.5*(GLfloat)w/(GLfloat)h, 0, 1.5, -10.0, 10.0);
}
可以把分辨率扩大4倍?/p>
而如果再修改一下glViewport(0, 0, 2 * (GLsizei)w, 2 * (GLsizei)h); 则可以把分L率扩?6倍?/p>
完整的测试程序:
/*Build on ubuntu 9.04*/
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
void init(void)
{
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat mat_shininess[] = {50.0};
GLfloat light_position[] = {1.0, 1.0f, 1.0, 0.0};
GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSolidSphere(1.0, 20, 16);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-1.5, 1.5, -1.5 * (GLfloat)h/(GLfloat)w, 1.5 * (GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho(-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
/*CMakeLists.txt*/
PROJECT(s5)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
ADD_EXECUTABLE(s5 main.cpp)
FIND_PACKAGE(OpenGL)
FIND_PACKAGE(GLUT)
IF(OPENGL_FOUND)
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OPENGL_LIBRARIES})
ELSE(OPENGL_FOUND)
MESSAGE(FATAL_ERROR "OpenGL not found")
ENDIF(OPENGL_FOUND)
IF(GLUT_FOUND)
INCLUDE_DIRECTORIES(${GLUT_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${GLUT_LIBRARIES})
ELSE(GLUT_FOUND)
ENDIF(GLUT_FOUND)
参? OpenGL~程指南(原书W??
本文来自CSDN博客Q{载请标明出处Q?a >http://blog.csdn.net/shizhipeng/archive/2009/12/13/4939529.aspx
W一步,选择一个编译环?br> 现在Windowspȝ的主编译环境有Visual StudioQBroland C++ BuilderQDev-C++{,它们都是支持OpenGL的。但q里我们选择Visual Studio 2005作ؓ学习OpenGL的环境?
W二步,安装GLUT工具?br> GLUT不是OpenGL所必须的,但它会给我们的学习带来一定的方便Q推荐安装?br>Windows环境下的GLUT下蝲地址Q(大小Uؓ150kQ?br>http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip
无法从以上地址下蝲的话请用下面的q接:
http://upload.programfan.com/upfile/200607311626279.zip
Windows环境下安装GLUT的步骤:
1、将下蝲的压~包解开Q将得到5个文?br>2、在“我的电脑”中搜?#8220;gl.h”Qƈ扑ֈ其所在文件夹Q如果是VisualStudio2005Q则应该是其安装目录下面?#8220;VC\PlatformSDK\include\gl文g?#8221;Q。把解压得到的glut.h攑ֈq个文g夏V?br>3、把解压得到的glut.lib和glut32.lib攑ֈ静态函数库所在文件夹Q如果是VisualStudio2005Q则应该是其安装目录下面?#8220;VC\lib”文g夹)?br>4、把解压得到的glut.dll和glut32.dll攑ֈ操作pȝ目录下面的system32文g夹内。(典型的位|ؓQC:\Windows\System32Q?br>W三步,建立一个OpenGL工程
q里以VisualStudio2005Z?br>选择File->New->ProjectQ然后选择Win32 Console ApplicationQ选择一个名字,然后按OK?br>在谈出的对话框左边点Application SettingsQ找到Empty projectq勾上,选择Finish?br>然后向该工程d一个代码文Ӟ取名?#8220;OpenGL.c”Q注意用.c来作为文件结?br>搞定了,pqx的工E没什么两L?
W一个OpenGLE序
一个简单的OpenGLE序如下Q(注意Q如果需要编译ƈq行Q需要正安装GLUTQ安装方法如上所qͼ
#include <GL/glut.h>
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("W一个OpenGLE序");
glutDisplayFunc(&myDisplay);
glutMainLoop();
return 0;
}
该程序的作用是在一个黑色的H口中央M个白色的矩Ş。下面对各行语句q行说明?
怎么P代码q不长吧?
首先Q需要包含头文g#include<GL/glut.h>Q这是GLUT的头文g?br>本来OpenGLE序一般还要包?lt;GL/gl.h>?lt;GL/glu.h>Q但GLUT的头文g中已l自动将q两个文件包含了Q不必再ơ包含?br>
然后看main函数?br>int main(int argc, char *argv[])Q这个是带命令行参数的main函数Q各位应该见q吧Q没见过的同志们请多ȝ书,{弄明白了再往下看?br>注意main函数中的各语句,除了最后的return之外Q其余全部以glut开头。这U以glut开头的函数都是GLUT工具包所提供的函敎ͼ下面对用到的几个函数q行介绍?br>1、glutInitQ对GLUTq行初始化,q个函数必须在其它的GLUT使用之前调用一ơ。其格式比较LQ一般照抄这句glutInit(&argc, argv)可以了?br>2、glutInitDisplayModeQ设|显C方式,其中GLUT_RGB表示使用RGB颜色Q与之对应的q有GLUT_INDEXQ表CZ用烦引颜Ԍ。GLUT_SINGLE表示使用单缓Ԍ与之对应的还有GLUT_DOUBLEQ用双~冲Q。更多信息,误己Google。当然以后的教程也会有一些讲解?br>3、glutInitWindowPositionQ这个简单,讄H口在屏q中的位|?br>4、glutInitWindowSizeQ这个也单,讄H口的大?br>5、glutCreateWindowQ根据前面设|的信息创徏H口。参数将被作为窗口的标题。注意:H口被创建后Qƈ不立xC到屏幕上。需要调用glutMainLoop才能看到H口?br>6、glutDisplayFuncQ设|一个函敎ͼ当需要进行画图时Q这个函数就会被调用。(q个说法不够准确Q但准确的说法可能初学者不太好理解Q暂时这栯吧)?br>7、glutMainLoopQ进行一个消息@环。(q个可能初学者也不太明白Q现在只需要知道这个函数可以显C窗口,q且{待H口关闭后才会返回,q就_了。)
在glutDisplayFunc函数中,我们讄?#8220;当需要画图时Q请调用myDisplay函数”。于是myDisplay函数q来画图。观察myDisplay中的三个函数调用Q发现它们都以gl开头。这U以gl开头的函数都是OpenGL的标准函敎ͼ下面对用到的函数q行介绍?br>1、glClearQ清除。GL_COLOR_BUFFER_BIT表示清除颜色QglClear函数q可以清除其它的东西Q但q里不作介绍?br>2、glRectfQ画一个矩形。四个参数分别表CZ位于对角U上的两个点的横、纵坐标?br>3、glFlushQ保证前面的OpenGL命o立即执行Q而不是让它们在缓冲区中等待)。其作用跟fflush(stdout)cM?
大家可以按照上面的叙qͼ自己讄~译器,下蝲GLUTQƈ亲手~译CZ代码?br>大家成功~
1 操作pȝq_Q?nbsp;
如果你的操作pȝ是WindowsQ你可以选择。如果是Unix、Linux{,那么只能用OpenGL?nbsp;
2 易学易用性:
OpenGL相对来说比DirectX易学Q能够很快入门(q是公认的)。即使你来可能要用到Direct3DQOpenGL仍然不失ZU好?D~程的入门途径QOpenGL中原汁原味的3D函数直和大多数计机囑Ş学教材中的伪代码一模一栗?nbsp;
3 文档支持Q?nbsp;
在网上你可以扑ֈ很多很好的OpenGL的文档、教E、例E等Q特别是“U宝?#8221;Q相关链接和文可以在本站OpenGL栏目扑ֈQ。但是,DirectX SDK所提供的文难嚼多了(公认Q,在网上你也难以找到好的教E(本站的DirectX栏目所提供的几乎是全部能找到的不重复的中文资料Q。另外,书店里有不少OpenGL的中文书Q而DirectX只有“希望”出的一U,q且不是讲Direct3D的?nbsp;
4 关于COMQ?nbsp;
DirectX是基于COM的,而OpenGL不是。如果你对COM不是那么感冒的话Q最好先选择OpenGL。但是,如果你将一直在Windowsq_上做3D~程的话Qd该熟悉Direct3DQ因为Microsoft/SGI/HP共同开发中的一U新?D接口是基于COM的,它将和Direct3D比较接近?nbsp;
5 UL性:
DirectX与Windows紧密相连Q难以移植。而OpenGL是一U非?#8220;q净?#8221;APIQ无ZVB语言到VC语言、还是从Windowsq_到Linuxq_Q几乎一LC代码Q的UL都非常容易(q且在GLUT里提供了q_无关的窗口管理库Q?nbsp;
6 多媒体性能Q?nbsp;
׃DirectX包括了DirectSound、DirectInput{,如果Direct3D和它们一起用,比较容易控制声韟뀁操U|{,q是DirectX的整体优ѝ当Ӟ没有人反对你同时使用OpenGL和DirectSoundQQuake是q样做的?nbsp;
7 速度Q?nbsp;
很难说哪个更快,QUAKE用的是OpenGL的引擎,而Unreal用的是Direct3DQ它们都非常著名。其实,E序的速度q不在于你选择了OpenGL或DirectXQ它q至和两个因素有关Q你写的代码的质量(依赖于你对你使用的接口的熟悉E度Q,g的支持(包括g的驱动程序的支持Q?nbsp;
8 强壮性:
q样说吧QOpenGL调用发生了错误,它什么都不做Q而DirectXZ错,它什么都做得?#8230;…
本文来自CSDN博客Q{载请标明出处Q?a >http://blog.csdn.net/didibabawu055/archive/2009/02/21/3919401.aspx