package classwork; import javax.media.opengl.*; import jocode.*; /** * GLART_12_copyframe.java *

* Copy the framebuffer to a texture. *

* There may be times that you want to make a copy of the screen or part of the screen. For instance * you can generate a texture dynamically using openGL drawing commands, or * you may want to have a scene animated within another scene, like a movie playing in a larger * scene, or a reflection on a mirror. One technique to accomplish this is to render to the framebuffer, * then save the framebuffer to a texture. * Since the framebuffer contents and the texture are stored on the graphics card, * this operation is relatively fast. *

* This demmo shows how to save the entire screen image to a texture, then draw that screen image back to * the framebuffer. *

* Normally when rendering a scene in OpenGL you'll clear the framebuffer (glClear()) and draw the * entire scene in each call to render(). In this case I wanted to leave faint trails behind as geometry * moved, so I did not call glClear(). This may cause odd flickering at times because OpenGL does not * guarantee that the framebuffer won't change betweem renders. In fact, the framebuffer may contain * the remnants of some other graphical operration, as the graphics card optimizes resources on the fly. * The solution is to save an image of the screen at the end of each render(), annd write that image * into the framebuffer at the beginnning of each render(). This way the framebuffer contents can change * between renders and it won't matter, we'll just write back our last screen before we render anything * else. *

* The functions: *

* glCopyTexSubImage() * makeTextureForScreen() * frameSave() * frameDraw() *

* See init() for the calls to create a texture to hold the screen image. * See render() for the calls to save and restore the screen image. */ public class GLART_12_copyframe extends JOApp { float rotation = 0f; float rotation2 = 0f; float rotationAmount = .08f; // some color values float R = 1f; float G = 1f; float B = 1f; // For copying screen image to a texture int screenTextureSize = 1024; // how large should texture be to hold screen // will hold screen image as texture int screenTextureHandle; /** * Main function just creates and runs the application. */ public static void main(String args[]) { GLART_12_copyframe app = new GLART_12_copyframe(); windowTitle = "Save Frame to Texture"; displayWidth = 800; displayHeight = 600; useCurrentDisplay = true; fullScreen = true; app.run(); } /** * Initialize the environment */ public void setup(){ // allocate a texture big enough to hold screen image // the texure will be square, the dimensions will be some power of two, as // large or larger than the width of the screen. screenTextureHandle = makeTextureForScreen(getWidth(),getHeight()); // Random value for rotation increment: .05 - 1.0 rotationAmount = (float) (.05 + (Math.random()*.05)); // Select the Projection Matrix (controls perspective) gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); // Reset The Projection Matrix // Define perspective glu.gluPerspective( 45.0f, // Field Of View (float)getWidth() / (float)getHeight(), // aspect ratio 0.1f, // near Z clipping plane 100.0f); // far Z clipping plane // Select The Modelview Matrix (controls model orientation) gl.glMatrixMode(GL.GL_MODELVIEW); // No need for depth, composition is flat gl.glDisable(GL.GL_DEPTH_TEST); gl.glDisable(GL.GL_CULL_FACE); // set the background color gl.glClearColor(.1f, .1f, .82f, 1); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // To create transparencies (alpha blending) gl.glEnable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // need textures on for frameDraw() to work gl.glEnable(GL.GL_TEXTURE_2D); // capture the screen now to initialize the texture image // It's a good idea to call glClear() before capturing the screen for the first time. frameCopy(screenTextureHandle); } /** * Render the scene. */ public void draw() { rotation += .05f; rotation2 += rotationAmount; // to leave trails behind drawing DON'T call glClear() // Reset the Modelview matrix gl.glMatrixMode(GL.GL_MODELVIEW); gl.glLoadIdentity(); // draw the screen image back to the framebuffer before we draw anything else // frameDraw() will switch the Projection matrix to ortho mode to draw the screen image frameDraw(screenTextureHandle); // be sure we're in modelview mode (frameDraw switches to Projection matrix) gl.glMatrixMode(GL.GL_MODELVIEW); // Place the 'eye' glu.gluLookAt( 0f, 0f, 5f, // eye position 0f, 0f, 0f, // target to look at 0f, 1f, 0f); // which way is up // rotate scene gl.glRotatef(rotation*3.3f, 0,0,1); gl.glTranslatef(2,0,0); // need textures on for frameDraw() to work gl.glDisable(GL.GL_TEXTURE_2D); // draw a red quad gl.glColor4f(R,0f,0f,.03f); gl.glPushMatrix(); { gl.glRotatef(rotation*.7f, 0,1,1); gl.glTranslatef(0,.5f,0); gl.glRotatef(rotation2, 0,0,1); drawQuad(); } gl.glPopMatrix(); // rotate more gl.glRotatef(rotation2*4.7f, 0,0,1); gl.glTranslatef(1,0,0); // draw a green quad gl.glColor4f(0f,G,0f,.03f); gl.glPushMatrix(); { gl.glRotatef(rotation2*2f, 0,0,1); gl.glTranslatef(-.5f,-.5f,0); gl.glRotatef(rotation2, 0,0,1); drawQuad(); } gl.glPopMatrix(); // draw a blue quad gl.glColor4f(0f,0f,B,.03f); gl.glPushMatrix(); { gl.glRotatef(rotation2, 1,0,1); gl.glTranslatef(.5f,-.5f,0); gl.glRotatef(rotation2, 0,0,1); drawQuad(); } gl.glPopMatrix(); // need textures on for frameCopy() to work gl.glEnable(GL.GL_TEXTURE_2D); // save the screen image to a texture // do this after you've drawn everything you want to save frameCopy(screenTextureHandle); } /** * draw a 1x1 square */ public void drawQuad() { gl.glBegin(GL.GL_QUADS); { gl.glTexCoord2f(0, 0); gl.glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left gl.glTexCoord2f(1, 0); gl.glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right gl.glTexCoord2f(1, 1); gl.glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right gl.glTexCoord2f(0, 1); gl.glVertex3f(-1.0f, 1.0f, 0.0f); // Top left } gl.glEnd(); } public void reshape(int newDisplayWidth, int newDisplayHeight) { setViewport(0,0,newDisplayWidth,newDisplayHeight); // Define perspective glu.gluPerspective( 45.0f, // Field Of View (float)getWidth() / (float)getHeight(), // aspect ratio 0.1f, // near Z clipping plane 100.0f); // far Z clipping plane } }