现在的位置: 首页 > 综合 > 正文

一个最小OpenGL框架

2014年01月13日 ⁄ 综合 ⁄ 共 5638字 ⁄ 字号 评论关闭

下面是一个基于glut的OpenGL程序框架,用的是正投影,可以方便的通过参数设置Frustum的大小。

通常可以用来做二维的demo,比如二维填充算法演示等等。


//迈克老狼整理,参考3D Graphics书
#include <stdlib.h>
#include <stdio.h>
#include <GL/glew.h>    // muse be placed before glut. gkd
#include <GL/glut.h>    // OpenGL Graphics Utility Library

// These variables control the current mode
//一共有5种模式, CurrentMode表示当前显示模式
int CurrentMode = 0;
const int NumModes = 5;

// These variables set the dimensions of the rectanglar region we wish to view.
// 设置视口的大小,后面我们设置点的坐标在这个范围内,可以显示,否则被裁减。
const double Xmin = 0.0, Xmax = 3.0;
const double Ymin = 0.0, Ymax = 3.0;

// glutKeyboardFunc is called below to set this function to handle
//        all "normal" ascii key presses.
// Only space bar and escape key have an effect.
//处理普通按键的回调函数
void myKeyboardFunc( unsigned char key, int x, int y )
{
    switch ( key ) 
    {

    case ' ':                                    // Space bar
        // Increment the current mode, and tell operating system screen needs redrawing
        CurrentMode = (CurrentMode+1)%NumModes;
        glutPostRedisplay();
        break;

    case 27:                                    // "27" is the Escape key
        exit(1);

    }
}


/*
 * drawScene() handles the animation and the redrawing of the
 *        graphics window contents.
 * 在窗口中画要显示的物体
 */
void drawScene(void)
{
    // Clear the rendering window
    //清楚颜色缓冲区和深度缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Set drawing color to white
    //设置画笔颜色为白色
    glColor3f( 1.0, 1.0, 1.0 );        

    switch (CurrentMode)
    {

    case 0:
        // Draw three points
        //画三个点
        glBegin(GL_POINTS);
        glVertex2f( 1.0, 1.0 );
        glVertex2f( 2.0, 1.0 );
        glVertex2f( 2.0, 2.0 );
        glEnd();
        break;

    case 1:
    case 2:
    case 3:
        if ( CurrentMode==1 )
        {
            // Draw lines in GL_LINES mode
            glBegin( GL_LINES );
        }
        else if ( CurrentMode==2 )
        {
            // Draw lines in GL_LINE_STRIP mode
            glBegin( GL_LINE_STRIP );
        }
        else 
        {
            // Draw lines in GL_LINE_LOOP mode
            glBegin( GL_LINE_LOOP );
        }
        glVertex2f( 0.5, 1.0 );
        glVertex2f( 2.0, 2.0 );
        glVertex2f( 1.8, 2.6 );
        glVertex2f( 0.7, 2.2 );
        glVertex2f( 1.6, 1.2 );
        glVertex2f( 1.0, 0.5 );
        glEnd();
        break;

    case 4:            // Overlapping triangles
        glBegin( GL_TRIANGLES );
        glColor3f( 1.0, 0.0, 0.0 );
        glVertex3f( 0.3, 1.0, 0.5 );
        glVertex3f( 2.7, 0.85, 0.0 );
        glVertex3f( 2.7, 1.15, 0.0 );

        glColor3f( 0.0, 1.0, 0.0 );
        glVertex3f(2.53, 0.71, 0.5 );
        glVertex3f(1.46, 2.86, 0.0 );
        glVertex3f(1.2, 2.71, 0.0 );

        glColor3f( 0.0, 0.0, 1.0 );
        glVertex3f(1.667, 2.79, 0.5);
        glColor3f( 1.0, 0.0, 0.0 );
        glVertex3f(0.337, 0.786, 0.0);
        glColor3f( 0.0, 1.0, 0.0 );
        glVertex3f(0.597, 0.636, 0.0);
        glEnd();
    }

    // Flush the pipeline.  (Not usually necessary.)
    glFlush();

}

// Initialize OpenGL's rendering modes
void initRendering()
{

    glEnable ( GL_DEPTH_TEST );

    // Uncomment out the first block of code below, and then the second block,
    //        to see how they affect line and point drawing.

    // The following commands should cause points and line to be drawn larger
    //    than a single pixel width.
    //  设置点的大小和线的宽度
    glPointSize(8);
    glLineWidth(5);

    // The following commands should induce OpenGL to create round points and 
    //    antialias points and lines.  (This is implementation dependent unfortunately).
    //RGBA mode antialias need cooperate with blend function.
    //点和线的反锯齿设置
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);    // Make round points, not square points
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);        // Antialias the lines
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


}

// Called when the window is resized
//        w, h - width and height of the window in pixels.
void resizeWindow(int w, int h)
{
    double scale, center;
    double windowXmin, windowXmax, windowYmin, windowYmax;

    // Define the portion of the window used for OpenGL rendering.
    glViewport( 0, 0, w, h );    // View port uses whole window

    // Set up the projection view matrix: orthographic projection
    // Determine the min and max values for x and y that should appear in the window.
    // The complication is that the aspect ratio of the window may not match the
    //        aspect ratio of the scene we want to view.
    // 根据纵横比来改变视口的大小,保证物体不会变形。
    w = (w==0) ? 1 : w;
    h = (h==0) ? 1 : h;
    if ( (Xmax-Xmin)/w < (Ymax-Ymin)/h ) 
    {
        scale = ((Ymax-Ymin)/h)/((Xmax-Xmin)/w);
        center = (Xmax+Xmin)/2;
        windowXmin = center - (center-Xmin)*scale;
        windowXmax = center + (Xmax-center)*scale;
        windowYmin = Ymin;
        windowYmax = Ymax;
    }
    else 
    {
        scale = ((Xmax-Xmin)/w)/((Ymax-Ymin)/h);
        center = (Ymax+Ymin)/2;
        windowYmin = center - (center-Ymin)*scale;
        windowYmax = center + (Ymax-center)*scale;
        windowXmin = Xmin;
        windowXmax = Xmax;
    }
    
    // Now that we know the max & min values for x & y that should be visible in the window,
    //        we set up the orthographic projection.
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( windowXmin, windowXmax, windowYmin, windowYmax, -1, 1 );

}


// Main routine
// Set up OpenGL, define the callbacks and start the main loop
int main( int argc, char** argv )
{
    glutInit(&argc,argv);

    // The image is not animated so single buffering is OK. 
    //单缓冲,RGB模式
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH );


    // Window position (from top corner), and size (width and hieght)
    glutInitWindowPosition( 20, 60 );
    glutInitWindowSize( 360, 360 );
    glutCreateWindow( "Simple OpenGL Demo - Press space bar to toggle images" );

    //initialize glew
    //初始化glew
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));

    }
    fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

    //check opengl version and function extensions.
    if (GLEW_ARB_vertex_program)
    {
        /* It is safe to use the ARB_vertex_program extension here. */
        fprintf(stdout, "glGenProgramsARB is suported\n");
    }
    if (glewIsSupported("GL_VERSION_1_4  GL_ARB_point_sprite"))
    {
        /* Great, we have OpenGL 1.4 + point sprites. */
        fprintf(stdout, "Great, we have OpenGL 1.4 + point sprites\n");
    }
    if (glewGetExtension("GL_ARB_fragment_program"))
    {
        /* Looks like ARB_fragment_program is supported. */
        fprintf(stdout, "Looks like ARB_fragment_program is supported\n");
    }

    // Initialize OpenGL as we like it..
    initRendering();

    // Set up callback functions for key presses
    glutKeyboardFunc( myKeyboardFunc );            // Handles "normal" ascii symbols
    // glutSpecialFunc( mySpecialKeyFunc );        // Handles "special" keyboard keys

    // Set up the callback function for resizing windows
    glutReshapeFunc( resizeWindow );

    // Call this for background processing
    // glutIdleFunc( myIdleFunction );

    // call this whenever window needs redrawing
    glutDisplayFunc( drawScene );

    fprintf(stdout, "Press space bar to toggle images; escape button to quit.\n");
    
    // Start the main loop.  glutMainLoop never returns.
    glutMainLoop(  );

    return(0);    // This line is never reached.
}

抱歉!评论已关闭.