#include #include #include #include #include #include #include // define texture width = N and height = M and v = 4*N*M #define N 640 #define M 480 #define v 4*N*M int main( int argc, char **argv ) { int i; // create three pointers to store our vectors x, y, z float * x = ( float * ) malloc( v * sizeof( float ) ); float * y = ( float * ) malloc( v * sizeof( float ) ); float * z = ( float * ) malloc( v * sizeof( float ) ); // fill up y and z with some data for ( i = 0; i < v; i++ ) { x[i] = (float)( i / 10.0 ); y[i] = (float)( i / 20.0 ); } // set up glut and glew glutInit( &argc, argv ); glutCreateWindow( "add" ); glewInit( ); // some obligatory OpenGL settings glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); gluOrtho2D( 0.0, N, 0.0, M ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity( ); glViewport( 0, 0, N, M ); // set up Cg context and profile CGcontext context = cgCreateContext( ); CGprofile profile = cgGLGetLatestProfile( CG_GL_FRAGMENT ); cgGLSetOptimalOptions( profile ); // create fragment program add from add.cg CGprogram program = cgCreateProgramFromFile( context, CG_SOURCE, "add.cg", profile, "add", 0 ); cgGLLoadProgram( program ); // create frame buffer object GLuint fb; glGenFramebuffersEXT( 1, &fb ); glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fb ); // create texture ids for x, y, z GLuint tex_x, tex_y, tex_z; glGenTextures( 1, &tex_x ); glGenTextures( 1, &tex_y ); glGenTextures( 1, &tex_z ); // bind texture x glBindTexture( GL_TEXTURE_RECTANGLE_ARB, tex_x ); // set texture parameters for x glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP ); // actually create texture x glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_FLOAT_RGBA32_NV, M, N, 0, GL_RGBA, GL_FLOAT, 0 ); // attach texture x glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, tex_x, 0 ); // transfer data x to texture x glTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, M, N, GL_RGBA, GL_FLOAT, x ); // do everything for y as well glBindTexture( GL_TEXTURE_RECTANGLE_ARB, tex_y ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP ); glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_FLOAT_RGBA32_NV, M, N, 0, GL_RGBA, GL_FLOAT, 0 ); glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, tex_y, 0 ); glTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, M, N, GL_RGBA, GL_FLOAT, y ); // do everything for z as well, except for transfering data to it glBindTexture( GL_TEXTURE_RECTANGLE_ARB, tex_z ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP ); glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_FLOAT_RGBA32_NV, M, N, 0, GL_RGBA, GL_FLOAT, 0 ); // specify the two arguments x and y of the program add cgGLSetTextureParameter( cgGetNamedParameter( program, "x" ), tex_x ); cgGLEnableTextureParameter( cgGetNamedParameter( program, "x" ) ); cgGLSetTextureParameter( cgGetNamedParameter( program, "y" ), tex_y ); cgGLEnableTextureParameter( cgGetNamedParameter( program, "y" ) ); // specify the outgoing texture to be z glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, tex_z, 0 ); glDrawBuffer( GL_COLOR_ATTACHMENT0_EXT ); // tell Cg to use our profile and program cgGLEnableProfile( profile ); cgGLBindProgram( program ); // run the program glBegin( GL_QUADS ); { glVertex2f( -M, -N ); glVertex2f( M, -N ); glVertex2f( M, N ); glVertex2f( -M, N ); } glEnd( ); // read back result from texture z glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, tex_z, 0 ); glReadBuffer( GL_COLOR_ATTACHMENT0_EXT ); glReadPixels( 0, 0, M, N, GL_RGBA, GL_FLOAT, z ); // now the result of z = x + y is pointed by pointer z, let's see the first couple of terms printf( "\nThese should be really equal, the first column is\n" ); printf( "the result from the GPU the second is from the CPU:\n\n" ); for( i = 0; i < 10; i++ ) { printf( "%f = %f\n", z[i], x[i] + y[i] ); } // do the clean up free( x ); free( y ); free( z ); glDeleteTextures( 1, &tex_x ); glDeleteTextures( 1, &tex_y ); glDeleteTextures( 1, &tex_z ); glDeleteFramebuffersEXT( 1, &fb ); return 0; }