delphi实例9--用的opengl实现旋转星球
- 格式:doc
- 大小:61.50 KB
- 文档页数:4
精品资料(完整版)O p e n G L中创建一个球体(q iútǐ)动画-使球体在窗口内做自由落体运动.........................................计算机图形学实验报告1、实验目的(mùdì)和要求利用第七章所学的知识,试在OpenGL中创建一个(yīɡè)球体动画,使球体在窗口内做自由落体运动,并在撞击地面后能够反弹回来。
并用相应的代码表示出来。
2、实验(shíyàn)内容利用(lìyòng)glutSolidSphere函数等其它函数,在OpenGL中创建一个球体动画,使球体在窗口内做自由落体运动(yùndòng),并在撞击地面后能够反弹回来3、实验步骤1)相关算法及原理描述我们所使用的glut实用工具中,正好就有一个绘制球体的现成函数:glutSolidSphere,这个函数在“原点”绘制出一个球体。
由于坐标是可以通过glTranslate*和glRotate*两个函数进行随意变换的,所以我们就可以在任意位置绘制球体了。
2)运行结果如下图,程序调试成功,并且能正常显示4、实验总结通过本次试验,进一步认识,感觉OpenGL的功能很强大,各种各样的物理模拟实验他都不在话下!!不得不说,这软件很好很强大!!由于自己不太擅长编程,所以有些功能还不能完全实现,但我会尽自己最大努力来克服自己的编程不足之处,多加练习。
5、附录(fùlù)带注释(zhùshì)的源程序#include "glut.h"#include<stdlib.h>#include<stdio.h>#include<time.h>#include<math.h>#define PI 3.1415926double move=20.0;int i=0;int down=1;int count=1;double timeSpan=0; //下降(xiàjiàng)到底所需时间double movey=0.0;double duration=0.0; //持续时间double length=0.0;clock_t start,end;void init(void){GLfloat mat_specular[]={220.220,220.0,220.0,220.0};GLfloat mat_shininess[]={100.0};GLfloat light_position[]={0.0, 0.0, 0.0, -2.0}; //r-l u-d f-bGLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };GLfloat diffuseLight[] = { 0.6f, 0.6f, 0.6f, 1.0f };GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};glClearColor(0.2,0.2,1.5,2.0); //bgcglColor3ub(100, 100, 215);glShadeModel(GL_SMOOTH);glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);glLightfv(GL_LIGHT0,GL_SPECULAR,specular);glLightfv(GL_LIGHT0,GL_POSITION,light_position);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glEnable(GL_DEPTH_TEST);}void reshape(int w,int h){glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w<=h)glOrtho(-12,12,-12*(GLfloat)(h)/(GLfloat)(w),12*(GLfloat)(h)/(GLfloat)(w), -1.0,1.0);elseglOrtho(-12*(GLfloat)(w)/(GLfloat)(h),12*(GLfloat)(w)/(GLfloat)(h),-12,12,-1.0,1.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void initDisplay(void){down=1; //向下(xiànɡ xià)运动glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glLoadIdentity();glTranslatef(0.0,20.0,0.0);glutSolidSphere(0.4,40,50);glutSwapBuffers();}void display(void){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glLoadIdentity();glTranslatef(0,move,0.0);glutSolidSphere(0.4,40,50);glutSwapBuffers();}void MoveSphereUp(){end=clock();duration = (double)(end - start-16.0) /CLOCKS_PER_SEC;length=5*(timeSpan-duration)*(timeSpan-duration);move=20-length;if(move>19.932) {move=20;down=1;printf("%i",down);start=clock();}display();glLoadIdentity();}void MoveSphereDown(){if(count==1){start=clock();count=0;}end=clock();duration = (double)(end - start) /CLOCKS_PER_SEC;length=5*duration*duration;move=20-length;if(move<-20) {timeSpan=duration; //记下下降(xiàjiàng)所经历的时间 move=-20;start=clock();down=0; //向上(xiàngshàng)运动}display();glLoadIdentity();}void TimerFunc2(int value){if(i==0){ //leftGLfloat light_position[]={2.0,0.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==1){ //left-upGLfloat light_position[]={2.0,2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==2){ //upGLfloat light_position[]={0.0,2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==3){ //up-rightGLfloat light_position[]={-2.0,2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==4){ //rightGLfloat light_position[]={-2.0,0.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==5){ //right-downGLfloat light_position[]={-2.0,-2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==6){ //downGLfloat light_position[]={0.0,-2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==7){ //down-leftGLfloat light_position[]={2.0,-2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }i=(++i)%8; //控制小球(xiǎo qiú)旋转的glutTimerFunc(60,TimerFunc2,1);}void TimerFunc1(int value){if(down==1){MoveSphereDown();}if(down==0){MoveSphereUp();}glutTimerFunc(10,TimerFunc1,0);}int main(int argc,char **argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);glutInitWindowSize(400,740);glutInitWindowPosition(300,20);glutCreateWindow(argv[0]);init();glutDisplayFunc(initDisplay);glutReshapeFunc(reshape);glutTimerFunc(1400,TimerFunc1,0); //毫秒glutTimerFunc(400,TimerFunc2,1); //毫秒glutMainLoop();return 0;}内容总结(1)(完整版)OpenGL中创建一个球体动画-使球体在窗口内做自由落体运动.。
GIS专业实验报告(计算机图形学)实验8 使用opengl程序实现三维星球环绕效果一.实验目的及要求使用opengl程序实现三维星球环绕效果。
二.理论基础三维图形变换:三维图形变换包括三维几何变换和投影变换,通过它可由简单图形得到复杂图形,可以用二维图形表示三维对象。
三.算法设计与分析程序源码如下:#include <gl/gl.h>#include <gl/glu.h>#include <gl/glut.h>static GLfloat angle = 0.0, moon_angle = 0.0;void display(){glClearColor( 1.0, 1.0, 0.0, 0.0 );glShadeModel( GL_SMOOTH );glMatrixMode( GL_PROJECTION );glLoadIdentity();gluPerspective( 80.0, 1.0, 1.0, 50.0 );glMatrixMode( GL_MODELVIEW );glLoadIdentity();gluLookAt(8.0, 5.0, 8.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );//定义太阳的光照//发出白色的光{GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat light_position[] = { 0.0, 0.0, 0.5, 1.0 };//最后一个参数为正数,表明是位置性光源glEnable( GL_LIGHT0 );glEnable( GL_LIGHTING );glEnable( GL_DEPTH_TEST );//定义太阳的材质//显红色GLfloat mat_ambient[] = { 0.3, 0.0, 0.0, 1.0 };GLfloat mat_emission[] = { 0.3, 0.0, 0.0, 1.0 };//绘制太阳glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient );glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse );glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular );glLightfv( GL_LIGHT0 ,GL_POSITION, light_position );glMaterialfv( GL_FRONT ,GL_AMBIENT_AND_DIFFUSE, mat_ambient );glMaterialfv( GL_FRONT, GL_EMISSION, mat_emission );GLfloat ambient[] = { 0.2, 0.2, 0.2, 1.0 };glLightModelfv( GL_AMBIENT, ambient );glutSolidSphere( 2.0, 40, 40 );}//定制地球不发光,有材质{GLfloat mat_ambient[] = { 0.0, 0.0, 0.5, 1.0 };GLfloat mat_specular[] = { 0.0, 0.0, 1.0, 1.0 };GLfloat mat_shiness[] = { 30.0 };GLfloat mat_emission[] = { 0.0, 0.0, 0.1, 1.0 };glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_ambient );glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );glMaterialfv( GL_FRONT, GL_EMISSION, mat_emission );glMaterialfv( GL_FRONT, GL_SHININESS, mat_shiness );glRotatef( angle, 0.0, 1.0, 0.0 );glTranslatef( 6.0, 0.0, 0.0 );glutSolidSphere( 0.5, 40, 40 );}//定制月球{GLfloat mat_ambient[] = { 0.2, 0.2, 0.2, 1.0 };GLfloat mat_specular[] = { 0.8, 0.8, 0.80, 1.0 };GLfloat mat_shiness[] = { 30.0 };GLfloat mat_emission[] = { 0.3, 0.3, 0.3, 1.0 };glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_ambient );glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );glMaterialfv( GL_FRONT, GL_EMISSION, mat_emission );glMaterialfv( GL_FRONT, GL_SHININESS, mat_shiness );glRotatef( moon_angle, 0.0, angle, 1.0 );glTranslatef( 1.0, 0.0, 0.0 );glutSolidSphere( 0.3, 30, 30 );}glutSwapBuffers();}void idle(){angle += 0.5;moon_angle += 2.0;if ( angle > 360.0 ){angle = 0.0f;}if ( moon_angle > 360.0 ){moon_angle = 0.0;}glutPostRedisplay();}void menu( int id ){if ( id == 1 ){exit( 0 );}}int main( int argc, char ** argv ){glutInit( &argc, argv );glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE ); glutInitWindowPosition( 100, 100 );glutInitWindowSize(800, 450 );glutCreateWindow("模拟星球");glutDisplayFunc( display );glutIdleFunc( idle );glutCreateMenu( menu );glutAddMenuEntry( "Out", 1 );glutAttachMenu( GLUT_RIGHT_BUTTON );glutMainLoop();}四.程序调试及运行结果的自我分析与自我评价运行结果见下图1。
Opengl实现太阳系天体运动本文主要讲OpenGL中的几何变换。
我们生活在一个三维的世界——如果要观察一个物体,我们可以:1、从不同的位置去观察它。
(视点变换/视图变换,gluLookAt)2、移动或者旋转它,当然了,如果它只是计算机里面的物体,我们还可以放大或缩小它。
(模型变换)3、如果把物体画下来,我们可以选择:是否需要一种“近大远小”的透视效果。
另外,我们可能只希望看到物体的一部分,而不是全部(剪裁)。
(投影变换)4、我们可能希望把整个看到的图形画下来,但它只占据纸张的一部分,而不是全部。
(视口变换)这些,都可以在OpenGL中实现。
1、模型变换和视图变换从“相对移动”的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性。
在OpenGL中,实现这两种功能甚至使用的是同样的函数。
由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前操作的矩阵为“模型视图矩阵”。
设置的方法是以GL_MODELVIEW为参数调用glMatrixMode函数,像这样:glMatrixMode(GL_MODELVIEW);通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。
这也只需要一行代码:glLoadIdentity();然后,就可以进行模型变换和视图变换了。
进行模型和视图变换,主要涉及到三个函数:glTranslate*,把当前矩阵和一个表示移动物体的矩阵相乘。
三个参数分别表示了在三个坐标上的位移值。
glRotate*,把当前矩阵和一个表示旋转物体的矩阵相乘。
物体将绕着(0,0,0)到(x,y,z)的直线以逆时针旋转,参数angle表示旋转的角度。
glScale*,把当前矩阵和一个表示缩放物体的矩阵相乘。
x,y,z分别表示在该方向上的缩放比例。
注意我都是说“与XX相乘”,而不是直接说“这个函数就是旋转”或者“这个函数就是移动”,这是有原因的,马上就会讲到。
假设当前矩阵为单位矩阵,然后先乘以一个表示旋转的矩阵R,再乘以一个表示移动的矩阵T,最后得到的矩阵再乘上每一个顶点的坐标矩阵v。
计算机图形学实验——利⽤OpenGL函数绘制五⾓星⼀、实验名称:五⾓星的绘制⼆、实验⽬的:了解 OpenGL 程序设计结构,掌握编程环三、境的设置,掌握绘制线段的⽅法。
四、实验内容:1.在 VC++ 环境下,练习利⽤ OpenGL 绘制三⾓形的程序。
2.编程实现绘制⼀个五⾓星。
(传统 OpenGL 或者 Shader)五、实验所需基本函数1.线段绘制glBegin(GL_LINES);//绘制参数GL_LINESglVertex2f(30,30);//起始点坐标glVertex2f(100,100);//终点坐标(两个为⼀组)glEnd();2.填充图像glBegin(GL_POLYGON);//绘制参数GL_POLYGONglVertex2f(x0, y0);//顶点坐标1glVertex2f(x1, y1);//2glVertex2f(cx, cy);//3glEnd();结果为对三个顶点组成的图像进⾏填充3.绘制颜⾊设置glColor3f(0.92, 0.89, 0.41);//⾦黄⾊六、实验原理根据⼩圆半径加⾓度算出第⼀个坐标然后⼤圆根据半径加⼀个⾓度算出第⼆个点坐标,然后旋转改变⾓度寻找所有顶点。
代码如下:1void DrawStar(float cx, float cy, float R,float r,float o)//五⾓星中⼼坐标x,y,⼤圆半径,⼩圆半径,初始⾓度2 {34float x0, y0, x1, y1;//5float o0 = o;//⼤圆对应⾓度6float o1 = o + 0.2 * 3.14;//⼩圆对应⾓度7for (int i = 0;i <10;i++)8 {9 x0 = cx+R * cos(o0);//⼤圆对应的x坐标10 y0 = cy+R * sin(o0);//⼤圆对应y坐标11 x1 = cx+r * cos(o1);//⼩圆对应x坐标12 y1 = cy+r * sin(o1);//⼩圆对应y坐标13if (i % 2 == 0)14 {15 glColor3f(1, 0, 0);16 }17else18 {19 glColor3f(0.92, 0.89, 0.41);20 }2122 glBegin(GL_POLYGON);//绘制23 glVertex2f(x0, y0);24 glVertex2f(x1, y1);25 glVertex2f(cx, cy);26 glEnd();27if (i % 2 == 0)28 {29 o0 = o0 + 0.4 * 3.14;//⼤圆对应⾓度变换30 }31else32 {33 o1 = o1 + 0.4 * 3.14;//⼩圆对应⾓度变换34 }3536 }37383940 }七、绘制结果⼋、附件所有代码1// OpenGLOld.cpp : 定义控制台应⽤程序的⼊⼝点。
旋转作为三维开发的基本功能,在任何3D程序中都需要。
用户通过旋转来实现对模型各个面的浏览,形成直观印象。
球面相机旋转这种旋转方式用户体验方式要优于x轴y轴混合旋转方式,模型旋转的方向和鼠标移动方向保持一致。
下面给出一种“球面相机”实现旋转的方法。
原理:移动鼠标时,通过gluLookAt来改变视点的位置(采用增量的方式),而模型保持不动。
即:只进行视点变换,不进行模型变换。
下图是用户按下左键,在屏幕上移动的一段距离(从A移动到B)。
由于屏幕坐标y轴向下,为了与投影平面坐标系(传统笛卡尔坐标)保持一致。
AM = y1-y2; /*将消息代码描述*/BM = x2-x1;建立屏幕和投影变换近裁截面之间的对应关系(如下图)。
代码实现:1 void setSphereCameraPos()2 {3 // 左键未按下,直接返回4 if (!is_left_button_down)5 return;67 // 从聚焦点指向视点的向量 OA向量8 vector3dd a(eye-target);910 // 计算球面相机半径11 radius = a.getLength();1213 // 将其单位化14 a.normailize();1516 // 当前相机向上方向与a做叉乘,计算投影面水平向右方向向量u17 vector3dd u = upvector.crossProduct(a);18 // 将其单位化19 u.normailize();2021 // 计算相机向上方向在投影面上的投影向量即垂直向上的方向向量v22 vector3dd v = a.crossProduct(u);23 // 将其单位化24 v.normailize();2526 // 计算屏幕AB在投影面上对应的向量 AB向量27 vector3dd m = u*delta_point.x + v*delta_point.y;2829 // 计算m向量的长度30 double len = m.getLength();31 // 降低灵敏度32 len /= 20.0;3334 if (len>0.0)35 {36 // 角度AOB 弧度表示弧长/半径37 double x = len/radius;38 // 将AB向量单位化39 m.normailize();4041 // 按相反方向转动视点到C 从而使得按与鼠标移动一致的方向转动模型42 x = -1*x;43 // 计算新的相机位置 C44 eye = target+(a*cos(x) + m*sin(x))*radius;4546 // 计算新的相机向上方向47 upvector = v;48 }49 }消息代码1 LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window2 UINT uMsg,// Message For This Window3 WPARAM wParam,// Additional Message Information4 LPARAM lParam)// Additional Message Information5 {6 switch(uMsg) // Check For Windows Messages7 {8 case WM_LBUTTONDOWN:9 {10 is_left_button_down = true;11 pre_point.x = LOWORD(lParam);12 pre_point.y = HIWORD(lParam);1314 return 0;15 }1617 case WM_MOUSEMOVE:18 {19 if (is_left_button_down)20 {21 cur_pt.x = LOWORD(lParam);22 cur_pt.y = HIWORD(lParam);// delta_point为增量点23 delta_point.x= cur_pt.x-pre_point.x);// 保持屏幕坐标系和投影平面坐标系一致24 delta_point.y =-1*(cur_pt.y-pre_point.y);// 将当前点赋值给前一个点25 pre_point = cur_pt;26// 计算相机新的位置27 setSphereCameraPos();28 }30 return 0;31 }3233 case WM_LBUTTONUP:34 {35 is_left_button_down = false;36 return 0;37 }38 }3940 // Pass All Unhandled Messages To DefWindowProc41 return DefWindowProc(hWnd,uMsg,wParam,lParam);42 }43vector3dd类vector3dd1 class vector3dd2 {3 private:4 double x,y,z;56 public:7 vector3dd(){};8 vector3dd(double a, double b, double c){x=a;y=b;z=c;}9 vector3dd(const vector3dd& v){*this=v;}11 public:12 void operator=(const vector3dd& v){x=v.x;y=v.y;z=v.z;}13 vector3dd operator*(double a)14 {15 return vector3dd(a*x,a*y,a*z);16 }17 vector3dd operator+(const vector3dd& v)18 {19 return vector3dd(x+v.x,y+v.y,z+v.z);20 }21 vector3dd operator-(const vector3dd& v)22 {23 return vector3dd(x-v.x,y-v.y,z-v.z);24 }2526 public:27 double getX(){return x;}28 double getY(){return y;}29 double getZ(){return z;}3031 void setValue(double a, double b, double c)32 {33 x = a;34 y = b;35 z = c;36 }3738 double getLength()39 {40 return sqrt(x*x+y*y+z*z);41 }4243 void normailize()44 {45 double length = getLength();46 x/=length;47 y/=length;48 z/=length;49 }5051 void invert()52 {53 x*=-1;54 y*=-1;55 z*=-1;56 }5758 vector3dd crossProduct(const vector3dd& v)59 {60 return vector3dd(y*v.z-z*v.y,z*v.x-x*v.z,x*v.y-y*v.x);61 }6263 double dotProduct(const vector3dd& v)64 {65 return (x*v.x+y*v.y+z*v.z);66 }6768 void traceMsg()69 {70 fprintf(stdout, "%.7f, %.7f, %.7f\n", x, y, z);71 }72 };效果图:。
glLoadIdentity()与glTranslatef()和glRotatef()--坐标变换glLoadIdentity()将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作1.X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。
2.OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。
3.中心左面的坐标值是负值,右面是正值。
移向屏幕顶端是正值,移向屏幕底端是负值。
移入屏幕深处是负值,移出屏幕则是正值。
glTranslatef(x, y, z)沿着X, Y和Z 轴移动。
注意在glTranslatef(x, y, z)中,当您移动的时候,您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。
其作用就是将你绘点坐标的原点在当前原点的基础上平移一个(x,y,z)向量。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////glLoadIdentity();glTranslatef(-1.5f,0.0f,-6.0f);glBegin(GL_TRIANGLES);glV ertex3f(0.0f,0.0f, 0.0f);glV ertex3f(1.0f,0.0f, 0.0f);glV ertex3f(0.0f,1.0f, 0.0f);glEnd();glLoadIdentity();glTranslatef(0.0f,0.0f,-6.0f);glBegin(GL_TRIANGLES);glV ertex3f(0.0f,0.0f, 0.0f);glV ertex3f(1.0f,0.0f, 0.0f);glV ertex3f(0.0f,1.0f, 0.0f);glEnd();/////////////////////////////////////////////////////////////////////////////////////程序的运行结果如下:左边的三角形是第一步绘制的,可以看到该三角形绘制的坐标系,实际上是以(-1.5f,0.0f,-6.0f)为原点的。
C语⾔使⽤OpenGL制作旋转地球前置步骤(安装依赖库):sudo apt-get updatesudo apt-get install build-essentialsudo apt-get install libgl1-mesa-devsudo apt-get install libglu1-mesa-dev$sudo apt-get install freeglut3-devsudo apt-get install libfreeimage3 sudo apt-get install libfreeimage-dev1.测试OpenGL环境#include<GL/glut.h>void init(){glClearColor(0.0, 0.0, 0.0, 0.0);glMatrixMode(GL_PROJECTION);glOrtho(-5, 5, -5, 5, 5, 15);gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);return ;}void display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0, 0);glutWireTeapot(3);glFlush();return;}int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(0, 0);glutInitWindowSize(300, 300);glutCreateWindow("OpenGL #D View");init();glutDisplayFunc(display);glutMainLoop();return0;}编译:gcc test.c -o test -lGL -lGLU -lglut运⾏:如果能出现这个图⽚,证明环境配置成功。
上一节中教给您三角形和四边形的着色。
这一课将教您如何将这些彩色对象绕着坐标轴旋转。
其实只需在上节的代码上增加几行就可以了。
下面将整个例程重写一遍。
方便您知道增加了什么,修改了什么。
增加两个变量来控制这两个对象的旋转。
这两个变量加在程序的开始处其他变量的后面( bool fullscreen=TRUE;下面的两行)。
它们是浮点类型的变量,使得我们能够非常精确地旋转对象。
浮点数包含小数位置,这意味着我们无需使用1、2、3...的角度。
你会发现浮点数是OpenGL编程的基础。
新变量中叫做 rtri 的用来旋转三角形, rquad 旋转四边形。
Var……rtri : GLfloat; // 用于三角形的角度 ( 新增 ) rquad : GLfloat; // 用于四边形的角度 ( 新增 )……然后修改 glDraw()如下:Procedure glDraw();BeginglClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存glLoadIdentity(); // 重置当前的模型观察矩阵//下一行代码是新的。
glRotatef(Angle,Xvector,Yvector,Zvector)负责让对象绕某个轴旋转。
//这个命令有很多用处。
Angle 通常是个变量代表对象转过的角度。
//Xvector , Yvector 和 Zvector 三个参数则共同决定旋转轴的方向。
//比如(1,0,0)所描述的矢量经过X坐标轴的1个单位处并且方向向右。
//(-1,0,0)所描述的矢量经过X坐标轴的1个单位处,但方向向左。
//D. Michael Traub:提供了对 Xvector , Yvector 和 Zvector 的上述解释。
//为了更好的理解X, Y 和 Z的旋转,我举些例子...//X轴-您正在使用一台台锯。
锯片中心的轴从左至右摆放(就像OpenGL中的X轴)。
NeHe的opengl教程delphi版(1)----基本框架将CKER翻译的NeHe的VC 的OPENGL框架转成了Delphi版,希望对用Delphi学习OPENGL的兄弟有所帮助,不知为什么,我的Delphi环境下无法直接运行,但是在别的机器上好像没问题我的机器只能编译后运行EXE文件。
感谢NeHe提供的这么好的框架,感谢CKER翻译的VC的资料Program Project1;Usesopengl,windows,Messages;ConstWND_TITLE = 'OPenGl基本框架'; //标题Var//========================================================================== =// 每一个OpenGL都被连接到一个着色描述表上。
着色描述表将所有的OpenGL调用命令连// 接到Device Context(设备描述表)上,将OpenGL的着色描述表定义为hRC ,要让程序能// 够绘制窗口的话,还需要创建一个设备描述表,Windows的设备描述表被定义为 hDC, // DC将窗口连接到GDI(Graphics Device Interface图形设备接口)。
而RC将OpenGL 连接// 到DC。
//========================================================================== =h_RC : HGLRC; // Rendering Context(着色描述表)。
h_DC : HDC; // Device Context(设备描述表)h_Wnd : HWND; // 窗口句柄h_Instance : HINST; // 程序Instance(实例)。
keys : Array[0..255] Of Boolean; // 用于键盘例程的数组{$R *.res}//========================================================================== ====//重新设置OpenGL场景的大小,而不管窗口的大小是否已经改变(假定没有使用全屏模式)。
OpenGL ES总结(二)OpenGL坐标变换之平移及旋转世界坐标系:在OpenGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。
你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。
长度单位这样来定:窗口范围按此单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角坐标为(1,1)。
当前绘图坐标系:是绘制物体时的坐标系。
程序刚初始化时,世界坐标系和当前绘图坐标系是重合的。
当用glTranslatef(),glScalef(), glRotatef()等对当前绘图坐标系进行平移、伸缩、旋转变换之后,世界坐标系和当前绘图坐标系不再重合。
注意,这里的平移旋转是将当前绘图坐标系看做一个整体在世界坐标系中进行旋转平移。
然后,改变以后,再用glVertex3f()等绘图函数绘图时,都是在当前绘图坐标系进行绘图,所有的函数参数也都是相对当前绘图坐标系来讲的。
其中四种坐标经常要在程序中用到:世界坐标,物体坐标,设备坐标和眼坐标。
1、世界坐标是OpenGL中用来描述场景的坐标,Z+轴垂直屏幕向外,X+从左到右,Y+轴从下到上,是右手笛卡尔坐标系统。
我们用这个坐标系来描述物体及光源的位置。
将物体放到场景中也就是将物体平移到特定位置、旋转一定角度,这些操作就是坐标变换。
OpenGL中提供了glTranslate*/glRotate*/glScale*三条坐标变换命令,利用OpenGL的矩阵运算命令,则可以实现任意复杂的坐标变换。
OpenGL中有一个坐标变换矩阵栈(ModelView),栈顶就是当前坐标变换矩阵,进入OpenGL 管道的每个坐标(齐次坐标)都会先乘上这个矩阵,结果才是对应点在场景中的世界坐标。
OpenGL中的坐标变换都是通过矩阵运算完成的,与图形学课本的描述完全一致。
要注意的是变换中的矩阵乘法是左乘,而矩阵乘法与算术乘法不同,不符合交换律(万一不明白去看矩阵代数书好了)。
OpenGL的glRotatef旋转变换函数详解OpenGL的glRotatef旋转变换函数详解先看⼀下函数定义:void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)angle:为旋转的⾓度,单位为度。
x,y,z:为对应xyz轴的布尔值变量。
重点是x,y,z表达的是什么意思呢?应该如何取值?如果说x,y,z表达的是⼀个坐标(x,y,z),那么这个函数就说明了当前⼏何图形围着这个坐标点旋转。
但往哪个⽅向旋转呢?所以很明显,x,y,z表达的意思并不是坐标点,⽽是要围绕哪个坐标轴旋转。
即其实这⾥的x,y,z值相当于⼀个布尔值,0.0表⽰假,⽽⾮零参数则表⽰真。
所以如果你想让当前的⼏何图形围绕着z轴旋转,那么x和y都设为0,⽽z设为⾮零值即可。
如果这⾥的x,y,z的值都设置为0.0,那么将围绕着x轴旋转。
还有⼀点需要注意,如果设置的旋转值(x,y,z的值)为正数,那么旋转的⽅向是逆时针的,如果旋转值是负数,那么旋转的⽅向是顺时针的。
假设:glRotatef(45,1,0,0)物体如何旋转?想象:从坐标(0,0,0)即原点,引出⼀条线到(1,0,0),⽤右⼿握住这条线.这时,你会问,如何握?右⼿⼤拇指指向(0,0,0)⾄(1,0,0)的⽅向才握。
另外四个⼿指的弯曲指向即是物体旋转⽅向。
为什么是右⼿握住,⽽不是左⼿呢?因为OpenGL是右⼿原则。
最后附上代码供参考:1 #include <stdio.h>2 #include <gl/glut.h>34/*5功能描述:使⽤OpenGL简单画⼀个旋转的三⾓形6旋转变换函数glRotatef7*/89//输出模式,0-单缓存模式;⾮0双缓存模式10#define OUTPUT_MODE 11112//⾓度13int angle = 0;1415int xyz[3] = {0, 0, 0};1617void display(void)18 {19//printf("xyz={%d, %d, %d\n}", xyz[0], xyz[1], xyz[2]);2021 glClear(GL_COLOR_BUFFER_BIT);222324 glLoadIdentity();25 glRotatef(angle, xyz[0], xyz[1], xyz[2]);2627 glBegin(GL_TRIANGLES);28 {29 glVertex3f(0.0f, 0.0f, 0.0f);30 glVertex3f(0.5f, 0.0f, 0.0f);31 glVertex3f(0.0f, 0.5f, 0.0f);32 }33 glEnd();3435 angle += 1;36 angle %= 360;3738if (OUTPUT_MODE == 0) {39 glFlush();//单缓存GLUT_SINGLE时使⽤40 } else {41 glutSwapBuffers();//因为使⽤的是双缓存GLUT_DOUBLE,所以这⾥必须要交换缓存才会显⽰42 }43 }4445//按键46void keyboard(unsigned char key, int x, int y)47 {48switch (key)49 {50case'x':51case'X':52 xyz[0] = 1;53 xyz[1] = xyz[2] = 0;54break;55case'y':56case'Y':57 xyz[1] = 1;58 xyz[0] = xyz[2] = 0;59break;60case'z':61case'Z':62 xyz[2] = 1;63 xyz[0] = xyz[1] = 0;64break;65case'a':66case'A':67 xyz[0] = xyz[1] = xyz[2] = 0;68break;69case'b':70case'B':71 xyz[0] = xyz[1] = xyz[2] = 1;72break;73default:74break;75 }76 printf("当前绕%c轴旋转\n", key);77 glutPostRedisplay();78 }7980void reshape(int w, int h)81 {82int offset = 50;83int dis = (w > h ? h : w) - offset * 2;8485//配置显⽰物体屏幕的⼤⼩86 glViewport(offset, offset, (GLsizei)dis, (GLsizei)dis);87 printf("reshape: w=%d, h=%d, dis=%d\n", w, h, dis);8889 glMatrixMode(GL_PROJECTION);90 glLoadIdentity();9192 glOrtho(-1.5, 1.5, -1.5, 1.5, 0, 10);93//gluOrtho2D(-1.5, 1.5, -1.5, 1.5);9495 glMatrixMode(GL_MODELVIEW);96 glLoadIdentity();97 }9899int main(int argc, char *argv[])100 {101 printf("可通过按键xyzab控制图形旋转原点/轴\n");102 glutInit(&argc, argv);103104 glutInitDisplayMode(GLUT_RGB | (OUTPUT_MODE == 0 ? GLUT_SINGLE : GLUT_DOUBLE)); 105 glutInitWindowPosition(100, 100);106 glutInitWindowSize(400, 400);107108 glutCreateWindow("第⼀个 OpenGL 程序");109110 glutDisplayFunc(&display);111 glutIdleFunc(display); //设置不断调⽤显⽰函数112 glutReshapeFunc(reshape);113 glutKeyboardFunc(&keyboard);114 glutMainLoop();115return0;116 }。
第一、准备好OpenGLwindows平台下:OpenGL是由SGI公司开发的低层三维图形API,目前已经成为工业标准,由独立非赢利组织ARB管理。
它在WINDOWS中以动态链接库的形式存在,Win95 osr2以上版本及Win NT 自带有微软公司实现的OpenGL。
但本人推荐使用SGI实现的OpenGL来调试程序,快速可靠而且功能丰富,缺点是它是纯软件实现,无法利用硬件加速。
下载了opengl95.exe或opengl2.exe之后执行之,按提示安装即可。
默认情况情况下会在C:\oglsdk,包括了VC和BC的库及头文件,还有两个演示程序,不妨看看,Fly in the Sky在窗口中移动鼠标就可控制飞行了,还有一份说明书,也不妨看看。
相关文件请到资源区下载Linux平台下:装一个Mesa好了,另外在gtk+(GtkGLArea)/qt(QGLWidget+QGLContext)中均包括了Open GL支持构件(WIDGET),gnome下有许多OpenGL的应用。
注意在LD_LIBRARY_PATH加上必要的路径,详见各软件的安装说明(通常叫README或INSTALL)。
Solaris:OpenGL Library装上随Solaris发售的OpenGL library 。
如果执行以下命令:> cd /usr/openwin/lib> ls libGL*结果显示如下:libGL.so@ libGLU.so@ libGLw.so@libGL.so.1* libGLU.so.1* libGLw.so.1*则意味着OpenGL运行库已经装好了。
通常LD_LIBRARY_PATH里会有该目录,如果没有自己加上就成。
在/usr/openwin/include/GL下有以下头文件:gl.h glu.h glxmd.h glxtokens.hglmacros.h glx.h glxproto.h在sun的网站有OpenGL开发者FAQ,可参阅。
浅述Delphi下的OpenGL图形开发OpenGL 是⼀个低层的图形库,最初由Silicon Graphics Inc. 公司开发。
在⽤户操作系统上对OpenGL具体的实现⼀般被称为OpenGL驱动,它允许⽤户使⽤⼀组⼏何元素(点,线,多边形,图象等等)来描述需要绘制的场景。
使⽤OpenGL对⼀个复杂的场景进⾏可视化通常只需要毫秒级的时间,这就意味着OpenGL图形库有⾜够的性能来⽀持⽤户创建动画和虚拟世界。
OpenGL驱动通常以⼆进制格式的库⽂件提供给⽤户,⽤户可以在应⽤程序中动态的连接这个库⽂件。
在Windows*台上,这个库⽂件的形式是⼀个DLL(就是⽤户系统⽬录下的opengl.dll⽂件)。
因为Delphi可以调⽤DLL⽂件,所以⽤Delphi进⾏OpenGL图形开发就像使⽤其它语⾔进⾏OpenGL图形开发⼀样容易。
这篇⽂章会帮助你熟悉使⽤Delphi进⾏OpenGL图形开发的过程。
数学基础OpenGL 具有很强的数学背景,你使⽤OpenGL进⾏图形开发所仅仅受到你想象⼒的限制。
在进⼊OpenGL的世界之前,先让我们先来看⼀个被⼤多数3D程序员使⽤的⾮常简单的3D坐标系统:这幅图描述了在绘制场景中屏幕的位置。
图中四条线汇集在⼀起的点就是虚拟世界中的观察者的视点。
OpenGL允许⽤户使⽤两个简单的函数调⽤来完成这样的设置:glMatrixMode(GL_PROJECTION);glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0);在这两个函数调⽤中,-0.1, 0.1, -0.1, 0.1 以左,右,下,上的顺序定义了虚拟屏幕的尺⼨; 0.3 定义了视点到屏幕的距离(等于*剪裁*⾯); 25.0 定义了远剪裁*⾯。
在*端剪裁*⾯之前和远端剪裁*⾯之后的场景都不会被显⽰出来。
当然,你也可以根据⾃⼰的需要来设置这些参数。
从图形元素到物体现在到了具有挑战性的⼀个部分:物体。
实例十用OpenGL实现星空闪电图【程序说明】实例九实现的OpenGL星体没有什么使用功能,而本例的星空闪电图则有一定的实用价值,因为不仅实现了背景贴图和声音资源的播放,还实现在背景上加载了一个OpenGL几何实体。
随着闪电的不断旋转,背景和闪电的颜色都不断忽明忽暗地变化着,很有星空闪电的效果。
本例程序运行结果如图10-1所示。
图10-1 用OpenGL实现星空闪电图【编程思路】本例同实例九不一样的地方就是它是完全在Delphi环境下实现的。
因此,我们可以从这个实例中一步一步地学会如何在Delphi环境下创建一个声影具备的OpenGL动画游戏。
下面是这个实例的一些关键技术。
1、在控制台环境下创建自定义的窗口。
2、Delpi环境下OpenGL初始环境设置。
3、用OpenGL技术绘制场景和闪电。
4、背景贴图技术。
5、声音媒体的播放。
这些技术的具体实现请参考后面的代码部分。
【编程步骤】.1.按照前面介绍的方法,新建一个控制台应用程序。
2.编写代码(1)在控制台环境下创建自定义的窗口,并根据具体情况初始化OpenGL设备环境。
function glCreateWnd(Width, Height : Integer; Fullscreen : Boolean; PixelDepth : Integer) : Boolean;varwndClass : TWndClass; // 窗口类型dwStyle : DWORD; // 窗口风格dwExStyle : DWORD; // 窗口扩张风格dmScreenSettings : DEVMODE; // 屏幕设置PixelFormat : GLuint; // OpenGL渲染设置h_Instance : HINST; // 当前实例pfd : TPIXELFORMATDESCRIPTOR; //OpenGL窗口相关设置ResHandle : THandle; //声音资源句柄begin…………(创建一个窗口,详细代码见光盘)//设置OpenGL窗口with pfd dobeginnSize:= SizeOf(TPIXELFORMA TDESCRIPTOR);nVersion := 1;dwFlags:= PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;iPixelType := PFD_TYPE_RGBA; // RGBA颜色格式cColorBits := PixelDepth; // OpenGL颜色深度cDepthBits := 16; // 指定深度缓冲区的深度iLayerType := PFD_MAIN_PLANE;end;PixelFormat := ChoosePixelFormat(h_DC, @pfd); //设置刚才设置的象素格式if (PixelFormat = 0) thenbeginglKillWnd(Fullscreen);MessageBox(0, '不能找到一个合适的象素格式!', '错误', MB_OK or MB_ICONERROR);Result := False;Exit;end;//设置象素格式if (not SetPixelFormat(h_DC, PixelFormat, @pfd)) thenbeginglKillWnd(Fullscreen);MessageBox(0, '不能设置象素格式', '错误', MB_OK or MB_ICONERROR);Result := False;Exit;end;//创建一个OpenGL 渲染环境h_RC := wglCreateContext(h_DC);if (h_RC = 0) thenbeginglKillWnd(Fullscreen);MessageBox(0, '不能创建一个OpenGL 渲染环境', '错误', MB_OK or MB_ICONERROR);Result := False;Exit;end;//设置当前的设备环境if (not wglMakeCurrent(h_DC, h_RC)) thenbeginglKillWnd(Fullscreen);MessageBox(0, '不能激活OpenGL渲染设备', '错误', MB_OK or MB_ICONERROR);Result := False;Exit;end;SetTimer(h_Wnd, FPS_TIMER, FPS_INTERV AL, nil); //初始化计算帧数的定时器ResHandle := FindResource(hInstance, 'Electric', 'WA VE'); //初始化声音设置,加载声音资源SndHandle := LoadResource(hInstance, ResHandle);ShowWindow(h_Wnd, SW_SHOW);SetForegroundWindow(h_Wnd); //设置当前窗口一直保持在最前面SetFocus(h_Wnd);//保证窗口可以正确地缩放glResizeWnd(Width, Height);glInit();Result := True;end;(2)用OpenGL技术绘制场景和闪电。
#include <GL/glut.h>static GLfloat angle = 0.0;static GLfloat movex = 0.0;static GLfloat movey = 0.0;static GLfloat len = 1.0;static GLint x=0.0,y=0.0,z=0.0;static void init(){glClearColor(1.0, 1.0, 1.0, 0.0);}void display(){glClear(GL_COLOR_BUFFER_BIT);glColor3f(0.0, 1.0, 1.0);glPushMatrix();glTranslatef(movex, movey, 0.0);glScalef( len, len, len );glRotatef(angle, x,y, z);glutWireSphere(40, 16, 16);glPopMatrix();glFlush();}void moveright(){movex+=10.0;if (movex>100.0)movex=0.0;glutPostRedisplay();}void moveleft(){movex-=10.0;if (movex<-100.0)movex=0.0;glutPostRedisplay();}void moveup(){movey+=10.0;if (movey>100.0)movey=0.0;glutPostRedisplay(); }void movedown(){movey-=10.0;if (movey<-100.0)movey=0.0;glutPostRedisplay(); }void zoom(){len+=0.1;if (len>10.0)len=10.0;glutPostRedisplay(); }void shrink(){len-=0.1;if (len<-10.0)len=-10.0;glutPostRedisplay(); }void rotatez(){z=1.0;x=0.0;y=0.0;angle+=20.0;if (angle>=360.0)angle=0.0;glutPostRedisplay(); }void rotatey(){z=0.0;y=1.0;x=0.0;angle+=20.0;if (angle>=360.0)angle=0.0;glutPostRedisplay();}void rotatex(){z=0.0;x=1.0;y=0.0;angle+=20.0;if (angle>=360.0)angle=0.0;glutPostRedisplay();}void reshape(GLsizei w, GLsizei h){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(-100.0, 100.0, -100.0, 100.0, 0.0, 100.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void specialKeyFunc( int key, int x, int y){switch(key){case GLUT_KEY_LEFT:moveleft();break;case GLUT_KEY_RIGHT:moveright();break;case GLUT_KEY_UP:moveup();break;case GLUT_KEY_DOWN:movedown();break;case GLUT_KEY_F1:zoom();break;case GLUT_KEY_F2:shrink();break;case GLUT_KEY_F7:rotatez();break;case GLUT_KEY_F6:rotatey();break;case GLUT_KEY_F5:rotatex();break;default:break;}}void main(){glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowPosition(50, 100);glutInitWindowSize(550, 600);glutCreateWindow("三维图形的旋转与平移");glutSpecialFunc(specialKeyFunc);init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutMainLoop();}。
实例九用OpenGL实现旋转星球【程序说明】在游戏制作领域,两个不可逃避的主题就是OpenGL和DirectX。
不管喜欢不喜欢,这两个是游戏设计的利器。
一个大型游戏如果缺少这两种技术是不可想象的。
在本书的最后两个游戏实例中,就介绍关于OpenGL技术的一些常见应用。
本例实现的是在窗口中显示一个旋转的星球,这个星球大小是飘忽不定的。
程序运行结果如图9-1所示。
图9-1 用OpenGL实现旋转星球【编程思路】在Delphi中,OpenGL可以作为自身动态运行时间库(RTL)的一部分,以pas单元的形式放在“……\Borland\Delphi5\Source\Rtl\Win”目录下,可以象使用其他单元文件一样方便地使用。
OpenGL的绘图环境与GDI(Graphic Devic Interface,图形设备接口)的绘图环境不同。
因此各自的使用方法也不一样。
下面详细介绍Opengl的绘图步骤:1.获取显示设备的句柄,这个句柄可以用GetDC开获取。
2.设置象素格式(pixelFormat)。
该步骤先用ChoosePixelFormat选取预先根据显示设备设置好的象素格式,然后用SetPixelFormat来设置象素格式。
3.建立新的OpenGL Rendering Context(HGLRC),这个参数相当于GDI中绘图设备的HDC,两者的调用方法也很相似。
如本例中的hrc:=wglCreateContext(Canvas.Handle),在创建了这样一个HRC之后,在设备上绘图时只要将这个HRC通过wglMakeCurrent(Canvas.Handle, hrc)设置为当前的绘图环境即可。
4.设置视口和透视投影坐标。
Opengl是一个三维绘图系统,所有绘制的图形都是建立在三维空间内的,因此要设置透视投影坐标,以便能观察绘制的图形效果。
经过了上述四个步骤之后,就可以在指定的设备上画图了。
本例中的画图操作在是由夹在glbegin()…glEnd中的函数体中的操作完成的。
在本例中,并没有使用Delphi自带的Opengl.pas文件,而是引入了Mike Lischke针对具体应用情况重新编写的OpenGL.pas单元。
主要原因是该单元已经将初始化设置和渲染设置已经很好地封闭了,可以非常方便而简洁地调用。
本例还将常用的几何实体变换封装成Geometry.pas单元。
有了这两个单元文件,在设计OpenGL游戏时,可以将主要的精力放在游戏的思路和总体规划中,而不是花在各种环境的设置和实体模型的创建和变换中。
本例也不打算对这两个单元进行说明了,只介绍如何调用它们实现本例的形体旋转效果。
特别要说明的是必须将新的OpenGL.pas和Geometry.pas和工程文件放在同一目录中。
另外,本例创建的是控制台程序,而不是标准的win32程序。
因此,一个重要的技术就是如何在控制台环境下实现窗口的创建和销毁等效果。
在后面的代码中有详尽的注释,这里就不细述了。
【编程步骤】.1.选择File|New|Other…,这时会弹出一个文件类型选择对话框。
在其中选择Console Application,新建一个控制台应用程序。
控制台应用程序的标志是在程序的头文件中有{$APPTYPE CONSOLE}的标志符。
2.编写代码。
下面是本例的主要代码。
program Project2; //工程文件名{$APPTYPE CONSOLE} //文件类型标志符uses Windows, Messages,OpenGL; //本例用到的几个单元文件varhParentWnd: hWnd; // 窗口句柄h_DC: hDC; // 设备环境的句柄h_RC: hGLRC; // 渲染环境的句柄WndClass: TWndClass; // 窗口类型iMessage: TMsg;PWndWidth, PWndHeight: Integer; // 旋转的星体所在窗口的大小Angle: Integer; //旋转角度// 处理父窗口消息的方法function MainWndProc(hWnd:hWnd; iMessage: uInt; wParam: wParam; lParam: lParam): lResult; export; stdcall;beginResult := 0;case iMessage ofWM_DESTROY: PostQuitMessage(0); // 通知窗口程序即将退出elseResult := DefWindowProc(hWnd, iMessage, wParam, lParam);end;end;// 创建自定义的窗口procedure PrepareWindow;beginif (hPrevInst = 0) thenbeginWndClass.style := CS_HREDRAW or CS_VREDRAW;WndClass.lpfnWndProc := @MainWndProc; // 指向处理窗口消息的过程WndClass.cbClsExtra := 0;WndClass.cbWndExtra := 0;WndClass.hInstance := GetModuleHandle(nil);WndClass.hIcon := 0;WndClass.hCursor := LOADCURSOR(0, IDC_ARROW);WndClass.hBrBackground := 0; //OpenGL场景不需要背景WndClass.lpszMenuName := nil;WndClass.lpszClassName := 'glClass';if RegisterClass(WndClass) = 0 thenbeginMessageBox(hParentWnd, '不能注册!', nil, MB_OK or MB_ICONSTOP or MB_TASKMODAL);Halt;end;end;PWndWidth := Round(GetSystemMetrics(SM_CXSCREEN)/2); //设置演示窗口的宽度PWndHeight := Round(GetSystemMetrics(SM_CYSCREEN)/2); //设置演示窗口的长度hParentWnd := CreateWindow('glClass', 'Delphi中演示OPENGL动画', WS_SYSMENU, 0, 0,PWndWidth, PWndHeight, 0, 0, hInstance, nil); //创建新窗口的关键代码end;// 绘制场景自定义函数procedure DrawScene;beginAngle := Angle+Random(20);{清除帧缓冲区,为绘制新的帧做准备}glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);glPushMatrix; // 保存当前矩阵glTranslatef(Random(2)/10, Random(2)/10,Random(2)-6);{将视点后移使全部的场景可见,前面两个数值分别是X,Y的坐标值,最后的数值决定对象大小} {转动对象的视点,后面三个数字表示旋转幅度,值越大幅度越大}glRotatef(Angle, 1, 1, 1);// glRotatef(Angle,0,0,0); {换一行这句代码吧,很强的视觉冲击效果}//以下是定义组成星体的点元素glBegin(GL_TRIANGLES);glNormal3f(-0.74116, -0.579615, 0.338716);glVertex3f(-0.475525, -0.142578, 0.154755);glVertex3f(-0.293854, -0.451569, 0.0235291);glVertex3f(-0.344055, -0.147278, 0.434387);glEnd;glBegin(GL_TRIANGLES);glNormal3f(-0.410835, -0.910633, -0.0442978);glVertex3f(-0.293854, -0.451569, 0.0235291);glVertex3f(-0.0111389, -0.565186, -0.262848);glVertex3f(0.168762, -0.656647, -0.0511475);glEnd;…………(建模语句,完整代码见光盘)glBegin(GL_TRIANGLES);glNormal3f(-0.206353, 0.0933145, 0.974018);glVertex3f(-0.0549011, 0, 0.5 );glVertex3f(-0.0811768, 0.360779, 0.459869);glVertex3f(-0.317749, -0.0470581, 0.448822);glEnd;glBegin(GL_TRIANGLES);glNormal3f(-0.408821, 0.761405, 0.503119);glVertex3f(-0.138153, 0.486145, 0.223846);glVertex3f(-0.344055, 0.324249, 0.301544);glVertex3f(-0.0811768, 0.360779, 0.459869);glEnd;SwapBuffers(h_DC); // 交换帧缓冲区glPopMatrix; // 处理当前矩阵end; // 置于先前保存的矩阵之后// 构造正式绘制Opengl场景函数procedure PrepareScene;beginglEnable(GL_DEPTH_TEST);glEnable(GL_CULL_FACE);glEnable(GL_NORMALIZE);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);glMatrixMode(GL_PROJECTION);glViewPort(0, 0, PWndWidth, PWndHeight); // 设置渲染的环境gluPerspective(60, 400/300, 1, 100); // 设置其余的场景范围glMatrixMode(GL_MODELVIEW);angle := 0;end;beginPrepareWindow;h_DC := GetDC(hParentWnd); // 从创建的窗口中获得一个句柄{--------下面几个函数都在OpenGL.pas中,详细代码参考光盘中本例目录下的OpenGL.pas---------} InitOpenGL; // 激活动态链接库,初始化象素设置h_RC :=CreateRenderingContext(h_DC, [opDoubleBuffered], 0, 0); // 设置Opengl的渲染环境ActivateRenderingContext(h_DC, h_RC); //激活设备句柄{---------------------------------------------------------------------------------}PrepareScene; //绘制场景ShowWindow(hParentWnd, SW_SHOW); // 使窗口可见// 下列消息使这个程序循环执行repeatPeekMessage(iMessage, 0, 0, 0, PM_REMOVE); // 解释消息TranslateMessage(iMessage);DispatchMessage(iMessage); // 给主窗口过程分派消息DrawScene;until (iMessage.message = WM_QUIT);// 退出演示后的相关处理DeactivateRenderingContext; //释放渲染环境,在OpenGL.pas中DestroyRenderingContext(h_RC); //销毁渲染环境,在OpenGL.pas中ReleaseDC(hParentWnd, h_DC); //释放设备句柄UnRegisterClass('glClass', hInstance); //销毁窗口类型CloseOpenGL; //关闭OpenGL环境设备,在OpenGL.pas中DestroyWindow(hParentWnd); //销毁窗口end.3.保存所有文件,然后按F9运行该程序。