|
|
@ -51,6 +51,7 @@ import com.jme3.scene.Mesh.Mode; |
|
|
|
import com.jme3.scene.VertexBuffer; |
|
|
|
import com.jme3.scene.VertexBuffer; |
|
|
|
import com.jme3.scene.VertexBuffer.Type; |
|
|
|
import com.jme3.scene.VertexBuffer.Type; |
|
|
|
import com.jme3.scene.VertexBuffer.Usage; |
|
|
|
import com.jme3.scene.VertexBuffer.Usage; |
|
|
|
|
|
|
|
import com.jme3.shader.Attribute; |
|
|
|
import com.jme3.shader.Shader; |
|
|
|
import com.jme3.shader.Shader; |
|
|
|
import com.jme3.shader.Shader.ShaderSource; |
|
|
|
import com.jme3.shader.Shader.ShaderSource; |
|
|
|
import com.jme3.shader.Uniform; |
|
|
|
import com.jme3.shader.Uniform; |
|
|
@ -64,10 +65,7 @@ import com.jme3.util.IntMap; |
|
|
|
import com.jme3.util.IntMap.Entry; |
|
|
|
import com.jme3.util.IntMap.Entry; |
|
|
|
import com.jme3.util.ListMap; |
|
|
|
import com.jme3.util.ListMap; |
|
|
|
import com.jme3.util.NativeObjectManager; |
|
|
|
import com.jme3.util.NativeObjectManager; |
|
|
|
import java.nio.Buffer; |
|
|
|
import java.nio.*; |
|
|
|
import java.nio.ByteBuffer; |
|
|
|
|
|
|
|
import java.nio.FloatBuffer; |
|
|
|
|
|
|
|
import java.nio.IntBuffer; |
|
|
|
|
|
|
|
import java.util.EnumSet; |
|
|
|
import java.util.EnumSet; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.logging.Level; |
|
|
|
import java.util.logging.Level; |
|
|
@ -91,6 +89,7 @@ public class JoglRenderer implements Renderer { |
|
|
|
private final StringBuilder stringBuf = new StringBuilder(250); |
|
|
|
private final StringBuilder stringBuf = new StringBuilder(250); |
|
|
|
private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); |
|
|
|
private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); |
|
|
|
private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16); |
|
|
|
private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16); |
|
|
|
|
|
|
|
protected FloatBuffer fb16 = BufferUtils.createFloatBuffer(16); |
|
|
|
private RenderContext context = new RenderContext(); |
|
|
|
private RenderContext context = new RenderContext(); |
|
|
|
private NativeObjectManager objManager = new NativeObjectManager(); |
|
|
|
private NativeObjectManager objManager = new NativeObjectManager(); |
|
|
|
private EnumSet<Caps> caps = EnumSet.noneOf(Caps.class); |
|
|
|
private EnumSet<Caps> caps = EnumSet.noneOf(Caps.class); |
|
|
@ -118,11 +117,6 @@ public class JoglRenderer implements Renderer { |
|
|
|
private final Statistics statistics = new Statistics(); |
|
|
|
private final Statistics statistics = new Statistics(); |
|
|
|
private int vpX, vpY, vpW, vpH; |
|
|
|
private int vpX, vpY, vpW, vpH; |
|
|
|
private int clipX, clipY, clipW, clipH; |
|
|
|
private int clipX, clipY, clipW, clipH; |
|
|
|
//TODO: remove?
|
|
|
|
|
|
|
|
protected Matrix4f worldMatrix = new Matrix4f(); |
|
|
|
|
|
|
|
protected Matrix4f viewMatrix = new Matrix4f(); |
|
|
|
|
|
|
|
protected Matrix4f projMatrix = new Matrix4f(); |
|
|
|
|
|
|
|
protected FloatBuffer fb16 = BufferUtils.createFloatBuffer(16); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public JoglRenderer() { |
|
|
|
public JoglRenderer() { |
|
|
|
} |
|
|
|
} |
|
|
@ -423,15 +417,23 @@ public class JoglRenderer implements Renderer { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void resetGLObjects() { |
|
|
|
public void resetGLObjects() { |
|
|
|
|
|
|
|
logger.log(Level.INFO, "Reseting objects and invalidating state"); |
|
|
|
objManager.resetObjects(); |
|
|
|
objManager.resetObjects(); |
|
|
|
statistics.clearMemory(); |
|
|
|
statistics.clearMemory(); |
|
|
|
boundShader = null; |
|
|
|
invalidateState(); |
|
|
|
lastFb = null; |
|
|
|
|
|
|
|
context.reset(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void cleanup() { |
|
|
|
public void cleanup() { |
|
|
|
|
|
|
|
logger.log(Level.INFO, "Deleting objects and invalidating state"); |
|
|
|
objManager.deleteAllObjects(this); |
|
|
|
objManager.deleteAllObjects(this); |
|
|
|
|
|
|
|
statistics.clearMemory(); |
|
|
|
|
|
|
|
invalidateState(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void checkCap(Caps cap) { |
|
|
|
|
|
|
|
if (!caps.contains(cap)) { |
|
|
|
|
|
|
|
throw new UnsupportedOperationException("Required capability missing: " + cap.name()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************\ |
|
|
|
/*********************************************************************\ |
|
|
@ -446,9 +448,23 @@ public class JoglRenderer implements Renderer { |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
int bits = 0; |
|
|
|
int bits = 0; |
|
|
|
if (color) { |
|
|
|
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; |
|
|
|
bits = GL.GL_COLOR_BUFFER_BIT; |
|
|
|
} |
|
|
|
} |
|
|
|
if (depth) { |
|
|
|
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; |
|
|
|
bits |= GL.GL_DEPTH_BUFFER_BIT; |
|
|
|
} |
|
|
|
} |
|
|
|
if (stencil) { |
|
|
|
if (stencil) { |
|
|
@ -476,15 +492,15 @@ public class JoglRenderer implements Renderer { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void applyRenderState(RenderState state) { |
|
|
|
public void applyRenderState(RenderState state) { |
|
|
|
//FIXME implement missing features
|
|
|
|
|
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
if (state.isWireframe() && !context.wireframe) { |
|
|
|
if (state.isWireframe() && !context.wireframe) { |
|
|
|
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE); |
|
|
|
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2.GL_LINE); |
|
|
|
context.wireframe = true; |
|
|
|
context.wireframe = true; |
|
|
|
} else if (!state.isWireframe() && context.wireframe) { |
|
|
|
} else if (!state.isWireframe() && context.wireframe) { |
|
|
|
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL); |
|
|
|
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2.GL_FILL); |
|
|
|
context.wireframe = false; |
|
|
|
context.wireframe = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (state.isDepthTest() && !context.depthTestEnabled) { |
|
|
|
if (state.isDepthTest() && !context.depthTestEnabled) { |
|
|
|
gl.glEnable(GL.GL_DEPTH_TEST); |
|
|
|
gl.glEnable(GL.GL_DEPTH_TEST); |
|
|
|
gl.glDepthFunc(GL.GL_LEQUAL); |
|
|
|
gl.glDepthFunc(GL.GL_LEQUAL); |
|
|
@ -493,14 +509,16 @@ public class JoglRenderer implements Renderer { |
|
|
|
gl.glDisable(GL.GL_DEPTH_TEST); |
|
|
|
gl.glDisable(GL.GL_DEPTH_TEST); |
|
|
|
context.depthTestEnabled = false; |
|
|
|
context.depthTestEnabled = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (state.isAlphaTest() && context.alphaTestFallOff == 0) { |
|
|
|
if (state.isAlphaTest() && context.alphaTestFallOff == 0) { |
|
|
|
gl.glEnable(GL2ES1.GL_ALPHA_TEST); |
|
|
|
gl.glEnable(GL2.GL_ALPHA_TEST); |
|
|
|
gl.getGL2().glAlphaFunc(GL.GL_GREATER, state.getAlphaFallOff()); |
|
|
|
gl.getGL2().glAlphaFunc(GL.GL_GREATER, state.getAlphaFallOff()); |
|
|
|
context.alphaTestFallOff = state.getAlphaFallOff(); |
|
|
|
context.alphaTestFallOff = state.getAlphaFallOff(); |
|
|
|
} else if (!state.isAlphaTest() && context.alphaTestFallOff != 0) { |
|
|
|
} else if (!state.isAlphaTest() && context.alphaTestFallOff != 0) { |
|
|
|
gl.glDisable(GL2ES1.GL_ALPHA_TEST); |
|
|
|
gl.glDisable(GL2.GL_ALPHA_TEST); |
|
|
|
context.alphaTestFallOff = 0; |
|
|
|
context.alphaTestFallOff = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (state.isDepthWrite() && !context.depthWriteEnabled) { |
|
|
|
if (state.isDepthWrite() && !context.depthWriteEnabled) { |
|
|
|
gl.glDepthMask(true); |
|
|
|
gl.glDepthMask(true); |
|
|
|
context.depthWriteEnabled = true; |
|
|
|
context.depthWriteEnabled = true; |
|
|
@ -508,6 +526,7 @@ public class JoglRenderer implements Renderer { |
|
|
|
gl.glDepthMask(false); |
|
|
|
gl.glDepthMask(false); |
|
|
|
context.depthWriteEnabled = false; |
|
|
|
context.depthWriteEnabled = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (state.isColorWrite() && !context.colorWriteEnabled) { |
|
|
|
if (state.isColorWrite() && !context.colorWriteEnabled) { |
|
|
|
gl.glColorMask(true, true, true, true); |
|
|
|
gl.glColorMask(true, true, true, true); |
|
|
|
context.colorWriteEnabled = true; |
|
|
|
context.colorWriteEnabled = true; |
|
|
@ -515,17 +534,43 @@ public class JoglRenderer implements Renderer { |
|
|
|
gl.glColorMask(false, false, false, false); |
|
|
|
gl.glColorMask(false, false, false, false); |
|
|
|
context.colorWriteEnabled = false; |
|
|
|
context.colorWriteEnabled = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (state.isPointSprite() && !context.pointSprite) { |
|
|
|
|
|
|
|
// Only enable/disable sprite
|
|
|
|
|
|
|
|
if (context.boundTextures[0] != null) { |
|
|
|
|
|
|
|
if (context.boundTextureUnit != 0) { |
|
|
|
|
|
|
|
gl.glActiveTexture(GL.GL_TEXTURE0); |
|
|
|
|
|
|
|
context.boundTextureUnit = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
gl.glEnable(GL2.GL_POINT_SPRITE); |
|
|
|
|
|
|
|
gl.glEnable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
context.pointSprite = true; |
|
|
|
|
|
|
|
} else if (!state.isPointSprite() && context.pointSprite) { |
|
|
|
|
|
|
|
if (context.boundTextures[0] != null) { |
|
|
|
|
|
|
|
if (context.boundTextureUnit != 0) { |
|
|
|
|
|
|
|
gl.glActiveTexture(GL.GL_TEXTURE0); |
|
|
|
|
|
|
|
context.boundTextureUnit = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
gl.glDisable(GL2.GL_POINT_SPRITE); |
|
|
|
|
|
|
|
gl.glDisable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE); |
|
|
|
|
|
|
|
context.pointSprite = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (state.isPolyOffset()) { |
|
|
|
if (state.isPolyOffset()) { |
|
|
|
if (!context.polyOffsetEnabled) { |
|
|
|
if (!context.polyOffsetEnabled) { |
|
|
|
gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); |
|
|
|
gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); |
|
|
|
gl.glPolygonOffset(state.getPolyOffsetFactor(), state.getPolyOffsetUnits()); |
|
|
|
gl.glPolygonOffset(state.getPolyOffsetFactor(), |
|
|
|
|
|
|
|
state.getPolyOffsetUnits()); |
|
|
|
context.polyOffsetEnabled = true; |
|
|
|
context.polyOffsetEnabled = true; |
|
|
|
context.polyOffsetFactor = state.getPolyOffsetFactor(); |
|
|
|
context.polyOffsetFactor = state.getPolyOffsetFactor(); |
|
|
|
context.polyOffsetUnits = state.getPolyOffsetUnits(); |
|
|
|
context.polyOffsetUnits = state.getPolyOffsetUnits(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if (state.getPolyOffsetFactor() != context.polyOffsetFactor |
|
|
|
if (state.getPolyOffsetFactor() != context.polyOffsetFactor |
|
|
|
|| state.getPolyOffsetUnits() != context.polyOffsetUnits) { |
|
|
|
|| state.getPolyOffsetUnits() != context.polyOffsetUnits) { |
|
|
|
gl.glPolygonOffset(state.getPolyOffsetFactor(), state.getPolyOffsetUnits()); |
|
|
|
gl.glPolygonOffset(state.getPolyOffsetFactor(), |
|
|
|
|
|
|
|
state.getPolyOffsetUnits()); |
|
|
|
context.polyOffsetFactor = state.getPolyOffsetFactor(); |
|
|
|
context.polyOffsetFactor = state.getPolyOffsetFactor(); |
|
|
|
context.polyOffsetUnits = state.getPolyOffsetUnits(); |
|
|
|
context.polyOffsetUnits = state.getPolyOffsetUnits(); |
|
|
|
} |
|
|
|
} |
|
|
@ -538,6 +583,7 @@ public class JoglRenderer implements Renderer { |
|
|
|
context.polyOffsetUnits = 0; |
|
|
|
context.polyOffsetUnits = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (state.getFaceCullMode() != context.cullMode) { |
|
|
|
if (state.getFaceCullMode() != context.cullMode) { |
|
|
|
if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) { |
|
|
|
if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) { |
|
|
|
gl.glDisable(GL.GL_CULL_FACE); |
|
|
|
gl.glDisable(GL.GL_CULL_FACE); |
|
|
@ -570,8 +616,6 @@ public class JoglRenderer implements Renderer { |
|
|
|
gl.glDisable(GL.GL_BLEND); |
|
|
|
gl.glDisable(GL.GL_BLEND); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
gl.glEnable(GL.GL_BLEND); |
|
|
|
gl.glEnable(GL.GL_BLEND); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (state.getBlendMode()) { |
|
|
|
switch (state.getBlendMode()) { |
|
|
|
case Off: |
|
|
|
case Off: |
|
|
|
break; |
|
|
|
break; |
|
|
@ -581,12 +625,12 @@ public class JoglRenderer implements Renderer { |
|
|
|
case AlphaAdditive: |
|
|
|
case AlphaAdditive: |
|
|
|
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE); |
|
|
|
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case Alpha: |
|
|
|
|
|
|
|
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case Color: |
|
|
|
case Color: |
|
|
|
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); |
|
|
|
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case Alpha: |
|
|
|
|
|
|
|
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); |
|
|
|
|
|
|
|
break; |
|
|
|
case PremultAlpha: |
|
|
|
case PremultAlpha: |
|
|
|
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); |
|
|
|
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -600,9 +644,50 @@ public class JoglRenderer implements Renderer { |
|
|
|
throw new UnsupportedOperationException("Unrecognized blend mode: " |
|
|
|
throw new UnsupportedOperationException("Unrecognized blend mode: " |
|
|
|
+ state.getBlendMode()); |
|
|
|
+ state.getBlendMode()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
context.blendMode = state.getBlendMode(); |
|
|
|
context.blendMode = state.getBlendMode(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (context.stencilTest != state.isStencilTest() |
|
|
|
|
|
|
|
|| context.frontStencilStencilFailOperation != state.getFrontStencilStencilFailOperation() |
|
|
|
|
|
|
|
|| context.frontStencilDepthFailOperation != state.getFrontStencilDepthFailOperation() |
|
|
|
|
|
|
|
|| context.frontStencilDepthPassOperation != state.getFrontStencilDepthPassOperation() |
|
|
|
|
|
|
|
|| context.backStencilStencilFailOperation != state.getBackStencilStencilFailOperation() |
|
|
|
|
|
|
|
|| context.backStencilDepthFailOperation != state.getBackStencilDepthFailOperation() |
|
|
|
|
|
|
|
|| context.backStencilDepthPassOperation != state.getBackStencilDepthPassOperation() |
|
|
|
|
|
|
|
|| context.frontStencilFunction != state.getFrontStencilFunction() |
|
|
|
|
|
|
|
|| context.backStencilFunction != state.getBackStencilFunction()) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context.frontStencilStencilFailOperation = state.getFrontStencilStencilFailOperation(); //terrible looking, I know
|
|
|
|
|
|
|
|
context.frontStencilDepthFailOperation = state.getFrontStencilDepthFailOperation(); |
|
|
|
|
|
|
|
context.frontStencilDepthPassOperation = state.getFrontStencilDepthPassOperation(); |
|
|
|
|
|
|
|
context.backStencilStencilFailOperation = state.getBackStencilStencilFailOperation(); |
|
|
|
|
|
|
|
context.backStencilDepthFailOperation = state.getBackStencilDepthFailOperation(); |
|
|
|
|
|
|
|
context.backStencilDepthPassOperation = state.getBackStencilDepthPassOperation(); |
|
|
|
|
|
|
|
context.frontStencilFunction = state.getFrontStencilFunction(); |
|
|
|
|
|
|
|
context.backStencilFunction = state.getBackStencilFunction(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (state.isStencilTest()) { |
|
|
|
|
|
|
|
gl.glEnable(GL.GL_STENCIL_TEST); |
|
|
|
|
|
|
|
gl.getGL2().glStencilOpSeparate(GL.GL_FRONT, |
|
|
|
|
|
|
|
convertStencilOperation(state.getFrontStencilStencilFailOperation()), |
|
|
|
|
|
|
|
convertStencilOperation(state.getFrontStencilDepthFailOperation()), |
|
|
|
|
|
|
|
convertStencilOperation(state.getFrontStencilDepthPassOperation())); |
|
|
|
|
|
|
|
gl.getGL2().glStencilOpSeparate(GL.GL_BACK, |
|
|
|
|
|
|
|
convertStencilOperation(state.getBackStencilStencilFailOperation()), |
|
|
|
|
|
|
|
convertStencilOperation(state.getBackStencilDepthFailOperation()), |
|
|
|
|
|
|
|
convertStencilOperation(state.getBackStencilDepthPassOperation())); |
|
|
|
|
|
|
|
gl.getGL2().glStencilFuncSeparate(GL.GL_FRONT, |
|
|
|
|
|
|
|
convertTestFunction(state.getFrontStencilFunction()), |
|
|
|
|
|
|
|
0, Integer.MAX_VALUE); |
|
|
|
|
|
|
|
gl.getGL2().glStencilFuncSeparate(GL.GL_BACK, |
|
|
|
|
|
|
|
convertTestFunction(state.getBackStencilFunction()), |
|
|
|
|
|
|
|
0, Integer.MAX_VALUE); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
gl.glDisable(GL.GL_STENCIL_TEST); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private int convertStencilOperation(RenderState.StencilOperation stencilOp) { |
|
|
|
private int convertStencilOperation(RenderState.StencilOperation stencilOp) { |
|
|
@ -654,13 +739,15 @@ public class JoglRenderer implements Renderer { |
|
|
|
/*********************************************************************\ |
|
|
|
/*********************************************************************\ |
|
|
|
|* Camera and World transforms *| |
|
|
|
|* Camera and World transforms *| |
|
|
|
\*********************************************************************/ |
|
|
|
\*********************************************************************/ |
|
|
|
public void setViewPort(int x, int y, int width, int height) { |
|
|
|
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 gl = GLContext.getCurrentGL(); |
|
|
|
gl.glViewport(x, y, width, height); |
|
|
|
gl.glViewport(x, y, w, h); |
|
|
|
vpX = x; |
|
|
|
vpX = x; |
|
|
|
vpY = y; |
|
|
|
vpY = y; |
|
|
|
vpW = width; |
|
|
|
vpW = w; |
|
|
|
vpH = height; |
|
|
|
vpH = h; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setClipRect(int x, int y, int width, int height) { |
|
|
|
public void setClipRect(int x, int y, int width, int height) { |
|
|
@ -669,7 +756,13 @@ public class JoglRenderer implements Renderer { |
|
|
|
gl.glEnable(GL.GL_SCISSOR_TEST); |
|
|
|
gl.glEnable(GL.GL_SCISSOR_TEST); |
|
|
|
context.clipRectEnabled = true; |
|
|
|
context.clipRectEnabled = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (clipX != x || clipY != y || clipW != width || clipH != height) { |
|
|
|
gl.glScissor(x, y, width, height); |
|
|
|
gl.glScissor(x, y, width, height); |
|
|
|
|
|
|
|
clipX = x; |
|
|
|
|
|
|
|
clipY = y; |
|
|
|
|
|
|
|
clipW = width; |
|
|
|
|
|
|
|
clipH = height; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void clearClipRect() { |
|
|
|
public void clearClipRect() { |
|
|
@ -677,6 +770,11 @@ public class JoglRenderer implements Renderer { |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
gl.glDisable(GL.GL_SCISSOR_TEST); |
|
|
|
gl.glDisable(GL.GL_SCISSOR_TEST); |
|
|
|
context.clipRectEnabled = false; |
|
|
|
context.clipRectEnabled = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clipX = 0; |
|
|
|
|
|
|
|
clipY = 0; |
|
|
|
|
|
|
|
clipW = 0; |
|
|
|
|
|
|
|
clipH = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1088,13 +1186,13 @@ public class JoglRenderer implements Renderer { |
|
|
|
if (gl.isExtensionAvailable("GL_EXT_framebuffer_blit")) { |
|
|
|
if (gl.isExtensionAvailable("GL_EXT_framebuffer_blit")) { |
|
|
|
int srcX0 = 0; |
|
|
|
int srcX0 = 0; |
|
|
|
int srcY0 = 0; |
|
|
|
int srcY0 = 0; |
|
|
|
int srcX1 = 0; |
|
|
|
int srcX1/* = 0*/; |
|
|
|
int srcY1 = 0; |
|
|
|
int srcY1/* = 0*/; |
|
|
|
|
|
|
|
|
|
|
|
int dstX0 = 0; |
|
|
|
int dstX0 = 0; |
|
|
|
int dstY0 = 0; |
|
|
|
int dstY0 = 0; |
|
|
|
int dstX1 = 0; |
|
|
|
int dstX1/* = 0*/; |
|
|
|
int dstY1 = 0; |
|
|
|
int dstY1/* = 0*/; |
|
|
|
|
|
|
|
|
|
|
|
int prevFBO = context.boundFBO; |
|
|
|
int prevFBO = context.boundFBO; |
|
|
|
|
|
|
|
|
|
|
@ -1800,6 +1898,7 @@ public class JoglRenderer implements Renderer { |
|
|
|
img.clearUpdateNeeded(); |
|
|
|
img.clearUpdateNeeded(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//FIXME remove it
|
|
|
|
private void checkTexturingUsed() { |
|
|
|
private void checkTexturingUsed() { |
|
|
|
IDList textureList = context.textureIndexList; |
|
|
|
IDList textureList = context.textureIndexList; |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
@ -1878,6 +1977,9 @@ public class JoglRenderer implements Renderer { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************\ |
|
|
|
|
|
|
|
|* Vertex Buffers and Attributes *| |
|
|
|
|
|
|
|
\*********************************************************************/ |
|
|
|
private int convertUsage(Usage usage) { |
|
|
|
private int convertUsage(Usage usage) { |
|
|
|
switch (usage) { |
|
|
|
switch (usage) { |
|
|
|
case Static: |
|
|
|
case Static: |
|
|
@ -1891,29 +1993,68 @@ public class JoglRenderer implements Renderer { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private int convertFormat(VertexBuffer.Format format) { |
|
|
|
|
|
|
|
switch (format) { |
|
|
|
|
|
|
|
case Byte: |
|
|
|
|
|
|
|
return GL.GL_BYTE; |
|
|
|
|
|
|
|
case UnsignedByte: |
|
|
|
|
|
|
|
return GL.GL_UNSIGNED_BYTE; |
|
|
|
|
|
|
|
case Short: |
|
|
|
|
|
|
|
return GL.GL_SHORT; |
|
|
|
|
|
|
|
case UnsignedShort: |
|
|
|
|
|
|
|
return GL.GL_UNSIGNED_SHORT; |
|
|
|
|
|
|
|
case Int: |
|
|
|
|
|
|
|
return GL2.GL_INT; |
|
|
|
|
|
|
|
case UnsignedInt: |
|
|
|
|
|
|
|
return GL.GL_UNSIGNED_INT; |
|
|
|
|
|
|
|
// case Half:
|
|
|
|
|
|
|
|
// return NVHalfFloat.GL_HALF_FLOAT_NV;
|
|
|
|
|
|
|
|
// return ARBHalfFloatVertex.GL_HALF_FLOAT;
|
|
|
|
|
|
|
|
case Float: |
|
|
|
|
|
|
|
return GL.GL_FLOAT; |
|
|
|
|
|
|
|
case Double: |
|
|
|
|
|
|
|
return GL2.GL_DOUBLE; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new UnsupportedOperationException("Unknown buffer format."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void updateBufferData(VertexBuffer vb) { |
|
|
|
public void updateBufferData(VertexBuffer vb) { |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
int bufId = vb.getId(); |
|
|
|
int bufId = vb.getId(); |
|
|
|
|
|
|
|
boolean created = false; |
|
|
|
if (bufId == -1) { |
|
|
|
if (bufId == -1) { |
|
|
|
// create buffer
|
|
|
|
// create buffer
|
|
|
|
gl.glGenBuffers(1, intBuf1); |
|
|
|
gl.glGenBuffers(1, intBuf1); |
|
|
|
bufId = intBuf1.get(0); |
|
|
|
bufId = intBuf1.get(0); |
|
|
|
vb.setId(bufId); |
|
|
|
vb.setId(bufId); |
|
|
|
objManager.registerForCleanup(vb); |
|
|
|
objManager.registerForCleanup(vb); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//statistics.onNewVertexBuffer();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
created = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// bind buffer
|
|
|
|
int target; |
|
|
|
int target; |
|
|
|
if (vb.getBufferType() == VertexBuffer.Type.Index) { |
|
|
|
if (vb.getBufferType() == VertexBuffer.Type.Index) { |
|
|
|
target = GL.GL_ELEMENT_ARRAY_BUFFER; |
|
|
|
target = GL.GL_ELEMENT_ARRAY_BUFFER; |
|
|
|
if (context.boundElementArrayVBO != bufId) { |
|
|
|
if (context.boundElementArrayVBO != bufId) { |
|
|
|
gl.glBindBuffer(target, bufId); |
|
|
|
gl.glBindBuffer(target, bufId); |
|
|
|
context.boundElementArrayVBO = bufId; |
|
|
|
context.boundElementArrayVBO = bufId; |
|
|
|
|
|
|
|
//statistics.onVertexBufferUse(vb, true);
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
//statistics.onVertexBufferUse(vb, false);
|
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
target = GL.GL_ARRAY_BUFFER; |
|
|
|
target = GL.GL_ARRAY_BUFFER; |
|
|
|
if (context.boundArrayVBO != bufId) { |
|
|
|
if (context.boundArrayVBO != bufId) { |
|
|
|
gl.glBindBuffer(target, bufId); |
|
|
|
gl.glBindBuffer(target, bufId); |
|
|
|
context.boundArrayVBO = bufId; |
|
|
|
context.boundArrayVBO = bufId; |
|
|
|
|
|
|
|
//statistics.onVertexBufferUse(vb, true);
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
//statistics.onVertexBufferUse(vb, false);
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1921,7 +2062,12 @@ public class JoglRenderer implements Renderer { |
|
|
|
Buffer data = vb.getData(); |
|
|
|
Buffer data = vb.getData(); |
|
|
|
data.rewind(); |
|
|
|
data.rewind(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (created || vb.hasDataSizeChanged()) { |
|
|
|
|
|
|
|
// upload data based on format
|
|
|
|
gl.glBufferData(target, data.capacity() * vb.getFormat().getComponentSize(), data, usage); |
|
|
|
gl.glBufferData(target, data.capacity() * vb.getFormat().getComponentSize(), data, usage); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
gl.glBufferSubData(target, 0, data.capacity() * vb.getFormat().getComponentSize(), data); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
vb.clearUpdateNeeded(); |
|
|
|
vb.clearUpdateNeeded(); |
|
|
|
} |
|
|
|
} |
|
|
@ -1935,9 +2081,101 @@ public class JoglRenderer implements Renderer { |
|
|
|
intBuf1.position(0).limit(1); |
|
|
|
intBuf1.position(0).limit(1); |
|
|
|
gl.glDeleteBuffers(1, intBuf1); |
|
|
|
gl.glDeleteBuffers(1, intBuf1); |
|
|
|
vb.resetObject(); |
|
|
|
vb.resetObject(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//statistics.onDeleteVertexBuffer();
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void clearVertexAttribs() { |
|
|
|
|
|
|
|
IDList attribList = context.attribIndexList; |
|
|
|
|
|
|
|
for (int i = 0; i < attribList.oldLen; i++) { |
|
|
|
|
|
|
|
int idx = attribList.oldList[i]; |
|
|
|
|
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
|
|
|
|
gl.getGL2().glDisableVertexAttribArray(idx); |
|
|
|
|
|
|
|
context.boundAttribs[idx] = null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
context.attribIndexList.copyNewToOld(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) { |
|
|
|
|
|
|
|
if (vb.getBufferType() == VertexBuffer.Type.Index) { |
|
|
|
|
|
|
|
throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int programId = context.boundShaderProgram; |
|
|
|
|
|
|
|
if (programId > 0) { |
|
|
|
|
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
|
|
|
|
Attribute attrib = boundShader.getAttribute(vb.getBufferType()); |
|
|
|
|
|
|
|
int loc = attrib.getLocation(); |
|
|
|
|
|
|
|
if (loc == -1) { |
|
|
|
|
|
|
|
return; // not defined
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (loc == -2) { |
|
|
|
|
|
|
|
stringBuf.setLength(0); |
|
|
|
|
|
|
|
stringBuf.append("in").append(vb.getBufferType().name()).append('\0'); |
|
|
|
|
|
|
|
updateNameBuffer(); |
|
|
|
|
|
|
|
loc = gl.getGL2().glGetAttribLocation(programId, stringBuf.toString()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// not really the name of it in the shader (inPosition\0) but
|
|
|
|
|
|
|
|
// the internal name of the enum (Position).
|
|
|
|
|
|
|
|
if (loc < 0) { |
|
|
|
|
|
|
|
attrib.setLocation(-1); |
|
|
|
|
|
|
|
return; // not available in shader.
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
attrib.setLocation(loc); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (vb.isUpdateNeeded() && idb == null) { |
|
|
|
|
|
|
|
updateBufferData(vb); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VertexBuffer[] attribs = context.boundAttribs; |
|
|
|
|
|
|
|
if (!context.attribIndexList.moveToNew(loc)) { |
|
|
|
|
|
|
|
gl.getGL2().glEnableVertexAttribArray(loc); |
|
|
|
|
|
|
|
//System.out.println("Enabled ATTRIB IDX: "+loc);
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (attribs[loc] != vb) { |
|
|
|
|
|
|
|
// NOTE: Use id from interleaved buffer if specified
|
|
|
|
|
|
|
|
int bufId = idb != null ? idb.getId() : vb.getId(); |
|
|
|
|
|
|
|
assert bufId != -1; |
|
|
|
|
|
|
|
if (context.boundArrayVBO != bufId) { |
|
|
|
|
|
|
|
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufId); |
|
|
|
|
|
|
|
context.boundArrayVBO = bufId; |
|
|
|
|
|
|
|
//statistics.onVertexBufferUse(vb, true);
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
//statistics.onVertexBufferUse(vb, false);
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl.getGL2().glVertexAttribPointer(loc, |
|
|
|
|
|
|
|
vb.getNumComponents(), |
|
|
|
|
|
|
|
convertFormat(vb.getFormat()), |
|
|
|
|
|
|
|
vb.isNormalized(), |
|
|
|
|
|
|
|
vb.getStride(), |
|
|
|
|
|
|
|
vb.getOffset()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
attribs[loc] = vb; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
throw new IllegalStateException("Cannot render mesh without shader bound"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setVertexAttrib(VertexBuffer vb) { |
|
|
|
|
|
|
|
setVertexAttrib(vb, null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) { |
|
|
|
|
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
|
|
|
|
if (count > 1) { |
|
|
|
|
|
|
|
gl.getGL2().glDrawArraysInstanced(convertElementMode(mode), 0, |
|
|
|
|
|
|
|
vertCount, count); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
gl.glDrawArrays(convertElementMode(mode), 0, vertCount); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//FIXME remove
|
|
|
|
private int convertArrayType(VertexBuffer.Type type) { |
|
|
|
private int convertArrayType(VertexBuffer.Type type) { |
|
|
|
switch (type) { |
|
|
|
switch (type) { |
|
|
|
case Position: |
|
|
|
case Position: |
|
|
@ -1953,6 +2191,7 @@ public class JoglRenderer implements Renderer { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//FIXME remove
|
|
|
|
private int convertVertexFormat(VertexBuffer.Format fmt) { |
|
|
|
private int convertVertexFormat(VertexBuffer.Format fmt) { |
|
|
|
switch (fmt) { |
|
|
|
switch (fmt) { |
|
|
|
case Byte: |
|
|
|
case Byte: |
|
|
@ -1978,6 +2217,93 @@ public class JoglRenderer implements Renderer { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) { |
|
|
|
|
|
|
|
if (indexBuf.getBufferType() != VertexBuffer.Type.Index) { |
|
|
|
|
|
|
|
throw new IllegalArgumentException("Only index buffers are allowed as triangle lists."); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (indexBuf.isUpdateNeeded()) { |
|
|
|
|
|
|
|
updateBufferData(indexBuf); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int bufId = indexBuf.getId(); |
|
|
|
|
|
|
|
assert bufId != -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
|
|
|
|
if (context.boundElementArrayVBO != bufId) { |
|
|
|
|
|
|
|
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, bufId); |
|
|
|
|
|
|
|
context.boundElementArrayVBO = bufId; |
|
|
|
|
|
|
|
//statistics.onVertexBufferUse(indexBuf, true);
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
//statistics.onVertexBufferUse(indexBuf, true);
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int vertCount = mesh.getVertexCount(); |
|
|
|
|
|
|
|
boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mesh.getMode() == Mode.Hybrid) { |
|
|
|
|
|
|
|
int[] modeStart = mesh.getModeStart(); |
|
|
|
|
|
|
|
int[] elementLengths = mesh.getElementLengths(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int elMode = convertElementMode(Mode.Triangles); |
|
|
|
|
|
|
|
int fmt = convertFormat(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]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (useInstancing) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
indexBuf.getData().position(curOffset); |
|
|
|
|
|
|
|
indexBuf.getData().limit(curOffset + elementLength); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl.getGL2GL3().glDrawElementsInstanced(elMode, |
|
|
|
|
|
|
|
elementLength, |
|
|
|
|
|
|
|
fmt, |
|
|
|
|
|
|
|
indexBuf.getData(), |
|
|
|
|
|
|
|
count); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
gl.getGL2().glDrawRangeElements(elMode, |
|
|
|
|
|
|
|
0, |
|
|
|
|
|
|
|
vertCount, |
|
|
|
|
|
|
|
elementLength, |
|
|
|
|
|
|
|
fmt, |
|
|
|
|
|
|
|
curOffset); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//FIXME check whether elSize is required
|
|
|
|
|
|
|
|
curOffset += elementLength/* * elSize*/; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (useInstancing) { |
|
|
|
|
|
|
|
gl.getGL2GL3().glDrawElementsInstanced(convertElementMode(mesh.getMode()), |
|
|
|
|
|
|
|
indexBuf.getData().limit(), |
|
|
|
|
|
|
|
convertFormat(indexBuf.getFormat()), |
|
|
|
|
|
|
|
indexBuf.getData(), |
|
|
|
|
|
|
|
count); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
gl.getGL2().glDrawRangeElements(convertElementMode(mesh.getMode()), |
|
|
|
|
|
|
|
0, |
|
|
|
|
|
|
|
vertCount, |
|
|
|
|
|
|
|
indexBuf.getData().limit(), |
|
|
|
|
|
|
|
convertFormat(indexBuf.getFormat()), |
|
|
|
|
|
|
|
0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************\ |
|
|
|
|
|
|
|
|* Render Calls *| |
|
|
|
|
|
|
|
\*********************************************************************/ |
|
|
|
private int convertElementMode(Mesh.Mode mode) { |
|
|
|
private int convertElementMode(Mesh.Mode mode) { |
|
|
|
switch (mode) { |
|
|
|
switch (mode) { |
|
|
|
case Points: |
|
|
|
case Points: |
|
|
@ -2095,102 +2421,8 @@ public class JoglRenderer implements Renderer { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) { |
|
|
|
|
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
|
|
|
|
int arrayType = convertArrayType(vb.getBufferType()); |
|
|
|
|
|
|
|
if (arrayType == -1) { |
|
|
|
|
|
|
|
return; // unsupported
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl.getGL2().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.clear(); |
|
|
|
|
|
|
|
data.position(vb.getOffset()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (vb.getBufferType()) { |
|
|
|
|
|
|
|
case Position: |
|
|
|
|
|
|
|
gl.getGL2().glVertexPointer(comps, type, vb.getStride(), data); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case Normal: |
|
|
|
|
|
|
|
gl.getGL2().glNormalPointer(type, vb.getStride(), data); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case Color: |
|
|
|
|
|
|
|
gl.getGL2().glColorPointer(comps, type, vb.getStride(), data); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case TexCoord: |
|
|
|
|
|
|
|
gl.getGL2().glTexCoordPointer(comps, type, vb.getStride(), data); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setVertexAttrib(VertexBuffer vb) { |
|
|
|
|
|
|
|
setVertexAttrib(vb, null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void clearVertexAttribs() { |
|
|
|
|
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
|
|
|
|
for (int i = 0; i < 16; i++) { |
|
|
|
|
|
|
|
VertexBuffer vb = context.boundAttribs[i]; |
|
|
|
|
|
|
|
if (vb != null) { |
|
|
|
|
|
|
|
int arrayType = convertArrayType(vb.getBufferType()); |
|
|
|
|
|
|
|
gl.getGL2().glDisableClientState(arrayType); |
|
|
|
|
|
|
|
context.boundAttribs[vb.getBufferType().ordinal()] = null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) { |
|
|
|
|
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
|
|
|
|
Mesh.Mode mode = mesh.getMode(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Buffer indexData = indexBuf.getData(); |
|
|
|
|
|
|
|
indexData.clear(); |
|
|
|
|
|
|
|
if (mesh.getMode() == Mode.Hybrid) { |
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
gl.glDrawElements(elMode, elementLength, fmt, indexData); |
|
|
|
|
|
|
|
curOffset += elementLength; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
gl.glDrawElements(convertElementMode(mode), indexData.capacity(), |
|
|
|
|
|
|
|
convertVertexFormat(indexBuf.getFormat()), indexData); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void renderMeshDefault(Mesh mesh, int lod, int count) { |
|
|
|
private void renderMeshDefault(Mesh mesh, int lod, int count) { |
|
|
|
VertexBuffer indices = null; |
|
|
|
VertexBuffer indices/* = null*/; |
|
|
|
VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); |
|
|
|
VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); |
|
|
|
IntMap<VertexBuffer> buffers = mesh.getBuffers(); |
|
|
|
IntMap<VertexBuffer> buffers = mesh.getBuffers(); |
|
|
|
if (mesh.getNumLodLevels() > 0) { |
|
|
|
if (mesh.getNumLodLevels() > 0) { |
|
|
@ -2230,7 +2462,7 @@ public class JoglRenderer implements Renderer { |
|
|
|
|
|
|
|
|
|
|
|
private void renderMeshVBO(Mesh mesh, int lod, int count) { |
|
|
|
private void renderMeshVBO(Mesh mesh, int lod, int count) { |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
GL gl = GLContext.getCurrentGL(); |
|
|
|
VertexBuffer indices = null; |
|
|
|
VertexBuffer indices/* = null*/; |
|
|
|
VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); |
|
|
|
VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); |
|
|
|
if (interleavedData != null && interleavedData.isUpdateNeeded()) { |
|
|
|
if (interleavedData != null && interleavedData.isUpdateNeeded()) { |
|
|
|
updateBufferData(interleavedData); |
|
|
|
updateBufferData(interleavedData); |
|
|
|