在网上看到了这段代码
http://blog.csdn.net/chunxiaopengshan/archive/2010/03/29/5426568.aspx
不方便之处在于,事先要使用一个已存在的bmp文件。看了一下bmp的文件格式,修改了代码。
修改后,就不需要使用一个已存在的bmp文件了。
代码如下
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include <gl/glut.h> //消除控制台窗口 #pragma comment( linker,"/subsystem:/"windows/" /entry:/"mainCRTStartup/"" ) static GLint windowWidthH = 500, windowHeightH = 500; static char head[54]={ 0x42, //0 0x4d, //1 0x66, //2 0x75, //3 0x00, //4 0x00, //5 0x00, //6 0x00, //7 0x00, //8 0x00, //9 0x36, //a 0x00, //b 0x00, //c 0x00, //d 0x28, //e 0x00,//f 0x00, //0 0x00, //1 0x64, //2 0x00, //3 0x00, //4 0x00, //5 0x64, //6 0x00, //7 0x00, //8 0x00, //9 0x01, //a 0x00, //b 0x18, //c 0x00, //d 0x00, //e 0x00,//f 0x00, //0 0x00, //1 0x30, //2 0x75//3 }; //函数功能:OpengGL抓图 //参数说明:width OpenGL窗体宽 // height OpeGL窗体高 void grab(GLint width, GLint height) { GLint pixelLength; GLubyte * pixelDate; FILE * wfile; //打开文件 wfile = fopen( "C://grab2.bmp", "wb" ); fwrite( head, 54, 1, wfile ); //更改grab.bmp的头文件中的高度和宽度 fseek( wfile, 0x0012, SEEK_SET ); fwrite( &width, sizeof(width), 1, wfile ); fwrite( &height, sizeof(height ), 1, wfile ); //为像素分配内存 pixelLength = width * 3; if ( pixelLength % 4 != 0 ) { pixelLength += 4 - pixelLength%4; } pixelLength *= height; pixelDate = (GLubyte *)malloc( pixelLength ); if ( pixelDate == 0 ) { printf( "/a/n分配内存失败!" ); } //读取窗口像素并存储 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glReadPixels( 0, 0, width, height, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixelDate ); //写入像素数据 fseek( wfile, 0, SEEK_END ); fwrite( pixelDate, pixelLength, 1, wfile ); fclose( wfile ); free( pixelDate ); } //画一个简单的正方形并截图 void display() { glClearColor( 0.7, 0.7, 0.7, 0.0 ); glClear( GL_COLOR_BUFFER_BIT ); glShadeModel( GL_SMOOTH ); glBegin( GL_POLYGON ); glColor3f( 1.0, 0.0, 0.0 ); glVertex2f( -0.5, -0.5 ); glColor3f( 0.0, 1.0, 0.0 ); glVertex2f( 0.5, -0.5 ); glColor3f( 0.0, 0.0, 1.0 ); glVertex2f( 0.5, 0.5 ); glColor3f( 1.0, 1.0, 0.0 ); glVertex2f( -0.5, 0.5 ); glEnd(); glFlush(); grab(windowWidthH, windowHeightH); } void myMenu( int value ) { if ( value == 1 ) { exit( 0 ); } } int main( int argc, char ** argv ) { glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE ); glutInitWindowPosition( 0, 0 ); glutInitWindowSize( windowWidthH, windowHeightH ); glutCreateWindow( "截图工具" ); glutDisplayFunc( display ); //创建一个右键退出菜单 glutCreateMenu( myMenu ); glutAddMenuEntry( "退出", 1 ); glutAttachMenu( GLUT_RIGHT_BUTTON ); glutMainLoop(); return 1; }
严重注意:
使用方法。在渲染显示出模型后,再点击截图按钮截图。
记录开发抓图接口遇到的问题:
1.如果渲染窗口,部分在显示器范围内。OpenGL只会渲染在显示器范围内的场景。导致,截图中有部分为黑色。这是OpenGL内部实现的问题。无论使用什么技术,如FBO渲染到纹理。都会有此问题。这是不可避免的。
2.如果在代码内部,在刚绘制完场景后,调用截图函数。会出现如两个问题:首次截图为黑屏,第二次截图有黑边。猜测这是因为OpenGL内部应该异步绘制图形。与CPU不同步,导致了这个问题。