Added "offscreen" demo, a very simple program that produces an onscreen
[freeglut] / progs / demos / offscreen / offscreen.c
1 /*
2  * freeglut offscreen rendering demo.
3  *
4  * Usage:
5  *
6  *    offscreen [standard GLUT options] [filename]
7  *
8  *    The filename is used to say where to write a PNM image file
9  *    that is the sole way to verify that this program is doing what
10  *    it should (i.e., rendering offscreen).
11  *
12  *    You can view the PNM file in image viewers and editors such as
13  *    the GIMP.  (Everyone doing any kind of graphics has at least one
14  *    multi-format-reading image manipulation program, right?)
15  *
16  *    If no filename is specified, the chosen filename is "offscreen.pnm".
17  *
18  * Some suggested uses for GLUT_OFFSCREEN:
19  *
20  *  * Implementation of a graphics language that writes bitmapped image files.
21  *  * Capture GLUT bitmapped fonts to a texture at runtime to make scalable
22  *    bitmapped fonts.
23  *  * Using OpenGL to create special-effect textures at run-time.
24  *  * Making stencils.
25  *  * Getting the depth-buffer for a height-field.
26  *  * Using OpenGL to create a poster texture (e.g., for pasting onto a a
27  *    video screen in a virtual world).
28  *  * Using OpenGL to prescale an image to a power-of-2 dimension (including
29  *    OpenGL antialiasing).  There's no reason that you couldn't do this
30  *    yourself, but OpenGL can do it for you, so why not?
31  *  * Rendering to a bitmap larger than the display has been suggested
32  *    as well.  This is a cheap way to produce arbitrarily high resolution
33  *    images for printing.
34  *
35  * In every case, there are at least cases where you would want to do this
36  * without actually rendering to a visible window.
37  *
38  */
39 #include <stdio.h>
40 #include <GL/freeglut.h>
41
42 #define OFFSCREEN_W 500
43 #define OFFSCREEN_H 250
44
45
46 int offscreen_id;
47 int onscreen_id;
48 const char *save_file_name = "offscreen.pnm";
49
50
51 void cb_onscreen_display( void )
52 {
53     glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
54     glColor3d( 1.0, 0.0, 0.0 );
55     glBegin( GL_LINE_LOOP );
56     glVertex2d( 0.0, 0.0 );
57     glVertex2d( 0.5, 0.0 );
58     glVertex2d( 0.5, 0.5 );
59     glVertex2d( 0.0, 0.5 );
60     glVertex2d( 0.0, 0.0 );
61     glEnd( );
62     glColor3d( 1.0, 1.0, 1.0 );
63     glRasterPos2d( -1.0, 0.8 );
64     glutBitmapString(
65         GLUT_BITMAP_TIMES_ROMAN_24, "Press `s' or `S' to Send to"
66     );
67     glRasterPos2d( -.8, 0.6 );
68     glutBitmapString(
69         GLUT_BITMAP_TIMES_ROMAN_24, "'offscreen.pnm'"
70     );
71     glRasterPos2d( -1.0, 0.3 );
72     glutBitmapString(
73         GLUT_BITMAP_TIMES_ROMAN_24, "Press `q', `Q', or Esc to quit."
74     );
75     
76     glutSwapBuffers( );
77 }
78
79 void write_raw_pnm( char *fname, char *pixels, int w, int h)
80 {
81     FILE *f;
82     
83     printf( "Trying to create: %s\n", fname );
84     f = fopen( fname, "wb" );
85     if( !f )
86         printf( "Ouch!  Cannot create file.\n" );
87     else
88     {
89         int row;
90
91         printf( "Opened file.\n" );
92         fprintf( f, "P6\n" );
93         fprintf( f, "# CREATOR: offscreen freeglut demo\n" );
94         fprintf( f, "%d %d\n", w, h );
95         fprintf( f, "255\n" );
96
97         /*
98          * Write the rows in reverse order because OpenGL's 0th row
99          * is at the bottom.
100          */
101         for( row = h; row; --row )
102             fwrite( pixels + ((row - 1)*w*3), 1, 3 * w, f );
103         
104         fclose( f );
105     }
106 }
107
108
109 void cb_offscreen_display( void )
110 {
111     static char pixels [OFFSCREEN_W * OFFSCREEN_H * 3];
112     int i;
113
114     cb_onscreen_display( );
115     glColor3d( 0.0, 1.0, 0.0 );
116     glBegin( GL_LINES );
117     for( i = 0; i < 100; ++i)
118     {
119         glVertex2d( +1 - (i/50.0), +1 );
120         glVertex2d( -1 + (i/50.0), -1 );
121     }
122     glEnd( );
123     glFinish( );
124
125     glPixelStorei( GL_PACK_ALIGNMENT, 1 );
126     glReadPixels(
127         0, 0, OFFSCREEN_W, OFFSCREEN_H,
128         GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)pixels
129     );
130     write_raw_pnm( save_file_name, pixels, OFFSCREEN_W, OFFSCREEN_H );
131 }
132
133
134 void cb_onscreen_keyboard( unsigned char key, int x, int y )
135 {
136     switch( key )
137     {
138     case 's':
139     case 'S':
140         glutSetWindow( offscreen_id );
141         glutPostRedisplay( );
142         break;
143         
144     case '\x1b':
145     case 'q':
146     case 'Q':
147         exit( 0 );
148         break;
149         
150     default:
151         break;
152     }
153 }
154
155 int main( int argc, char **argv )
156 {
157     glutInit( &argc, argv );
158     if( argv[ 1 ] )
159         save_file_name = argv[ 1 ];
160     
161     glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
162     onscreen_id = glutCreateWindow( "Offscreen demo" );
163     glutDisplayFunc( cb_onscreen_display );
164     glutKeyboardFunc( cb_onscreen_keyboard );
165
166     glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_OFFSCREEN );
167     glutInitWindowSize( OFFSCREEN_W, OFFSCREEN_H );
168     offscreen_id = glutCreateWindow( "" );
169     glutDisplayFunc( cb_offscreen_display );
170     
171     glutMainLoop( );
172 }