Hi,
I am working on an application using JOGL (NEWT) and occasionally the drawing uses the stencil functions. The onscreen drawing works exactly as intended. I would like to add the facility to save the screen to an image file. To achieve a better quality image, this is being performed in an offscreen drawable where the contents are drawn at a higher scale and then scaled down when the image is saved. Tiles are used due to the total size and the offscreen drawing uses the same methods as the onscreen drawing. All works perfectly until the stencil functons are used. I have written a small test program (below) which illustrates the problem. In the case below, a small square is drawn into the stencil buffer and then the screen is filled with blue by drawing a large blue square. The screen displays exactly as intended (the area where the small square was drawn remains black and the remainder of the area is blue). However, the image file written to disk is simply a complete blue square. Not sure if I'm doing something wrong, but would appreciate any suggestions. Thanks! public class OffscreenScreenshotProblem { private static GLWindow window; public static void main(String[] args) { GLProfile profile = GLProfile.getDefault(); GLCapabilities capabilities = new GLCapabilities(profile); window = GLWindow.create(capabilities); Canvas canvas = new Canvas(); window.addGLEventListener(canvas); final NewtCanvasAWT newtCanvas = new NewtCanvasAWT(window); final JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); panel.add(newtCanvas, BorderLayout.CENTER); final JFrame frame = new JFrame("Offscreen Screenshot Problem"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(panel); frame.setSize(600, 600); frame.setVisible(true); } private static class Canvas implements GLEventListener { private int width; private int height; private boolean screenshotSaved; public Canvas() { super(); screenshotSaved = false; } @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { final GL2 gl = drawable.getGL().getGL2(); gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); gl.glOrthof(0, width, 0, height, 0, 1); gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); this.width = width; this.height = height; } @Override public void init(GLAutoDrawable drawable) { final GL2 gl = drawable.getGL().getGL2(); gl.glClearColor(0, 0, 0, 0); } @Override public void dispose(GLAutoDrawable drawable) { } @Override public void display(GLAutoDrawable drawable) { final GL2 gl = drawable.getGL().getGL2(); draw(gl); takeScreenshot(gl); } private void draw(GL2 gl) { gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); gl.glLoadIdentity(); gl.glColor3f(0.0f, 0.0f, 0.0f); //Set up the stencil. gl.glEnable(GL2.GL_STENCIL_TEST); gl.glClear(GL2.GL_STENCIL_BUFFER_BIT); gl.glStencilFunc(GL2.GL_NEVER, 1, 1); gl.glStencilOp(GL2.GL_REPLACE, GL2.GL_REPLACE, GL2.GL_REPLACE); //Draw a small square into the stencil. gl.glBegin(GL2.GL_POLYGON); gl.glVertex3f(100.0f, 100.0f, 0.0f); gl.glVertex3f(200.0f, 100.0f, 0.0f); gl.glVertex3f(200.0f, 200.0f, 0.0f); gl.glVertex3f(100.0f, 200.0f, 0.0f); gl.glEnd(); //Set up the stencil. gl.glStencilFunc(GL2.GL_NOTEQUAL, 1, 1); gl.glStencilOp(GL2.GL_KEEP, GL2.GL_KEEP, GL2.GL_KEEP); gl.glColor3f(0.0f, 0.0f, 1.0f); //Fill the screen with blue. gl.glBegin(GL2.GL_POLYGON); gl.glVertex3f(0.0f, 0.0f, 0.0f); gl.glVertex3f(width, 0.0f, 0.0f); gl.glVertex3f(width, height, 0.0f); gl.glVertex3f(0.0f, height, 0.0f); gl.glEnd(); gl.glDisable(GL2.GL_STENCIL_TEST); } private void takeScreenshot(GL2 gl) { if(!screenshotSaved) { GLProfile profile = GLProfile.get(GLProfile.GL2); GLCapabilities capabilities = new GLCapabilities(profile); capabilities.setDoubleBuffered(false); capabilities.setOnscreen(false); capabilities.setHardwareAccelerated(true); GLDrawable offscreenDrawable = window.getFactory().createOffscreenDrawable(null, capabilities, null, width, height); offscreenDrawable.setRealized(true); GLContext offscreenContext = offscreenDrawable.createContext(gl.getContext()); offscreenContext.makeCurrent(); GL2 offscreenGL = offscreenContext.getGL().getGL2(); offscreenGL.glViewport(0, 0, width, height); offscreenGL.glMatrixMode(GL2.GL_PROJECTION); offscreenGL.glLoadIdentity(); offscreenGL.glOrthof(0, width, 0, height, 0, 1); offscreenGL.glMatrixMode(GL2.GL_MODELVIEW); offscreenGL.glLoadIdentity(); offscreenGL.glClearColor(0, 0, 0, 0); offscreenGL.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); draw(offscreenGL); BufferedImage image = Screenshot.readToBufferedImage(width, height, false); offscreenContext.release(); gl.getContext().makeCurrent(); File imageFile = new File(System.getProperty("user.dir") + File.separator + "Test.png"); try { ImageIO.write(image, "png", imageFile); } catch(Exception e) { System.err.println(e.toString()); } screenshotSaved = true; } } } } |
Free forum by Nabble | Edit this page |