159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.renderer.lwjgl; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.light.LightList; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.RenderState; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.RenderState.StencilOperation; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.RenderState.TestFunction; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.*; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.*; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh.Mode; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Format; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Type; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Usage; 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Attribute; 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Shader; 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Shader.ShaderSource; 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Shader.ShaderType; 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Uniform; 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.FrameBuffer; 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.FrameBuffer.RenderBuffer; 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Image; 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture; 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture.WrapAxis; 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils; 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.IntMap; 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.IntMap.Entry; 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.ListMap; 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.NativeObjectManager; 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.SafeArrayList; 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.*; 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.EnumSet; 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.List; 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level; 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger; 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport jme3tools.converters.MipMapGenerator; 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.ARBTextureMultisample.*; 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.EXTFramebufferBlit.*; 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.EXTFramebufferMultisample.*; 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.EXTFramebufferObject.*; 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL11.*; 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL12.*; 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL13.*; 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL14.*; 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL15.*; 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL20.*; 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport org.lwjgl.opengl.*; 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//import static org.lwjgl.opengl.ARBDrawInstanced.*; 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class LwjglRenderer implements Renderer { 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final Logger logger = Logger.getLogger(LwjglRenderer.class.getName()); 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final boolean VALIDATE_SHADER = false; 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final StringBuilder stringBuf = new StringBuilder(250); 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16); 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final RenderContext context = new RenderContext(); 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final NativeObjectManager objManager = new NativeObjectManager(); 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class); 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // current state 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Shader boundShader; 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int initialDrawBuf, initialReadBuf; 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int glslVer; 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int vertexTextureUnits; 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int fragTextureUnits; 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int vertexUniforms; 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int fragUniforms; 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int vertexAttribs; 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxFBOSamples; 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxFBOAttachs; 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxMRTFBOAttachs; 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxRBSize; 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxTexSize; 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxCubeTexSize; 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxVertCount; 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxTriCount; 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxColorTexSamples; 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxDepthTexSamples; 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean tdc; 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private FrameBuffer lastFb = null; 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private FrameBuffer mainFbOverride = null; 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final Statistics statistics = new Statistics(); 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int vpX, vpY, vpW, vpH; 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int clipX, clipY, clipW, clipH; 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public LwjglRenderer() { 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void updateNameBuffer() { 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int len = stringBuf.length(); 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nameBuf.position(0); 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nameBuf.limit(len); 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < len; i++) { 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nameBuf.put((byte) stringBuf.charAt(i)); 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nameBuf.rewind(); 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Statistics getStatistics() { 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return statistics; 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public EnumSet<Caps> getCaps() { 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return caps; 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @SuppressWarnings("fallthrough") 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void initialize() { 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ContextCapabilities ctxCaps = GLContext.getCapabilities(); 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.OpenGL20) { 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.OpenGL20); 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.OpenGL21) { 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.OpenGL21); 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.OpenGL30) { 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.OpenGL30); 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.OpenGL31) { 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.OpenGL31); 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.OpenGL32) { 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.OpenGL32); 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String versionStr = null; 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.OpenGL20) { 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta versionStr = glGetString(GL_SHADING_LANGUAGE_VERSION); 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (versionStr == null || versionStr.equals("")) { 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glslVer = -1; 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("GLSL and OpenGL2 is " 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "required for the LWJGL " 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "renderer!"); 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Fix issue in TestRenderToMemory when GL_FRONT is the main 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // buffer being used. 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta initialDrawBuf = glGetInteger(GL_DRAW_BUFFER); 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta initialReadBuf = glGetInteger(GL_READ_BUFFER); 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // XXX: This has to be GL_BACK for canvas on Mac 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Since initialDrawBuf is GL_FRONT for pbuffer, gotta 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // change this value later on ... 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// initialDrawBuf = GL_BACK; 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// initialReadBuf = GL_BACK; 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int spaceIdx = versionStr.indexOf(" "); 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (spaceIdx >= 1) { 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta versionStr = versionStr.substring(0, spaceIdx); 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float version = Float.parseFloat(versionStr); 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glslVer = (int) (version * 100); 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (glslVer) { 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (glslVer < 400) { 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // so that future OpenGL revisions wont break jme3 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // fall through intentional 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 400: 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 330: 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 150: 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.GLSL150); 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 140: 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.GLSL140); 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 130: 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.GLSL130); 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 120: 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.GLSL120); 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 110: 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.GLSL110); 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 100: 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.GLSL100); 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!caps.contains(Caps.GLSL100)) { 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "Force-adding GLSL100 support, since OpenGL2 is supported."); 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.GLSL100); 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16); 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexTextureUnits = intBuf16.get(0); 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "VTF Units: {0}", vertexTextureUnits); 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vertexTextureUnits > 0) { 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.VertexTextureFetch); 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS, intBuf16); 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fragTextureUnits = intBuf16.get(0); 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Texture Units: {0}", fragTextureUnits); 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16); 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexUniforms = intBuf16.get(0); 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms); 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16); 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fragUniforms = intBuf16.get(0); 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms); 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_VERTEX_ATTRIBS, intBuf16); 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexAttribs = intBuf16.get(0); 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Vertex Attributes: {0}", vertexAttribs); 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_SUBPIXEL_BITS, intBuf16); 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int subpixelBits = intBuf16.get(0); 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Subpixel Bits: {0}", subpixelBits); 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_ELEMENTS_VERTICES, intBuf16); 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxVertCount = intBuf16.get(0); 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Preferred Batch Vertex Count: {0}", maxVertCount); 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_ELEMENTS_INDICES, intBuf16); 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxTriCount = intBuf16.get(0); 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Preferred Batch Index Count: {0}", maxTriCount); 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_TEXTURE_SIZE, intBuf16); 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxTexSize = intBuf16.get(0); 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Maximum Texture Resolution: {0}", maxTexSize); 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_CUBE_MAP_TEXTURE_SIZE, intBuf16); 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxCubeTexSize = intBuf16.get(0); 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Maximum CubeMap Resolution: {0}", maxCubeTexSize); 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_color_buffer_float) { 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // XXX: Require both 16 and 32 bit float support for FloatColorBuffer. 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_half_float_pixel) { 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.FloatColorBuffer); 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_depth_buffer_float) { 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.FloatDepthBuffer); 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_draw_instanced) { 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.MeshInstancing); 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_fragment_program) { 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.ARBprogram); 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_texture_buffer_object) { 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.TextureBuffer); 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_texture_float) { 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_half_float_pixel) { 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.FloatTexture); 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_vertex_array_object) { 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.VertexBufferArray); 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_texture_non_power_of_two) { 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.NonPowerOfTwoTextures); 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "Your graphics card does not " 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "support non-power-of-2 textures. " 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "Some features might not work."); 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean latc = ctxCaps.GL_EXT_texture_compression_latc; 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean atdc = ctxCaps.GL_ATI_texture_compression_3dc; 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (latc || atdc) { 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.TextureCompressionLATC); 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (atdc && !latc) { 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tdc = true; 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_EXT_packed_float) { 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.PackedFloatColorBuffer); 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_half_float_pixel) { 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // because textures are usually uploaded as RGB16F 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // need half-float pixel 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.PackedFloatTexture); 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_EXT_texture_array) { 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.TextureArray); 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_EXT_texture_shared_exponent) { 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.SharedExponentTexture); 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_EXT_framebuffer_object) { 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.FrameBuffer); 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_RENDERBUFFER_SIZE_EXT, intBuf16); 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxRBSize = intBuf16.get(0); 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize); 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_COLOR_ATTACHMENTS_EXT, intBuf16); 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxFBOAttachs = intBuf16.get(0); 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs); 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_EXT_framebuffer_multisample) { 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.FrameBufferMultisample); 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_SAMPLES_EXT, intBuf16); 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxFBOSamples = intBuf16.get(0); 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples); 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_texture_multisample) { 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.TextureMultisample); 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_COLOR_TEXTURE_SAMPLES, intBuf16); 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxColorTexSamples = intBuf16.get(0); 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Texture Multisample Color Samples: {0}", maxColorTexSamples); 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(GL_MAX_DEPTH_TEXTURE_SAMPLES, intBuf16); 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxDepthTexSamples = intBuf16.get(0); 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Texture Multisample Depth Samples: {0}", maxDepthTexSamples); 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_draw_buffers) { 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta caps.add(Caps.FrameBufferMRT); 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB, intBuf16); 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxMRTFBOAttachs = intBuf16.get(0); 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs); 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ctxCaps.GL_ARB_multisample) { 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(ARBMultisample.GL_SAMPLE_BUFFERS_ARB, intBuf16); 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean available = intBuf16.get(0) != 0; 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetInteger(ARBMultisample.GL_SAMPLES_ARB, intBuf16); 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int samples = intBuf16.get(0); 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Samples: {0}", samples); 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean enabled = glIsEnabled(ARBMultisample.GL_MULTISAMPLE_ARB); 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (samples > 0 && available && !enabled) { 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(ARBMultisample.GL_MULTISAMPLE_ARB); 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "Caps: {0}", caps); 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void invalidateState() { 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.reset(); 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boundShader = null; 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta lastFb = null; 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta initialDrawBuf = glGetInteger(GL_DRAW_BUFFER); 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta initialReadBuf = glGetInteger(GL_READ_BUFFER); 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void resetGLObjects() { 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "Reseting objects and invalidating state"); 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.resetObjects(); 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.clearMemory(); 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta invalidateState(); 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void cleanup() { 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "Deleting objects and invalidating state"); 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.deleteAllObjects(this); 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.clearMemory(); 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta invalidateState(); 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void checkCap(Caps cap) { 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!caps.contains(cap)) { 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Required capability missing: " + cap.name()); 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /*********************************************************************\ 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta |* Render State *| 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta \*********************************************************************/ 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setDepthRange(float start, float end) { 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDepthRange(start, end); 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void clearBuffers(boolean color, boolean depth, boolean stencil) { 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int bits = 0; 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (color) { 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //See explanations of the depth below, we must enable color write to be able to clear the color buffer 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.colorWriteEnabled == false) { 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glColorMask(true, true, true, true); 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.colorWriteEnabled = true; 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bits = GL_COLOR_BUFFER_BIT; 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (depth) { 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //glClear(GL_DEPTH_BUFFER_BIT) seems to not work when glDepthMask is false 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //here s some link on openl board 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=257223 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //if depth clear is requested, we enable the depthMask 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.depthWriteEnabled == false) { 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDepthMask(true); 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.depthWriteEnabled = true; 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bits |= GL_DEPTH_BUFFER_BIT; 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (stencil) { 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bits |= GL_STENCIL_BUFFER_BIT; 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (bits != 0) { 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glClear(bits); 44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setBackgroundColor(ColorRGBA color) { 45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glClearColor(color.r, color.g, color.b, color.a); 45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setAlphaToCoverage(boolean value) { 45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (value) { 45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(ARBMultisample.GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); 45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(ARBMultisample.GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); 46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void applyRenderState(RenderState state) { 46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.isWireframe() && !context.wireframe) { 46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.wireframe = true; 46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (!state.isWireframe() && context.wireframe) { 46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.wireframe = false; 47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.isDepthTest() && !context.depthTestEnabled) { 47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_DEPTH_TEST); 47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDepthFunc(GL_LEQUAL); 47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.depthTestEnabled = true; 47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (!state.isDepthTest() && context.depthTestEnabled) { 47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_DEPTH_TEST); 47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.depthTestEnabled = false; 47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.isAlphaTest() && !context.alphaTestEnabled) { 48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_ALPHA_TEST); 48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glAlphaFunc(GL_GREATER, state.getAlphaFallOff()); 48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.alphaTestEnabled = true; 48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (!state.isAlphaTest() && context.alphaTestEnabled) { 48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_ALPHA_TEST); 48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.alphaTestEnabled = false; 48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.isDepthWrite() && !context.depthWriteEnabled) { 49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDepthMask(true); 49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.depthWriteEnabled = true; 49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (!state.isDepthWrite() && context.depthWriteEnabled) { 49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDepthMask(false); 49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.depthWriteEnabled = false; 49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.isColorWrite() && !context.colorWriteEnabled) { 49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glColorMask(true, true, true, true); 50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.colorWriteEnabled = true; 50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (!state.isColorWrite() && context.colorWriteEnabled) { 50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glColorMask(false, false, false, false); 50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.colorWriteEnabled = false; 50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.isPointSprite() && !context.pointSprite) { 50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Only enable/disable sprite 50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextures[0] != null){ 50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextureUnit != 0){ 51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glActiveTexture(GL_TEXTURE0); 51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundTextureUnit = 0; 51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_POINT_SPRITE); 51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); 51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.pointSprite = true; 51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (!state.isPointSprite() && context.pointSprite) { 51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextures[0] != null){ 51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextureUnit != 0){ 52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glActiveTexture(GL_TEXTURE0); 52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundTextureUnit = 0; 52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_POINT_SPRITE); 52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); 52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.pointSprite = false; 52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.isPolyOffset()) { 53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!context.polyOffsetEnabled) { 53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_POLYGON_OFFSET_FILL); 53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glPolygonOffset(state.getPolyOffsetFactor(), 53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta state.getPolyOffsetUnits()); 53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.polyOffsetEnabled = true; 53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.polyOffsetFactor = state.getPolyOffsetFactor(); 53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.polyOffsetUnits = state.getPolyOffsetUnits(); 53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.getPolyOffsetFactor() != context.polyOffsetFactor 53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || state.getPolyOffsetUnits() != context.polyOffsetUnits) { 54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glPolygonOffset(state.getPolyOffsetFactor(), 54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta state.getPolyOffsetUnits()); 54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.polyOffsetFactor = state.getPolyOffsetFactor(); 54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.polyOffsetUnits = state.getPolyOffsetUnits(); 54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.polyOffsetEnabled) { 54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_POLYGON_OFFSET_FILL); 54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.polyOffsetEnabled = false; 55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.polyOffsetFactor = 0; 55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.polyOffsetUnits = 0; 55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.getFaceCullMode() != context.cullMode) { 55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) { 55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_CULL_FACE); 55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_CULL_FACE); 56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (state.getFaceCullMode()) { 56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Off: 56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Back: 56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glCullFace(GL_BACK); 56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Front: 56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glCullFace(GL_FRONT); 57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case FrontAndBack: 57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glCullFace(GL_FRONT_AND_BACK); 57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unrecognized face cull mode: " 57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + state.getFaceCullMode()); 57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.cullMode = state.getFaceCullMode(); 58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.getBlendMode() != context.blendMode) { 58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.getBlendMode() == RenderState.BlendMode.Off) { 58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_BLEND); 58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_BLEND); 58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (state.getBlendMode()) { 58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Off: 58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Additive: 59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBlendFunc(GL_ONE, GL_ONE); 59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case AlphaAdditive: 59459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBlendFunc(GL_SRC_ALPHA, GL_ONE); 59559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 59659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Color: 59759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); 59859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 59959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Alpha: 60059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 60159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 60259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case PremultAlpha: 60359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 60459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 60559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Modulate: 60659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBlendFunc(GL_DST_COLOR, GL_ZERO); 60759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 60859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case ModulateX2: 60959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); 61059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 61159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 61259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unrecognized blend mode: " 61359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + state.getBlendMode()); 61459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 61559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 61659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 61759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.blendMode = state.getBlendMode(); 61859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 61959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 62059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.stencilTest != state.isStencilTest() 62159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || context.frontStencilStencilFailOperation != state.getFrontStencilStencilFailOperation() 62259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || context.frontStencilDepthFailOperation != state.getFrontStencilDepthFailOperation() 62359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || context.frontStencilDepthPassOperation != state.getFrontStencilDepthPassOperation() 62459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || context.backStencilStencilFailOperation != state.getBackStencilStencilFailOperation() 62559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || context.backStencilDepthFailOperation != state.getBackStencilDepthFailOperation() 62659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || context.backStencilDepthPassOperation != state.getBackStencilDepthPassOperation() 62759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || context.frontStencilFunction != state.getFrontStencilFunction() 62859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || context.backStencilFunction != state.getBackStencilFunction()) { 62959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 63059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.frontStencilStencilFailOperation = state.getFrontStencilStencilFailOperation(); //terrible looking, I know 63159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.frontStencilDepthFailOperation = state.getFrontStencilDepthFailOperation(); 63259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.frontStencilDepthPassOperation = state.getFrontStencilDepthPassOperation(); 63359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.backStencilStencilFailOperation = state.getBackStencilStencilFailOperation(); 63459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.backStencilDepthFailOperation = state.getBackStencilDepthFailOperation(); 63559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.backStencilDepthPassOperation = state.getBackStencilDepthPassOperation(); 63659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.frontStencilFunction = state.getFrontStencilFunction(); 63759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.backStencilFunction = state.getBackStencilFunction(); 63859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 63959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (state.isStencilTest()) { 64059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_STENCIL_TEST); 64159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glStencilOpSeparate(GL_FRONT, 64259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertStencilOperation(state.getFrontStencilStencilFailOperation()), 64359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertStencilOperation(state.getFrontStencilDepthFailOperation()), 64459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertStencilOperation(state.getFrontStencilDepthPassOperation())); 64559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glStencilOpSeparate(GL_BACK, 64659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertStencilOperation(state.getBackStencilStencilFailOperation()), 64759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertStencilOperation(state.getBackStencilDepthFailOperation()), 64859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertStencilOperation(state.getBackStencilDepthPassOperation())); 64959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glStencilFuncSeparate(GL_FRONT, 65059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertTestFunction(state.getFrontStencilFunction()), 65159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 0, Integer.MAX_VALUE); 65259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glStencilFuncSeparate(GL_BACK, 65359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertTestFunction(state.getBackStencilFunction()), 65459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 0, Integer.MAX_VALUE); 65559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 65659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_STENCIL_TEST); 65759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 65859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 65959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 66059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 66159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertStencilOperation(StencilOperation stencilOp) { 66259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (stencilOp) { 66359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Keep: 66459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_KEEP; 66559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Zero: 66659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_ZERO; 66759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Replace: 66859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_REPLACE; 66959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Increment: 67059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_INCR; 67159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case IncrementWrap: 67259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_INCR_WRAP; 67359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Decrement: 67459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_DECR; 67559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case DecrementWrap: 67659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_DECR_WRAP; 67759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Invert: 67859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_INVERT; 67959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 68059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unrecognized stencil operation: " + stencilOp); 68159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 68259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 68359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 68459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertTestFunction(TestFunction testFunc) { 68559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (testFunc) { 68659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Never: 68759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_NEVER; 68859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Less: 68959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LESS; 69059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case LessOrEqual: 69159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LEQUAL; 69259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Greater: 69359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_GREATER; 69459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GreaterOrEqual: 69559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_GEQUAL; 69659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Equal: 69759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_EQUAL; 69859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case NotEqual: 69959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_NOTEQUAL; 70059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Always: 70159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_ALWAYS; 70259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 70359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unrecognized test function: " + testFunc); 70459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 70559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 70659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 70759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /*********************************************************************\ 70859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta |* Camera and World transforms *| 70959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta \*********************************************************************/ 71059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setViewPort(int x, int y, int w, int h) { 71159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (x != vpX || vpY != y || vpW != w || vpH != h) { 71259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glViewport(x, y, w, h); 71359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vpX = x; 71459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vpY = y; 71559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vpW = w; 71659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vpH = h; 71759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 71859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 71959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 72059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setClipRect(int x, int y, int width, int height) { 72159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!context.clipRectEnabled) { 72259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(GL_SCISSOR_TEST); 72359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.clipRectEnabled = true; 72459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 72559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (clipX != x || clipY != y || clipW != width || clipH != height) { 72659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glScissor(x, y, width, height); 72759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clipX = x; 72859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clipY = y; 72959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clipW = width; 73059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clipH = height; 73159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 73259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 73359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 73459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void clearClipRect() { 73559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.clipRectEnabled) { 73659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_SCISSOR_TEST); 73759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.clipRectEnabled = false; 73859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 73959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clipX = 0; 74059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clipY = 0; 74159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clipW = 0; 74259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clipH = 0; 74359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 74459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 74559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 74659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void onFrame() { 74759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.deleteUnused(this); 74859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// statistics.clearFrame(); 74959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 75059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 75159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setWorldMatrix(Matrix4f worldMatrix) { 75259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 75359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 75459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) { 75559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 75659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 75759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /*********************************************************************\ 75859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta |* Shaders *| 75959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta \*********************************************************************/ 76059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void updateUniformLocation(Shader shader, Uniform uniform) { 76159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.setLength(0); 76259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.append(uniform.getName()).append('\0'); 76359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateNameBuffer(); 76459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int loc = glGetUniformLocation(shader.getId(), nameBuf); 76559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (loc < 0) { 76659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uniform.setLocation(-1); 76759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // uniform is not declared in shader 76859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "Uniform {0} is not declared in shader {1}.", new Object[]{uniform.getName(), shader.getSources()}); 76959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 77059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uniform.setLocation(loc); 77159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 77259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 77359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 77459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void bindProgram(Shader shader){ 77559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int shaderId = shader.getId(); 77659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundShaderProgram != shaderId) { 77759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUseProgram(shaderId); 77859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onShaderUse(shader, true); 77959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boundShader = shader; 78059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundShaderProgram = shaderId; 78159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 78259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onShaderUse(shader, false); 78359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 78459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 78559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 78659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void updateUniform(Shader shader, Uniform uniform) { 78759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int shaderId = shader.getId(); 78859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 78959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert uniform.getName() != null; 79059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert shader.getId() > 0; 79159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 79259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bindProgram(shader); 79359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 79459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int loc = uniform.getLocation(); 79559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (loc == -1) { 79659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 79759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 79859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 79959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (loc == -2) { 80059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // get uniform location 80159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateUniformLocation(shader, uniform); 80259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (uniform.getLocation() == -1) { 80359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // not declared, ignore 80459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uniform.clearUpdateNeeded(); 80559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 80659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 80759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta loc = uniform.getLocation(); 80859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 80959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 81059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (uniform.getVarType() == null) { 81159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; // value not set yet.. 81259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 81359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onUniformSet(); 81459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 81559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uniform.clearUpdateNeeded(); 81659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FloatBuffer fb; 81759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (uniform.getVarType()) { 81859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Float: 81959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Float f = (Float) uniform.getValue(); 82059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform1f(loc, f.floatValue()); 82159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 82259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Vector2: 82359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector2f v2 = (Vector2f) uniform.getValue(); 82459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform2f(loc, v2.getX(), v2.getY()); 82559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 82659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Vector3: 82759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f v3 = (Vector3f) uniform.getValue(); 82859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform3f(loc, v3.getX(), v3.getY(), v3.getZ()); 82959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 83059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Vector4: 83159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Object val = uniform.getValue(); 83259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (val instanceof ColorRGBA) { 83359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ColorRGBA c = (ColorRGBA) val; 83459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform4f(loc, c.r, c.g, c.b, c.a); 83559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (val instanceof Vector4f) { 83659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector4f c = (Vector4f) val; 83759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform4f(loc, c.x, c.y, c.z, c.w); 83859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 83959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Quaternion c = (Quaternion) uniform.getValue(); 84059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform4f(loc, c.getX(), c.getY(), c.getZ(), c.getW()); 84159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 84259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 84359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Boolean: 84459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Boolean b = (Boolean) uniform.getValue(); 84559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform1i(loc, b.booleanValue() ? GL_TRUE : GL_FALSE); 84659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 84759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Matrix3: 84859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb = (FloatBuffer) uniform.getValue(); 84959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert fb.remaining() == 9; 85059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniformMatrix3(loc, false, fb); 85159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 85259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Matrix4: 85359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb = (FloatBuffer) uniform.getValue(); 85459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert fb.remaining() == 16; 85559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniformMatrix4(loc, false, fb); 85659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 85759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case FloatArray: 85859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb = (FloatBuffer) uniform.getValue(); 85959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform1(loc, fb); 86059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 86159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Vector2Array: 86259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb = (FloatBuffer) uniform.getValue(); 86359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform2(loc, fb); 86459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 86559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Vector3Array: 86659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb = (FloatBuffer) uniform.getValue(); 86759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform3(loc, fb); 86859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 86959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Vector4Array: 87059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb = (FloatBuffer) uniform.getValue(); 87159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform4(loc, fb); 87259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 87359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Matrix4Array: 87459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb = (FloatBuffer) uniform.getValue(); 87559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniformMatrix4(loc, false, fb); 87659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 87759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Int: 87859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Integer i = (Integer) uniform.getValue(); 87959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glUniform1i(loc, i.intValue()); 88059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 88159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 88259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType()); 88359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 88459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 88559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 88659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void updateShaderUniforms(Shader shader) { 88759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ListMap<String, Uniform> uniforms = shader.getUniformMap(); 88859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// for (Uniform uniform : shader.getUniforms()){ 88959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < uniforms.size(); i++) { 89059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Uniform uniform = uniforms.getValue(i); 89159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (uniform.isUpdateNeeded()) { 89259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateUniform(shader, uniform); 89359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 89459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 89559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 89659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 89759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void resetUniformLocations(Shader shader) { 89859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ListMap<String, Uniform> uniforms = shader.getUniformMap(); 89959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// for (Uniform uniform : shader.getUniforms()){ 90059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < uniforms.size(); i++) { 90159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Uniform uniform = uniforms.getValue(i); 90259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uniform.reset(); // e.g check location again 90359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 90459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 90559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 90659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /* 90759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * (Non-javadoc) 90859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Only used for fixed-function. Ignored. 90959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 91059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setLighting(LightList list) { 91159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 91259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 91359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int convertShaderType(ShaderType type) { 91459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (type) { 91559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Fragment: 91659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_FRAGMENT_SHADER; 91759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Vertex: 91859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_VERTEX_SHADER; 91959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case Geometry: 92059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// return ARBGeometryShader4.GL_GEOMETRY_SHADER_ARB; 92159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 92259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unrecognized shader type."); 92359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 92459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 92559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 92659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateShaderSourceData(ShaderSource source, String language) { 92759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = source.getId(); 92859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id == -1) { 92959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create id 93059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta id = glCreateShader(convertShaderType(source.getType())); 93159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id <= 0) { 93259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("Invalid ID received when trying to create shader."); 93359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 93459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 93559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta source.setId(id); 93659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 93759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("Cannot recompile shader source"); 93859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 93959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 94059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // upload shader source 94159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // merge the defines and source code 94259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 94359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.setLength(0); 94459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (language.startsWith("GLSL")) { 94559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int version = Integer.parseInt(language.substring(4)); 94659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (version > 100) { 94759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.append("#version "); 94859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.append(language.substring(4)); 94959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (version >= 150) { 95059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.append(" core"); 95159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 95259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.append("\n"); 95359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 95459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 95559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateNameBuffer(); 95659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 95759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte[] definesCodeData = source.getDefines().getBytes(); 95859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte[] sourceCodeData = source.getSource().getBytes(); 95959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ByteBuffer codeBuf = BufferUtils.createByteBuffer(nameBuf.limit() 96059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + definesCodeData.length 96159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + sourceCodeData.length); 96259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta codeBuf.put(nameBuf); 96359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta codeBuf.put(definesCodeData); 96459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta codeBuf.put(sourceCodeData); 96559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta codeBuf.flip(); 96659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 96759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glShaderSource(id, codeBuf); 96859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glCompileShader(id); 96959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 97059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetShader(id, GL_COMPILE_STATUS, intBuf1); 97159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 97259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean compiledOK = intBuf1.get(0) == GL_TRUE; 97359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String infoLog = null; 97459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 97559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (VALIDATE_SHADER || !compiledOK) { 97659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // even if compile succeeded, check 97759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // log for warnings 97859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetShader(id, GL_INFO_LOG_LENGTH, intBuf1); 97959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int length = intBuf1.get(0); 98059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (length > 3) { 98159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // get infos 98259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ByteBuffer logBuf = BufferUtils.createByteBuffer(length); 98359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetShaderInfoLog(id, null, logBuf); 98459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte[] logBytes = new byte[length]; 98559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logBuf.get(logBytes, 0, length); 98659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // convert to string, etc 98759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta infoLog = new String(logBytes); 98859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 98959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 99059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 99159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (compiledOK) { 99259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (infoLog != null) { 99359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "{0} compile success\n{1}", 99459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta new Object[]{source.getName(), infoLog}); 99559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 99659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINE, "{0} compile success", source.getName()); 99759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 99859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 99959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "Bad compile of:\n{0}{1}", 100059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta new Object[]{source.getDefines(), source.getSource()}); 100159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (infoLog != null) { 100259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("compile error in:" + source + " error:" + infoLog); 100359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 100459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("compile error in:" + source + " error: <not provided>"); 100559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 100659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 100759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 100859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta source.clearUpdateNeeded(); 100959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // only usable if compiled 101059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta source.setUsable(compiledOK); 101159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!compiledOK) { 101259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // make sure to dispose id cause all program's 101359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // shaders will be cleared later. 101459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDeleteShader(id); 101559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 101659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // register for cleanup since the ID is usable 101759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: From now on cleanup is handled 101859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // by the parent shader object so no need 101959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // to register. 102059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //objManager.registerForCleanup(source); 102159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 102259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 102359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 102459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateShaderData(Shader shader) { 102559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = shader.getId(); 102659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean needRegister = false; 102759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id == -1) { 102859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create program 102959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta id = glCreateProgram(); 103059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id == 0) { 103159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("Invalid ID (" + id + ") received when trying to create shader program."); 103259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 103359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 103459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shader.setId(id); 103559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta needRegister = true; 103659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 103759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 103859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (ShaderSource source : shader.getSources()) { 103959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (source.isUpdateNeeded()) { 104059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateShaderSourceData(source, shader.getLanguage()); 104159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // shader has been compiled here 104259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 104359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 104459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!source.isUsable()) { 104559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // it's useless.. just forget about everything.. 104659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shader.setUsable(false); 104759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shader.clearUpdateNeeded(); 104859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 104959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 105059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glAttachShader(id, source.getId()); 105159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 105259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 105359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (caps.contains(Caps.OpenGL30)) { 105459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Check if GLSL version is 1.5 for shader 105559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta GL30.glBindFragDataLocation(id, 0, "outFragColor"); 105659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 105759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 105859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // link shaders to program 105959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glLinkProgram(id); 106059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetProgram(id, GL_LINK_STATUS, intBuf1); 106159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean linkOK = intBuf1.get(0) == GL_TRUE; 106259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String infoLog = null; 106359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 106459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (VALIDATE_SHADER || !linkOK) { 106559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetProgram(id, GL_INFO_LOG_LENGTH, intBuf1); 106659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int length = intBuf1.get(0); 106759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (length > 3) { 106859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // get infos 106959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ByteBuffer logBuf = BufferUtils.createByteBuffer(length); 107059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetProgramInfoLog(id, null, logBuf); 107159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 107259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // convert to string, etc 107359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte[] logBytes = new byte[length]; 107459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logBuf.get(logBytes, 0, length); 107559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta infoLog = new String(logBytes); 107659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 107759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 107859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 107959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (linkOK) { 108059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (infoLog != null) { 108159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "shader link success. \n{0}", infoLog); 108259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 108359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.fine("shader link success"); 108459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 108559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 108659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (infoLog != null) { 108759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog); 108859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 108959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>"); 109059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 109159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 109259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 109359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shader.clearUpdateNeeded(); 109459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!linkOK) { 109559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // failure.. forget about everything 109659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shader.resetSources(); 109759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shader.setUsable(false); 109859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta deleteShader(shader); 109959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 110059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shader.setUsable(true); 110159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (needRegister) { 110259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.registerForCleanup(shader); 110359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onNewShader(); 110459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 110559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // OpenGL spec: uniform locations may change after re-link 110659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta resetUniformLocations(shader); 110759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 110859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 110959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 111059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 111159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setShader(Shader shader) { 111259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (shader == null) { 111359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("shader cannot be null"); 111459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (context.boundShaderProgram > 0) { 111559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// glUseProgram(0); 111659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// statistics.onShaderUse(null, true); 111759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// context.boundShaderProgram = 0; 111859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// boundShader = null; 111959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 112059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 112159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (shader.isUpdateNeeded()) { 112259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateShaderData(shader); 112359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 112459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 112559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: might want to check if any of the 112659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // sources need an update? 112759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 112859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!shader.isUsable()) { 112959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 113059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 113159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 113259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert shader.getId() > 0; 113359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 113459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateShaderUniforms(shader); 113559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bindProgram(shader); 113659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 113759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 113859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 113959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void deleteShaderSource(ShaderSource source) { 114059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (source.getId() < 0) { 114159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.warning("Shader source is not uploaded to GPU, cannot delete."); 114259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 114359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 114459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta source.setUsable(false); 114559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta source.clearUpdateNeeded(); 114659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDeleteShader(source.getId()); 114759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta source.resetObject(); 114859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 114959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 115059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void deleteShader(Shader shader) { 115159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (shader.getId() == -1) { 115259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.warning("Shader is not uploaded to GPU, cannot delete."); 115359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 115459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 115559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 115659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (ShaderSource source : shader.getSources()) { 115759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (source.getId() != -1) { 115859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDetachShader(shader.getId(), source.getId()); 115959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta deleteShaderSource(source); 116059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 116159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 116259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 116359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // kill all references so sources can be collected 116459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // if needed. 116559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shader.resetSources(); 116659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDeleteProgram(shader.getId()); 116759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 116859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onDeleteShader(); 116959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 117059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 117159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /*********************************************************************\ 117259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta |* Framebuffers *| 117359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta \*********************************************************************/ 117459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { 117559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta copyFrameBuffer(src, dst, true); 117659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 117759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 117859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) { 117959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) { 118059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int srcW = 0; 118159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int srcH = 0; 118259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int dstW = 0; 118359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int dstH = 0; 118459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int prevFBO = context.boundFBO; 118559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 118659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src != null && src.isUpdateNeeded()) { 118759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFrameBuffer(src); 118859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 118959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 119059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dst != null && dst.isUpdateNeeded()) { 119159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFrameBuffer(dst); 119259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 119359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 119459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src == null) { 119559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); 119659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// srcW = viewWidth; 119759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// srcH = viewHeight; 119859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 119959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src.getId()); 120059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta srcW = src.getWidth(); 120159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta srcH = src.getHeight(); 120259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 120359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dst == null) { 120459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); 120559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// dstW = viewWidth; 120659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// dstH = viewHeight; 120759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 120859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst.getId()); 120959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dstW = dst.getWidth(); 121059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dstH = dst.getHeight(); 121159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 121259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int mask = GL_COLOR_BUFFER_BIT; 121359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (copyDepth) { 121459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mask |= GL_DEPTH_BUFFER_BIT; 121559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 121659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBlitFramebufferEXT(0, 0, srcW, srcH, 121759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 0, 0, dstW, dstH, mask, 121859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta GL_NEAREST); 121959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 122059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 122159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO); 122259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 122359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkFrameBufferError(); 122459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (IllegalStateException ex) { 122559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.SEVERE, "Source FBO:\n{0}", src); 122659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst); 122759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw ex; 122859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 122959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 123059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("EXT_framebuffer_blit required."); 123159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // TODO: support non-blit copies? 123259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 123359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 123459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 123559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private String getTargetBufferName(int buffer){ 123659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (buffer){ 123759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_NONE: return "NONE"; 123859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRONT: return "GL_FRONT"; 123959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_BACK: return "GL_BACK"; 124059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 124159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if ( buffer >= GL_COLOR_ATTACHMENT0_EXT 124259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta && buffer <= GL_COLOR_ATTACHMENT15_EXT){ 124359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return "GL_COLOR_ATTACHMENT" + 124459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta (buffer - GL_COLOR_ATTACHMENT0_EXT); 124559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 124659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return "UNKNOWN? " + buffer; 124759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 124859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 124959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 125059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 125159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name){ 125259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("== Renderbuffer " + name + " =="); 125359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("RB ID: " + rb.getId()); 125459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Is proper? " + glIsRenderbufferEXT(rb.getId())); 125559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 125659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int attachment = convertAttachmentSlot(rb.getSlot()); 125759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 125859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int type = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT, 125959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attachment, 126059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT); 126159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 126259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int rbName = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT, 126359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attachment, 126459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT); 126559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 126659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (type){ 126759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_NONE: 126859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Type: None"); 126959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; // note: return from method as other queries will be invalid 127059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_TEXTURE: 127159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Type: Texture"); 127259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 127359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_RENDERBUFFER_EXT: 127459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Type: Buffer"); 127559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("RB ID: " + rbName); 127659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 127759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 127859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 127959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 128059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 128159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 128259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 128359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void printRealFrameBufferInfo(FrameBuffer fb) { 128459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean doubleBuffer = glGetBoolean(GL_DOUBLEBUFFER); 128559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String drawBuf = getTargetBufferName(glGetInteger(GL_DRAW_BUFFER)); 128659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER)); 128759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 128859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int fbId = fb.getId(); 128959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int curDrawBinding = glGetInteger(ARBFramebufferObject.GL_DRAW_FRAMEBUFFER_BINDING); 129059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING); 129159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 129259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("=== OpenGL FBO State ==="); 129359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Context doublebuffered? " + doubleBuffer); 129459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("FBO ID: " + fbId); 129559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Is proper? " + glIsFramebufferEXT(fbId)); 129659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Is bound to draw? " + (fbId == curDrawBinding)); 129759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Is bound to read? " + (fbId == curReadBinding)); 129859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Draw buffer: " + drawBuf); 129959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("Read buffer: " + readBuf); 130059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 130159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundFBO != fbId){ 130259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbId); 130359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundFBO = fbId; 130459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 130559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 130659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getDepthBuffer() != null){ 130759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth"); 130859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 130959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < fb.getNumColorBuffers(); i++){ 131059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i); 131159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 131259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 131359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 131459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void checkFrameBufferError() { 131559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 131659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (status) { 131759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_COMPLETE_EXT: 131859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 131959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_UNSUPPORTED_EXT: 132059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //Choose different formats 132159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Framebuffer object format is " 132259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "unsupported by the video hardware."); 132359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: 132459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Framebuffer has erronous attachment."); 132559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: 132659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Framebuffer doesn't have any renderbuffers attached."); 132759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: 132859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Framebuffer attachments must have same dimensions."); 132959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: 133059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Framebuffer attachments must have same formats."); 133159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: 133259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Incomplete draw buffer."); 133359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: 133459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Incomplete read buffer."); 133559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: 133659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Incomplete multisample buffer."); 133759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 133859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //Programming error; will fail on all hardware 133959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Some video driver error " 134059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "or programming error occured. " 134159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "Framebuffer object status is invalid. "); 134259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 134359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 134459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 134559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) { 134659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = rb.getId(); 134759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id == -1) { 134859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGenRenderbuffersEXT(intBuf1); 134959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta id = intBuf1.get(0); 135059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rb.setId(id); 135159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 135259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 135359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundRB != id) { 135459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id); 135559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundRB = id; 135659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 135759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 135859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) { 135959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("Resolution " + fb.getWidth() 136059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + ":" + fb.getHeight() + " is not supported."); 136159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 136259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 136359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureUtil.checkFormatSupported(rb.getFormat()); 136459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 136559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getSamples() > 1 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample) { 136659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int samples = fb.getSamples(); 136759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (maxFBOSamples < samples) { 136859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta samples = maxFBOSamples; 136959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 137059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 137159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta samples, 137259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureUtil.convertTextureFormat(rb.getFormat()), 137359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.getWidth(), 137459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.getHeight()); 137559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 137659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, 137759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureUtil.convertTextureFormat(rb.getFormat()), 137859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.getWidth(), 137959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.getHeight()); 138059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 138159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 138259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 138359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertAttachmentSlot(int attachmentSlot) { 138459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // can also add support for stencil here 138559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (attachmentSlot == -100) { 138659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_DEPTH_ATTACHMENT_EXT; 138759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (attachmentSlot < 0 || attachmentSlot >= 16) { 138859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot); 138959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 139059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 139159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_COLOR_ATTACHMENT0_EXT + attachmentSlot; 139259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 139359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 139459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) { 139559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Texture tex = rb.getTexture(); 139659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Image image = tex.getImage(); 139759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (image.isUpdateNeeded()) { 139859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels(), 0); 139959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 140059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: For depth textures, sets nearest/no-mips mode 140159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Required to fix "framebuffer unsupported" 140259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // for old NVIDIA drivers! 140359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setupTextureParams(tex); 140459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 140559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 140659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 140759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertAttachmentSlot(rb.getSlot()), 140859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertTextureType(tex.getType(), image.getMultiSamples()), 140959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta image.getId(), 141059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 0); 141159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 141259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 141359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) { 141459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean needAttach; 141559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (rb.getTexture() == null) { 141659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // if it hasn't been created yet, then attach is required. 141759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta needAttach = rb.getId() == -1; 141859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateRenderBuffer(fb, rb); 141959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 142059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta needAttach = false; 142159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateRenderTexture(fb, rb); 142259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 142359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (needAttach) { 142459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 142559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertAttachmentSlot(rb.getSlot()), 142659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta GL_RENDERBUFFER_EXT, 142759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rb.getId()); 142859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 142959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 143059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 143159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateFrameBuffer(FrameBuffer fb) { 143259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = fb.getId(); 143359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id == -1) { 143459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create FBO 143559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGenFramebuffersEXT(intBuf1); 143659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta id = intBuf1.get(0); 143759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.setId(id); 143859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.registerForCleanup(fb); 143959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 144059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onNewFrameBuffer(); 144159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 144259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 144359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundFBO != id) { 144459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); 144559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0 144659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundDrawBuf = 0; 144759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundFBO = id; 144859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 144959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 145059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer(); 145159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (depthBuf != null) { 145259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFrameBufferAttachment(fb, depthBuf); 145359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 145459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 145559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < fb.getNumColorBuffers(); i++) { 145659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i); 145759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFrameBufferAttachment(fb, colorBuf); 145859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 145959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 146059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.clearUpdateNeeded(); 146159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 146259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 146359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Vector2f[] getFrameBufferSamplePositions(FrameBuffer fb) { 146459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getSamples() <= 1) { 146559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("Framebuffer must be multisampled"); 146659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 146759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 146859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setFrameBuffer(fb); 146959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 147059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector2f[] samplePositions = new Vector2f[fb.getSamples()]; 147159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FloatBuffer samplePos = BufferUtils.createFloatBuffer(2); 147259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < samplePositions.length; i++) { 147359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGetMultisample(GL_SAMPLE_POSITION, i, samplePos); 147459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta samplePos.clear(); 147559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta samplePositions[i] = new Vector2f(samplePos.get(0) - 0.5f, 147659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta samplePos.get(1) - 0.5f); 147759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 147859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return samplePositions; 147959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 148059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 148159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setMainFrameBufferOverride(FrameBuffer fb){ 148259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mainFbOverride = fb; 148359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 148459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 148559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setFrameBuffer(FrameBuffer fb) { 148659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb == null && mainFbOverride != null){ 148759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb = mainFbOverride; 148859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 148959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 149059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (lastFb == fb) { 149159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb == null || !fb.isUpdateNeeded()){ 149259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 149359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 149459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 149559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 149659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // generate mipmaps for last FB if needed 149759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (lastFb != null) { 149859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < lastFb.getNumColorBuffers(); i++) { 149959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta RenderBuffer rb = lastFb.getColorBuffer(i); 150059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Texture tex = rb.getTexture(); 150159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tex != null 150259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta && tex.getMinFilter().usesMipMapLevels()) { 150359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setTexture(0, rb.getTexture()); 150459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 150559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples()); 150659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(textureType); 150759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGenerateMipmapEXT(textureType); 150859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(textureType); 150959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 151059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 151159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 151259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 151359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb == null) { 151459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // unbind any fbos 151559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundFBO != 0) { 151659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 151759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onFrameBufferUse(null, true); 151859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 151959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundFBO = 0; 152059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 152159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // select back buffer 152259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundDrawBuf != -1) { 152359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDrawBuffer(initialDrawBuf); 152459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundDrawBuf = -1; 152559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 152659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundReadBuf != -1) { 152759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glReadBuffer(initialReadBuf); 152859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundReadBuf = -1; 152959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 153059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 153159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta lastFb = null; 153259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 153359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null){ 153459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("The framebuffer: " + fb + 153559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "\nDoesn't have any color/depth buffers"); 153659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 153759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 153859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.isUpdateNeeded()) { 153959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFrameBuffer(fb); 154059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 154159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 154259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundFBO != fb.getId()) { 154359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb.getId()); 154459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onFrameBufferUse(fb, true); 154559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 154659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // update viewport to reflect framebuffer's resolution 154759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setViewPort(0, 0, fb.getWidth(), fb.getHeight()); 154859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 154959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundFBO = fb.getId(); 155059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 155159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onFrameBufferUse(fb, false); 155259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 155359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getNumColorBuffers() == 0) { 155459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // make sure to select NONE as draw buf 155559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // no color buffer attached. select NONE 155659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundDrawBuf != -2) { 155759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDrawBuffer(GL_NONE); 155859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundDrawBuf = -2; 155959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 156059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundReadBuf != -2) { 156159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glReadBuffer(GL_NONE); 156259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundReadBuf = -2; 156359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 156459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 156559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.isMultiTarget()) { 156659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getNumColorBuffers() > maxMRTFBOAttachs) { 156759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("Framebuffer has more" 156859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + " targets than are supported" 156959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + " on the system!"); 157059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 157159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 157259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) { 157359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf16.clear(); 157459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < fb.getNumColorBuffers(); i++) { 157559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf16.put(GL_COLOR_ATTACHMENT0_EXT + i); 157659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 157759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 157859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf16.flip(); 157959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDrawBuffers(intBuf16); 158059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundDrawBuf = 100 + fb.getNumColorBuffers(); 158159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 158259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 158359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex()); 158459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // select this draw buffer 158559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundDrawBuf != rb.getSlot()) { 158659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot()); 158759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundDrawBuf = rb.getSlot(); 158859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 158959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 159059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 159159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 159259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert fb.getId() >= 0; 159359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert context.boundFBO == fb.getId(); 159459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 159559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta lastFb = fb; 159659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 159759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 159859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkFrameBufferError(); 159959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (IllegalStateException ex) { 160059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb); 160159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta printRealFrameBufferInfo(fb); 160259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw ex; 160359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 160459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 160559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 160659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 160759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) { 160859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb != null) { 160959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta RenderBuffer rb = fb.getColorBuffer(); 161059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (rb == null) { 161159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("Specified framebuffer" 161259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + " does not have a colorbuffer"); 161359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 161459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 161559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setFrameBuffer(fb); 161659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundReadBuf != rb.getSlot()) { 161759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot()); 161859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundReadBuf = rb.getSlot(); 161959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 162059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 162159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setFrameBuffer(null); 162259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 162359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 162459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glReadPixels(vpX, vpY, vpW, vpH, /*GL_RGBA*/ GL_BGRA, GL_UNSIGNED_BYTE, byteBuf); 162559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 162659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 162759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) { 162859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf1.put(0, rb.getId()); 162959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDeleteRenderbuffersEXT(intBuf1); 163059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 163159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 163259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void deleteFrameBuffer(FrameBuffer fb) { 163359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getId() != -1) { 163459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundFBO == fb.getId()) { 163559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 163659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundFBO = 0; 163759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 163859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 163959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getDepthBuffer() != null) { 164059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta deleteRenderBuffer(fb, fb.getDepthBuffer()); 164159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 164259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fb.getColorBuffer() != null) { 164359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta deleteRenderBuffer(fb, fb.getColorBuffer()); 164459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 164559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 164659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf1.put(0, fb.getId()); 164759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDeleteFramebuffersEXT(intBuf1); 164859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.resetObject(); 164959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 165059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onDeleteFrameBuffer(); 165159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 165259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 165359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 165459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /*********************************************************************\ 165559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta |* Textures *| 165659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta \*********************************************************************/ 165759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertTextureType(Texture.Type type, int samples) { 165859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (type) { 165959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case TwoDimensional: 166059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (samples > 1) { 166159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return ARBTextureMultisample.GL_TEXTURE_2D_MULTISAMPLE; 166259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 166359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_TEXTURE_2D; 166459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 166559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case TwoDimensionalArray: 166659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (samples > 1) { 166759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return ARBTextureMultisample.GL_TEXTURE_2D_MULTISAMPLE_ARRAY; 166859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 166959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT; 167059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 167159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case ThreeDimensional: 167259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_TEXTURE_3D; 167359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case CubeMap: 167459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_TEXTURE_CUBE_MAP; 167559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 167659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown texture type: " + type); 167759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 167859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 167959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 168059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertMagFilter(Texture.MagFilter filter) { 168159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (filter) { 168259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Bilinear: 168359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LINEAR; 168459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Nearest: 168559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_NEAREST; 168659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 168759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown mag filter: " + filter); 168859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 168959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 169059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 169159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertMinFilter(Texture.MinFilter filter) { 169259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (filter) { 169359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Trilinear: 169459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LINEAR_MIPMAP_LINEAR; 169559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case BilinearNearestMipMap: 169659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LINEAR_MIPMAP_NEAREST; 169759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case NearestLinearMipMap: 169859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_NEAREST_MIPMAP_LINEAR; 169959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case NearestNearestMipMap: 170059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_NEAREST_MIPMAP_NEAREST; 170159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case BilinearNoMipMaps: 170259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LINEAR; 170359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case NearestNoMipMaps: 170459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_NEAREST; 170559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 170659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown min filter: " + filter); 170759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 170859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 170959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 171059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertWrapMode(Texture.WrapMode mode) { 171159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (mode) { 171259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case BorderClamp: 171359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_CLAMP_TO_BORDER; 171459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Clamp: 171559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_CLAMP; 171659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case EdgeClamp: 171759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_CLAMP_TO_EDGE; 171859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Repeat: 171959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_REPEAT; 172059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case MirroredRepeat: 172159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_MIRRORED_REPEAT; 172259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 172359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown wrap mode: " + mode); 172459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 172559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 172659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 172759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @SuppressWarnings("fallthrough") 172859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void setupTextureParams(Texture tex) { 172959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Image image = tex.getImage(); 173059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1); 173159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 173259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // filter things 173359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int minFilter = convertMinFilter(tex.getMinFilter()); 173459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int magFilter = convertMagFilter(tex.getMagFilter()); 173559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilter); 173659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilter); 173759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 173859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tex.getAnisotropicFilter() > 1) { 173959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic) { 174059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameterf(target, 174159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, 174259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tex.getAnisotropicFilter()); 174359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 174459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 174559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 174659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.pointSprite) { 174759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; // Attempt to fix glTexParameter crash for some ATI GPUs 174859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 174959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // repeat modes 175059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (tex.getType()) { 175159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case ThreeDimensional: 175259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case CubeMap: // cubemaps use 3D coords 175359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R))); 175459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case TwoDimensional: 175559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case TwoDimensionalArray: 175659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T))); 175759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // fall down here is intentional.. 175859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case OneDimensional: 175959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S))); 176059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 176159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 176259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown texture type: " + tex.getType()); 176359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 176459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 176559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // R to Texture compare mode 176659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) { 176759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); 176859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); 176959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) { 177059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_GEQUAL); 177159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 177259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); 177359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 177459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 177559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 177659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 177759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateTexImageData(Image img, Texture.Type type, boolean mips, int unit) { 177859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int texId = img.getId(); 177959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (texId == -1) { 178059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create texture 178159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGenTextures(intBuf1); 178259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta texId = intBuf1.get(0); 178359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta img.setId(texId); 178459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.registerForCleanup(img); 178559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 178659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onNewTexture(); 178759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 178859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 178959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // bind texture 179059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int target = convertTextureType(type, img.getMultiSamples()); 179159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextureUnit != unit) { 179259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glActiveTexture(GL_TEXTURE0 + unit); 179359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundTextureUnit = unit; 179459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 179559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextures[unit] != img) { 179659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindTexture(target, texId); 179759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundTextures[unit] = img; 179859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 179959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onTextureUse(img, true); 180059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 180159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 180259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!img.hasMipmaps() && mips) { 180359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // No pregenerated mips available, 180459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // generate from base level if required 180559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!GLContext.getCapabilities().OpenGL30) { 180659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE); 180759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 180859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 180959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0 ); 181059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (img.getMipMapSizes() != null) { 181159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, img.getMipMapSizes().length); 181259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 181359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 181459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 181559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int imageSamples = img.getMultiSamples(); 181659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (imageSamples > 1) { 181759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (img.getFormat().isDepthFormat()) { 181859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta img.setMultiSamples(Math.min(maxDepthTexSamples, imageSamples)); 181959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 182059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta img.setMultiSamples(Math.min(maxColorTexSamples, imageSamples)); 182159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 182259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 182359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 182459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT. 182559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) { 182659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (img.getWidth() != 0 && img.getHeight() != 0) { 182759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!FastMath.isPowerOfTwo(img.getWidth()) 182859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || !FastMath.isPowerOfTwo(img.getHeight())) { 182959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (img.getData(0) == null) { 183059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware"); 183159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 183259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta MipMapGenerator.resizeToPowerOf2(img); 183359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 183459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 183559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 183659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 183759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 183859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Check if graphics card doesn't support multisample textures 183959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!GLContext.getCapabilities().GL_ARB_texture_multisample) { 184059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (img.getMultiSamples() > 1) { 184159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RendererException("Multisample textures not supported by graphics hardware"); 184259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 184359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 184459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 184559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (target == GL_TEXTURE_CUBE_MAP) { 184659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<ByteBuffer> data = img.getData(); 184759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (data.size() != 6) { 184859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "Invalid texture: {0}\n" 184959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "Cubemap textures must contain 6 data units.", img); 185059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 185159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 185259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < 6; i++) { 185359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureUtil.uploadTexture(img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc); 185459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 185559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT) { 185659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<ByteBuffer> data = img.getData(); 185759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // -1 index specifies prepare data for 2D Array 185859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureUtil.uploadTexture(img, target, -1, 0, tdc); 185959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < data.size(); i++) { 186059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // upload each slice of 2D array in turn 186159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // this time with the appropriate index 186259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureUtil.uploadTexture(img, target, i, 0, tdc); 186359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 186459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 186559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureUtil.uploadTexture(img, target, 0, 0, tdc); 186659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 186759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 186859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (img.getMultiSamples() != imageSamples) { 186959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta img.setMultiSamples(imageSamples); 187059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 187159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 187259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (GLContext.getCapabilities().OpenGL30) { 187359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!img.hasMipmaps() && mips && img.getData() != null) { 187459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // XXX: Required for ATI 187559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnable(target); 187659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGenerateMipmapEXT(target); 187759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(target); 187859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 187959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 188059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 188159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta img.clearUpdateNeeded(); 188259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 188359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 188459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setTexture(int unit, Texture tex) { 188559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Image image = tex.getImage(); 188659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (image.isUpdateNeeded()) { 188759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels(), unit); 188859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 188959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 189059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int texId = image.getId(); 189159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert texId != -1; 189259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 189359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Image[] textures = context.boundTextures; 189459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 189559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int type = convertTextureType(tex.getType(), image.getMultiSamples()); 189659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (!context.textureIndexList.moveToNew(unit)) { 189759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (context.boundTextureUnit != unit){ 189859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// glActiveTexture(GL_TEXTURE0 + unit); 189959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// context.boundTextureUnit = unit; 190059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 190159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// glEnable(type); 190259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 190359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 190459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextureUnit != unit) { 190559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glActiveTexture(GL_TEXTURE0 + unit); 190659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundTextureUnit = unit; 190759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 190859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (textures[unit] != image) { 190959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindTexture(type, texId); 191059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta textures[unit] = image; 191159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 191259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onTextureUse(image, true); 191359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 191459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onTextureUse(image, false); 191559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 191659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 191759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setupTextureParams(tex); 191859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 191959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 192059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void clearTextureUnits() { 192159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// IDList textureList = context.textureIndexList; 192259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// Image[] textures = context.boundTextures; 192359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// for (int i = 0; i < textureList.oldLen; i++) { 192459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// int idx = textureList.oldList[i]; 192559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (context.boundTextureUnit != idx){ 192659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// glActiveTexture(GL_TEXTURE0 + idx); 192759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// context.boundTextureUnit = idx; 192859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 192959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// glDisable(convertTextureType(textures[idx].getType())); 193059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// textures[idx] = null; 193159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 193259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// context.textureIndexList.copyNewToOld(); 193359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 193459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 193559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void deleteImage(Image image) { 193659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int texId = image.getId(); 193759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (texId != -1) { 193859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf1.put(0, texId); 193959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf1.position(0).limit(1); 194059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDeleteTextures(intBuf1); 194159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta image.resetObject(); 194259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 194359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onDeleteTexture(); 194459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 194559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 194659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 194759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /*********************************************************************\ 194859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta |* Vertex Buffers and Attributes *| 194959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta \*********************************************************************/ 195059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertUsage(Usage usage) { 195159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (usage) { 195259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Static: 195359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_STATIC_DRAW; 195459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Dynamic: 195559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_DYNAMIC_DRAW; 195659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Stream: 195759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_STREAM_DRAW; 195859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 195959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown usage type."); 196059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 196159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 196259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 196359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertFormat(Format format) { 196459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (format) { 196559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Byte: 196659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_BYTE; 196759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedByte: 196859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_UNSIGNED_BYTE; 196959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Short: 197059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_SHORT; 197159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedShort: 197259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_UNSIGNED_SHORT; 197359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Int: 197459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_INT; 197559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedInt: 197659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_UNSIGNED_INT; 197759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Half: 197859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return NVHalfFloat.GL_HALF_FLOAT_NV; 197959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// return ARBHalfFloatVertex.GL_HALF_FLOAT; 198059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Float: 198159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_FLOAT; 198259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Double: 198359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_DOUBLE; 198459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 198559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown buffer format."); 198659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 198759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 198859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 198959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 199059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateBufferData(VertexBuffer vb) { 199159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int bufId = vb.getId(); 199259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean created = false; 199359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (bufId == -1) { 199459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create buffer 199559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glGenBuffers(intBuf1); 199659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bufId = intBuf1.get(0); 199759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vb.setId(bufId); 199859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.registerForCleanup(vb); 199959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 200059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onNewVertexBuffer(); 200159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 200259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta created = true; 200359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 200459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 200559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // bind buffer 200659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int target; 200759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vb.getBufferType() == VertexBuffer.Type.Index) { 200859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta target = GL_ELEMENT_ARRAY_BUFFER; 200959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundElementArrayVBO != bufId) { 201059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindBuffer(target, bufId); 201159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundElementArrayVBO = bufId; 201259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onVertexBufferUse(vb, true); 201359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 201459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onVertexBufferUse(vb, false); 201559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 201659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 201759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta target = GL_ARRAY_BUFFER; 201859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundArrayVBO != bufId) { 201959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindBuffer(target, bufId); 202059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundArrayVBO = bufId; 202159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onVertexBufferUse(vb, true); 202259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 202359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onVertexBufferUse(vb, false); 202459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 202559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 202659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 202759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int usage = convertUsage(vb.getUsage()); 202859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vb.getData().rewind(); 202959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 203059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (created || vb.hasDataSizeChanged()) { 203159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // upload data based on format 203259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (vb.getFormat()) { 203359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Byte: 203459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedByte: 203559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferData(target, (ByteBuffer) vb.getData(), usage); 203659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 203759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // case Half: 203859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Short: 203959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedShort: 204059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferData(target, (ShortBuffer) vb.getData(), usage); 204159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 204259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Int: 204359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedInt: 204459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferData(target, (IntBuffer) vb.getData(), usage); 204559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 204659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Float: 204759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferData(target, (FloatBuffer) vb.getData(), usage); 204859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 204959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Double: 205059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferData(target, (DoubleBuffer) vb.getData(), usage); 205159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 205259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 205359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown buffer format."); 205459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 205559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 205659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (vb.getFormat()) { 205759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Byte: 205859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedByte: 205959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferSubData(target, 0, (ByteBuffer) vb.getData()); 206059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 206159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Short: 206259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedShort: 206359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferSubData(target, 0, (ShortBuffer) vb.getData()); 206459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 206559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Int: 206659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case UnsignedInt: 206759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferSubData(target, 0, (IntBuffer) vb.getData()); 206859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 206959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Float: 207059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferSubData(target, 0, (FloatBuffer) vb.getData()); 207159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 207259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Double: 207359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBufferSubData(target, 0, (DoubleBuffer) vb.getData()); 207459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 207559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 207659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unknown buffer format."); 207759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 207859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 207959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// }else{ 208059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (created || vb.hasDataSizeChanged()){ 208159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// glBufferData(target, vb.getData().capacity() * vb.getFormat().getComponentSize(), usage); 208259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 208359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// 208459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// ByteBuffer buf = glMapBuffer(target, 208559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// GL_WRITE_ONLY, 208659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// vb.getMappedData()); 208759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// 208859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (buf != vb.getMappedData()){ 208959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// buf = buf.order(ByteOrder.nativeOrder()); 209059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// vb.setMappedData(buf); 209159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 209259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// 209359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// buf.clear(); 209459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// 209559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// switch (vb.getFormat()){ 209659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case Byte: 209759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case UnsignedByte: 209859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// buf.put( (ByteBuffer) vb.getData() ); 209959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// break; 210059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case Short: 210159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case UnsignedShort: 210259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// buf.asShortBuffer().put( (ShortBuffer) vb.getData() ); 210359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// break; 210459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case Int: 210559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case UnsignedInt: 210659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// buf.asIntBuffer().put( (IntBuffer) vb.getData() ); 210759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// break; 210859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case Float: 210959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// buf.asFloatBuffer().put( (FloatBuffer) vb.getData() ); 211059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// break; 211159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// case Double: 211259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// break; 211359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// default: 211459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// throw new RuntimeException("Unknown buffer format."); 211559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 211659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// 211759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// glUnmapBuffer(target); 211859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 211959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 212059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vb.clearUpdateNeeded(); 212159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 212259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 212359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void deleteBuffer(VertexBuffer vb) { 212459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int bufId = vb.getId(); 212559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (bufId != -1) { 212659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // delete buffer 212759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf1.put(0, bufId); 212859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta intBuf1.position(0).limit(1); 212959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDeleteBuffers(intBuf1); 213059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vb.resetObject(); 213159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 213259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onDeleteVertexBuffer(); 213359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 213459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 213559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 213659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void clearVertexAttribs() { 213759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta IDList attribList = context.attribIndexList; 213859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < attribList.oldLen; i++) { 213959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int idx = attribList.oldList[i]; 214059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisableVertexAttribArray(idx); 214159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundAttribs[idx] = null; 214259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 214359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.attribIndexList.copyNewToOld(); 214459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 214559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 214659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) { 214759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vb.getBufferType() == VertexBuffer.Type.Index) { 214859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib"); 214959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 215059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 215159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int programId = context.boundShaderProgram; 215259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (programId > 0) { 215359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Attribute attrib = boundShader.getAttribute(vb.getBufferType()); 215459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int loc = attrib.getLocation(); 215559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (loc == -1) { 215659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; // not defined 215759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 215859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (loc == -2) { 215959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.setLength(0); 216059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stringBuf.append("in").append(vb.getBufferType().name()).append('\0'); 216159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateNameBuffer(); 216259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta loc = glGetAttribLocation(programId, nameBuf); 216359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 216459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // not really the name of it in the shader (inPosition\0) but 216559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // the internal name of the enum (Position). 216659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (loc < 0) { 216759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attrib.setLocation(-1); 216859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; // not available in shader. 216959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 217059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attrib.setLocation(loc); 217159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 217259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 217359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 217459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vb.isUpdateNeeded() && idb == null) { 217559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateBufferData(vb); 217659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 217759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 217859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer[] attribs = context.boundAttribs; 217959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!context.attribIndexList.moveToNew(loc)) { 218059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glEnableVertexAttribArray(loc); 218159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //System.out.println("Enabled ATTRIB IDX: "+loc); 218259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 218359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (attribs[loc] != vb) { 218459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: Use id from interleaved buffer if specified 218559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int bufId = idb != null ? idb.getId() : vb.getId(); 218659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert bufId != -1; 218759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundArrayVBO != bufId) { 218859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindBuffer(GL_ARRAY_BUFFER, bufId); 218959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundArrayVBO = bufId; 219059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onVertexBufferUse(vb, true); 219159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 219259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onVertexBufferUse(vb, false); 219359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 219459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 219559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glVertexAttribPointer(loc, 219659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vb.getNumComponents(), 219759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertFormat(vb.getFormat()), 219859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vb.isNormalized(), 219959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vb.getStride(), 220059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vb.getOffset()); 220159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 220259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attribs[loc] = vb; 220359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 220459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 220559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Cannot render mesh without shader bound"); 220659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 220759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 220859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 220959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setVertexAttrib(VertexBuffer vb) { 221059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setVertexAttrib(vb, null); 221159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 221259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 221359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) { 221459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (count > 1) { 221559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ARBDrawInstanced.glDrawArraysInstancedARB(convertElementMode(mode), 0, 221659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertCount, count); 221759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 221859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDrawArrays(convertElementMode(mode), 0, vertCount); 221959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 222059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 222159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 222259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) { 222359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (indexBuf.getBufferType() != VertexBuffer.Type.Index) { 222459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("Only index buffers are allowed as triangle lists."); 222559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 222659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 222759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (indexBuf.isUpdateNeeded()) { 222859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateBufferData(indexBuf); 222959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 223059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 223159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int bufId = indexBuf.getId(); 223259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert bufId != -1; 223359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 223459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundElementArrayVBO != bufId) { 223559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufId); 223659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundElementArrayVBO = bufId; 223759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onVertexBufferUse(indexBuf, true); 223859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 223959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //statistics.onVertexBufferUse(indexBuf, true); 224059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 224159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 224259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int vertCount = mesh.getVertexCount(); 224359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing); 224459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 224559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh.getMode() == Mode.Hybrid) { 224659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int[] modeStart = mesh.getModeStart(); 224759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int[] elementLengths = mesh.getElementLengths(); 224859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 224959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int elMode = convertElementMode(Mode.Triangles); 225059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int fmt = convertFormat(indexBuf.getFormat()); 225159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int elSize = indexBuf.getFormat().getComponentSize(); 225259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int listStart = modeStart[0]; 225359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int stripStart = modeStart[1]; 225459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int fanStart = modeStart[2]; 225559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int curOffset = 0; 225659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < elementLengths.length; i++) { 225759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (i == stripStart) { 225859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta elMode = convertElementMode(Mode.TriangleStrip); 225959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (i == fanStart) { 226059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta elMode = convertElementMode(Mode.TriangleStrip); 226159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 226259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int elementLength = elementLengths[i]; 226359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 226459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (useInstancing) { 226559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ARBDrawInstanced.glDrawElementsInstancedARB(elMode, 226659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta elementLength, 226759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fmt, 226859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta curOffset, 226959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta count); 227059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 227159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDrawRangeElements(elMode, 227259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 0, 227359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertCount, 227459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta elementLength, 227559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fmt, 227659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta curOffset); 227759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 227859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 227959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta curOffset += elementLength * elSize; 228059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 228159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 228259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (useInstancing) { 228359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ARBDrawInstanced.glDrawElementsInstancedARB(convertElementMode(mesh.getMode()), 228459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBuf.getData().limit(), 228559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertFormat(indexBuf.getFormat()), 228659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 0, 228759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta count); 228859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 228959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDrawRangeElements(convertElementMode(mesh.getMode()), 229059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 0, 229159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertCount, 229259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBuf.getData().limit(), 229359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta convertFormat(indexBuf.getFormat()), 229459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 0); 229559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 229659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 229759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 229859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 229959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /*********************************************************************\ 230059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta |* Render Calls *| 230159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta \*********************************************************************/ 230259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int convertElementMode(Mesh.Mode mode) { 230359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (mode) { 230459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Points: 230559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_POINTS; 230659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Lines: 230759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LINES; 230859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case LineLoop: 230959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LINE_LOOP; 231059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case LineStrip: 231159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_LINE_STRIP; 231259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Triangles: 231359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_TRIANGLES; 231459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case TriangleFan: 231559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_TRIANGLE_FAN; 231659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case TriangleStrip: 231759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return GL_TRIANGLE_STRIP; 231859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 231959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unrecognized mesh mode: " + mode); 232059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 232159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 232259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 232359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateVertexArray(Mesh mesh) { 232459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = mesh.getId(); 232559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id == -1) { 232659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta IntBuffer temp = intBuf1; 232759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ARBVertexArrayObject.glGenVertexArrays(temp); 232859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta id = temp.get(0); 232959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setId(id); 233059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 233159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 233259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundVertexArray != id) { 233359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ARBVertexArrayObject.glBindVertexArray(id); 233459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundVertexArray = id; 233559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 233659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 233759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); 233859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (interleavedData != null && interleavedData.isUpdateNeeded()) { 233959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateBufferData(interleavedData); 234059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 234159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 234259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta IntMap<VertexBuffer> buffers = mesh.getBuffers(); 234359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Entry<VertexBuffer> entry : buffers) { 234459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer vb = entry.getValue(); 234559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 234659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vb.getBufferType() == Type.InterleavedData 234759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers 234859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || vb.getBufferType() == Type.Index) { 234959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta continue; 235059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 235159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 235259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vb.getStride() == 0) { 235359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // not interleaved 235459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setVertexAttrib(vb); 235559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 235659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // interleaved 235759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setVertexAttrib(vb, interleavedData); 235859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 235959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 236059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 236159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 236259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void renderMeshVertexArray(Mesh mesh, int lod, int count) { 236359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh.getId() == -1){ 236459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateVertexArray(mesh); 236559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 236659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // TODO: Check if it was updated 236759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 236859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 236959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundVertexArray != mesh.getId()) { 237059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ARBVertexArrayObject.glBindVertexArray(mesh.getId()); 237159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundVertexArray = mesh.getId(); 237259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 237359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 237459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// IntMap<VertexBuffer> buffers = mesh.getBuffers(); 237559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer indices = null; 237659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh.getNumLodLevels() > 0) { 237759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indices = mesh.getLodLevel(lod); 237859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 237959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indices = mesh.getBuffer(Type.Index); 238059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 238159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (indices != null) { 238259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta drawTriangleList(indices, mesh, count); 238359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 238459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount()); 238559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 238659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearVertexAttribs(); 238759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearTextureUnits(); 238859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 238959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 239059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void renderMeshDefault(Mesh mesh, int lod, int count) { 239159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer indices = null; 239259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 239359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); 239459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (interleavedData != null && interleavedData.isUpdateNeeded()) { 239559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateBufferData(interleavedData); 239659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 239759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 239859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// IntMap<VertexBuffer> buffers = mesh.getBuffers(); 239959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta SafeArrayList<VertexBuffer> buffersList = mesh.getBufferList(); 240059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 240159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh.getNumLodLevels() > 0) { 240259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indices = mesh.getLodLevel(lod); 240359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 240459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indices = mesh.getBuffer(Type.Index); 240559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 240659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 240759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// for (Entry<VertexBuffer> entry : buffers) { 240859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// VertexBuffer vb = entry.getValue(); 240959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (VertexBuffer vb : mesh.getBufferList().getArray()){ 241059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vb.getBufferType() == Type.InterleavedData 241159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers 241259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || vb.getBufferType() == Type.Index) { 241359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta continue; 241459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 241559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 241659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vb.getStride() == 0) { 241759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // not interleaved 241859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setVertexAttrib(vb); 241959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 242059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // interleaved 242159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setVertexAttrib(vb, interleavedData); 242259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 242359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 242459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 242559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (indices != null) { 242659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta drawTriangleList(indices, mesh, count); 242759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 242859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount()); 242959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 243059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearVertexAttribs(); 243159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearTextureUnits(); 243259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 243359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 243459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void renderMesh(Mesh mesh, int lod, int count) { 243559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh.getVertexCount() == 0) { 243659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 243759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 243859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 243959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.pointSprite && mesh.getMode() != Mode.Points){ 244059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // XXX: Hack, disable point sprite mode if mesh not in point mode 244159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextures[0] != null){ 244259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.boundTextureUnit != 0){ 244359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glActiveTexture(GL_TEXTURE0); 244459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.boundTextureUnit = 0; 244559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 244659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_POINT_SPRITE); 244759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); 244859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.pointSprite = false; 244959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 245059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 245159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 245259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.pointSize != mesh.getPointSize()) { 245359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glPointSize(mesh.getPointSize()); 245459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.pointSize = mesh.getPointSize(); 245559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 245659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (context.lineWidth != mesh.getLineWidth()) { 245759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta glLineWidth(mesh.getLineWidth()); 245859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta context.lineWidth = mesh.getLineWidth(); 245959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 246059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 246159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta statistics.onMeshDrawn(mesh, lod); 246259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (GLContext.getCapabilities().GL_ARB_vertex_array_object){ 246359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// renderMeshVertexArray(mesh, lod, count); 246459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// }else{ 246559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta renderMeshDefault(mesh, lod, count); 246659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 246759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 246859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 2469