diff --git a/jme3-core/src/main/java/com/jme3/renderer/Caps.java b/jme3-core/src/main/java/com/jme3/renderer/Caps.java index 5ff564136..b43e38bd6 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Caps.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Caps.java @@ -316,7 +316,15 @@ public enum Caps { * {@link Texture.MinFilter#NearestNoMipMaps} * */ - PartialNonPowerOfTwoTextures; + PartialNonPowerOfTwoTextures, + + /** + * When sampling cubemap edges, interpolate between the adjecent faces + * instead of just sampling one face. + *

+ * Improves the quality of environment mapping. + */ + SeamlessCubemap; /** * Returns true if given the renderer capabilities, the texture diff --git a/jme3-core/src/main/java/com/jme3/renderer/Limits.java b/jme3-core/src/main/java/com/jme3/renderer/Limits.java new file mode 100644 index 000000000..b10c539b8 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/renderer/Limits.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009-2015 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.renderer; + +/** + * Limits allows querying the limits of certain features in + * {@link Renderer}. + *

+ * For example, maximum texture sizes or number of samples. + * + * @author Kirill Vainer + */ +public enum Limits { + /** + * Maximum number of vertex texture units, or number of textures + * that can be used in the vertex shader. + */ + VertexTextureUnits, + + /** + * Maximum number of fragment texture units, or number of textures + * that can be used in the fragment shader. + */ + FragmentTextureUnits, + + FragmentUniforms, + + VertexAttributes, + + FrameBufferSamples, + + FrameBufferAttachments, + + FrameBufferMrtAttachments, + + RenderBufferSize, + + TextureSize, + + CubemapSize, + + VertexCount, + + TriangleCount, + + ColorTextureSamples, + + DepthTextureSamples, +} diff --git a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java index 358460716..18b1d5a56 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java +++ b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java @@ -265,6 +265,8 @@ public class RenderContext { public ColorRGBA clearColor = new ColorRGBA(0,0,0,0); + public boolean seamlessCubemap = false; + /** * Reset the RenderContext to default GL state */ @@ -317,5 +319,6 @@ public class RenderContext { depthFunc = RenderState.TestFunction.LessOrEqual; alphaFunc = RenderState.TestFunction.Greater; clearColor.set(0,0,0,0); + seamlessCubemap = false; } } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugGL2.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java similarity index 100% rename from jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugGL2.java rename to jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java index b3cc832a8..f2bb272ae 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java @@ -67,6 +67,7 @@ public interface GLExt extends GLFbo { public static final int GL_MAX_DRAW_BUFFERS_ARB = 0x8824; public static final int GL_MAX_SAMPLES_EXT = 0x8D57; public static final int GL_MULTISAMPLE_ARB = 0x809D; + public static final int GL_NUM_PROGRAM_BINARY_FORMATS = 0x87FE; public static final int GL_R11F_G11F_B10F_EXT = 0x8C3A; public static final int GL_RGBA8 = 0x8058; public static final int GL_RGB16F_ARB = 0x881B; @@ -85,6 +86,7 @@ public interface GLExt extends GLFbo { public static final int GL_TEXTURE_2D_ARRAY_EXT = 0x8C1A; public static final int GL_TEXTURE_2D_MULTISAMPLE = 0x9100; public static final int GL_TEXTURE_2D_MULTISAMPLE_ARRAY = 0x9102; + public static final int GL_TEXTURE_CUBE_MAP_SEAMLESS = 0x884F; public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE; public static final int GL_UNSIGNED_INT_10F_11F_11F_REV_EXT = 0x8C3B; public static final int GL_UNSIGNED_INT_24_8_EXT = 0x84FA; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 5a714d205..7da45a0e1 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -56,6 +56,7 @@ import com.jme3.util.BufferUtils; import com.jme3.util.ListMap; import com.jme3.util.NativeObjectManager; import java.nio.*; +import java.util.EnumMap; import java.util.EnumSet; import java.util.HashSet; import java.util.List; @@ -79,22 +80,23 @@ public class GLRenderer implements Renderer { private final RenderContext context = new RenderContext(); private final NativeObjectManager objManager = new NativeObjectManager(); private final EnumSet caps = EnumSet.noneOf(Caps.class); - - private int vertexTextureUnits; - private int fragTextureUnits; - private int vertexUniforms; - private int fragUniforms; - private int vertexAttribs; - private int maxFBOSamples; - private int maxFBOAttachs; - private int maxMRTFBOAttachs; - private int maxRBSize; - private int maxTexSize; - private int maxCubeTexSize; - private int maxVertCount; - private int maxTriCount; - private int maxColorTexSamples; - private int maxDepthTexSamples; + private final EnumMap limits = new EnumMap(Limits.class); + +// private int vertexTextureUnits; +// private int fragTextureUnits; +// private int vertexUniforms; +// private int fragUniforms; +// private int vertexAttribs; +// private int maxFBOSamples; +// private int maxFBOAttachs; +// private int maxMRTFBOAttachs; +// private int maxRBSize; +// private int maxTexSize; +// private int maxCubeTexSize; +// private int maxVertCount; +// private int maxTriCount; +// private int maxColorTexSamples; +// private int maxDepthTexSamples; private FrameBuffer mainFbOverride = null; private final Statistics statistics = new Statistics(); private int vpX, vpY, vpW, vpH; @@ -228,14 +230,12 @@ public class GLRenderer implements Renderer { private void loadCapabilitiesCommon() { extensions = loadExtensions(gl.glGetString(GL.GL_EXTENSIONS)); - vertexTextureUnits = getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - logger.log(Level.FINER, "VTF Units: {0}", vertexTextureUnits); - if (vertexTextureUnits > 0) { + limits.put(Limits.VertexTextureUnits, getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)); + if (limits.get(Limits.VertexTextureUnits) > 0) { caps.add(Caps.VertexTextureFetch); } - fragTextureUnits = getInteger(GL.GL_MAX_TEXTURE_IMAGE_UNITS); - logger.log(Level.FINER, "Texture Units: {0}", fragTextureUnits); + limits.put(Limits.FragmentTextureUnits, getInteger(GL.GL_MAX_TEXTURE_IMAGE_UNITS)); // gl.glGetInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16); // vertexUniforms = intBuf16.get(0); @@ -245,22 +245,9 @@ public class GLRenderer implements Renderer { // fragUniforms = intBuf16.get(0); // logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms); - vertexAttribs = getInteger(GL.GL_MAX_VERTEX_ATTRIBS); - logger.log(Level.FINER, "Vertex Attributes: {0}", vertexAttribs); - -// gl.glGetInteger(GL.GL_MAX_ELEMENTS_VERTICES, intBuf16); -// maxVertCount = intBuf16.get(0); -// logger.log(Level.FINER, "Preferred Batch Vertex Count: {0}", maxVertCount); -// -// gl.glGetInteger(GL.GL_MAX_ELEMENTS_INDICES, intBuf16); -// maxTriCount = intBuf16.get(0); -// logger.log(Level.FINER, "Preferred Batch Index Count: {0}", maxTriCount); - - maxTexSize = getInteger(GL.GL_MAX_TEXTURE_SIZE); - logger.log(Level.FINER, "Maximum Texture Resolution: {0}", maxTexSize); - - maxCubeTexSize = getInteger(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE); - logger.log(Level.FINER, "Maximum CubeMap Resolution: {0}", maxCubeTexSize); + limits.put(Limits.VertexAttributes, getInteger(GL.GL_MAX_VERTEX_ATTRIBS)); + limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE)); + limits.put(Limits.CubemapSize, getInteger(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE)); if (hasExtension("GL_ARB_draw_instanced") && hasExtension("GL_ARB_instanced_arrays")) { @@ -374,42 +361,36 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_EXT_framebuffer_object")) { caps.add(Caps.FrameBuffer); - - maxRBSize = getInteger(GLExt.GL_MAX_RENDERBUFFER_SIZE_EXT); - logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize); - - maxFBOAttachs = getInteger(GLExt.GL_MAX_COLOR_ATTACHMENTS_EXT); - logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs); - + + limits.put(Limits.RenderBufferSize, getInteger(GLExt.GL_MAX_RENDERBUFFER_SIZE_EXT)); + limits.put(Limits.FrameBufferAttachments, getInteger(GLExt.GL_MAX_COLOR_ATTACHMENTS_EXT)); + if (hasExtension("GL_EXT_framebuffer_blit")) { caps.add(Caps.FrameBufferBlit); } if (hasExtension("GL_EXT_framebuffer_multisample")) { caps.add(Caps.FrameBufferMultisample); - - maxFBOSamples = getInteger(GLExt.GL_MAX_SAMPLES_EXT); - logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples); + limits.put(Limits.FrameBufferSamples, getInteger(GLExt.GL_MAX_SAMPLES_EXT)); } if (hasExtension("GL_ARB_texture_multisample")) { caps.add(Caps.TextureMultisample); - - maxColorTexSamples = getInteger(GLExt.GL_MAX_COLOR_TEXTURE_SAMPLES); - logger.log(Level.FINER, "Texture Multisample Color Samples: {0}", maxColorTexSamples); - - maxDepthTexSamples = getInteger(GLExt.GL_MAX_DEPTH_TEXTURE_SAMPLES); - logger.log(Level.FINER, "Texture Multisample Depth Samples: {0}", maxDepthTexSamples); + limits.put(Limits.ColorTextureSamples, getInteger(GLExt.GL_MAX_COLOR_TEXTURE_SAMPLES)); + limits.put(Limits.DepthTextureSamples, getInteger(GLExt.GL_MAX_DEPTH_TEXTURE_SAMPLES)); + if (!limits.containsKey(Limits.FrameBufferSamples)) { + // In case they want to query samples on main FB ... + limits.put(Limits.FrameBufferSamples, limits.get(Limits.ColorTextureSamples)); + } } if (hasExtension("GL_ARB_draw_buffers")) { - maxMRTFBOAttachs = getInteger(GLExt.GL_MAX_DRAW_BUFFERS_ARB); - if (maxMRTFBOAttachs > 1) { + limits.put(Limits.FrameBufferMrtAttachments, getInteger(GLExt.GL_MAX_DRAW_BUFFERS_ARB)); + if (limits.get(Limits.FrameBufferMrtAttachments) > 1) { caps.add(Caps.FrameBufferMRT); - logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs); } } else { - maxMRTFBOAttachs = 1; + limits.put(Limits.FrameBufferMrtAttachments, 1); } } @@ -419,6 +400,8 @@ public class GLRenderer implements Renderer { logger.log(Level.FINER, "Samples: {0}", samples); boolean enabled = gl.glIsEnabled(GLExt.GL_MULTISAMPLE_ARB); if (samples > 0 && available && !enabled) { + // Doesn't seem to be neccessary .. OGL spec says its always + // set by default? gl.glEnable(GLExt.GL_MULTISAMPLE_ARB); } caps.add(Caps.Multisample); @@ -430,6 +413,17 @@ public class GLRenderer implements Renderer { caps.add(Caps.Srgb); } + // Supports seamless cubemap + if (hasExtension("GL_ARB_seamless_cube_map") || caps.contains(Caps.OpenGL32)) { + caps.add(Caps.SeamlessCubemap); + } + + if (hasExtension("GL_ARB_get_program_binary")) { + // OK .. + int binaryFormats = getInteger(GLExt.GL_NUM_PROGRAM_BINARY_FORMATS); + System.out.println("Binary Formats: " + binaryFormats); + } + logger.log(Level.FINE, "Caps: {0}", caps); texUtil.initialize(caps); @@ -564,24 +558,24 @@ public class GLRenderer implements Renderer { context.depthFunc = state.getDepthFunc(); } - if (gl2 != null) { - if (state.isAlphaTest() && !context.alphaTestEnabled) { - gl2.glEnable(GL2.GL_ALPHA_TEST); - gl2.glAlphaFunc(convertTestFunction(context.alphaFunc), context.alphaTestFallOff); - context.alphaTestEnabled = true; - } else if (!state.isAlphaTest() && context.alphaTestEnabled) { - gl2.glDisable(GL2.GL_ALPHA_TEST); - context.alphaTestEnabled = false; - } - if (state.getAlphaFallOff() != context.alphaTestFallOff) { - gl2.glAlphaFunc(convertTestFunction(context.alphaFunc), context.alphaTestFallOff); - context.alphaTestFallOff = state.getAlphaFallOff(); - } - if (state.getAlphaFunc() != context.alphaFunc) { - gl2.glAlphaFunc(convertTestFunction(state.getAlphaFunc()), context.alphaTestFallOff); - context.alphaFunc = state.getAlphaFunc(); - } - } +// if (gl2 != null) { +// if (state.isAlphaTest() && !context.alphaTestEnabled) { +// gl2.glEnable(GL2.GL_ALPHA_TEST); +// gl2.glAlphaFunc(convertTestFunction(context.alphaFunc), context.alphaTestFallOff); +// context.alphaTestEnabled = true; +// } else if (!state.isAlphaTest() && context.alphaTestEnabled) { +// gl2.glDisable(GL2.GL_ALPHA_TEST); +// context.alphaTestEnabled = false; +// } +// if (state.getAlphaFallOff() != context.alphaTestFallOff) { +// gl2.glAlphaFunc(convertTestFunction(context.alphaFunc), context.alphaTestFallOff); +// context.alphaTestFallOff = state.getAlphaFallOff(); +// } +// if (state.getAlphaFunc() != context.alphaFunc) { +// gl2.glAlphaFunc(convertTestFunction(state.getAlphaFunc()), context.alphaTestFallOff); +// context.alphaFunc = state.getAlphaFunc(); +// } +// } if (state.isDepthWrite() && !context.depthWriteEnabled) { gl.glDepthMask(true); @@ -1128,7 +1122,7 @@ public class GLRenderer implements Renderer { // Check if GLSL version is 1.5 for shader gl3.glBindFragDataLocation(id, 0, "outFragColor"); // For MRT - for (int i = 0; i < maxMRTFBOAttachs; i++) { + for (int i = 0; i < limits.get(Limits.FrameBufferMrtAttachments); i++) { gl3.glBindFragDataLocation(id, i, "outFragData[" + i + "]"); } } @@ -1346,7 +1340,8 @@ public class GLRenderer implements Renderer { context.boundRB = id; } - if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) { + int rbSize = limits.get(Limits.RenderBufferSize); + if (fb.getWidth() > rbSize || fb.getHeight() > rbSize) { throw new RendererException("Resolution " + fb.getWidth() + ":" + fb.getHeight() + " is not supported."); } @@ -1355,8 +1350,9 @@ public class GLRenderer implements Renderer { if (fb.getSamples() > 1 && caps.contains(Caps.FrameBufferMultisample)) { int samples = fb.getSamples(); - if (maxFBOSamples < samples) { - samples = maxFBOSamples; + int maxSamples = limits.get(Limits.FrameBufferSamples); + if (maxSamples < samples) { + samples = maxSamples; } glext.glRenderbufferStorageMultisampleEXT(GLExt.GL_RENDERBUFFER_EXT, samples, @@ -1576,7 +1572,7 @@ public class GLRenderer implements Renderer { } } } else { - if (fb.getNumColorBuffers() > maxFBOAttachs) { + if (fb.getNumColorBuffers() > limits.get(Limits.FrameBufferAttachments)) { throw new RendererException("Framebuffer has more color " + "attachments than are supported" + " by the video hardware!"); @@ -1586,7 +1582,7 @@ public class GLRenderer implements Renderer { throw new RendererException("Multiple render targets " + " are not supported by the video hardware"); } - if (fb.getNumColorBuffers() > maxMRTFBOAttachs) { + if (fb.getNumColorBuffers() > limits.get(Limits.FrameBufferMrtAttachments)) { throw new RendererException("Framebuffer has more" + " multi targets than are supported" + " by the video hardware!"); @@ -1809,6 +1805,17 @@ public class GLRenderer implements Renderer { gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter); image.getLastTextureState().minFilter = tex.getMinFilter(); } + if (caps.contains(Caps.SeamlessCubemap) && tex.getType() == Texture.Type.CubeMap) { + if (haveMips && !context.seamlessCubemap) { + // We can enable seamless cubemap filtering. + gl.glEnable(GLExt.GL_TEXTURE_CUBE_MAP_SEAMLESS); + context.seamlessCubemap = true; + } else if (!haveMips && context.seamlessCubemap) { + // For skyboxes (no mipmaps), disable seamless cubemap filtering. + gl.glDisable(GLExt.GL_TEXTURE_CUBE_MAP_SEAMLESS); + context.seamlessCubemap = false; + } + } if (tex.getAnisotropicFilter() > 1) { if (caps.contains(Caps.TextureFilterAnisotropic)) { @@ -1940,11 +1947,12 @@ public class GLRenderer implements Renderer { // bind texture int target = convertTextureType(type, img.getMultiSamples(), -1); - if (context.boundTextureUnit != unit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + unit); - context.boundTextureUnit = unit; - } if (context.boundTextures[unit] != img) { + if (context.boundTextureUnit != unit) { + gl.glActiveTexture(GL.GL_TEXTURE0 + unit); + context.boundTextureUnit = unit; + } + gl.glBindTexture(target, texId); context.boundTextures[unit] = img; @@ -1975,9 +1983,9 @@ public class GLRenderer implements Renderer { int imageSamples = img.getMultiSamples(); if (imageSamples > 1) { if (img.getFormat().isDepthFormat()) { - img.setMultiSamples(Math.min(maxDepthTexSamples, imageSamples)); + img.setMultiSamples(Math.min(limits.get(Limits.DepthTextureSamples), imageSamples)); } else { - img.setMultiSamples(Math.min(maxColorTexSamples, imageSamples)); + img.setMultiSamples(Math.min(limits.get(Limits.ColorTextureSamples), imageSamples)); } } @@ -1995,15 +2003,17 @@ public class GLRenderer implements Renderer { if (target == GL.GL_TEXTURE_CUBE_MAP) { // Check max texture size before upload - if (img.getWidth() > maxCubeTexSize || img.getHeight() > maxCubeTexSize) { - throw new RendererException("Cannot upload cubemap " + img + ". The maximum supported cubemap resolution is " + maxCubeTexSize); + int cubeSize = limits.get(Limits.CubemapSize); + if (img.getWidth() > cubeSize || img.getHeight() > cubeSize) { + throw new RendererException("Cannot upload cubemap " + img + ". The maximum supported cubemap resolution is " + cubeSize); } if (img.getWidth() != img.getHeight()) { throw new RendererException("Cubemaps must have square dimensions"); } } else { - if (img.getWidth() > maxTexSize || img.getHeight() > maxTexSize) { - throw new RendererException("Cannot upload texture " + img + ". The maximum supported texture resolution is " + maxTexSize); + int texSize = limits.get(Limits.TextureSize); + if (img.getWidth() > texSize || img.getHeight() > texSize) { + throw new RendererException("Cannot upload texture " + img + ". The maximum supported texture resolution is " + texSize); } } diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java index 2a3b10b58..12da0bbca 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java @@ -42,7 +42,7 @@ import com.jme3.renderer.lwjgl.LwjglGLExt; import com.jme3.renderer.opengl.GL; import com.jme3.renderer.opengl.GL2; import com.jme3.renderer.opengl.GL3; -import com.jme3.renderer.opengl.GLDebugGL2; +import com.jme3.renderer.opengl.GLDebugDesktop; import com.jme3.renderer.opengl.GLExt; import com.jme3.renderer.opengl.GLFbo; import com.jme3.renderer.opengl.GLRenderer; @@ -218,12 +218,12 @@ public abstract class LwjglContext implements JmeContext { GLFbo glfbo = new LwjglGLExt(); if (settings.getBoolean("GraphicsDebug")) { - gl = new GLDebugGL2(gl, glfbo); + gl = new GLDebugDesktop(gl, glfbo); glfbo = (GLFbo) gl; } if (settings.getBoolean("GraphicsTrace")) { - gl = (GL) GLTracer.createDesktopGlTracer(gl, GL2.class); + gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class); glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLExt.class); }