|
@@ -1,1261 +0,0 @@
|
|
|
-/*
|
|
|
- * Copyright (c) 2009-2012 jMonkeyEngine
|
|
|
- * All rights reserved.
|
|
|
- *
|
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
|
- * modification, are permitted provided that the following conditions are
|
|
|
- * met:
|
|
|
- *
|
|
|
- * * Redistributions of source code must retain the above copyright
|
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
|
- *
|
|
|
- * * Redistributions in binary form must reproduce the above copyright
|
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
|
- * documentation and/or other materials provided with the distribution.
|
|
|
- *
|
|
|
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
|
- * may be used to endorse or promote products derived from this software
|
|
|
- * without specific prior written permission.
|
|
|
- *
|
|
|
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
|
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
- */
|
|
|
-package com.jme3.renderer.jogl;
|
|
|
-
|
|
|
-import java.nio.Buffer;
|
|
|
-import java.nio.ByteBuffer;
|
|
|
-import java.nio.FloatBuffer;
|
|
|
-import java.nio.IntBuffer;
|
|
|
-import java.nio.ShortBuffer;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.EnumSet;
|
|
|
-import java.util.logging.Level;
|
|
|
-import java.util.logging.Logger;
|
|
|
-
|
|
|
-import javax.media.opengl.GL;
|
|
|
-import javax.media.opengl.GL2;
|
|
|
-import javax.media.opengl.GL2ES1;
|
|
|
-import javax.media.opengl.GL2ES2;
|
|
|
-import javax.media.opengl.GL2GL3;
|
|
|
-import javax.media.opengl.GLContext;
|
|
|
-import javax.media.opengl.fixedfunc.GLLightingFunc;
|
|
|
-import javax.media.opengl.fixedfunc.GLMatrixFunc;
|
|
|
-import javax.media.opengl.fixedfunc.GLPointerFunc;
|
|
|
-
|
|
|
-import jme3tools.converters.MipMapGenerator;
|
|
|
-
|
|
|
-import com.jme3.light.DirectionalLight;
|
|
|
-import com.jme3.light.Light;
|
|
|
-import com.jme3.light.LightList;
|
|
|
-import com.jme3.light.PointLight;
|
|
|
-import com.jme3.light.SpotLight;
|
|
|
-import com.jme3.material.FixedFuncBinding;
|
|
|
-import com.jme3.material.RenderState;
|
|
|
-import com.jme3.math.ColorRGBA;
|
|
|
-import com.jme3.math.FastMath;
|
|
|
-import com.jme3.math.Matrix4f;
|
|
|
-import com.jme3.math.Vector3f;
|
|
|
-import com.jme3.renderer.Caps;
|
|
|
-import com.jme3.renderer.GL1Renderer;
|
|
|
-import com.jme3.renderer.RenderContext;
|
|
|
-import com.jme3.renderer.RendererException;
|
|
|
-import com.jme3.renderer.Statistics;
|
|
|
-import com.jme3.scene.Mesh;
|
|
|
-import com.jme3.scene.Mesh.Mode;
|
|
|
-import com.jme3.scene.VertexBuffer;
|
|
|
-import com.jme3.scene.VertexBuffer.Type;
|
|
|
-import com.jme3.scene.VertexBuffer.Usage;
|
|
|
-import com.jme3.shader.Shader;
|
|
|
-import com.jme3.shader.Shader.ShaderSource;
|
|
|
-import com.jme3.texture.FrameBuffer;
|
|
|
-import com.jme3.texture.Image;
|
|
|
-import com.jme3.texture.Texture;
|
|
|
-import com.jme3.texture.Texture.WrapAxis;
|
|
|
-import com.jme3.util.BufferUtils;
|
|
|
-import com.jme3.util.NativeObjectManager;
|
|
|
-
|
|
|
-public class JoglGL1Renderer implements GL1Renderer {
|
|
|
-
|
|
|
- private static final Logger logger = Logger.getLogger(JoglRenderer.class.getName());
|
|
|
- private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250);
|
|
|
- private final StringBuilder stringBuf = new StringBuilder(250);
|
|
|
- private final IntBuffer ib1 = BufferUtils.createIntBuffer(1);
|
|
|
- private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16);
|
|
|
- private final FloatBuffer fb16 = BufferUtils.createFloatBuffer(16);
|
|
|
- private final FloatBuffer fb4Null = BufferUtils.createFloatBuffer(4);
|
|
|
- private final RenderContext context = new RenderContext();
|
|
|
- private final NativeObjectManager objManager = new NativeObjectManager();
|
|
|
- private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
|
|
|
- private int maxTexSize;
|
|
|
- private int maxCubeTexSize;
|
|
|
- private int maxVertCount;
|
|
|
- private int maxTriCount;
|
|
|
- private int maxLights;
|
|
|
- private boolean gl12 = false;
|
|
|
- private final Statistics statistics = new Statistics();
|
|
|
- private int vpX, vpY, vpW, vpH;
|
|
|
- private int clipX, clipY, clipW, clipH;
|
|
|
-
|
|
|
- private Matrix4f worldMatrix = new Matrix4f();
|
|
|
- private Matrix4f viewMatrix = new Matrix4f();
|
|
|
-
|
|
|
- private ArrayList<Light> lightList = new ArrayList<Light>(8);
|
|
|
- private ColorRGBA materialAmbientColor = new ColorRGBA();
|
|
|
- private Vector3f tempVec = new Vector3f();
|
|
|
-
|
|
|
- protected void updateNameBuffer() {
|
|
|
- int len = stringBuf.length();
|
|
|
-
|
|
|
- nameBuf.position(0);
|
|
|
- nameBuf.limit(len);
|
|
|
- for (int i = 0; i < len; i++) {
|
|
|
- nameBuf.put((byte) stringBuf.charAt(i));
|
|
|
- }
|
|
|
-
|
|
|
- nameBuf.rewind();
|
|
|
- }
|
|
|
-
|
|
|
- public Statistics getStatistics() {
|
|
|
- return statistics;
|
|
|
- }
|
|
|
-
|
|
|
- public EnumSet<Caps> getCaps() {
|
|
|
- return caps;
|
|
|
- }
|
|
|
-
|
|
|
- public void initialize() {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (gl.isExtensionAvailable("GL_VERSION_1_2")){
|
|
|
- gl12 = true;
|
|
|
- }
|
|
|
-
|
|
|
- //workaround, always assume we support GLSL100
|
|
|
- //some cards just don't report this correctly
|
|
|
- caps.add(Caps.GLSL100);
|
|
|
-
|
|
|
- // Default values for certain GL state.
|
|
|
- gl.getGL2ES1().glShadeModel(GLLightingFunc.GL_SMOOTH);
|
|
|
- gl.getGL2().glColorMaterial(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_DIFFUSE);
|
|
|
- gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
|
|
|
-
|
|
|
- // Enable rescaling/normaling of normal vectors.
|
|
|
- // Fixes lighting issues with scaled models.
|
|
|
- if (gl12){
|
|
|
- gl.glEnable(GL2ES1.GL_RESCALE_NORMAL);
|
|
|
- }else{
|
|
|
- gl.glEnable(GLLightingFunc.GL_NORMALIZE);
|
|
|
- }
|
|
|
-
|
|
|
- if (gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two")) {
|
|
|
- caps.add(Caps.NonPowerOfTwoTextures);
|
|
|
- } else {
|
|
|
- logger.log(Level.WARNING, "Your graphics card does not "
|
|
|
- + "support non-power-of-2 textures. "
|
|
|
- + "Some features might not work.");
|
|
|
- }
|
|
|
-
|
|
|
- gl.glGetIntegerv(GL2ES1.GL_MAX_LIGHTS, ib1);
|
|
|
- maxLights = ib1.get(0);
|
|
|
-
|
|
|
- gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, ib1);
|
|
|
- maxTexSize = ib1.get(0);
|
|
|
- }
|
|
|
-
|
|
|
- public void invalidateState() {
|
|
|
- context.reset();
|
|
|
- }
|
|
|
-
|
|
|
- public void resetGLObjects() {
|
|
|
- logger.log(Level.FINE, "Reseting objects and invalidating state");
|
|
|
- objManager.resetObjects();
|
|
|
- statistics.clearMemory();
|
|
|
- invalidateState();
|
|
|
- }
|
|
|
-
|
|
|
- public void cleanup() {
|
|
|
- logger.log(Level.FINE, "Deleting objects and invalidating state");
|
|
|
- objManager.deleteAllObjects(this);
|
|
|
- statistics.clearMemory();
|
|
|
- invalidateState();
|
|
|
- }
|
|
|
-
|
|
|
- public void setDepthRange(float start, float end) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.getGL2ES2().glDepthRange(start, end);
|
|
|
- }
|
|
|
-
|
|
|
- public void clearBuffers(boolean color, boolean depth, boolean stencil) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- int bits = 0;
|
|
|
- if (color) {
|
|
|
- //See explanations of the depth below, we must enable color write to be able to clear the color buffer
|
|
|
- if (context.colorWriteEnabled == false) {
|
|
|
- gl.glColorMask(true, true, true, true);
|
|
|
- context.colorWriteEnabled = true;
|
|
|
- }
|
|
|
- bits = GL.GL_COLOR_BUFFER_BIT;
|
|
|
- }
|
|
|
- if (depth) {
|
|
|
-
|
|
|
- //glClear(GL_DEPTH_BUFFER_BIT) seems to not work when glDepthMask is false
|
|
|
- //here s some link on openl board
|
|
|
- //http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=257223
|
|
|
- //if depth clear is requested, we enable the depthMask
|
|
|
- if (context.depthWriteEnabled == false) {
|
|
|
- gl.glDepthMask(true);
|
|
|
- context.depthWriteEnabled = true;
|
|
|
- }
|
|
|
- bits |= GL.GL_DEPTH_BUFFER_BIT;
|
|
|
- }
|
|
|
- if (stencil) {
|
|
|
- bits |= GL.GL_STENCIL_BUFFER_BIT;
|
|
|
- }
|
|
|
- if (bits != 0) {
|
|
|
- gl.glClear(bits);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void setBackgroundColor(ColorRGBA color) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.glClearColor(color.r, color.g, color.b, color.a);
|
|
|
- }
|
|
|
-
|
|
|
- private void setMaterialColor(int type, ColorRGBA color, ColorRGBA defaultColor) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (color != null){
|
|
|
- fb16.put(color.r).put(color.g).put(color.b).put(color.a).flip();
|
|
|
- }else{
|
|
|
- fb16.put(defaultColor.r).put(defaultColor.g).put(defaultColor.b).put(defaultColor.a).flip();
|
|
|
- }
|
|
|
- gl.getGL2().glMaterialfv(GL.GL_FRONT_AND_BACK, type, fb16);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Applies fixed function bindings from the context to OpenGL
|
|
|
- */
|
|
|
- private void applyFixedFuncBindings(boolean forLighting){
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (forLighting) {
|
|
|
- gl.getGL2().glMaterialf(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_SHININESS, context.shininess);
|
|
|
- setMaterialColor(GLLightingFunc.GL_AMBIENT, context.ambient, ColorRGBA.DarkGray);
|
|
|
- setMaterialColor(GLLightingFunc.GL_DIFFUSE, context.diffuse, ColorRGBA.White);
|
|
|
- setMaterialColor(GLLightingFunc.GL_SPECULAR, context.specular, ColorRGBA.Black);
|
|
|
-
|
|
|
- if (context.useVertexColor) {
|
|
|
- gl.glEnable(GLLightingFunc.GL_COLOR_MATERIAL);
|
|
|
- } else {
|
|
|
- gl.glDisable(GLLightingFunc.GL_COLOR_MATERIAL);
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Ignore other values as they have no effect when
|
|
|
- // GL_LIGHTING is disabled.
|
|
|
- ColorRGBA color = context.color;
|
|
|
- if (color != null) {
|
|
|
- gl.getGL2().glColor4f(color.r, color.g, color.b, color.a);
|
|
|
- } else {
|
|
|
- gl.getGL2().glColor4f(1, 1, 1, 1);
|
|
|
- }
|
|
|
- }
|
|
|
- if (context.alphaTestFallOff > 0f) {
|
|
|
- gl.glEnable(GL2ES1.GL_ALPHA_TEST);
|
|
|
- gl.getGL2ES1().glAlphaFunc(GL.GL_GREATER, context.alphaTestFallOff);
|
|
|
- } else {
|
|
|
- gl.glDisable(GL2ES1.GL_ALPHA_TEST);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Reset fixed function bindings to default values.
|
|
|
- */
|
|
|
- private void resetFixedFuncBindings(){
|
|
|
- context.alphaTestFallOff = 0f; // zero means disable alpha test!
|
|
|
- context.color = null;
|
|
|
- context.ambient = null;
|
|
|
- context.diffuse = null;
|
|
|
- context.specular = null;
|
|
|
- context.shininess = 0;
|
|
|
- context.useVertexColor = false;
|
|
|
- }
|
|
|
-
|
|
|
- public void setFixedFuncBinding(FixedFuncBinding ffBinding, Object val) {
|
|
|
- switch (ffBinding) {
|
|
|
- case Color:
|
|
|
- context.color = (ColorRGBA) val;
|
|
|
- break;
|
|
|
- case MaterialAmbient:
|
|
|
- context.ambient = (ColorRGBA) val;
|
|
|
- break;
|
|
|
- case MaterialDiffuse:
|
|
|
- context.diffuse = (ColorRGBA) val;
|
|
|
- break;
|
|
|
- case MaterialSpecular:
|
|
|
- context.specular = (ColorRGBA) val;
|
|
|
- break;
|
|
|
- case MaterialShininess:
|
|
|
- context.shininess = (Float) val;
|
|
|
- break;
|
|
|
- case UseVertexColor:
|
|
|
- context.useVertexColor = (Boolean) val;
|
|
|
- break;
|
|
|
- case AlphaTestFallOff:
|
|
|
- context.alphaTestFallOff = (Float) val;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void applyRenderState(RenderState state) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (state.isWireframe() && !context.wireframe) {
|
|
|
- gl.getGL2GL3().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
|
|
|
- context.wireframe = true;
|
|
|
- } else if (!state.isWireframe() && context.wireframe) {
|
|
|
- gl.getGL2GL3().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
|
|
|
- context.wireframe = false;
|
|
|
- }
|
|
|
-
|
|
|
- if (state.isDepthTest() && !context.depthTestEnabled) {
|
|
|
- gl.glEnable(GL.GL_DEPTH_TEST);
|
|
|
- gl.glDepthFunc(GL.GL_LEQUAL);
|
|
|
- context.depthTestEnabled = true;
|
|
|
- } else if (!state.isDepthTest() && context.depthTestEnabled) {
|
|
|
- gl.glDisable(GL.GL_DEPTH_TEST);
|
|
|
- context.depthTestEnabled = false;
|
|
|
- }
|
|
|
-
|
|
|
- if (state.isAlphaTest()) {
|
|
|
- setFixedFuncBinding(FixedFuncBinding.AlphaTestFallOff, state.getAlphaFallOff());
|
|
|
- } else {
|
|
|
- setFixedFuncBinding(FixedFuncBinding.AlphaTestFallOff, 0f); // disable it
|
|
|
- }
|
|
|
-
|
|
|
- if (state.isDepthWrite() && !context.depthWriteEnabled) {
|
|
|
- gl.glDepthMask(true);
|
|
|
- context.depthWriteEnabled = true;
|
|
|
- } else if (!state.isDepthWrite() && context.depthWriteEnabled) {
|
|
|
- gl.glDepthMask(false);
|
|
|
- context.depthWriteEnabled = false;
|
|
|
- }
|
|
|
-
|
|
|
- if (state.isColorWrite() && !context.colorWriteEnabled) {
|
|
|
- gl.glColorMask(true, true, true, true);
|
|
|
- context.colorWriteEnabled = true;
|
|
|
- } else if (!state.isColorWrite() && context.colorWriteEnabled) {
|
|
|
- gl.glColorMask(false, false, false, false);
|
|
|
- context.colorWriteEnabled = false;
|
|
|
- }
|
|
|
-
|
|
|
- if (state.isPointSprite()) {
|
|
|
- logger.log(Level.WARNING, "Point Sprite unsupported!");
|
|
|
- }
|
|
|
-
|
|
|
- if (state.isPolyOffset()) {
|
|
|
- if (!context.polyOffsetEnabled) {
|
|
|
- gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
|
|
|
- gl.glPolygonOffset(state.getPolyOffsetFactor(),
|
|
|
- state.getPolyOffsetUnits());
|
|
|
- context.polyOffsetEnabled = true;
|
|
|
- context.polyOffsetFactor = state.getPolyOffsetFactor();
|
|
|
- context.polyOffsetUnits = state.getPolyOffsetUnits();
|
|
|
- } else {
|
|
|
- if (state.getPolyOffsetFactor() != context.polyOffsetFactor
|
|
|
- || state.getPolyOffsetUnits() != context.polyOffsetUnits) {
|
|
|
- gl.glPolygonOffset(state.getPolyOffsetFactor(),
|
|
|
- state.getPolyOffsetUnits());
|
|
|
- context.polyOffsetFactor = state.getPolyOffsetFactor();
|
|
|
- context.polyOffsetUnits = state.getPolyOffsetUnits();
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (context.polyOffsetEnabled) {
|
|
|
- gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);
|
|
|
- context.polyOffsetEnabled = false;
|
|
|
- context.polyOffsetFactor = 0;
|
|
|
- context.polyOffsetUnits = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- if (state.getFaceCullMode() != context.cullMode) {
|
|
|
- if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) {
|
|
|
- gl.glDisable(GL.GL_CULL_FACE);
|
|
|
- } else {
|
|
|
- gl.glEnable(GL.GL_CULL_FACE);
|
|
|
- }
|
|
|
-
|
|
|
- switch (state.getFaceCullMode()) {
|
|
|
- case Off:
|
|
|
- break;
|
|
|
- case Back:
|
|
|
- gl.glCullFace(GL.GL_BACK);
|
|
|
- break;
|
|
|
- case Front:
|
|
|
- gl.glCullFace(GL.GL_FRONT);
|
|
|
- break;
|
|
|
- case FrontAndBack:
|
|
|
- gl.glCullFace(GL.GL_FRONT_AND_BACK);
|
|
|
- break;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unrecognized face cull mode: "
|
|
|
- + state.getFaceCullMode());
|
|
|
- }
|
|
|
-
|
|
|
- context.cullMode = state.getFaceCullMode();
|
|
|
- }
|
|
|
-
|
|
|
- if (state.getBlendMode() != context.blendMode) {
|
|
|
- if (state.getBlendMode() == RenderState.BlendMode.Off) {
|
|
|
- gl.glDisable(GL.GL_BLEND);
|
|
|
- } else {
|
|
|
- gl.glEnable(GL.GL_BLEND);
|
|
|
- switch (state.getBlendMode()) {
|
|
|
- case Off:
|
|
|
- break;
|
|
|
- case Additive:
|
|
|
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE);
|
|
|
- break;
|
|
|
- case AlphaAdditive:
|
|
|
- gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE);
|
|
|
- break;
|
|
|
- case Color:
|
|
|
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR);
|
|
|
- break;
|
|
|
- case Alpha:
|
|
|
- gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
|
|
|
- break;
|
|
|
- case PremultAlpha:
|
|
|
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
|
|
|
- break;
|
|
|
- case Modulate:
|
|
|
- gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_ZERO);
|
|
|
- break;
|
|
|
- case ModulateX2:
|
|
|
- gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_SRC_COLOR);
|
|
|
- break;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unrecognized blend mode: "
|
|
|
- + state.getBlendMode());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- context.blendMode = state.getBlendMode();
|
|
|
- }
|
|
|
-
|
|
|
- if (state.isStencilTest()) {
|
|
|
- throw new UnsupportedOperationException("OpenGL 1.1 doesn't support two sided stencil operations.");
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public void setViewPort(int x, int y, int w, int h) {
|
|
|
- if (x != vpX || vpY != y || vpW != w || vpH != h) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.glViewport(x, y, w, h);
|
|
|
- vpX = x;
|
|
|
- vpY = y;
|
|
|
- vpW = w;
|
|
|
- vpH = h;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void setClipRect(int x, int y, int width, int height) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (!context.clipRectEnabled) {
|
|
|
- gl.glEnable(GL.GL_SCISSOR_TEST);
|
|
|
- context.clipRectEnabled = true;
|
|
|
- }
|
|
|
- if (clipX != x || clipY != y || clipW != width || clipH != height) {
|
|
|
- gl.glScissor(x, y, width, height);
|
|
|
- clipX = x;
|
|
|
- clipY = y;
|
|
|
- clipW = width;
|
|
|
- clipH = height;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void clearClipRect() {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (context.clipRectEnabled) {
|
|
|
- gl.glDisable(GL.GL_SCISSOR_TEST);
|
|
|
- context.clipRectEnabled = false;
|
|
|
-
|
|
|
- clipX = 0;
|
|
|
- clipY = 0;
|
|
|
- clipW = 0;
|
|
|
- clipH = 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void onFrame() {
|
|
|
- objManager.deleteUnused(this);
|
|
|
-// statistics.clearFrame();
|
|
|
- }
|
|
|
-
|
|
|
- private FloatBuffer storeMatrix(Matrix4f matrix, FloatBuffer store) {
|
|
|
- store.clear();
|
|
|
- matrix.fillFloatBuffer(store, true);
|
|
|
- store.clear();
|
|
|
- return store;
|
|
|
- }
|
|
|
-
|
|
|
- private void setModelView(Matrix4f modelMatrix, Matrix4f viewMatrix){
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (context.matrixMode != GLMatrixFunc.GL_MODELVIEW) {
|
|
|
- gl.getGL2ES1().glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
|
|
- context.matrixMode = GLMatrixFunc.GL_MODELVIEW;
|
|
|
- }
|
|
|
-
|
|
|
- gl.getGL2ES1().glLoadMatrixf(storeMatrix(viewMatrix, fb16));
|
|
|
- gl.getGL2ES1().glMultMatrixf(storeMatrix(modelMatrix, fb16));
|
|
|
- }
|
|
|
-
|
|
|
- private void setProjection(Matrix4f projMatrix){
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (context.matrixMode != GLMatrixFunc.GL_PROJECTION) {
|
|
|
- gl.getGL2ES1().glMatrixMode(GLMatrixFunc.GL_PROJECTION);
|
|
|
- context.matrixMode = GLMatrixFunc.GL_PROJECTION;
|
|
|
- }
|
|
|
-
|
|
|
- gl.getGL2ES1().glLoadMatrixf(storeMatrix(projMatrix, fb16));
|
|
|
- }
|
|
|
-
|
|
|
- public void setWorldMatrix(Matrix4f worldMatrix) {
|
|
|
- this.worldMatrix.set(worldMatrix);
|
|
|
- }
|
|
|
-
|
|
|
- public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) {
|
|
|
- this.viewMatrix.set(viewMatrix);
|
|
|
- setProjection(projMatrix);
|
|
|
- }
|
|
|
-
|
|
|
- public void setLighting(LightList list) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- // XXX: This is abuse of setLighting() to
|
|
|
- // apply fixed function bindings
|
|
|
- // and do other book keeping.
|
|
|
- if (list == null || list.size() == 0){
|
|
|
- gl.glDisable(GLLightingFunc.GL_LIGHTING);
|
|
|
- applyFixedFuncBindings(false);
|
|
|
- setModelView(worldMatrix, viewMatrix);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Number of lights set previously
|
|
|
- int numLightsSetPrev = lightList.size();
|
|
|
-
|
|
|
- // If more than maxLights are defined, they will be ignored.
|
|
|
- // The GL1 renderer is not permitted to crash due to a
|
|
|
- // GL1 limitation. It must render anything that the GL2 renderer
|
|
|
- // can render (even incorrectly).
|
|
|
- lightList.clear();
|
|
|
- materialAmbientColor.set(0, 0, 0, 0);
|
|
|
-
|
|
|
- for (int i = 0; i < list.size(); i++){
|
|
|
- Light l = list.get(i);
|
|
|
- if (l.getType() == Light.Type.Ambient){
|
|
|
- // Gather
|
|
|
- materialAmbientColor.addLocal(l.getColor());
|
|
|
- }else{
|
|
|
- // Add to list
|
|
|
- lightList.add(l);
|
|
|
-
|
|
|
- // Once maximum lights reached, exit loop.
|
|
|
- if (lightList.size() >= maxLights){
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- applyFixedFuncBindings(true);
|
|
|
-
|
|
|
- gl.glEnable(GLLightingFunc.GL_LIGHTING);
|
|
|
-
|
|
|
- fb16.clear();
|
|
|
- fb16.put(materialAmbientColor.r)
|
|
|
- .put(materialAmbientColor.g)
|
|
|
- .put(materialAmbientColor.b)
|
|
|
- .put(1).flip();
|
|
|
-
|
|
|
- gl.getGL2ES1().glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT, fb16);
|
|
|
-
|
|
|
- if (context.matrixMode != GLMatrixFunc.GL_MODELVIEW) {
|
|
|
- gl.getGL2ES1().glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
|
|
- context.matrixMode = GLMatrixFunc.GL_MODELVIEW;
|
|
|
- }
|
|
|
- // Lights are already in world space, so just convert
|
|
|
- // them to view space.
|
|
|
- gl.getGL2ES1().glLoadMatrixf(storeMatrix(viewMatrix, fb16));
|
|
|
-
|
|
|
- for (int i = 0; i < lightList.size(); i++){
|
|
|
- int glLightIndex = GLLightingFunc.GL_LIGHT0 + i;
|
|
|
- Light light = lightList.get(i);
|
|
|
- Light.Type lightType = light.getType();
|
|
|
- ColorRGBA col = light.getColor();
|
|
|
- Vector3f pos;
|
|
|
-
|
|
|
- // Enable the light
|
|
|
- gl.glEnable(glLightIndex);
|
|
|
-
|
|
|
- // OGL spec states default value for light ambient is black
|
|
|
- switch (lightType){
|
|
|
- case Directional:
|
|
|
- DirectionalLight dLight = (DirectionalLight) light;
|
|
|
-
|
|
|
- fb16.clear();
|
|
|
- fb16.put(col.r).put(col.g).put(col.b).put(col.a).flip();
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_DIFFUSE, fb16);
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_SPECULAR, fb16);
|
|
|
-
|
|
|
- pos = tempVec.set(dLight.getDirection()).negateLocal().normalizeLocal();
|
|
|
- fb16.clear();
|
|
|
- fb16.put(pos.x).put(pos.y).put(pos.z).put(0.0f).flip();
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_POSITION, fb16);
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_SPOT_CUTOFF, 180);
|
|
|
- break;
|
|
|
- case Point:
|
|
|
- PointLight pLight = (PointLight) light;
|
|
|
-
|
|
|
- fb16.clear();
|
|
|
- fb16.put(col.r).put(col.g).put(col.b).put(col.a).flip();
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_DIFFUSE, fb16);
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_SPECULAR, fb16);
|
|
|
-
|
|
|
- pos = pLight.getPosition();
|
|
|
- fb16.clear();
|
|
|
- fb16.put(pos.x).put(pos.y).put(pos.z).put(1.0f).flip();
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_POSITION, fb16);
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_SPOT_CUTOFF, 180);
|
|
|
-
|
|
|
- if (pLight.getRadius() > 0) {
|
|
|
- // Note: this doesn't follow the same attenuation model
|
|
|
- // as the one used in the lighting shader.
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_CONSTANT_ATTENUATION, 1);
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_LINEAR_ATTENUATION, pLight.getInvRadius() * 2);
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_QUADRATIC_ATTENUATION, pLight.getInvRadius() * pLight.getInvRadius());
|
|
|
- }else{
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_CONSTANT_ATTENUATION, 1);
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_LINEAR_ATTENUATION, 0);
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_QUADRATIC_ATTENUATION, 0);
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- case Spot:
|
|
|
- SpotLight sLight = (SpotLight) light;
|
|
|
-
|
|
|
- fb16.clear();
|
|
|
- fb16.put(col.r).put(col.g).put(col.b).put(col.a).flip();
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_DIFFUSE, fb16);
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_SPECULAR, fb16);
|
|
|
-
|
|
|
- pos = sLight.getPosition();
|
|
|
- fb16.clear();
|
|
|
- fb16.put(pos.x).put(pos.y).put(pos.z).put(1.0f).flip();
|
|
|
- gl.getGL2().glLightfv(glLightIndex, GLLightingFunc.GL_POSITION, fb16);
|
|
|
-
|
|
|
- Vector3f dir = sLight.getDirection();
|
|
|
- fb16.clear();
|
|
|
- fb16.put(dir.x).put(dir.y).put(dir.z).put(1.0f).flip();
|
|
|
- gl.getGL2ES1().glLightfv(glLightIndex, GLLightingFunc.GL_SPOT_DIRECTION, fb16);
|
|
|
-
|
|
|
- float outerAngleRad = sLight.getSpotOuterAngle();
|
|
|
- float innerAngleRad = sLight.getSpotInnerAngle();
|
|
|
- float spotCut = outerAngleRad * FastMath.RAD_TO_DEG;
|
|
|
- float spotExpo = 0.0f;
|
|
|
- if (outerAngleRad > 0) {
|
|
|
- spotExpo = (1.0f - (innerAngleRad / outerAngleRad)) * 128.0f;
|
|
|
- }
|
|
|
-
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_SPOT_CUTOFF, spotCut);
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_SPOT_EXPONENT, spotExpo);
|
|
|
-
|
|
|
- if (sLight.getSpotRange() > 0) {
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_LINEAR_ATTENUATION, sLight.getInvSpotRange());
|
|
|
- }else{
|
|
|
- gl.getGL2ES1().glLightf(glLightIndex, GLLightingFunc.GL_LINEAR_ATTENUATION, 0);
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException(
|
|
|
- "Unrecognized light type: " + lightType);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Disable lights after the index
|
|
|
- for (int i = lightList.size(); i < numLightsSetPrev; i++){
|
|
|
- gl.glDisable(GLLightingFunc.GL_LIGHT0 + i);
|
|
|
- }
|
|
|
-
|
|
|
- // This will set view matrix as well.
|
|
|
- setModelView(worldMatrix, viewMatrix);
|
|
|
- }
|
|
|
-
|
|
|
- private int convertTextureType(Texture.Type type) {
|
|
|
- switch (type) {
|
|
|
- case TwoDimensional:
|
|
|
- return GL.GL_TEXTURE_2D;
|
|
|
-// case ThreeDimensional:
|
|
|
-// return GL_TEXTURE_3D;
|
|
|
-// case CubeMap:
|
|
|
-// return GL_TEXTURE_CUBE_MAP;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unknown texture type: " + type);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private int convertMagFilter(Texture.MagFilter filter) {
|
|
|
- switch (filter) {
|
|
|
- case Bilinear:
|
|
|
- return GL.GL_LINEAR;
|
|
|
- case Nearest:
|
|
|
- return GL.GL_NEAREST;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unknown mag filter: " + filter);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private int convertMinFilter(Texture.MinFilter filter) {
|
|
|
- switch (filter) {
|
|
|
- case Trilinear:
|
|
|
- return GL.GL_LINEAR_MIPMAP_LINEAR;
|
|
|
- case BilinearNearestMipMap:
|
|
|
- return GL.GL_LINEAR_MIPMAP_NEAREST;
|
|
|
- case NearestLinearMipMap:
|
|
|
- return GL.GL_NEAREST_MIPMAP_LINEAR;
|
|
|
- case NearestNearestMipMap:
|
|
|
- return GL.GL_NEAREST_MIPMAP_NEAREST;
|
|
|
- case BilinearNoMipMaps:
|
|
|
- return GL.GL_LINEAR;
|
|
|
- case NearestNoMipMaps:
|
|
|
- return GL.GL_NEAREST;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unknown min filter: " + filter);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private int convertWrapMode(Texture.WrapMode mode) {
|
|
|
- switch (mode) {
|
|
|
- case EdgeClamp:
|
|
|
- case Clamp:
|
|
|
- case BorderClamp:
|
|
|
- return GL2.GL_CLAMP;
|
|
|
- case Repeat:
|
|
|
- return GL.GL_REPEAT;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unknown wrap mode: " + mode);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void setupTextureParams(Texture tex) {
|
|
|
- int target = convertTextureType(tex.getType());
|
|
|
-
|
|
|
- // filter things
|
|
|
- int minFilter = convertMinFilter(tex.getMinFilter());
|
|
|
- int magFilter = convertMagFilter(tex.getMagFilter());
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter);
|
|
|
- gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, magFilter);
|
|
|
-
|
|
|
- // repeat modes
|
|
|
- switch (tex.getType()) {
|
|
|
-// case ThreeDimensional:
|
|
|
-// case CubeMap:
|
|
|
-// glTexParameteri(target, GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
|
|
|
- case TwoDimensional:
|
|
|
- gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T)));
|
|
|
- // fall down here is intentional..
|
|
|
-// case OneDimensional:
|
|
|
- gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S)));
|
|
|
- break;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unknown texture type: " + tex.getType());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void updateTexImageData(Image img, Texture.Type type, int unit) {
|
|
|
- int texId = img.getId();
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (texId == -1) {
|
|
|
- // create texture
|
|
|
- gl.glGenTextures(1, ib1);
|
|
|
- texId = ib1.get(0);
|
|
|
- img.setId(texId);
|
|
|
- objManager.registerObject(img);
|
|
|
-
|
|
|
- statistics.onNewTexture();
|
|
|
- }
|
|
|
-
|
|
|
- // bind texture
|
|
|
- int target = convertTextureType(type);
|
|
|
-// if (context.boundTextureUnit != unit) {
|
|
|
-// glActiveTexture(GL_TEXTURE0 + unit);
|
|
|
-// context.boundTextureUnit = unit;
|
|
|
-// }
|
|
|
- if (context.boundTextures[unit] != img) {
|
|
|
- gl.glEnable(target);
|
|
|
- gl.glBindTexture(target, texId);
|
|
|
- context.boundTextures[unit] = img;
|
|
|
-
|
|
|
- statistics.onTextureUse(img, true);
|
|
|
- }
|
|
|
-
|
|
|
- // Check sizes if graphics card doesn't support NPOT
|
|
|
- if (!gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") && img.isNPOT()) {
|
|
|
- // Resize texture to Power-of-2 size
|
|
|
- MipMapGenerator.resizeToPowerOf2(img);
|
|
|
- }
|
|
|
-
|
|
|
- if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired()) {
|
|
|
- // No pregenerated mips available,
|
|
|
- // generate from base level if required
|
|
|
-
|
|
|
- // Check if hardware mips are supported
|
|
|
- if (gl.isExtensionAvailable("GL_VERSION_1_4")) {
|
|
|
- gl.glTexParameteri(target, GL2ES1.GL_GENERATE_MIPMAP, GL.GL_TRUE);
|
|
|
- } else {
|
|
|
- MipMapGenerator.generateMipMaps(img);
|
|
|
- }
|
|
|
- img.setMipmapsGenerated(true);
|
|
|
- } else {
|
|
|
- }
|
|
|
-
|
|
|
- if (img.getWidth() > maxTexSize || img.getHeight() > maxTexSize) {
|
|
|
- throw new RendererException("Cannot upload texture " + img + ". The maximum supported texture resolution is " + maxTexSize);
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- if (target == GL_TEXTURE_CUBE_MAP) {
|
|
|
- List<ByteBuffer> data = img.getData();
|
|
|
- if (data.size() != 6) {
|
|
|
- logger.log(Level.WARNING, "Invalid texture: {0}\n"
|
|
|
- + "Cubemap textures must contain 6 data units.", img);
|
|
|
- return;
|
|
|
- }
|
|
|
- for (int i = 0; i < 6; i++) {
|
|
|
- TextureUtil.uploadTexture(img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc);
|
|
|
- }
|
|
|
- } else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT) {
|
|
|
- List<ByteBuffer> data = img.getData();
|
|
|
- // -1 index specifies prepare data for 2D Array
|
|
|
- TextureUtil.uploadTexture(img, target, -1, 0, tdc);
|
|
|
- for (int i = 0; i < data.size(); i++) {
|
|
|
- // upload each slice of 2D array in turn
|
|
|
- // this time with the appropriate index
|
|
|
- TextureUtil.uploadTexture(img, target, i, 0, tdc);
|
|
|
- }
|
|
|
- } else {*/
|
|
|
- TextureUtil.uploadTexture(img, target, 0, 0,false);
|
|
|
- //}
|
|
|
-
|
|
|
- img.clearUpdateNeeded();
|
|
|
- }
|
|
|
-
|
|
|
- public void setTexture(int unit, Texture tex) {
|
|
|
- if (unit != 0 || tex.getType() != Texture.Type.TwoDimensional) {
|
|
|
- //throw new UnsupportedOperationException();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- Image image = tex.getImage();
|
|
|
- if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated()) ) {
|
|
|
- updateTexImageData(image, tex.getType(), unit);
|
|
|
- }
|
|
|
-
|
|
|
- int texId = image.getId();
|
|
|
- assert texId != -1;
|
|
|
-
|
|
|
- Image[] textures = context.boundTextures;
|
|
|
-
|
|
|
- int type = convertTextureType(tex.getType());
|
|
|
-// if (!context.textureIndexList.moveToNew(unit)) {
|
|
|
-// if (context.boundTextureUnit != unit){
|
|
|
-// gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
|
|
|
-// context.boundTextureUnit = unit;
|
|
|
-// }
|
|
|
-// gl.glEnable(type);
|
|
|
-// }
|
|
|
-
|
|
|
-// if (context.boundTextureUnit != unit) {
|
|
|
-// gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
|
|
|
-// context.boundTextureUnit = unit;
|
|
|
-// }
|
|
|
-
|
|
|
- if (textures[unit] != image) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.glEnable(type);
|
|
|
- gl.glBindTexture(type, texId);
|
|
|
- textures[unit] = image;
|
|
|
-
|
|
|
- statistics.onTextureUse(image, true);
|
|
|
- } else {
|
|
|
- statistics.onTextureUse(image, false);
|
|
|
- }
|
|
|
-
|
|
|
- setupTextureParams(tex);
|
|
|
- }
|
|
|
-
|
|
|
- public void modifyTexture(Texture tex, Image pixels, int x, int y) {
|
|
|
- setTexture(0, tex);
|
|
|
- TextureUtil.uploadSubTexture(pixels, convertTextureType(tex.getType()), 0, x, y, false);
|
|
|
- }
|
|
|
-
|
|
|
- private void clearTextureUnits() {
|
|
|
- Image[] textures = context.boundTextures;
|
|
|
- if (textures[0] != null) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.glDisable(GL.GL_TEXTURE_2D);
|
|
|
- textures[0] = null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void deleteImage(Image image) {
|
|
|
- int texId = image.getId();
|
|
|
- if (texId != -1) {
|
|
|
- ib1.put(0, texId);
|
|
|
- ib1.position(0).limit(1);
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.glDeleteTextures(ib1.limit() ,ib1);
|
|
|
- image.resetObject();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private int convertArrayType(VertexBuffer.Type type) {
|
|
|
- switch (type) {
|
|
|
- case Position:
|
|
|
- return GLPointerFunc.GL_VERTEX_ARRAY;
|
|
|
- case Normal:
|
|
|
- return GLPointerFunc.GL_NORMAL_ARRAY;
|
|
|
- case TexCoord:
|
|
|
- return GLPointerFunc.GL_TEXTURE_COORD_ARRAY;
|
|
|
- case Color:
|
|
|
- return GLPointerFunc.GL_COLOR_ARRAY;
|
|
|
- default:
|
|
|
- return -1; // unsupported
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private int convertVertexFormat(VertexBuffer.Format fmt) {
|
|
|
- switch (fmt) {
|
|
|
- case Byte:
|
|
|
- return GL.GL_BYTE;
|
|
|
- case Float:
|
|
|
- return GL.GL_FLOAT;
|
|
|
- case Int:
|
|
|
- return GL2ES2.GL_INT;
|
|
|
- case Short:
|
|
|
- return GL.GL_SHORT;
|
|
|
- case UnsignedByte:
|
|
|
- return GL.GL_UNSIGNED_BYTE;
|
|
|
- case UnsignedInt:
|
|
|
- return GL.GL_UNSIGNED_INT;
|
|
|
- case UnsignedShort:
|
|
|
- return GL.GL_UNSIGNED_SHORT;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unrecognized vertex format: " + fmt);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private int convertElementMode(Mesh.Mode mode) {
|
|
|
- switch (mode) {
|
|
|
- case Points:
|
|
|
- return GL.GL_POINTS;
|
|
|
- case Lines:
|
|
|
- return GL.GL_LINES;
|
|
|
- case LineLoop:
|
|
|
- return GL.GL_LINE_LOOP;
|
|
|
- case LineStrip:
|
|
|
- return GL.GL_LINE_STRIP;
|
|
|
- case Triangles:
|
|
|
- return GL.GL_TRIANGLES;
|
|
|
- case TriangleFan:
|
|
|
- return GL.GL_TRIANGLE_FAN;
|
|
|
- case TriangleStrip:
|
|
|
- return GL.GL_TRIANGLE_STRIP;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException("Unrecognized mesh mode: " + mode);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) {
|
|
|
- if (count > 1) {
|
|
|
- throw new UnsupportedOperationException();
|
|
|
- }
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.glDrawArrays(convertElementMode(mode), 0, vertCount);
|
|
|
- }
|
|
|
-
|
|
|
- public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) {
|
|
|
- if (vb.getBufferType() == VertexBuffer.Type.Color && !context.useVertexColor) {
|
|
|
- // Ignore vertex color buffer if vertex color is disabled.
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- int arrayType = convertArrayType(vb.getBufferType());
|
|
|
- if (arrayType == -1) {
|
|
|
- return; // unsupported
|
|
|
- }
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.getGL2GL3().glEnableClientState(arrayType);
|
|
|
- context.boundAttribs[vb.getBufferType().ordinal()] = vb;
|
|
|
-
|
|
|
- if (vb.getBufferType() == Type.Normal) {
|
|
|
- // normalize if requested
|
|
|
- if (vb.isNormalized() && !context.normalizeEnabled) {
|
|
|
- gl.glEnable(GLLightingFunc.GL_NORMALIZE);
|
|
|
- context.normalizeEnabled = true;
|
|
|
- } else if (!vb.isNormalized() && context.normalizeEnabled) {
|
|
|
- gl.glDisable(GLLightingFunc.GL_NORMALIZE);
|
|
|
- context.normalizeEnabled = false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // NOTE: Use data from interleaved buffer if specified
|
|
|
- Buffer data = idb != null ? idb.getData() : vb.getData();
|
|
|
- int comps = vb.getNumComponents();
|
|
|
- int type = convertVertexFormat(vb.getFormat());
|
|
|
-
|
|
|
- data.rewind();
|
|
|
-
|
|
|
- switch (vb.getBufferType()) {
|
|
|
- case Position:
|
|
|
- if (!(data instanceof FloatBuffer)) {
|
|
|
- throw new UnsupportedOperationException();
|
|
|
- }
|
|
|
-
|
|
|
- gl.getGL2().glVertexPointer(comps, type, vb.getStride(), (FloatBuffer) data);
|
|
|
- break;
|
|
|
- case Normal:
|
|
|
- if (!(data instanceof FloatBuffer)) {
|
|
|
- throw new UnsupportedOperationException();
|
|
|
- }
|
|
|
-
|
|
|
- gl.getGL2().glNormalPointer(type, vb.getStride(), (FloatBuffer) data);
|
|
|
- break;
|
|
|
- case Color:
|
|
|
- if (data instanceof FloatBuffer) {
|
|
|
- gl.getGL2().glColorPointer(comps, type, vb.getStride(), (FloatBuffer) data);
|
|
|
- } else if (data instanceof ByteBuffer) {
|
|
|
- gl.getGL2().glColorPointer(comps, type, vb.getStride(), (ByteBuffer) data);
|
|
|
- } else {
|
|
|
- throw new UnsupportedOperationException();
|
|
|
- }
|
|
|
- break;
|
|
|
- case TexCoord:
|
|
|
- if (!(data instanceof FloatBuffer)) {
|
|
|
- throw new UnsupportedOperationException();
|
|
|
- }
|
|
|
-
|
|
|
- gl.getGL2().glTexCoordPointer(comps, type, vb.getStride(), (FloatBuffer) data);
|
|
|
- break;
|
|
|
- default:
|
|
|
- // Ignore, this is an unsupported attribute for OpenGL1.
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void setVertexAttrib(VertexBuffer vb) {
|
|
|
- setVertexAttrib(vb, null);
|
|
|
- }
|
|
|
-
|
|
|
- private void drawElements(int mode, int format, Buffer data) {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- switch (format) {
|
|
|
- case GL.GL_UNSIGNED_BYTE:
|
|
|
- gl.getGL2().glDrawElements(mode, data.limit(), format, (ByteBuffer) data);
|
|
|
- break;
|
|
|
- case GL.GL_UNSIGNED_SHORT:
|
|
|
- gl.getGL2().glDrawElements(mode, data.limit(), format, (ShortBuffer) data);
|
|
|
- break;
|
|
|
- case GL.GL_UNSIGNED_INT:
|
|
|
- gl.getGL2().glDrawElements(mode, data.limit(), format, (IntBuffer) data);
|
|
|
- break;
|
|
|
- default:
|
|
|
- throw new UnsupportedOperationException();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) {
|
|
|
- Mesh.Mode mode = mesh.getMode();
|
|
|
-
|
|
|
- Buffer indexData = indexBuf.getData();
|
|
|
- indexData.rewind();
|
|
|
-
|
|
|
- if (mesh.getMode() == Mode.Hybrid) {
|
|
|
- throw new UnsupportedOperationException();
|
|
|
- /*
|
|
|
- int[] modeStart = mesh.getModeStart();
|
|
|
- int[] elementLengths = mesh.getElementLengths();
|
|
|
-
|
|
|
- int elMode = convertElementMode(Mode.Triangles);
|
|
|
- int fmt = convertVertexFormat(indexBuf.getFormat());
|
|
|
- // int elSize = indexBuf.getFormat().getComponentSize();
|
|
|
- // int listStart = modeStart[0];
|
|
|
- int stripStart = modeStart[1];
|
|
|
- int fanStart = modeStart[2];
|
|
|
- int curOffset = 0;
|
|
|
- for (int i = 0; i < elementLengths.length; i++) {
|
|
|
- if (i == stripStart) {
|
|
|
- elMode = convertElementMode(Mode.TriangleStrip);
|
|
|
- } else if (i == fanStart) {
|
|
|
- elMode = convertElementMode(Mode.TriangleStrip);
|
|
|
- }
|
|
|
- int elementLength = elementLengths[i];
|
|
|
- indexData.position(curOffset);
|
|
|
-
|
|
|
- drawElements(elMode,
|
|
|
- fmt,
|
|
|
- indexData);
|
|
|
-
|
|
|
- curOffset += elementLength;
|
|
|
- }*/
|
|
|
- } else {
|
|
|
- drawElements(convertElementMode(mode),
|
|
|
- convertVertexFormat(indexBuf.getFormat()),
|
|
|
- indexData);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void clearVertexAttribs() {
|
|
|
- for (int i = 0; i < 16; i++) {
|
|
|
- VertexBuffer vb = context.boundAttribs[i];
|
|
|
- if (vb != null) {
|
|
|
- int arrayType = convertArrayType(vb.getBufferType());
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.getGL2().glDisableClientState(arrayType);
|
|
|
- context.boundAttribs[vb.getBufferType().ordinal()] = null;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void renderMeshDefault(Mesh mesh, int lod, int count) {
|
|
|
- VertexBuffer indices;
|
|
|
-
|
|
|
- VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
|
|
|
- if (interleavedData != null && interleavedData.isUpdateNeeded()) {
|
|
|
- updateBufferData(interleavedData);
|
|
|
- }
|
|
|
-
|
|
|
- if (mesh.getNumLodLevels() > 0) {
|
|
|
- indices = mesh.getLodLevel(lod);
|
|
|
- } else {
|
|
|
- indices = mesh.getBuffer(Type.Index);
|
|
|
- }
|
|
|
- for (VertexBuffer vb : mesh.getBufferList().getArray()) {
|
|
|
- if (vb.getBufferType() == Type.InterleavedData
|
|
|
- || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers
|
|
|
- || vb.getBufferType() == Type.Index) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if (vb.getStride() == 0) {
|
|
|
- // not interleaved
|
|
|
- setVertexAttrib(vb);
|
|
|
- } else {
|
|
|
- // interleaved
|
|
|
- setVertexAttrib(vb, interleavedData);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (indices != null) {
|
|
|
- drawTriangleList(indices, mesh, count);
|
|
|
- } else {
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- gl.glDrawArrays(convertElementMode(mesh.getMode()), 0, mesh.getVertexCount());
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: Fix these to use IDList??
|
|
|
- clearVertexAttribs();
|
|
|
- clearTextureUnits();
|
|
|
- resetFixedFuncBindings();
|
|
|
- }
|
|
|
-
|
|
|
- public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) {
|
|
|
- if (mesh.getVertexCount() == 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
- GL gl = GLContext.getCurrentGL();
|
|
|
- if (context.pointSize != mesh.getPointSize()) {
|
|
|
- gl.getGL2().glPointSize(mesh.getPointSize());
|
|
|
- context.pointSize = mesh.getPointSize();
|
|
|
- }
|
|
|
- if (context.lineWidth != mesh.getLineWidth()) {
|
|
|
- gl.getGL2().glLineWidth(mesh.getLineWidth());
|
|
|
- context.lineWidth = mesh.getLineWidth();
|
|
|
- }
|
|
|
-
|
|
|
- boolean dynamic = false;
|
|
|
- if (mesh.getBuffer(Type.InterleavedData) != null) {
|
|
|
- throw new UnsupportedOperationException("Interleaved meshes are not supported");
|
|
|
- }
|
|
|
-
|
|
|
- if (mesh.getNumLodLevels() == 0) {
|
|
|
- for (VertexBuffer vb : mesh.getBufferList().getArray()) {
|
|
|
- if (vb.getUsage() != VertexBuffer.Usage.Static) {
|
|
|
- dynamic = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- dynamic = true;
|
|
|
- }
|
|
|
-
|
|
|
- statistics.onMeshDrawn(mesh, lod);
|
|
|
-
|
|
|
-// if (!dynamic) {
|
|
|
- // dealing with a static object, generate display list
|
|
|
-// renderMeshDisplayList(mesh);
|
|
|
-// } else {
|
|
|
- renderMeshDefault(mesh, lod, count);
|
|
|
-// }
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public void setAlphaToCoverage(boolean value) {
|
|
|
- }
|
|
|
-
|
|
|
- public void setShader(Shader shader) {
|
|
|
- }
|
|
|
-
|
|
|
- public void deleteShader(Shader shader) {
|
|
|
- }
|
|
|
-
|
|
|
- public void deleteShaderSource(ShaderSource source) {
|
|
|
- }
|
|
|
-
|
|
|
- public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
|
|
|
- }
|
|
|
-
|
|
|
- public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
|
|
|
- }
|
|
|
-
|
|
|
- public void setMainFrameBufferOverride(FrameBuffer fb){
|
|
|
- }
|
|
|
-
|
|
|
- public void setFrameBuffer(FrameBuffer fb) {
|
|
|
- }
|
|
|
-
|
|
|
- public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
|
|
|
- }
|
|
|
-
|
|
|
- public void deleteFrameBuffer(FrameBuffer fb) {
|
|
|
- }
|
|
|
-
|
|
|
- public void updateBufferData(VertexBuffer vb) {
|
|
|
- }
|
|
|
-
|
|
|
- public void deleteBuffer(VertexBuffer vb) {
|
|
|
- }
|
|
|
-
|
|
|
- public void setMainFrameBufferSrgb(boolean srgb) {
|
|
|
- }
|
|
|
-
|
|
|
- public void setLinearizeSrgbImages(boolean linearize) {
|
|
|
- }
|
|
|
-}
|