zoukankan      html  css  js  c++  java
  • opengl学习

    #include"stdafx.h"
    #define GLUT_DISABLE_ATEXIT_HACK  
    #include <GL/glut.h>
    //glut自动将gl.h和glu.h包含了
    #include"math.h"
    #include <time.h>
    
    const int n = 20; 
    const GLfloat R = 20.0f; 
    const GLfloat Pi = 3.1415926536f;
    // 太阳、地球和月亮 
    // 假设每个月都是30天 
    // 一年12个月,共是360天 
    static int day = 200; // day的变化:从0到359
    
    #define WIDTH 400 
    #define HEIGHT 400 
    static GLfloat angle = 0.0f;
    
    #define ColoredVertex(c, v) do{ glColor3fv(c); glVertex3fv(v); }while(0)
    
    void myDisplay5(void) 
    { 
        static int list = 0; 
        if( list == 0 ) 
        {
            // 如果显示列表不存在,则创建 
            /* GLfloat PointA[] = {-0.5, -5*sqrt(5)/48, sqrt(3)/6}, 
                       PointB[] = { 0.5, -5*sqrt(5)/48, sqrt(3)/6}, 
                       PointC[] = { 0, -5*sqrt(5)/48, -sqrt(3)/3}, 
                       PointD[] = { 0, 11*sqrt(6)/48, 0}; 
                       */ 
            // 2007年4月27日修改 
            GLfloat PointA[] = { 0.5f, -sqrt(6.0f)/12, -sqrt(3.0f)/6}, 
                    PointB[] = {-0.5f, -sqrt(6.0f)/12, -sqrt(3.0f)/6},
                    PointC[] = { 0.0f, -sqrt(6.0f)/12, sqrt(3.0f)/3},
                    PointD[] = { 0.0f, sqrt(6.0f)/4, 0}; 
            
            GLfloat ColorR[] = {1, 0, 0}, 
                    ColorG[] = {0, 1, 0}, 
                    ColorB[] = {0, 0, 1}, 
                    ColorY[] = {1, 1, 0};
            //一、分配显示列表编号
            //要分配i个连续的未使用的显示列表编号,返回的是分配的若干连续编号中最小的一个。
            //。如果函数返回零,表示分配失败。
            list = glGenLists(1); 
            
            //二、创建显示列表
            //glNewList有两个参数,
            //第一个参数是一个正整数表示装入到哪个显示列表。
            //第二个参数有两种取值,如果为GL_COMPILE,则表示以下的内容只是装入到显示列表,但现在不执行它们;
            //如果为GL_COMPILE_AND_EXECUTE,表示在装入的同时,把装入的内容执行一遍。
            glNewList(list, GL_COMPILE); 
            //显示列表只能装入OpenGL函数,而不能装入其它内容
            glBegin(GL_TRIANGLES); 
            // 平面ABC 
            ColoredVertex(ColorR, PointA); 
            ColoredVertex(ColorG, PointB); 
            ColoredVertex(ColorB, PointC);
            // 平面ACD 
            ColoredVertex(ColorR, PointA); 
            ColoredVertex(ColorB, PointC);
            ColoredVertex(ColorY, PointD); 
            // 平面CBD 
            ColoredVertex(ColorB, PointC); 
            ColoredVertex(ColorG, PointB);
            ColoredVertex(ColorY, PointD); 
            // 平面BAD 
            ColoredVertex(ColorG, PointB);
            ColoredVertex(ColorR, PointA);
            ColoredVertex(ColorY, PointD); 
            glEnd(); 
            glEndList(); 
            glEnable(GL_DEPTH_TEST);
            } 
            // 已经创建了显示列表,在每次绘制正四面体时将调用它 
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glPushMatrix(); 
            glRotatef(angle, 1, 0.5, 0); 
            
            //三、调用显示列表
            //使用glCallList函数可以调用一个显示列表。该函数有一个参数,表示要调用的显示列表的编号。
            glCallList(list); 
            glPopMatrix(); 
            
            //
            //使用glDeleteLists来销毁一串编号连续的显示列表。
            glutSwapBuffers();
    }
    void myIdle2(void) 
    { 
        ++angle; 
        if( angle >= 360.0f ) 
            angle = 0.0f; 
        myDisplay5(); 
    }
    
    void myDisplay4(void)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
        // 创建透视效果视图 
        glMatrixMode(GL_PROJECTION); 
        glLoadIdentity(); 
        //透视投影
        gluPerspective(90.0f, 1.0f, 1.0f, 20.0f); 
        glMatrixMode(GL_MODELVIEW); 
        glLoadIdentity(); 
        gluLookAt(0.0, 5.0, -10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
        // 定义太阳光源,它是一种白色的光源 
        { 
            GLfloat sun_light_position[] = {0.0f, 0.0f, 0.0f, 1.0f};
            GLfloat sun_light_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
            GLfloat sun_light_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; 
            GLfloat sun_light_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
            glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); 
            glLightfv(GL_LIGHT0, GL_AMBIENT, sun_light_ambient); 
            glLightfv(GL_LIGHT0, GL_DIFFUSE, sun_light_diffuse); 
            glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular); 
            glEnable(GL_LIGHT0); 
            glEnable(GL_LIGHTING); 
            glEnable(GL_DEPTH_TEST);
        }
        // 定义太阳的材质并绘制太阳 
        { 
            GLfloat sun_mat_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f}; 
            GLfloat sun_mat_diffuse[] = {0.0f, 0.0f, 0.0f, 1.0f}; 
            GLfloat sun_mat_specular[] = {0.0f, 0.0f, 0.0f, 1.0f}; 
            GLfloat sun_mat_emission[] = {0.5f, 0.0f, 0.0f, 1.0f}; 
            GLfloat sun_mat_shininess = 0.0f; 
            glMaterialfv(GL_FRONT, GL_AMBIENT, sun_mat_ambient); 
            glMaterialfv(GL_FRONT, GL_DIFFUSE, sun_mat_diffuse); 
            glMaterialfv(GL_FRONT, GL_SPECULAR, sun_mat_specular); 
            glMaterialfv(GL_FRONT, GL_EMISSION, sun_mat_emission); 
            glMaterialf (GL_FRONT, GL_SHININESS, sun_mat_shininess); 
            glutSolidSphere(2.0, 40, 32); 
        } 
        // 定义地球的材质并绘制地球 
        { 
            GLfloat earth_mat_ambient[] = {0.0f, 0.0f, 0.5f, 1.0f}; 
            GLfloat earth_mat_diffuse[] = {0.0f, 0.0f, 0.5f, 1.0f}; 
            GLfloat earth_mat_specular[] = {0.0f, 0.0f, 1.0f, 1.0f};
            GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f}; 
            GLfloat earth_mat_shininess = 30.0f; 
            glMaterialfv(GL_FRONT, GL_AMBIENT, earth_mat_ambient); 
            glMaterialfv(GL_FRONT, GL_DIFFUSE, earth_mat_diffuse);
            glMaterialfv(GL_FRONT, GL_SPECULAR, earth_mat_specular); 
            glMaterialfv(GL_FRONT, GL_EMISSION, earth_mat_emission);
            glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess); 
            glRotatef(angle, 0.0f, -1.0f, 0.0f); 
            glTranslatef(5.0f, 0.0f, 0.0f); 
            glutSolidSphere(2.0, 40, 32); 
        } 
            glutSwapBuffers();
    
            //使用glLight*函数可设置光源的属性,使用glMaterial*函数可设置材质的属性,使用glLightModel*函数可设置光照模式。
    }
    double CalFrequency() 
    { 
        static int count; 
        static double save;
        static clock_t last, current; 
        double timegap; 
        ++count; 
        if( count <= 50 ) 
            return save; 
        count = 0; 
        last = current; 
        current = clock();
        timegap = (current-last)/(double)CLK_TCK; 
        save = 50.0/timegap; 
        return save;
    }
    void myDisplay2(void) 
    { 
        glEnable(GL_DEPTH_TEST); 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
        glMatrixMode(GL_PROJECTION); 
        glLoadIdentity(); 
        gluPerspective(75, 1, 1, 400000000);
        glMatrixMode(GL_MODELVIEW); 
        glLoadIdentity(); 
        gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1);
        // 绘制红色的“太阳” 
        glColor3f(1.0f, 0.0f, 0.0f); 
        glutSolidSphere(69600000, 20, 20); 
        // 绘制蓝色的“地球” 
        glColor3f(0.0f, 0.0f, 1.0f); 
        glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f); 
        glTranslatef(150000000, 0.0f, 0.0f); 
        glutSolidSphere(15945000, 20, 20); 
        // 绘制黄色的“月亮” 
        glColor3f(1.0f, 1.0f, 0.0f); 
        glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f); 
        glTranslatef(38000000, 0.0f, 0.0f); 
        glutSolidSphere(4345000, 20, 20); 
        
        glFlush();
    
        //小结:本课开始,我们正式进入了三维的OpenGL世界。
        //OpenGL通过矩阵变换来把三维物体转变为二维图象,进而在屏幕上显示出来。
        //为了指定当前操作的是何种矩阵,我们使用了函数glMatrixMode。 
        //我们可以移动、旋转观察点或者移动、旋转物体,使用的函数是glTranslate*和glRotate*。 
        //我们可以缩放物体,使用的函数是glScale*。 
        //我们可以定义可视空间,这个空间可以是“正投影”的(使用glOrtho或gluOrtho2D),
        //也可以是“透视投影”的(使用glFrustum或gluPerspective)。 
        //我们可以定义绘制到窗口的范围,使用的函数是glViewport。 
        //矩阵有自己的“堆栈”,方便进行保存和恢复。
        //这在绘制复杂图形时很有帮助。使用的函数是glPushMatrix和glPopMatrix。
    }
    
    void myDisplay3(void) 
    { 
        double FPS = CalFrequency();
        printf("FPS = %f
    ", FPS);
        glEnable(GL_DEPTH_TEST); 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
        glMatrixMode(GL_PROJECTION); 
        glLoadIdentity(); 
        gluPerspective(75, 1, 1, 400000000);
        glMatrixMode(GL_MODELVIEW); 
        glLoadIdentity(); 
        gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1);
        // 绘制红色的“太阳” 
        glColor3f(1.0f, 0.0f, 0.0f); 
        glutSolidSphere(69600000, 20, 20); 
        // 绘制蓝色的“地球” 
        glColor3f(0.0f, 0.0f, 1.0f); 
        glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f); 
        glTranslatef(150000000, 0.0f, 0.0f); 
        glutSolidSphere(15945000, 20, 20); 
        // 绘制黄色的“月亮” 
        glColor3f(1.0f, 1.0f, 0.0f); 
        glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f); 
        glTranslatef(38000000, 0.0f, 0.0f); 
        glutSolidSphere(4345000, 20, 20); 
        
        glFlush();
        glutSwapBuffers();
    
        //OpenGL动画和传统意义上的动画相似,都是把画面一幅一幅的呈现在观众面前。
        //一旦画面变换的速度快了,观众就会认为画面是连续的。 
        //双缓冲技术是一种在计算机图形中普遍采用的技术,绝大多数OpenGL实现都支持双缓冲技术。 
        //通常都是利用CPU空闲的时候绘制动画,但也可以有其它的选择。 
        //介绍了垂直同步的相关知识。 
        //介绍了一种简单的计算帧速(FPS)的方法。
    }
    
    void myIdle1(void) 
    { 
        /* 新的函数,在空闲时调用,作用是把日期往后移动一天并重新绘制,达到动画效果 */ 
        angle += 0.05f; 
        if( angle >= 360.0f ) 
            angle = 0.0f;
        myDisplay4(); 
    }
    
    void myIdle(void) 
    { 
        /* 新的函数,在空闲时调用,作用是把日期往后移动一天并重新绘制,达到动画效果 */ 
        ++day; 
        if( day >= 360 ) 
            day = 0; 
        myDisplay3(); 
    }
    
    //gl是基本函数库
    //glu是gl的一些方便的和直观的高级应用
    //这两个都和OS无关
    //glut是和os打交道的库
    //lut是一个系统无关的窗口系统,不用它就要用api或MFC画窗口,而glut窗口操作比较简单的,适合初学者或者编小型的程序
    void init(void)
    {
        glClearColor(1.0,1.0,1.0,0.0);
        //设置当前操作的矩阵
        glMatrixMode(GL_PROJECTION);
    
        //前把当前矩阵设置为单位矩阵。
        //glLoadIdentity();
    
        //将当前的可视空间设置为透视投影空间
        //glFrustum();
    
        //将当前的可视空间设置为正投影空间
        gluOrtho2D(0.0,200.0,0.0,150.0);
    
        //使用glViewport来定义视口
    
        //操作矩阵堆栈
        //当我们需要保存时,调用glPushMatrix函数。
        //当需要恢复最近一次的保存时,调用glPopMatrix函数。
    }
    
    void myDisplay(void) 
    { 
        double FPS = CalFrequency();
        printf("FPS = %f
    ", FPS);
        glClear(GL_COLOR_BUFFER_BIT); 
        glColor3f(1.0,0.0,0.0);
    
        glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式 
        glPolygonMode(GL_BACK, GL_LINE); // 设置反面为线形模式 
        glFrontFace(GL_CCW); // 设置逆时针方向为正面 
    
        glBegin(GL_POLYGON); // 按逆时针绘制一个正方形,在左下方
        glVertex2f(-10.5f, -10.5f); 
        glVertex2f(10.0f, -10.5f); 
        glVertex2f(10.0f, 10.0f); 
        glVertex2f(-10.5f, 10.0f); 
        glEnd(); 
    
        glBegin(GL_POLYGON); // 按顺时针绘制一个正方形,在右上方 
        glVertex2f(10.0f, 10.0f); 
        glVertex2f(10.0f, 15.0f); 
        glVertex2f(15.0f, 15.0f); 
        glVertex2f(15.0f, 10.0f); 
        glEnd(); 
    
        glFlush(); 
    }
    
    void myDisplay1(void) 
    { 
        static GLubyte Mask[128]; 
        FILE *fp; 
        fp = fopen("11.bmp", "rb"); 
        if( !fp ) 
            exit(0); 
        if( fseek(fp, -(int)sizeof(Mask), SEEK_END) ) 
            exit(0); 
        if( !fread(Mask, sizeof(Mask), 1, fp) ) 
            exit(0); 
        fclose(fp); 
    
        glClear(GL_COLOR_BUFFER_BIT); 
        glColor3f(1.0,0.0,0.0);
    
        glEnable(GL_POLYGON_STIPPLE);
        glPolygonStipple(Mask); 
        glRectf(0.0f, 0.0f, 50.0f, 50.0f); 
        // 在左下方绘制一个有镂空效果的正方形 
        glDisable(GL_POLYGON_STIPPLE); 
    
        //glRectf(50.0f, 50.0f, 100.0f, 100.0f); 
        // 在右上方绘制一个无镂空效果的正方形 
        glFlush(); 
    }
    
    void lineSegment(void)
    {
        //清除。GL_COLOR_BUFFER_BIT表示清除颜色
        glClear(GL_COLOR_BUFFER_BIT);
    
        //指定顶点颜色
        glColor3f(1.0,0.0,0.0);
        
        //使用glNormal*函数则可以指定法线向量
    
        //光源是通过glLight*函数来设置
        //,OpenGL至少会支持8个光源,即GL_LIGHT0到GL_LIGHT7
        //,glEnable(GL_LIGHT0);可以开启第0号光源。使用glDisable函数则可以关闭光源。
        //光源的属性GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR属性。这三个属性表示了光源所发出的光的反射特性(以及颜色)
        //GL_POSITION属性。表示光源所在的位置。
        //)GL_SPOT_DIRECTION、GL_SPOT_EXPONENT、GL_SPOT_CUTOFF属性。表示将光源作为聚光灯使用(这些属性只对位置性光源有效)
    
        //OpenGL默认是关闭光照处理的。
        //要打开光照处理功能,使用下面的语句: glEnable(GL_LIGHTING); 
        //要关闭光照处理功能,使用glDisable(GL_LIGHTING);即可。
    
        //材质则是通过glMaterial*函数来设置
    
        //glBegin支持参数
        //GL_POINTS点、GL_LINES线、
        //GL_LINE_STRIP不闭合多边形、
        //GL_LINE_LOOP闭合多边形、
        //GL_TRIANGLES三角形、
        //GL_TRIANGLE_STRIP、
        //GL_TRIANGLE_FAN
        //GL_POLYGON
        //GL_QUODS
        //GL_QUOD_STRIP
        
        //设置点的大小,单位为像素,默认为1.
        glPointSize(5.0f);
        glBegin(GL_POINTS); 
        glVertex2f(30.0f, 45.0f); 
        glVertex2f(78.0f, 54.0f); 
        glEnd();
        
        //设置线的宽度,与glPointSize用法类似
        glLineWidth(5.0f);
        //启动虚线模式
        glEnable(GL_LINE_STIPPLE);
        glLineStipple(2, 0x0F0F);
        glBegin(GL_LINES);
        glVertex2i(100,0);
        glVertex2i(0,50);
        glEnd();
        //关闭虚线模式
        glDisable(GL_LINE_STIPPLE);
    
        //可知坐标系原点在窗口的左下角
        int i; 
        int x = 100,y = 50;
        //glClear(GL_COLOR_BUFFER_BIT); 
        glBegin(GL_POLYGON); 
        for(i=0; i<n; ++i) 
            glVertex2f(x + R*cos(2*Pi/n*i),y + R*sin(2*Pi/n*i)); 
        glEnd();
    
        /*从三维的角度来看,一个多边形具有两个面。
        每一个面都可以设置不同的绘制方式:填充、只绘制边缘轮廓线、只绘制顶点,
        其中“填充”是默认的方式。可以为两个面分别设置不同的方式。*/ 
    
        //glPolygonMode(GL_FRONT, GL_FILL); 设置正面为填充方式 
        //glPolygonMode(GL_BACK, GL_LINE); 设置反面为边缘绘制方式 
        //glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式
        
        //一般约定为“顶点以逆时针顺序出现在屏幕上的面”为“正面”,另一个面即成为“反面”。
        //glFrontFace(GL_CCW); // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针 
        //glFrontFace(GL_CW); // 设置CW方向为“正面”,CW即ClockWise,顺时针
    
        //使用glEnable(GL_CULL_FACE);来启动剔除功能(使用glDisable(GL_CULL_FACE)可以关闭之)
        //使用glCullFace来进行剔除。参数可以是GL_FRONT,GL_BACK或者GL_FRONT_AND_BACK。
    
        //直线可以被画成虚线,而多边形则可以进行镂空。 
        //首先,使用glEnable(GL_POLYGON_STIPPLE);来启动镂空模式(使用glDisable(GL_POLYGON_STIPPLE)可以关闭之)。 
        //然后,使用glPolygonStipple来设置镂空的样式。
    
        //保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)。其作用跟fflush(stdout)类似。
        glFlush();
    }
    
    //argc 是指命令行输入参数的个数(以空白符分隔) argv存储了所有的命令行参数 
    int main(int argc, char **argv)
    {    
        //以glut 开头的函数都是GLUT工具包所提供的函数
        
        //对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次。
        glutInit(&argc,argv);
    
        //设置显示方式
        //GLUT_RGB表示使用RGB颜色,GLUT_INDEX表示使用索引颜色
        //GLUT_SINGLE表示使用单缓冲,GLUT_DOUBLE使用双缓冲
        glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
    
        //设置窗口在屏幕中的位置
        glutInitWindowPosition(100,100);
    
        //设置窗口的大小
        glutInitWindowSize(WIDTH,HEIGHT);
    
        //根据前面设置的信息创建窗口。参数将被作为窗口的标题。注意:窗口被创建后,并不立即显示到屏幕上。需要调用glutMainLoop才能看到窗口
        glutCreateWindow("测试");
    
        init();
    
        //设置一个函数,当需要进行画图时,这个函数就会被调用
        glutDisplayFunc(myDisplay4);
    
        glutIdleFunc(&myIdle1); // 新加入了这句,空闲时调用,实现动画效果
    
        glutMainLoop();
    
        return 0;
    }
  • 相关阅读:
    模仿jquery框架源码 -成熟---选择器
    模仿jquery框架源码---网络
    jquery链式语法
    jquery跟DOM转换
    jquery选择器
    基本jquery
    滚屏加载--无刷新动态加载数据技术的应用
    CenterFactory
    IImage--factory
    redis的使用及方法
  • 原文地址:https://www.cnblogs.com/cugwx/p/3711170.html
Copyright © 2011-2022 走看看