package classwork; import javax.media.opengl.*; import java.awt.event.*; import jocode.*; /** * GLART_10_pbuffer.java *
* Render into a Frame buffer object (or "FBO") and save the contents to a file. *
* FBOs function just like the normal OpenGL framebuffer but are not drawn * to the video screen. They can be larger than the screen, up to the memory * limits of the graphics card. FBOs are often used to generate textures * dynamically. A texture can be attached to the FBO and gl rendering * commands will draw into the texture. *
* This demo creates an FBO that is several times larger than the screen, * draws a simple image into it and saves the image to a PNG file. *
* Hit F1 to save the image to screen_capture.png and pbuffer_capture.png. *
* NOTE: screenshots from large FBOs can consume a lot of memory. Be sure to
* allocate more memory to java. Add the parameters to the JRE when java runs:
* -Xms128m -Xmx128m
* This will force java to run with 128 megabytes of memory.
*
* @see JOFrameBuffer.java class that manages FBO */ public class GLART_10_pbuffer extends JOApp { float rotation = 0f; float rotation2 = 0f; float rotationAmount = .08f; // JOFrameBuffer class wraps a "framebuffer object", a virtual // screen that can be rendered to just like the Display. JOFrameBuffer FBO; // Set the FBO size relative to the screen. Most OpenGL rendering // will scale to fit the FBO dimensions. float fboScale = 4f; // flag: when true, we'll capture the current screen from the Pbuffer boolean bufferCapture = false; /** * Main function just creates and runs the application. */ public static void main(String args[]) { GLART_10_pbuffer app = new GLART_10_pbuffer(); windowTitle = "FBO Demo"; displayWidth = 800; displayHeight = 600; //app.fullScreen = true; app.run(); } /** * Initialize the environment */ public void setup() { // Random value for rotation increment: .05 - 1.0 rotationAmount = (float) (.05 + (Math.random()*.05)); // Create a frame buffer object. May be larger than screen FBO = new JOFrameBuffer( (int) (getWidth()*fboScale), (int) (getHeight()*fboScale) ); // "Select" the FBO, so rendering commands will go to the offscreen frame buffer FBO.activate(); // Initialize the OpenGL context FOR THE FBO initGL(getWidth(), getHeight()); // rendering commands will now go the screen FBO.deactivate(); // Initialize the OpenGL context FOR THE default framebuffer initGL(getWidth(), getHeight()); // 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)displayWidth / (float)displayHeight, // 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); } /** * Initialize OpenGL * */ public void initGL(int displayWidth, int displayHeight) { // No need for depth, composition is flat gl.glDisable(GL.GL_DEPTH_TEST); // set the background color gl.glClearColor(.1f, .1f, .12f, 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); } /** * Render the scene. */ public void draw() { rotation += .08f; rotation2 += rotationAmount; renderFrame(); // Save default framebuffer and FBO pixels to PNG image // OpenGL scales most rendering operations to fit the current // screen proportions, except for glLineWidth() and glPointSize(), // which are absolute sizes and do not scale. Before drawing // to the FBO scale up the lineWidth. if (bufferCapture) { // save screen screenShot("screen_capture.png"); // select Pbuffer FBO.activate(); // adjust the line width to match pbuffer scale gl.glLineWidth(fboScale); // draw the scene into pbuffer renderFrame(); // further drawing will go to screen FBO.deactivate(); // save the pbuffer to PNG FBO.screenShot("screen_capture_fbo.png"); // reset the line width to normal scale gl.glLineWidth(1); // lower the flag bufferCapture = false; } } /** * Render the scene. */ public void renderFrame() { gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // Reset the Modelview matrix gl.glMatrixMode(GL.GL_MODELVIEW); gl.glLoadIdentity(); // 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(.5f,0,0); // draw a red quad gl.glColor4f(1,0f,0f,.7f); 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,1,0f,.7f); 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,1,.7f); gl.glPushMatrix(); { gl.glRotatef(rotation2, 1,0,1); gl.glTranslatef(.5f,-.5f,0); gl.glRotatef(rotation2, 0,0,1); drawQuadLine(); } gl.glPopMatrix(); // draw lines gl.glPushMatrix(); { gl.glRotatef(rotation2*2.1f, 1,0,1); gl.glColor4f(0f,.5f,1,.7f); drawQuadLine(); gl.glRotatef(2f, 1,0,1); gl.glColor4f(0f,.6f,1,.7f); drawQuadLine(); gl.glRotatef(3f, 1,0,1); gl.glColor4f(0f,.8f,1,.7f); drawQuadLine(); } gl.glPopMatrix(); } /** * 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(); } /** * draw a 1x1 square */ public void drawQuadLine() { gl.glBegin(GL.GL_LINE_STRIP); { 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.glTexCoord2f(0, 0); gl.glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left } gl.glEnd(); } /** */ public void keyUp(int keycode) { // set flag to save screen (see render()) if (keycode == KeyEvent.VK_F1) { bufferCapture = true; } } /** * Cleanup all the resources. * */ public void exit() { //if (FBO != null) { // FBO.cleanup(); //} super.exit(); } }