OpenGLUT 0.6.3 development - OpenGLUT: offscreen.c File Reference
Keywords: OpenGLUT, FreeGLUT, OpenGL, GLUT, X11, Windows, Programming, Documentation, Download, Development, Sourceforge

OpenGLUT Documentation
Introduction | Documentation | Examples | Proposals | Authors | Copying | Todo | Bugs | Links

# offscreen.c File Reference

## Detailed Description

OpenGLUT offscreen rendering demo.

Usage:

offscreen [standard GLUT options] [filename]

          Touch-type
              on the teapot
          with me.

Normal printable ASCII characters work as might be expected. The return and backspace keys also work for editing.

^S Saves a PNM image of the window to filename

The filename specifies the output PNM image file, the default is "offscreen.pnm".

PNM files are widely supported in image editing and viewing appliations such as The Gimp.

Some suggested uses for GLUT_OFFSCREEN:

- Reliable capturing of OpenGL screen shots.
- Image output applications, tools and languages.
- Texture generation.
- Make stencils.
- Height field generation.
- Poster texture generation (e.g., for pasting onto a video screen)
- Textured imposter generation.
- Rendering to a high resolution bitmap for printing.

Author:
  Copyright (C) 2004, the OpenGLUT project contributors.

OpenGLUT Offscreen Rendering Demonstration

    #include <GL/openglut.h>

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int offscreen_id;
    int onscreen_id;

    /*
     * The filename to which to save PNM screenshots.
     * Can be overridden by a commandline option.
     *
     * Save images with a ^S.
     */
    const char *save_file_name = "offscreen.pnm";

    static GLuint texName;

    double theta = 0;

    /*
     * Our text block.  80x25 is standard for a console, so why not?
     * Though with a 15-pixel font, you get more like 28x8.  The
     * terminal size should probably be computed at runtime from the
     * texture dimensions, which should be a user parameter.  Oh well.
     */
    #define ROWS 25
    #define COLS 80
    char text[ ROWS ][ COLS+2 ];
    #define OFFSCREEN_W 256
    #define OFFSCREEN_H 128

    void write_raw_pnm( const char *fname, char *pixels, int w, int h )
    {
        FILE *f;

        f = fopen( fname, "wb" );
        if( !f )
            printf( "Ouch!  Cannot create file.\n" );
        else
        {
            int row;

            fprintf( f, "P6\n" );
            fprintf( f, "# CREATOR: offscreen freeglut demo\n" );
            fprintf( f, "%d %d\n", w, h );
            fprintf( f, "255\n" );

            /*
             * Write the rows in reverse order because OpenGL's 0th row
             * is at the bottom.
             */
            for( row = h; row; --row )
                fwrite( pixels + ((row - 1)*w*3), 1, 3 * w, f );

            fclose( f );
        }
    }

    void save_window( const char *file_name )
    {
        char *pixels;
        int width  = glutGet( GLUT_WINDOW_WIDTH );
        int height = glutGet( GLUT_WINDOW_HEIGHT );
        pixels = malloc( 3 * width * height);
        if( pixels )
        {
            glPixelStorei( GL_PACK_ALIGNMENT, 1 );
            glReadPixels(
                0, 0, width, height,
                GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)pixels
            );
            write_raw_pnm( file_name, pixels, width, height );
        }
    }

    void cb_idle( void )
    {
        glutSetWindow( onscreen_id );
        glutPostRedisplay( );
    }

    void cb_offscreen_display( void )
    {
        static char pixels [OFFSCREEN_W * OFFSCREEN_H * 3];
        int i;

        glEnable( GL_DEPTH_TEST );

        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glColor3d( 1.0, 0, 0 );
        glPushMatrix( );
        glRotated( .0071234 * glutGet( GLUT_ELAPSED_TIME ), 0, 1, 0 );
        glutSolidTorus( .2, .6, 20, 20 );
        glPopMatrix( );

        glDisable( GL_LIGHTING );
        glMatrixMode( GL_PROJECTION );
        glPushMatrix( );
        glLoadIdentity( );
        glColor3d( 0.0, 1.0, 0.0 );
        glRasterPos2f( -1, 1 - ( ( 2.0 * 10 ) / OFFSCREEN_H ) );
        glNormal3d( 0, 0, 1 );
        for( i = 7; i > -1; --i )
            glutBitmapString( GLUT_BITMAP_9_BY_15, text[ i ] );

        glPopMatrix( );
        glMatrixMode( GL_MODELVIEW );
        glEnable( GL_LIGHTING );

        glReadPixels(
            0, 0, OFFSCREEN_W, OFFSCREEN_H,
            GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)pixels
        );
        glutSetWindow( onscreen_id );
        glBindTexture( GL_TEXTURE_2D, texName );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
        glTexImage2D (
            GL_TEXTURE_2D, 0, GL_RGB, OFFSCREEN_W, OFFSCREEN_H,
            0, GL_RGB, GL_UNSIGNED_BYTE, (void *)pixels
        );
        glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
        glDisable( GL_DEPTH_TEST );
    }

    void cb_onscreen_display( void )
    {
        const static GLfloat flip_it_matrix[ 16 ] =
            { -1, 0, 0, 0,
              0, -1, 0, 0,
              0,  0, 1, 0,
              0,  0, 0, 1
            };

        glutSetWindow( offscreen_id );
        cb_offscreen_display( );

        glDisable( GL_LIGHTING );
        glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
        glColor3d( 1.0, 0.0, 0.0 );
        glBegin( GL_LINE_LOOP );
        glVertex2d( 0.0, 0.0 );
        glVertex2d( 0.5, 0.0 );
        glVertex2d( 0.5, 0.5 );
        glVertex2d( 0.0, 0.5 );
        glVertex2d( 0.0, 0.0 );
        glEnd( );
        glColor3d( 1.0, 1.0, 1.0 );
        glRasterPos2d( -2.0, 0.8 );
        glutBitmapString(
            GLUT_BITMAP_TIMES_ROMAN_24, "Press ^S to Send to"
        );
        glRasterPos2d( -1.8, 0.6 );
        glutBitmapString( GLUT_BITMAP_TIMES_ROMAN_24, "'" );
        glutBitmapString(
            GLUT_BITMAP_9_BY_15, save_file_name );
        glutBitmapString( GLUT_BITMAP_TIMES_ROMAN_24, "'" );
        glRasterPos2d( -2.0, 0.3 );
        glutBitmapString(
            GLUT_BITMAP_TIMES_ROMAN_24, "Press Esc to quit."
        );

        glEnable( GL_DEPTH_TEST );
        glEnable( GL_TEXTURE_2D );
        glBindTexture( GL_TEXTURE_2D, texName );
        glBegin( GL_QUADS );
          glNormal3f( 0, 0, -1 );
          glTexCoord2i( 0, 0 ); glVertex3i( -9, -9, -4 );
          glTexCoord2i( 1, 0 ); glVertex3i(  9, -9, -4 );
          glTexCoord2i( 1, 1 ); glVertex3i(  9,  9, -4 );
          glTexCoord2i( 0, 1 ); glVertex3i( -9,  9, -4 );
          glTexCoord2i( 0, 0 ); glVertex3i( -9, -9, -4 );
        glEnd( );

        glEnable( GL_LIGHTING );
        glDisable( GL_LIGHTING );
        glPushMatrix( );
        theta = .01 * glutGet( GLUT_ELAPSED_TIME );
        glRotated( theta, 0, 1, 0 );
        glMatrixMode( GL_TEXTURE );
        glLoadMatrixf( flip_it_matrix );
        glMatrixMode( GL_MODELVIEW );
        glutSolidTeapot( 1.0 );
        glMatrixMode( GL_TEXTURE );
        glLoadIdentity( );
        glMatrixMode( GL_MODELVIEW );
        glDisable( GL_TEXTURE_2D );
        glPopMatrix( );
        glDisable( GL_DEPTH_TEST );

        glutSwapBuffers( );
    }

    static int cursor;
    void vscroll( void )
    {
        int i;
        for( i = ROWS-1; i; --i )
            strcpy( text[ i ], text[ i-1 ] );
        cursor = 0;
        text[ 0 ][ 0 ] = '\n';
        text[ 0 ][ 1 ] = 0;
    }
    void hscroll( void )
    {
        int i = 0;
        if( text[ 0 ][ 0 ] )
            for( i = 0; i < COLS; ++i )
                text[ 0 ][ i ] = text[ 0 ][ i+1 ];
        text[ 0 ][ COLS ] = 0;
        --cursor;
        text[ 0 ][ cursor ] = '\n';
    }
    void add_char( char c )
    {
        text[ 0 ][ cursor++ ] = c;
        text[ 0 ][ cursor   ] = '\n';
        text[ 0 ][ cursor+1 ] = 0;
        if( COLS <= cursor )
            hscroll( );
    }

    void cb_onscreen_keyboard( unsigned char key, int x, int y )
    {
        int texture_updated = 1;

        switch( key )
        {
        case '\n':
        case '\r':
            vscroll( );
        case 'R' - '@': /* ^R */
            break;

        case 'S' - '@': /* ^S */
            save_window( save_file_name );
            texture_updated = 0;
            break;

        case '\x08': /* backspace */
            if( cursor )
            {
                --cursor;
                text[ 0 ][ cursor+1 ] = 0;
                text[ 0 ][ cursor   ] = '\n';
            }
            break;

        case '\x1b':
                exit( 0 );
            break;

        default:
            add_char( key );
            break;
        }
        glutSetWindow( offscreen_id );
        glutPostRedisplay( );
    }

    void cb_onscreen_reshape( int w, int h)
    {
        double ar = w * 1.0/h;
        glEnable( GL_CULL_FACE );
        glCullFace( GL_BACK );
        glViewport( 0, 0, w, h );
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity( );
        if( ar > 1 )
            glFrustum( -ar, ar, -1, 1, 2, 30 );
        else
            glFrustum( -1, 1, -1/ar, 1/ar, 2, 30 );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity( );
        glTranslated( 0, 0, -5 );
    }
    void cb_offscreen_reshape( int w, int h)
    {
        static GLfloat light_1_loc[ 3 ] = { 3, 4, 5 };
        static GLfloat light_1_col[ 3 ] = { 1, 1, 1 };
        static GLfloat material_diff[ 3 ] = { 1, 0, 0 };
        static GLfloat material_spec[ 3 ] = { 1, 1, 1 };
        double ar = w * 1.0/h;

        glEnable( GL_CULL_FACE );
        glViewport( 0, 0, w, h );
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity( );
        if( ar > 1 )
            glFrustum( -ar, ar, -1, 1, 2, 30 );
        else
            glFrustum( -1, 1, -1/ar, 1/ar, 2, 30 );
        glTranslated( 0, 0, -3 );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity( );
        glEnable( GL_LIGHT1 );
        glEnable( GL_LIGHTING );
        glLightfv( GL_LIGHT1, GL_POSITION, light_1_loc );
        glLightfv( GL_LIGHT1, GL_DIFFUSE, light_1_col );
        glLightfv( GL_LIGHT1, GL_SPECULAR, light_1_col );
        glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, material_diff );
        glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, material_spec );
        glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 90 );
    }

    int main( int argc, char **argv )
    {
        glutInit( &argc, argv );
        if( argv[ 1 ] )
            save_file_name = argv[ 1 ];

        strcpy( text[ 4 ], "Touch type,\n" );
        strcpy( text[ 3 ], "on the\n" );
        strcpy( text[ 2 ], "teapot\n" );
        strcpy( text[ 1 ], "with me.\n" );
        strcpy( text[ 0 ], "\n" );
        glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
        onscreen_id = glutCreateWindow( "Offscreen demo" );
        glutDisplayFunc( cb_onscreen_display );
        glutKeyboardFunc( cb_onscreen_keyboard );
        glutReshapeFunc( cb_onscreen_reshape );

        glutInitDisplayMode(
            GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH | GLUT_OFFSCREEN
        );
        glutInitWindowSize( OFFSCREEN_W, OFFSCREEN_H );
        offscreen_id = glutCreateWindow( "" );
        glutDisplayFunc( cb_offscreen_display );
        cb_offscreen_reshape(  OFFSCREEN_W, OFFSCREEN_H );

        glGenTextures( 1, &texName );
        glBindTexture( GL_TEXTURE_2D, texName );

        glutIdleFunc( cb_idle );

        glutMainLoop( );
        return EXIT_SUCCESS;
    }

OpenGLUT Development @ Sourceforge
Homepage | Summary | Files | CVS | Forums | Lists | Bugs | RFE
Generated on Tue Oct 5 18:44:24 2004 for OpenGLUT by doxygen 1.3.8
The OpenGLUT project is hosted by sourceforge.net.