diff options
author | renanse <[email protected]> | 2013-02-03 12:10:05 -0600 |
---|---|---|
committer | renanse <[email protected]> | 2013-02-03 12:10:05 -0600 |
commit | e757ccd563c81206aebc586fead0ede52dca2f58 (patch) | |
tree | 6cc8d81b246788d6302af801676a2376f350d038 | |
parent | dc29c24ed025144452bade21fbe45ab609c6b854 (diff) |
Added detection of MSAA FBO and FBO blit.
Fixed multisample support on LwjglHeadlessCanvas - still needs fixing in
FBO texture rendering.
5 files changed, 111 insertions, 40 deletions
diff --git a/ardor3d-core/src/main/java/com/ardor3d/renderer/ContextCapabilities.java b/ardor3d-core/src/main/java/com/ardor3d/renderer/ContextCapabilities.java index f2ac794..3e8d55c 100644 --- a/ardor3d-core/src/main/java/com/ardor3d/renderer/ContextCapabilities.java +++ b/ardor3d-core/src/main/java/com/ardor3d/renderer/ContextCapabilities.java @@ -43,6 +43,8 @@ public class ContextCapabilities { protected boolean _pbufferSupported = false; protected boolean _fboSupported = false; + protected boolean _supportsFBOMultisample = false; + protected boolean _supportsFBOBlit = false; protected int _maxFBOColorAttachments = 1; protected int _maxFBOSamples = 0; @@ -227,6 +229,20 @@ public class ContextCapabilities { } /** + * @return true if we support fbo multisampling (antialiasing) + */ + public boolean isFBOMultisampleSupported() { + return _supportsFBOMultisample; + } + + /** + * @return true if we support fbo blitting + */ + public boolean isFBOBlitSupported() { + return _supportsFBOBlit; + } + + /** * @return true if we support setting a constant color for use with *Constant* type BlendFunctions. */ public boolean isConstantBlendColorSupported() { diff --git a/ardor3d-examples/src/main/java/com/ardor3d/example/basic/LwjglHeadlessExample.java b/ardor3d-examples/src/main/java/com/ardor3d/example/basic/LwjglHeadlessExample.java index c0f147f..516b46a 100644 --- a/ardor3d-examples/src/main/java/com/ardor3d/example/basic/LwjglHeadlessExample.java +++ b/ardor3d-examples/src/main/java/com/ardor3d/example/basic/LwjglHeadlessExample.java @@ -110,7 +110,8 @@ public class LwjglHeadlessExample implements Scene { */ public LwjglHeadlessExample() { // Setup our headless canvas for rendering. - settings = new DisplaySettings(800, 600, 0, 0, false); + // settings = new DisplaySettings(800, 600, 0, 0, 0, 16, 0, 4, false, false); // use this to try MSAA + settings = new DisplaySettings(800, 600, 0, 0, 0, 16, 0, 0, false, false); canvas = new LwjglHeadlessCanvas(settings, this); canvas.getRenderer().setBackgroundColor(ColorRGBA.BLACK_NO_ALPHA); diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java index 7bc4e01..bfb39bd 100644 --- a/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java +++ b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java @@ -74,10 +74,11 @@ public class JoglContextCapabilities extends ContextCapabilities { _geometryShader4Supported = gl.isExtensionAvailable("GL_ARB_geometry_shader4") && _glslSupported; - _geometryInstancingSupported = gl.isExtensionAvailable("GL_EXT_draw_instanced") || gl.isExtensionAvailable("GL_VERSION_3_0"); - + _geometryInstancingSupported = gl.isExtensionAvailable("GL_EXT_draw_instanced") + || gl.isExtensionAvailable("GL_VERSION_3_0"); + _tessellationShadersSupported = gl.isExtensionAvailable("GL_ARB_tessellation_shader") && _glslSupported; - + if (_glslSupported) { gl.glGetIntegerv(GL2.GL_MAX_VERTEX_ATTRIBS_ARB, buf); _maxGLSLVertexAttribs = buf.get(0); @@ -89,6 +90,10 @@ public class JoglContextCapabilities extends ContextCapabilities { // FBO _fboSupported = gl.isExtensionAvailable("GL_EXT_framebuffer_object"); if (_fboSupported) { + + _supportsFBOMultisample = gl.isExtensionAvailable("GL_EXT_framebuffer_multisample"); + _supportsFBOBlit = gl.isExtensionAvailable("GL_EXT_framebuffer_blit"); + if (gl.isExtensionAvailable("GL_ARB_draw_buffers")) { gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, buf); _maxFBOColorAttachments = buf.get(0); @@ -122,11 +127,11 @@ public class JoglContextCapabilities extends ContextCapabilities { // Check for support of multitextures. _supportsMultiTexture = gl.isExtensionAvailable("GL_ARB_multitexture"); - // Support for texture formats - _supportsFloatTextures = gl.isExtensionAvailable("GL_ARB_texture_float"); - _supportsIntegerTextures = gl.isExtensionAvailable("GL_EXT_texture_integer"); - _supportsOneTwoComponentTextures = gl.isExtensionAvailable("GL_ARB_texture_rg"); - + // Support for texture formats + _supportsFloatTextures = gl.isExtensionAvailable("GL_ARB_texture_float"); + _supportsIntegerTextures = gl.isExtensionAvailable("GL_EXT_texture_integer"); + _supportsOneTwoComponentTextures = gl.isExtensionAvailable("GL_ARB_texture_rg"); + // Check for support of fixed function dot3 environment settings _supportsEnvDot3 = gl.isExtensionAvailable("GL_ARB_texture_env_dot3"); @@ -172,8 +177,8 @@ public class JoglContextCapabilities extends ContextCapabilities { } // Now determine the maximum number of supported texture units - _numTotalTexUnits = Math.max(_numFragmentTexCoordUnits, Math.max(_numFixedTexUnits, Math.max( - _numFragmentTexUnits, _numVertexTexUnits))); + _numTotalTexUnits = Math.max(_numFragmentTexCoordUnits, + Math.max(_numFixedTexUnits, Math.max(_numFragmentTexUnits, _numVertexTexUnits))); // Check for S3 texture compression capability. _supportsS3TCCompression = gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc"); diff --git a/ardor3d-lwjgl/src/main/java/com/ardor3d/framework/lwjgl/LwjglHeadlessCanvas.java b/ardor3d-lwjgl/src/main/java/com/ardor3d/framework/lwjgl/LwjglHeadlessCanvas.java index 26f8d78..895bc63 100644 --- a/ardor3d-lwjgl/src/main/java/com/ardor3d/framework/lwjgl/LwjglHeadlessCanvas.java +++ b/ardor3d-lwjgl/src/main/java/com/ardor3d/framework/lwjgl/LwjglHeadlessCanvas.java @@ -16,6 +16,8 @@ import java.nio.IntBuffer; import org.lwjgl.LWJGLException; import org.lwjgl.opengl.ARBMultisample; +import org.lwjgl.opengl.EXTFramebufferBlit; +import org.lwjgl.opengl.EXTFramebufferMultisample; import org.lwjgl.opengl.EXTFramebufferObject; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; @@ -36,7 +38,6 @@ import com.ardor3d.renderer.lwjgl.LwjglContextCapabilities; import com.ardor3d.renderer.lwjgl.LwjglRenderer; import com.ardor3d.renderer.lwjgl.LwjglTextureRenderer; import com.ardor3d.util.Ardor3dException; -import com.ardor3d.util.Constants; import com.ardor3d.util.geom.BufferUtils; /** @@ -57,6 +58,8 @@ public class LwjglHeadlessCanvas { protected Camera _camera; protected int _fboID, _depthRBID, _colorRBID; + protected int _msfboID, _msdepthRBID, _mscolorRBID; + protected boolean _useMSAA = false; protected IntBuffer _data; protected Pbuffer _buff; @@ -82,19 +85,11 @@ public class LwjglHeadlessCanvas { try { // Create a Pbuffer so we can have a valid gl context to work with final PixelFormat format = new PixelFormat(_settings.getAlphaBits(), _settings.getDepthBits(), - _settings.getStencilBits()).withSamples(_settings.getSamples()); + _settings.getStencilBits()); _buff = new Pbuffer(1, 1, format, null); _buff.makeCurrent(); } catch (final LWJGLException ex) { - try { - // try again without samples - final PixelFormat format = new PixelFormat(_settings.getAlphaBits(), _settings.getDepthBits(), - _settings.getStencilBits()); - _buff = new Pbuffer(1, 1, format, null); - _buff.makeCurrent(); - } catch (final LWJGLException ex2) { - ex2.printStackTrace(); - } + ex.printStackTrace(); } // Set up our Ardor3D context and capabilities objects @@ -105,6 +100,10 @@ public class LwjglHeadlessCanvas { throw new Ardor3dException("Headless requires FBO support."); } + if (caps.isFBOMultisampleSupported() && caps.isFBOBlitSupported() && _settings.getSamples() > 0) { + _useMSAA = true; + } + // Init our FBO. final IntBuffer buffer = BufferUtils.createIntBuffer(1); EXTFramebufferObject.glGenFramebuffersEXT(buffer); // generate id @@ -113,12 +112,13 @@ public class LwjglHeadlessCanvas { _fboID = buffer.get(0); EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, _fboID); - // initial our color renderbuffer + // initialize our color renderbuffer EXTFramebufferObject.glGenRenderbuffersEXT(buffer); // generate id _colorRBID = buffer.get(0); EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, _colorRBID); EXTFramebufferObject.glRenderbufferStorageEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, GL11.GL_RGBA, width, height); + // Attach color renderbuffer to framebuffer EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, _colorRBID); @@ -129,6 +129,7 @@ public class LwjglHeadlessCanvas { EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, _depthRBID); EXTFramebufferObject.glRenderbufferStorageEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, GL11.GL_DEPTH_COMPONENT, width, height); + // Attach depth renderbuffer to framebuffer EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_DEPTH_ATTACHMENT_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, _depthRBID); @@ -136,6 +137,47 @@ public class LwjglHeadlessCanvas { // Check FBO complete LwjglTextureRenderer.checkFBOComplete(_fboID); + // Now do it all again for multisample, if requested and supported + if (_useMSAA) { + + // Init our ms FBO. + EXTFramebufferObject.glGenFramebuffersEXT(buffer); // generate id + + // Bind the ms FBO + _msfboID = buffer.get(0); + EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, _msfboID); + + // initialize our ms color renderbuffer + EXTFramebufferObject.glGenRenderbuffersEXT(buffer); // generate id + _mscolorRBID = buffer.get(0); + EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, _mscolorRBID); + EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, + _settings.getSamples(), GL11.GL_RGBA, width, height); + + // Attach ms color renderbuffer to ms framebuffer + EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, + EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, + _mscolorRBID); + + // initialize our ms depth renderbuffer + EXTFramebufferObject.glGenRenderbuffersEXT(buffer); // generate id + _msdepthRBID = buffer.get(0); + EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, _msdepthRBID); + EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, + _settings.getSamples(), GL11.GL_DEPTH_COMPONENT, width, height); + + // Attach ms depth renderbuffer to ms framebuffer + EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, + EXTFramebufferObject.GL_DEPTH_ATTACHMENT_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, + _msdepthRBID); + + // Check MS FBO complete + LwjglTextureRenderer.checkFBOComplete(_msfboID); + + // enable multisample + GL11.glEnable(ARBMultisample.GL_MULTISAMPLE_ARB); + } + // Setup our data buffer for storing rendered image data. _data = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); @@ -143,11 +185,6 @@ public class LwjglHeadlessCanvas { ContextManager.addContext(this, currentContext); ContextManager.switchContext(this); - // Turn on multisample if requested... - if (_settings.getSamples() != 0 && caps.isMultisampleSupported()) { - GL11.glEnable(ARBMultisample.GL_MULTISAMPLE_ARB); - } - // Setup a default bg color. _renderer.setBackgroundColor(ColorRGBA.BLACK); @@ -163,17 +200,14 @@ public class LwjglHeadlessCanvas { final Vector3 dir = new Vector3(0.0f, 0f, -1.0f); _camera.setFrame(loc, left, up, dir); - if (Constants.useMultipleContexts) { - // release our FBO until used. - EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0); - } + // release our FBO(s) until used. + EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0); } public void draw() { - if (Constants.useMultipleContexts) { - // activate FBO - EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, _fboID); - } + // bind correct fbo + EXTFramebufferObject + .glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, _useMSAA ? _msfboID : _fboID); // Make sure this OpenGL context is current. ContextManager.switchContext(this); @@ -197,15 +231,25 @@ public class LwjglHeadlessCanvas { _scene.renderUnto(_renderer); _renderer.flushFrame(false); + // if we're multisampled, we need to blit to a non-multisampled fbo first + if (_useMSAA) { + EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferBlit.GL_DRAW_FRAMEBUFFER_EXT, _fboID); + EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferBlit.GL_READ_FRAMEBUFFER_EXT, _msfboID); + EXTFramebufferBlit.glBlitFramebufferEXT(0, 0, _settings.getWidth(), _settings.getHeight(), 0, 0, + _settings.getWidth(), _settings.getHeight(), GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT + | GL11.GL_STENCIL_BUFFER_BIT, GL11.GL_NEAREST); + + // get ready to read non-msaa fbo + EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, _fboID); + } + // read data from our color buffer _data.rewind(); GL11.glReadBuffer(EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT); GL11.glReadPixels(0, 0, _settings.getWidth(), _settings.getHeight(), GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, _data); - if (Constants.useMultipleContexts) { - // release our FBO. - EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0); - } + // release our FBO. + EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0); } public void releaseContext() throws LWJGLException { diff --git a/ardor3d-lwjgl/src/main/java/com/ardor3d/renderer/lwjgl/LwjglContextCapabilities.java b/ardor3d-lwjgl/src/main/java/com/ardor3d/renderer/lwjgl/LwjglContextCapabilities.java index af52d28..08f6e32 100644 --- a/ardor3d-lwjgl/src/main/java/com/ardor3d/renderer/lwjgl/LwjglContextCapabilities.java +++ b/ardor3d-lwjgl/src/main/java/com/ardor3d/renderer/lwjgl/LwjglContextCapabilities.java @@ -80,7 +80,12 @@ public class LwjglContextCapabilities extends ContextCapabilities { // FBO _fboSupported = caps.GL_EXT_framebuffer_object; + System.err.println(caps.GL_EXT_framebuffer_multisample); if (_fboSupported) { + + _supportsFBOMultisample = caps.GL_EXT_framebuffer_multisample; + _supportsFBOBlit = caps.GL_EXT_framebuffer_blit; + if (caps.GL_ARB_draw_buffers) { GL11.glGetInteger(EXTFramebufferObject.GL_MAX_COLOR_ATTACHMENTS_EXT, buf); _maxFBOColorAttachments = buf.get(0); |