下面是一个基于glut的OpenGL程序框架,用的是正投影,可以方便的通过参数设置Frustum的大小。
通常可以用来做二维的demo,比如二维填充算法演示等等。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//
迈克老狼整理,参考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.
}
#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.
}