diff options
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/util/glsl')
20 files changed, 1877 insertions, 469 deletions
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java index 602d283d6..1f402f48b 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java @@ -33,40 +33,47 @@ import java.nio.Buffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; -import jogamp.opengl.util.GLArrayHandler; import jogamp.opengl.util.GLArrayHandlerFlat; +import jogamp.opengl.util.GLVBOArrayHandler; import com.jogamp.opengl.util.GLArrayDataEditable; import com.jogamp.opengl.util.glsl.ShaderState; /** - * Used for 1:1 GLSL arrays, i.e. where the buffer data - * represents this array only. + * Used for 1:1 GLSL arrays, i.e. where the buffer data + * represents this array only. */ -public class GLSLArrayHandler implements GLArrayHandler { - private GLArrayDataEditable ad; +public class GLSLArrayHandler extends GLVBOArrayHandler { public GLSLArrayHandler(GLArrayDataEditable ad) { - this.ad = ad; + super(ad); } - + + @Override public final void setSubArrayVBOName(int vboName) { throw new UnsupportedOperationException(); } - + + @Override public final void addSubHandler(GLArrayHandlerFlat handler) { throw new UnsupportedOperationException(); } - - public final void syncData(GL gl, boolean enable, Object ext) { + + @Override + public final void enableState(GL gl, boolean enable, Object ext) { final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - + if( null != ext ) { + enableShaderState(glsl, enable, (ShaderState)ext); + } else { + enableSimple(glsl, enable); + } + } + + private final void enableShaderState(GL2ES2 glsl, boolean enable, ShaderState st) { if(enable) { - final Buffer buffer = ad.getBuffer(); /* * This would be the non optimized code path: - * + * if(ad.isVBO()) { glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); if(!ad.isVBOWritten()) { @@ -78,6 +85,7 @@ public class GLSLArrayHandler implements GLArrayHandler { } st.vertexAttribPointer(glsl, ad); */ + final Buffer buffer = ad.getBuffer(); if(ad.isVBO()) { // bind and refresh the VBO / vertex-attr only if necessary if(!ad.isVBOWritten()) { @@ -87,6 +95,7 @@ public class GLSLArrayHandler implements GLArrayHandler { } ad.setVBOWritten(true); st.vertexAttribPointer(glsl, ad); + glsl.glBindBuffer(ad.getVBOTarget(), 0); } else if(st.getAttribLocation(glsl, ad) >= 0) { // didn't experience a performance hit on this query .. // (using ShaderState's location query above to validate the location) @@ -95,26 +104,69 @@ public class GLSLArrayHandler implements GLArrayHandler { if(ad.getVBOName() != qi[0]) { glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); st.vertexAttribPointer(glsl, ad); + glsl.glBindBuffer(ad.getVBOTarget(), 0); } } } else if(null!=buffer) { st.vertexAttribPointer(glsl, ad); } - } else if(ad.isVBO()) { - glsl.glBindBuffer(ad.getVBOTarget(), 0); - } - } - - public final void enableState(GL gl, boolean enable, Object ext) { - final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - - if(enable) { + st.enableVertexAttribArray(glsl, ad); } else { st.disableVertexAttribArray(glsl, ad); } } + private final void enableSimple(GL2ES2 glsl, boolean enable) { + final int location = ad.getLocation(); + if( 0 > location ) { + return; + } + if(enable) { + /* + * This would be the non optimized code path: + * + if(ad.isVBO()) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + if(!ad.isVBOWritten()) { + if(null!=buffer) { + glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage()); + } + ad.setVBOWritten(true); + } + } + st.vertexAttribPointer(glsl, ad); + */ + final Buffer buffer = ad.getBuffer(); + if(ad.isVBO()) { + // bind and refresh the VBO / vertex-attr only if necessary + if(!ad.isVBOWritten()) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + if(null!=buffer) { + glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage()); + } + ad.setVBOWritten(true); + glsl.glVertexAttribPointer(ad); + glsl.glBindBuffer(ad.getVBOTarget(), 0); + } else { + // didn't experience a performance hit on this query .. + // (using ShaderState's location query above to validate the location) + final int[] qi = new int[1]; + glsl.glGetVertexAttribiv(location, GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); + if(ad.getVBOName() != qi[0]) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + glsl.glVertexAttribPointer(ad); + glsl.glBindBuffer(ad.getVBOTarget(), 0); + } + } + } else if(null!=buffer) { + glsl.glVertexAttribPointer(ad); + } + + glsl.glEnableVertexAttribArray(location); + } else { + glsl.glDisableVertexAttribArray(location); + } + } } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java index c4b761b13..34a381d7d 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java @@ -37,7 +37,7 @@ import com.jogamp.opengl.util.GLArrayDataWrapper; import com.jogamp.opengl.util.glsl.ShaderState; /** - * Used for interleaved GLSL arrays, i.e. where the buffer data itself is handled + * Used for interleaved GLSL arrays, i.e. where the buffer data itself is handled * separately and interleaves many arrays. */ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat { @@ -47,43 +47,57 @@ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat { this.ad = ad; } + @Override public GLArrayDataWrapper getData() { return ad; } - - public final void syncData(GL gl, boolean enable, boolean force, Object ext) { - if(enable) { - final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; + @Override + public final void syncData(GL gl, Object ext) { + final GL2ES2 glsl = gl.getGL2ES2(); + if( null != ext ) { + ((ShaderState)ext).vertexAttribPointer(glsl, ad); + } else { + if( 0 <= ad.getLocation() ) { + glsl.glVertexAttribPointer(ad); + } + } + /** + * Due to probable application VBO switching, this might not make any sense .. + * + if(!written) { st.vertexAttribPointer(glsl, ad); - /** - * Due to probable application VBO switching, this might not make any sense .. - * - if(force) { + } else if(st.getAttribLocation(glsl, ad) >= 0) { + final int[] qi = new int[1]; + glsl.glGetVertexAttribiv(ad.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); + if(ad.getVBOName() != qi[0]) { + System.err.println("XXX1: "+ad.getName()+", vbo ad "+ad.getVBOName()+", gl "+qi[0]+", "+ad); st.vertexAttribPointer(glsl, ad); - } else if(st.getAttribLocation(glsl, ad) >= 0) { - final int[] qi = new int[1]; - glsl.glGetVertexAttribiv(ad.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); - if(ad.getVBOName() != qi[0]) { - System.err.println("XXX1: "+ad.getName()+", vbo ad "+ad.getVBOName()+", gl "+qi[0]+", "+ad); - st.vertexAttribPointer(glsl, ad); - } else { - System.err.println("XXX0: "+ad.getName()+", vbo ad "+ad.getVBOName()+", gl "+qi[0]+", "+ad); - } - }*/ - } + } else { + System.err.println("XXX0: "+ad.getName()+", vbo ad "+ad.getVBOName()+", gl "+qi[0]+", "+ad); + } + }*/ } + @Override public final void enableState(GL gl, boolean enable, Object ext) { final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - - if(enable) { - st.enableVertexAttribArray(glsl, ad); + if( null != ext ) { + final ShaderState st = (ShaderState)ext; + if(enable) { + st.enableVertexAttribArray(glsl, ad); + } else { + st.disableVertexAttribArray(glsl, ad); + } } else { - st.disableVertexAttribArray(glsl, ad); + final int location = ad.getLocation(); + if( 0 <= location ) { + if(enable) { + glsl.glEnableVertexAttribArray(location); + } else { + glsl.glDisableVertexAttribArray(location); + } + } } - } + } } - diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java index f50429623..e153082e0 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java @@ -28,75 +28,59 @@ package jogamp.opengl.util.glsl; -import java.nio.Buffer; import java.util.ArrayList; import java.util.List; import javax.media.opengl.GL; -import jogamp.opengl.util.GLArrayHandler; import jogamp.opengl.util.GLArrayHandlerFlat; +import jogamp.opengl.util.GLVBOArrayHandler; import com.jogamp.opengl.util.GLArrayDataEditable; /** - * Interleaved fixed function arrays, i.e. where this buffer data - * represents many arrays. + * Interleaved fixed function arrays, i.e. where this buffer data + * represents many arrays. */ -public class GLSLArrayHandlerInterleaved implements GLArrayHandler { - private GLArrayDataEditable ad; - private List<GLArrayHandlerFlat> subArrays = new ArrayList<GLArrayHandlerFlat>(); +public class GLSLArrayHandlerInterleaved extends GLVBOArrayHandler { + private final List<GLArrayHandlerFlat> subArrays = new ArrayList<GLArrayHandlerFlat>(); public GLSLArrayHandlerInterleaved(GLArrayDataEditable ad) { - this.ad = ad; + super(ad); } - + + @Override public final void setSubArrayVBOName(int vboName) { for(int i=0; i<subArrays.size(); i++) { subArrays.get(i).getData().setVBOName(vboName); - } + } } - + + @Override public final void addSubHandler(GLArrayHandlerFlat handler) { subArrays.add(handler); } - private final void syncSubData(GL gl, boolean enable, boolean force, Object ext) { + private final void syncSubData(GL gl, Object ext) { for(int i=0; i<subArrays.size(); i++) { - subArrays.get(i).syncData(gl, enable, force, ext); - } - } - - public final void syncData(GL gl, boolean enable, Object ext) { - if(!ad.isVBO()) { - throw new InternalError("Interleaved handle is not VBO: "+ad); - } - + subArrays.get(i).syncData(gl, ext); + } + } + + @Override + public final void enableState(GL gl, boolean enable, Object ext) { if(enable) { - final Buffer buffer = ad.getBuffer(); - final boolean vboWritten = ad.isVBOWritten(); - - // always bind and refresh the VBO mgr, - // in case more than one gl*Pointer objects are in use - gl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); - if(!vboWritten) { - if(null!=buffer) { - gl.glBufferData(ad.getVBOTarget(), buffer.limit() * ad.getComponentSizeInBytes(), buffer, ad.getVBOUsage()); - } - ad.setVBOWritten(true); + if(!ad.isVBO()) { + throw new InternalError("Interleaved handle is not VBO: "+ad); } - // sub data will decide weather to update the vertex attrib pointer - syncSubData(gl, true, !vboWritten, ext); - } else { - // NOP on GLSL: syncSubData(gl, false, ext); - gl.glBindBuffer(ad.getVBOTarget(), 0); + bindBuffer(gl, true); + // sub data will decide whether to update the vertex attrib pointer + syncSubData(gl, ext); + bindBuffer(gl, false); } - } - - public final void enableState(GL gl, boolean enable, Object ext) { for(int i=0; i<subArrays.size(); i++) { subArrays.get(i).enableState(gl, enable, ext); - } + } } } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java new file mode 100644 index 000000000..dba408554 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java @@ -0,0 +1,195 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.opengl.util.glsl; + +import java.nio.FloatBuffer; + +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLArrayData; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +public class GLSLTextureRaster { + private final boolean textureVertFlipped; + private final int textureUnit; + + private ShaderProgram sp; + private PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + private GLUniformData activeTexUniform; + private GLArrayDataServer interleavedVBO; + + public GLSLTextureRaster(int textureUnit, boolean textureVertFlipped) { + this.textureVertFlipped = textureVertFlipped; + this.textureUnit = textureUnit; + } + + public int getTextureUnit() { return textureUnit; } + + static final String shaderBasename = "texture01_xxx"; + static final String shaderSrcPath = "../../shader"; + static final String shaderBinPath = "../../shader/bin"; + + public void init(GL2ES2 gl) { + // Create & Compile the shader objects + final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), + shaderSrcPath, shaderBinPath, shaderBasename, true); + final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), + shaderSrcPath, shaderBinPath, shaderBasename, true); + rsVp.defaultShaderCustomization(gl, true, true); + rsFp.defaultShaderCustomization(gl, true, true); + + // Create & Link the shader program + sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + if(!sp.link(gl, System.err)) { + throw new GLException("Couldn't link program: "+sp); + } + sp.useProgram(gl, true); + + // setup mgl_PMVMatrix + pmvMatrix = new PMVMatrix(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + if( pmvMatrixUniform.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Couldn't locate "+pmvMatrixUniform+" in shader: "+sp); + } + gl.glUniform(pmvMatrixUniform); + + activeTexUniform = new GLUniformData("mgl_Texture0", textureUnit); + if( activeTexUniform.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Couldn't locate "+activeTexUniform+" in shader: "+sp); + } + gl.glUniform(activeTexUniform); + + final float[] s_quadTexCoords; + if( textureVertFlipped ) { + s_quadTexCoords = s_quadTexCoords01; + } else { + s_quadTexCoords = s_quadTexCoords00; + } + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+2, GL.GL_FLOAT, false, 2*4, GL.GL_STATIC_DRAW); + { + final GLArrayData vArrayData = interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + if( vArrayData.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Couldn't locate "+vArrayData+" in shader: "+sp); + } + final GLArrayData tArrayData = interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + if( tArrayData.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Couldn't locate "+tArrayData+" in shader: "+sp); + } + final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + for(int i=0; i<4; i++) { + ib.put(s_quadVertices, i*3, 3); + ib.put(s_quadTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + + sp.useProgram(gl, false); + } + + public void reshape(GL2ES2 gl, int x, int y, int width, int height) { + if(null != sp) { + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + sp.useProgram(gl, true); + gl.glUniform(pmvMatrixUniform); + sp.useProgram(gl, false); + } + } + + public void dispose(GL2ES2 gl) { + if(null != pmvMatrixUniform) { + pmvMatrixUniform = null; + } + if(null != pmvMatrix) { + pmvMatrix.destroy(); + pmvMatrix=null; + } + if(null != interleavedVBO) { + interleavedVBO.destroy(gl); + interleavedVBO=null; + } + if(null != sp) { + sp.destroy(gl); + sp=null; + } + } + + public void display(GL2ES2 gl) { + if(null != sp) { + sp.useProgram(gl, true); + interleavedVBO.enableBuffer(gl, true); + + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + + interleavedVBO.enableBuffer(gl, false); + sp.useProgram(gl, false); + } + } + + private static final float[] s_quadVertices = { + -1f, -1f, 0f, // LB + 1f, -1f, 0f, // RB + -1f, 1f, 0f, // LT + 1f, 1f, 0f // RT + }; + private static final float[] s_quadTexCoords00 = { + 0f, 0f, // LB + 1f, 0f, // RB + 0f, 1f, // LT + 1f, 1f // RT + }; + private static final float[] s_quadTexCoords01 = { + 0f, 1f, // LB + 1f, 1f, // RB + 0f, 0f, // LT + 1f, 0f // RT + }; +} + diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java index 897967f8b..458a9c94f 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java @@ -29,87 +29,115 @@ package jogamp.opengl.util.glsl.fixedfunc; -import javax.media.opengl.*; -import javax.media.opengl.fixedfunc.*; -import com.jogamp.common.nio.Buffers; -import com.jogamp.opengl.util.*; +import java.nio.Buffer; +import java.nio.IntBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLArrayData; +import javax.media.opengl.GLException; +import javax.media.opengl.fixedfunc.GLLightingFunc; +import javax.media.opengl.fixedfunc.GLMatrixFunc; +import javax.media.opengl.fixedfunc.GLPointerFunc; -import java.nio.*; +import com.jogamp.common.nio.Buffers; +import com.jogamp.common.util.ValueConv; +import com.jogamp.opengl.util.GLArrayDataWrapper; +import com.jogamp.opengl.util.GLBuffers; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode; public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFunc { public static final int MAX_TEXTURE_UNITS = 8; - protected FixedFuncPipeline fixedFunction=null; - protected PMVMatrix pmvMatrix=null; - protected GL2ES2 gl=null; + protected FixedFuncPipeline fixedFunction; + protected PMVMatrix pmvMatrix; + protected boolean ownsPMVMatrix; + protected GL2ES2 gl; - public FixedFuncHook (GL2ES2 gl) { - this(gl, null); + /** + * @param gl + * @param mode TODO + * @param pmvMatrix optional pass through PMVMatrix for the {@link FixedFuncHook} and {@link FixedFuncPipeline} + */ + public FixedFuncHook (GL2ES2 gl, ShaderSelectionMode mode, PMVMatrix pmvMatrix) { + this.gl = gl; + if(null != pmvMatrix) { + this.ownsPMVMatrix = false; + this.pmvMatrix = pmvMatrix; + } else { + this.ownsPMVMatrix = true; + this.pmvMatrix = new PMVMatrix(); + } + fixedFunction = new FixedFuncPipeline(this.gl, mode, this.pmvMatrix); } - public FixedFuncHook (GL2ES2 gl, PMVMatrix matrix) { + /** + * @param gl + * @param mode TODO + * @param pmvMatrix optional pass through PMVMatrix for the {@link FixedFuncHook} and {@link FixedFuncPipeline} + */ + public FixedFuncHook(GL2ES2 gl, ShaderSelectionMode mode, PMVMatrix pmvMatrix, + Class<?> shaderRootClass, String shaderSrcRoot, String shaderBinRoot, + String vertexColorFile, String vertexColorLightFile, + String fragmentColorFile, String fragmentColorTextureFile) { this.gl = gl; - pmvMatrix = (null!=matrix)?matrix:new PMVMatrix(); + if(null != pmvMatrix) { + this.ownsPMVMatrix = false; + this.pmvMatrix = pmvMatrix; + } else { + this.ownsPMVMatrix = true; + this.pmvMatrix = new PMVMatrix(); + } - fixedFunction = new FixedFuncPipeline(gl, pmvMatrix); + fixedFunction = new FixedFuncPipeline(this.gl, mode, this.pmvMatrix, shaderRootClass, shaderSrcRoot, + shaderBinRoot, vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile); } - public FixedFuncHook(GL2ES2 gl, PMVMatrix matrix, - Class<?> shaderRootClass, String shaderSrcRoot, String shaderBinRoot, - String vertexColorFile, - String vertexColorLightFile, - String fragmentColorFile, - String fragmentColorTextureFile) { - this.gl = gl; - pmvMatrix = matrix; + public boolean verbose() { return fixedFunction.verbose(); } - fixedFunction = new FixedFuncPipeline(gl, pmvMatrix, - shaderRootClass, shaderSrcRoot, shaderBinRoot, - vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile); - } + public void setVerbose(boolean v) { fixedFunction.setVerbose(v); } public void destroy() { fixedFunction.destroy(gl); fixedFunction = null; + if(ownsPMVMatrix) { + pmvMatrix.destroy(); + } + pmvMatrix=null; + gl=null; } public PMVMatrix getMatrix() { return pmvMatrix; } // - // FixedFuncHookIf - hooks + // FixedFuncHookIf - hooks // public void glDrawArrays(int mode, int first, int count) { - fixedFunction.validate(gl); - gl.glDrawArrays(mode, first, count); + fixedFunction.glDrawArrays(gl, mode, first, count); } public void glDrawElements(int mode, int count, int type, java.nio.Buffer indices) { - fixedFunction.validate(gl); - gl.glDrawElements(mode, count, type, indices); + fixedFunction.glDrawElements(gl, mode, count, type, indices); } public void glDrawElements(int mode, int count, int type, long indices_buffer_offset) { - fixedFunction.validate(gl); - gl.glDrawElements(mode, count, type, indices_buffer_offset); + fixedFunction.glDrawElements(gl, mode, count, type, indices_buffer_offset); } public void glActiveTexture(int texture) { - fixedFunction.glActiveTexture(gl, texture); + fixedFunction.glActiveTexture(texture); gl.glActiveTexture(texture); } public void glEnable(int cap) { - if(fixedFunction.glEnable(gl, cap, true)) { + if(fixedFunction.glEnable(cap, true)) { gl.glEnable(cap); } } public void glDisable(int cap) { - if(fixedFunction.glEnable(gl, cap, false)) { + if(fixedFunction.glEnable(cap, false)) { gl.glDisable(cap); } } - public void glCullFace(int faceName) { - fixedFunction.glCullFace(gl, faceName); - gl.glCullFace(faceName); - } - + @Override public void glGetFloatv(int pname, java.nio.FloatBuffer params) { if(PMVMatrix.isMatrixGetName(pname)) { pmvMatrix.glGetFloatv(pname, params); @@ -117,6 +145,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } gl.glGetFloatv(pname, params); } + @Override public void glGetFloatv(int pname, float[] params, int params_offset) { if(PMVMatrix.isMatrixGetName(pname)) { pmvMatrix.glGetFloatv(pname, params, params_offset); @@ -124,6 +153,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } gl.glGetFloatv(pname, params, params_offset); } + @Override public void glGetIntegerv(int pname, IntBuffer params) { if(PMVMatrix.isMatrixGetName(pname)) { pmvMatrix.glGetIntegerv(pname, params); @@ -131,6 +161,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } gl.glGetIntegerv(pname, params); } + @Override public void glGetIntegerv(int pname, int[] params, int params_offset) { if(PMVMatrix.isMatrixGetName(pname)) { pmvMatrix.glGetIntegerv(pname, params, params_offset); @@ -139,95 +170,193 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun gl.glGetIntegerv(pname, params, params_offset); } - // + public void glTexEnvi(int target, int pname, int value) { + fixedFunction.glTexEnvi(target, pname, value); + } + public void glGetTexEnviv(int target, int pname, IntBuffer params) { + fixedFunction.glGetTexEnviv(target, pname, params); + } + public void glGetTexEnviv(int target, int pname, int[] params, int params_offset) { + fixedFunction.glGetTexEnviv(target, pname, params, params_offset); + } + public void glBindTexture(int target, int texture) { + fixedFunction.glBindTexture(target, texture); + gl.glBindTexture(target, texture); + } + public void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, + int format, int type, Buffer pixels) { + // align internalformat w/ format, an ES2 requirement + switch(internalformat) { + case 3: internalformat= ( GL.GL_RGBA == format ) ? GL.GL_RGBA : GL.GL_RGB; break; + case 4: internalformat= ( GL.GL_RGB == format ) ? GL.GL_RGB : GL.GL_RGBA; break; + } + fixedFunction.glTexImage2D(target, /* level, */ internalformat, /*width, height, border, */ format /*, type, pixels*/); + gl.glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); + } + public void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, + int format, int type, long pixels_buffer_offset) { + // align internalformat w/ format, an ES2 requirement + switch(internalformat) { + case 3: internalformat= ( GL.GL_RGBA == format ) ? GL.GL_RGBA : GL.GL_RGB; break; + case 4: internalformat= ( GL.GL_RGB == format ) ? GL.GL_RGB : GL.GL_RGBA; break; + } + fixedFunction.glTexImage2D(target, /* level, */ internalformat, /*width, height, border, */ format /*, type, pixels*/); + gl.glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels_buffer_offset); + } + + public void glPointSize(float size) { + fixedFunction.glPointSize(size); + } + public void glPointParameterf(int pname, float param) { + fixedFunction.glPointParameterf(pname, param); + } + public void glPointParameterfv(int pname, float[] params, int params_offset) { + fixedFunction.glPointParameterfv(pname, params, params_offset); + } + public void glPointParameterfv(int pname, java.nio.FloatBuffer params) { + fixedFunction.glPointParameterfv(pname, params); + } + + // // MatrixIf // public int glGetMatrixMode() { return pmvMatrix.glGetMatrixMode(); } + @Override public void glMatrixMode(int mode) { pmvMatrix.glMatrixMode(mode); } + @Override public void glLoadMatrixf(java.nio.FloatBuffer m) { pmvMatrix.glLoadMatrixf(m); } + @Override public void glLoadMatrixf(float[] m, int m_offset) { glLoadMatrixf(GLBuffers.newDirectFloatBuffer(m, m_offset)); } + @Override public void glPopMatrix() { pmvMatrix.glPopMatrix(); } + @Override public void glPushMatrix() { pmvMatrix.glPushMatrix(); } + @Override public void glLoadIdentity() { pmvMatrix.glLoadIdentity(); } + @Override public void glMultMatrixf(java.nio.FloatBuffer m) { pmvMatrix.glMultMatrixf(m); } + @Override public void glMultMatrixf(float[] m, int m_offset) { glMultMatrixf(GLBuffers.newDirectFloatBuffer(m, m_offset)); } + @Override public void glTranslatef(float x, float y, float z) { pmvMatrix.glTranslatef(x, y, z); } + @Override public void glRotatef(float angdeg, float x, float y, float z) { pmvMatrix.glRotatef(angdeg, x, y, z); } + @Override public void glScalef(float x, float y, float z) { pmvMatrix.glScalef(x, y, z); } + public void glOrtho(double left, double right, double bottom, double top, double near_val, double far_val) { + glOrthof((float) left, (float) right, (float) bottom, (float) top, (float) near_val, (float) far_val); + } + @Override public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) { pmvMatrix.glOrthof(left, right, bottom, top, zNear, zFar); } + public void glFrustum(double left, double right, double bottom, double top, double zNear, double zFar) { + glFrustumf((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar); + } + @Override public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar) { pmvMatrix.glFrustumf(left, right, bottom, top, zNear, zFar); } - // + // // LightingIf // + @Override public void glColor4f(float red, float green, float blue, float alpha) { - fixedFunction.glColor4fv(gl, GLBuffers.newDirectFloatBuffer(new float[] { red, green, blue, alpha })); + fixedFunction.glColor4f(gl, red, green, blue, alpha); } + public void glColor4ub(byte red, byte green, byte blue, byte alpha) { + glColor4f(ValueConv.byte_to_float(red, false), + ValueConv.byte_to_float(green, false), + ValueConv.byte_to_float(blue, false), + ValueConv.byte_to_float(alpha, false) ); + } + @Override public void glLightfv(int light, int pname, java.nio.FloatBuffer params) { fixedFunction.glLightfv(gl, light, pname, params); } + @Override public void glLightfv(int light, int pname, float[] params, int params_offset) { glLightfv(light, pname, GLBuffers.newDirectFloatBuffer(params, params_offset)); } + @Override public void glMaterialfv(int face, int pname, java.nio.FloatBuffer params) { fixedFunction.glMaterialfv(gl, face, pname, params); } + @Override public void glMaterialfv(int face, int pname, float[] params, int params_offset) { glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(params, params_offset)); } + @Override public void glMaterialf(int face, int pname, float param) { glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(new float[] { param })); } + + // + // Misc Simple States + // + @Override public void glShadeModel(int mode) { fixedFunction.glShadeModel(gl, mode); } + public void glAlphaFunc(int func, float ref) { + fixedFunction.glAlphaFunc(func, ref); + } + + /** ES2 supports CullFace implicit + public void glCullFace(int faceName) { + fixedFunction.glCullFace(faceName); + gl.glCullFace(faceName); + } */ // // PointerIf // + public void glClientActiveTexture(int textureUnit) { + fixedFunction.glClientActiveTexture(textureUnit); + } + @Override public void glEnableClientState(int glArrayIndex) { fixedFunction.glEnableClientState(gl, glArrayIndex); } + @Override public void glDisableClientState(int glArrayIndex) { fixedFunction.glDisableClientState(gl, glArrayIndex); } + @Override public void glVertexPointer(GLArrayData array) { if(array.isVBO()) { - if(!gl.glIsVBOArrayEnabled()) { + if(!gl.isVBOArrayBound()) { throw new GLException("VBO array is not enabled: "+array); } } else { - if(gl.glIsVBOArrayEnabled()) { + if(gl.isVBOArrayBound()) { throw new GLException("VBO array is not disabled: "+array); } Buffers.rangeCheck(array.getBuffer(), 1); @@ -237,25 +366,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun fixedFunction.glVertexPointer(gl, array); } + @Override public void glVertexPointer(int size, int type, int stride, java.nio.Buffer pointer) { - glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, false, stride, pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER)); + glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride, + pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER)); } + @Override public void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset) { - int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); if(vboName==0) { throw new GLException("no GL_ARRAY_BUFFER VBO bound"); } - glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, false, stride, + glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride, null, vboName, pointer_buffer_offset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)); } + @Override public void glColorPointer(GLArrayData array) { if(array.isVBO()) { - if(!gl.glIsVBOArrayEnabled()) { + if(!gl.isVBOArrayBound()) { throw new GLException("VBO array is not enabled: "+array); } } else { - if(gl.glIsVBOArrayEnabled()) { + if(gl.isVBOArrayBound()) { throw new GLException("VBO array is not disabled: "+array); } Buffers.rangeCheck(array.getBuffer(), 1); @@ -264,29 +397,32 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } fixedFunction.glColorPointer(gl, array); } + @Override public void glColorPointer(int size, int type, int stride, java.nio.Buffer pointer) { - glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, false, stride, + glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride, pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER)); } + @Override public void glColorPointer(int size, int type, int stride, long pointer_buffer_offset) { - int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); if(vboName==0) { throw new GLException("no GL_ARRAY_BUFFER VBO bound"); } - glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, false, stride, + glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride, null, vboName, pointer_buffer_offset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)); } + @Override public void glNormalPointer(GLArrayData array) { if(array.getComponentCount()!=3) { throw new GLException("Only 3 components per normal allowed"); } if(array.isVBO()) { - if(!gl.glIsVBOArrayEnabled()) { + if(!gl.isVBOArrayBound()) { throw new GLException("VBO array is not enabled: "+array); } } else { - if(gl.glIsVBOArrayEnabled()) { + if(gl.isVBOArrayBound()) { throw new GLException("VBO array is not disabled: "+array); } Buffers.rangeCheck(array.getBuffer(), 1); @@ -295,26 +431,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } fixedFunction.glNormalPointer(gl, array); } + @Override public void glNormalPointer(int type, int stride, java.nio.Buffer pointer) { - glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, false, stride, + glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, GLBuffers.isGLTypeFixedPoint(type), stride, pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER)); } + @Override public void glNormalPointer(int type, int stride, long pointer_buffer_offset) { - int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); if(vboName==0) { throw new GLException("no GL_ARRAY_BUFFER VBO bound"); } - glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, false, stride, + glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, GLBuffers.isGLTypeFixedPoint(type), stride, null, vboName, pointer_buffer_offset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)); } + @Override public void glTexCoordPointer(GLArrayData array) { if(array.isVBO()) { - if(!gl.glIsVBOArrayEnabled()) { + if(!gl.isVBOArrayBound()) { throw new GLException("VBO array is not enabled: "+array); } } else { - if(gl.glIsVBOArrayEnabled()) { + if(gl.isVBOArrayBound()) { throw new GLException("VBO array is not disabled: "+array); } Buffers.rangeCheck(array.getBuffer(), 1); @@ -323,25 +462,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } fixedFunction.glTexCoordPointer(gl, array); } + @Override public void glTexCoordPointer(int size, int type, int stride, java.nio.Buffer pointer) { glTexCoordPointer( - GLArrayDataWrapper.createFixed(GL_TEXTURE_COORD_ARRAY, size, type, false, stride, pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER)); + GLArrayDataWrapper.createFixed(GL_TEXTURE_COORD_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride, + pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER)); } + @Override public void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset) { - int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); if(vboName==0) { throw new GLException("no GL_ARRAY_BUFFER VBO bound"); } glTexCoordPointer( - GLArrayDataWrapper.createFixed(GL_TEXTURE_COORD_ARRAY, size, type, false, stride, + GLArrayDataWrapper.createFixed(GL_TEXTURE_COORD_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride, null, vboName, pointer_buffer_offset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER) ); } + @Override public final String toString() { StringBuilder buf = new StringBuilder(); buf.append(getClass().getName()+" ("); if(null!=pmvMatrix) { - buf.append(", matrixDirty: "+pmvMatrix.isDirty()); + buf.append(", matrixDirty: "+ (0 != pmvMatrix.getModifiedBits(false))); } buf.append("\n\t, FixedFunction: "+fixedFunction); buf.append(gl); diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java index bfe2e13c2..42269588d 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java @@ -29,33 +29,87 @@ package jogamp.opengl.util.glsl.fixedfunc; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; + +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.GLArrayData; +import javax.media.opengl.GLES2; +import javax.media.opengl.GLException; +import javax.media.opengl.GLRunnable2; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLLightingFunc; +import javax.media.opengl.fixedfunc.GLPointerFunc; +import javax.media.opengl.fixedfunc.GLPointerFuncUtil; + +import jogamp.opengl.Debug; + import com.jogamp.common.nio.Buffers; -import javax.media.opengl.*; -import javax.media.opengl.fixedfunc.*; -import com.jogamp.opengl.util.*; -import com.jogamp.opengl.util.glsl.*; -import java.nio.*; +import com.jogamp.common.util.IntIntHashMap; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode; +/** + * + * <p> + * Note: Certain GL FFP state values (e.g.: alphaTestFunc and cullFace) + * are mapped to a lower number range so they can be stored in low precision storage, + * i.e. in a 'lowp int' (GL ES2). + * </p> + */ public class FixedFuncPipeline { + protected static final boolean DEBUG; + + static { + Debug.initSingleton(); + DEBUG = Debug.isPropertyDefined("jogl.debug.FixedFuncPipeline", true); + } + + /** The maximum texture units which could be used, depending on {@link ShaderSelectionMode}. */ public static final int MAX_TEXTURE_UNITS = 8; public static final int MAX_LIGHTS = 8; - public FixedFuncPipeline(GL2ES2 gl, PMVMatrix pmvMatrix) { - init(gl, pmvMatrix, FixedFuncPipeline.class, shaderSrcRootDef, shaderBinRootDef, - vertexColorFileDef, vertexColorLightFileDef, fragmentColorFileDef, fragmentColorTextureFileDef); + public FixedFuncPipeline(GL2ES2 gl, ShaderSelectionMode mode, PMVMatrix pmvMatrix) { + shaderRootClass = FixedFuncPipeline.class; + shaderSrcRoot = shaderSrcRootDef; + shaderBinRoot = shaderBinRootDef; + vertexColorFile = vertexColorFileDef; + vertexColorLightFile = vertexColorLightFileDef; + fragmentColorFile = fragmentColorFileDef; + fragmentColorTextureFile = fragmentColorTextureFileDef; + init(gl, mode, pmvMatrix); } - public FixedFuncPipeline(GL2ES2 gl, PMVMatrix pmvMatrix, Class shaderRootClass, String shaderSrcRoot, String shaderBinRoot, - String vertexColorFile, - String vertexColorLightFile, - String fragmentColorFile, - String fragmentColorTextureFile) { - init(gl, pmvMatrix, shaderRootClass, shaderSrcRoot, shaderBinRoot, - vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile); + public FixedFuncPipeline(GL2ES2 gl, ShaderSelectionMode mode, PMVMatrix pmvMatrix, + Class<?> shaderRootClass, String shaderSrcRoot, + String shaderBinRoot, + String vertexColorFile, String vertexColorLightFile, + String fragmentColorFile, String fragmentColorTextureFile) { + this.shaderRootClass = shaderRootClass; + this.shaderSrcRoot = shaderSrcRoot; + this.shaderBinRoot = shaderBinRoot; + this.vertexColorFile = vertexColorFile; + this.vertexColorLightFile = vertexColorLightFile; + this.fragmentColorFile = fragmentColorFile; + this.fragmentColorTextureFile = fragmentColorTextureFile; + init(gl, mode, pmvMatrix); } + public ShaderSelectionMode getShaderSelectionMode() { return requestedShaderSelectionMode; } + public void setShaderSelectionMode(ShaderSelectionMode mode) { requestedShaderSelectionMode=mode; } + public ShaderSelectionMode getCurrentShaderSelectionMode() { return currentShaderSelectionMode; } + public boolean verbose() { return verbose; } - public void setVerbose(boolean v) { verbose=v; } + public void setVerbose(boolean v) { verbose = DEBUG || v; } public boolean isValid() { return shaderState.linked(); @@ -69,46 +123,83 @@ public class FixedFuncPipeline { return activeTextureUnit; } - public String getArrayIndexName(int glArrayIndex) { - String name = GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex); - switch(glArrayIndex) { - case GLPointerFunc.GL_VERTEX_ARRAY: - case GLPointerFunc.GL_NORMAL_ARRAY: - case GLPointerFunc.GL_COLOR_ARRAY: - break; - case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: - name = name + activeTextureUnit; - } - return name; - } - public void destroy(GL2ES2 gl) { - shaderProgramColor.release(gl, true); - shaderProgramColorLight.release(gl, true); - shaderProgramColorTexture.release(gl, true); - shaderProgramColorTextureLight.release(gl, true); + if(null != shaderProgramColor) { + shaderProgramColor.release(gl, true); + } + if(null != shaderProgramColorLight) { + shaderProgramColorLight.release(gl, true); + } + if(null != shaderProgramColorTexture2) { + shaderProgramColorTexture2.release(gl, true); + } + if(null != shaderProgramColorTexture4) { + shaderProgramColorTexture4.release(gl, true); + } + if(null != shaderProgramColorTexture4) { + shaderProgramColorTexture4.release(gl, true); + } + if(null != shaderProgramColorTexture8Light) { + shaderProgramColorTexture8Light.release(gl, true); + } shaderState.destroy(gl); } - public void glEnableClientState(GL2ES2 gl, int glArrayIndex) { - shaderState.useProgram(gl, true); + // + // Simple Globals + // + public void glColor4f(GL2ES2 gl, float red, float green, float blue, float alpha) { + colorStatic.put(0, red); + colorStatic.put(1, green); + colorStatic.put(2, blue); + colorStatic.put(3, alpha); - shaderState.enableVertexAttribArray(gl, getArrayIndexName(glArrayIndex)); - // textureCoordsEnabled |= (1 << activeTextureUnit); - if ( textureCoordsEnabled.get(activeTextureUnit) != 1 ) { - textureCoordsEnabled.put(activeTextureUnit, 1); - textureCoordsEnabledDirty = true; + shaderState.useProgram(gl, true); + final GLUniformData ud = shaderState.getUniform(mgl_ColorStatic); + if(null!=ud) { + // same data object .. + shaderState.uniform(gl, ud); + } else { + throw new GLException("Failed to update: mgl_ColorStatic"); } } + // + // Arrays / States + // + + public void glEnableClientState(GL2ES2 gl, int glArrayIndex) { + glToggleClientState(gl, glArrayIndex, true); + } + public void glDisableClientState(GL2ES2 gl, int glArrayIndex) { - shaderState.useProgram(gl, true); + glToggleClientState(gl, glArrayIndex, false); + } - shaderState.disableVertexAttribArray(gl, getArrayIndexName(glArrayIndex)); - // textureCoordsEnabled &= ~(1 << activeTextureUnit); - if ( textureCoordsEnabled.get(activeTextureUnit) != 0 ) { - textureCoordsEnabled.put(activeTextureUnit, 0); - textureCoordsEnabledDirty = true; + private void glToggleClientState(GL2ES2 gl, int glArrayIndex, boolean enable) { + final String arrayName = GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex, clientActiveTextureUnit); + if(null == arrayName) { + throw new GLException("arrayIndex "+toHexString(glArrayIndex)+" unknown"); + } + shaderState.useProgram(gl, true); + if(enable) { + shaderState.enableVertexAttribArray(gl, arrayName ); + } else { + shaderState.disableVertexAttribArray(gl, arrayName ); + } + switch( glArrayIndex ) { + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + final int enableV = enable ? 1 : 0; + // enable-bitwise: textureCoordsEnabled |= (1 << clientActiveTextureUnit); + // disable-bitwise: textureCoordsEnabled &= ~(1 << clientActiveTextureUnit); + if ( textureCoordEnabled.get(clientActiveTextureUnit) != enableV) { + textureCoordEnabled.put(clientActiveTextureUnit, enableV); + textureCoordEnabledDirty = true; + } + break; + case GLPointerFunc.GL_COLOR_ARRAY: + colorVAEnabledDirty = true; + break; } } @@ -122,26 +213,235 @@ public class FixedFuncPipeline { shaderState.vertexAttribPointer(gl, data); } - public void glColor4fv(GL2ES2 gl, FloatBuffer data ) { + public void glNormalPointer(GL2ES2 gl, GLArrayData data) { shaderState.useProgram(gl, true); - GLUniformData ud = shaderState.getUniform(mgl_ColorStatic); - if(null!=ud) { - ud.setData(data); - shaderState.uniform(gl, ud); + shaderState.vertexAttribPointer(gl, data); + } + + // + // MULTI-TEXTURE + // + + /** Enables/Disables the named texture unit (if changed), returns previous state */ + private boolean glEnableTexture(boolean enable, int unit) { + final boolean isEnabled = 0 != ( textureEnabledBits & ( 1 << activeTextureUnit ) ); + if( isEnabled != enable ) { + if(enable) { + textureEnabledBits |= ( 1 << unit ); + textureEnabled.put(unit, 1); + } else { + textureEnabledBits &= ~( 1 << unit ); + textureEnabled.put(unit, 0); + } + textureEnabledDirty=true; } + return isEnabled; } - public void glNormalPointer(GL2ES2 gl, GLArrayData data) { - shaderState.useProgram(gl, true); - shaderState.vertexAttribPointer(gl, data); + public void glClientActiveTexture(int textureUnit) { + textureUnit -= GL.GL_TEXTURE0; + if(0 <= textureUnit && textureUnit<MAX_TEXTURE_UNITS) { + clientActiveTextureUnit = textureUnit; + } else { + throw new GLException("glClientActiveTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit); + } + } + + public void glActiveTexture(int textureUnit) { + textureUnit -= GL.GL_TEXTURE0; + if(0 <= textureUnit && textureUnit<MAX_TEXTURE_UNITS) { + activeTextureUnit = textureUnit; + } else { + throw new GLException("glActivateTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit); + } } public void glTexCoordPointer(GL2ES2 gl, GLArrayData data) { + if( GLPointerFunc.GL_TEXTURE_COORD_ARRAY != data.getIndex() ) { + throw new GLException("Invalid GLArrayData Index "+toHexString(data.getIndex())+", "+data); + } shaderState.useProgram(gl, true); - data.setName( getArrayIndexName(data.getIndex()) ); + data.setName( GLPointerFuncUtil.getPredefinedArrayIndexName(data.getIndex(), clientActiveTextureUnit) ) ; shaderState.vertexAttribPointer(gl, data); } + public void glBindTexture(int target, int texture) { + if(GL.GL_TEXTURE_2D == target) { + if( texture != boundTextureObject[activeTextureUnit] ) { + boundTextureObject[activeTextureUnit] = texture; + textureFormatDirty = true; + } + } else { + System.err.println("FixedFuncPipeline: Unimplemented glBindTexture for target "+toHexString(target)+". Texture name "+toHexString(texture)); + } + } + + public void glTexImage2D(int target, /* int level, */ int internalformat, /*, int width, int height, int border, */ + int format /*, int type, Buffer pixels */) { + final int ifmt; + if(GL.GL_TEXTURE_2D == target) { + switch(internalformat) { + case 3: + case GL.GL_RGB: + case GL.GL_RGB565: + case GL.GL_RGB8: + case GL.GL_RGB10: + ifmt = 3; + break; + case 4: + case GL.GL_RGBA: + case GL.GL_RGB5_A1: + case GL.GL_RGBA4: + case GL.GL_RGBA8: + case GL.GL_RGB10_A2: + ifmt = 4; + break; + default: + System.err.println("FixedFuncPipeline: glTexImage2D TEXTURE_2D: Unimplemented internalformat "+toHexString(internalformat)); + ifmt = 4; + break; + } + if( ifmt != texID2Format.put(boundTextureObject[activeTextureUnit], ifmt) ) { + textureFormatDirty = true; + // System.err.println("glTexImage2D TEXTURE_2D: internalformat ifmt "+toHexString(internalformat)+" fmt "+toHexString(format)+" -> "+toHexString(ifmt)); + } + } else { + System.err.println("FixedFuncPipeline: Unimplemented glTexImage2D: target "+toHexString(target)+", internalformat "+toHexString(internalformat)); + } + } + /* + public void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, + int format, int type, long pixels_buffer_offset) { + textureFormat.put(activeTextureUnit, internalformat); + textureFormatDirty = true; + }*/ + + public void glTexEnvi(int target, int pname, int value) { + if(GL2ES1.GL_TEXTURE_ENV == target && GL2ES1.GL_TEXTURE_ENV_MODE == pname) { + final int mode; + switch( value ) { + case GL2ES1.GL_ADD: + mode = 1; + break; + case GL2ES1.GL_MODULATE: + mode = 2; + break; + case GL2ES1.GL_DECAL: + mode = 3; + break; + case GL2ES1.GL_BLEND: + mode = 4; + break; + case GL2ES1.GL_REPLACE: + mode = 5; + break; + case GL2ES1.GL_COMBINE: + mode = 2; // FIXME + System.err.println("FixedFuncPipeline: glTexEnv GL_TEXTURE_ENV_MODE: unimplemented mode: "+toHexString(value)); + break; + default: + throw new GLException("glTexEnv GL_TEXTURE_ENV_MODE: invalid mode: "+toHexString(value)); + } + setTextureEnvMode(mode); + } else if(verbose) { + System.err.println("FixedFuncPipeline: Unimplemented TexEnv: target "+toHexString(target)+", pname "+toHexString(pname)+", mode: "+toHexString(value)); + } + } + private void setTextureEnvMode(int value) { + if( value != textureEnvMode.get(activeTextureUnit) ) { + textureEnvMode.put(activeTextureUnit, value); + textureEnvModeDirty = true; + } + } + public void glGetTexEnviv(int target, int pname, IntBuffer params) { // FIXME + System.err.println("FixedFuncPipeline: Unimplemented glGetTexEnviv: target "+toHexString(target)+", pname "+toHexString(pname)); + } + public void glGetTexEnviv(int target, int pname, int[] params, int params_offset) { // FIXME + System.err.println("FixedFuncPipeline: Unimplemented glGetTexEnviv: target "+toHexString(target)+", pname "+toHexString(pname)); + } + + // + // Point Sprites + // + public void glPointSize(float size) { + pointParams.put(0, size); + pointParamsDirty = true; + } + public void glPointParameterf(int pname, float param) { + switch(pname) { + case GL2ES1.GL_POINT_SIZE_MIN: + pointParams.put(2, param); + break; + case GL2ES1.GL_POINT_SIZE_MAX: + pointParams.put(3, param); + break; + case GL2ES2.GL_POINT_FADE_THRESHOLD_SIZE: + pointParams.put(4+3, param); + break; + } + pointParamsDirty = true; + } + public void glPointParameterfv(int pname, float[] params, int params_offset) { + switch(pname) { + case GL2ES1.GL_POINT_DISTANCE_ATTENUATION: + pointParams.put(4+0, params[params_offset + 0]); + pointParams.put(4+1, params[params_offset + 1]); + pointParams.put(4+2, params[params_offset + 2]); + break; + } + pointParamsDirty = true; + } + public void glPointParameterfv(int pname, java.nio.FloatBuffer params) { + final int o = params.position(); + switch(pname) { + case GL2ES1.GL_POINT_DISTANCE_ATTENUATION: + pointParams.put(4+0, params.get(o + 0)); + pointParams.put(4+1, params.get(o + 1)); + pointParams.put(4+2, params.get(o + 2)); + break; + } + pointParamsDirty = true; + } + + // private int[] pointTexObj = new int[] { 0 }; + + private void glDrawPoints(GL2ES2 gl, GLRunnable2<Object,Object> glDrawAction, Object args) { + if(gl.isGL2GL3()) { + gl.glEnable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE); + } + if(gl.isGL2ES1()) { + gl.glEnable(GL2ES1.GL_POINT_SPRITE); + } + loadShaderPoints(gl); + shaderState.attachShaderProgram(gl, shaderProgramPoints, true); + validate(gl, false); // sync uniforms + + glDrawAction.run(gl, args); + + if(gl.isGL2ES1()) { + gl.glDisable(GL2ES1.GL_POINT_SPRITE); + } + if(gl.isGL2GL3()) { + gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE); + } + shaderState.attachShaderProgram(gl, selectShaderProgram(gl, currentShaderSelectionMode), true); + } + private static final GLRunnable2<Object, Object> glDrawArraysAction = new GLRunnable2<Object,Object>() { + @Override + public Object run(GL gl, Object args) { + int[] _args = (int[])args; + gl.glDrawArrays(GL.GL_POINTS, _args[0], _args[1]); + return null; + } + }; + private final void glDrawPointArrays(GL2ES2 gl, int first, int count) { + glDrawPoints(gl, glDrawArraysAction, new int[] { first, count }); + } + + // + // Lighting + // + public void glLightfv(GL2ES2 gl, int light, int pname, java.nio.FloatBuffer params) { shaderState.useProgram(gl, true); light -=GLLightingFunc.GL_LIGHT0; @@ -179,17 +479,14 @@ public class FixedFuncPipeline { ud = shaderState.getUniform(mgl_LightSource+"["+light+"].quadraticAttenuation"); break; default: - if(verbose) { - System.err.println("glLightfv pname not within [GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION GL_SPOT_DIRECTION]: "+pname); - } - return; + throw new GLException("glLightfv invalid pname: "+toHexString(pname)); } if(null!=ud) { ud.setData(params); shaderState.uniform(gl, ud); } - } else if(verbose) { - System.err.println("glLightfv light not within [0.."+MAX_LIGHTS+"]: "+light); + } else { + throw new GLException("glLightfv light not within [0.."+MAX_LIGHTS+"]: "+light); } } @@ -201,10 +498,8 @@ public class FixedFuncPipeline { case GL.GL_FRONT_AND_BACK: break; case GL.GL_BACK: - if(verbose) { - System.err.println("glMaterialfv face GL_BACK currently not supported"); - } - break; + System.err.println("FixedFuncPipeline: Unimplemented glMaterialfv GL_BACK face"); + return; default: } @@ -214,7 +509,13 @@ public class FixedFuncPipeline { ud = shaderState.getUniform(mgl_FrontMaterial+".ambient"); break; case GLLightingFunc.GL_AMBIENT_AND_DIFFUSE: - glMaterialfv(gl, face, GLLightingFunc.GL_AMBIENT, params); + { + ud = shaderState.getUniform(mgl_FrontMaterial+".ambient"); + if(null!=ud) { + ud.setData(params); + shaderState.uniform(gl, ud); + } + } // fall through intended .. case GLLightingFunc.GL_DIFFUSE: ud = shaderState.getUniform(mgl_FrontMaterial+".diffuse"); @@ -229,17 +530,20 @@ public class FixedFuncPipeline { ud = shaderState.getUniform(mgl_FrontMaterial+".shininess"); break; default: - if(verbose) { - System.err.println("glMaterialfv pname not within [GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_EMISSION GL_SHININESS]: "+pname); - } - return; + throw new GLException("glMaterialfv invalid pname: "+toHexString(pname)); } if(null!=ud) { ud.setData(params); shaderState.uniform(gl, ud); + } else if(verbose) { + } } + // + // Misc States + // + public void glShadeModel(GL2ES2 gl, int mode) { shaderState.useProgram(gl, true); GLUniformData ud = shaderState.getUniform(mgl_ShadeModel); @@ -249,46 +553,135 @@ public class FixedFuncPipeline { } } - public void glActiveTexture(GL2ES2 gl, int textureUnit) { - textureUnit -= GL.GL_TEXTURE0; - if(0 <= textureUnit && textureUnit<MAX_TEXTURE_UNITS) { - shaderState.useProgram(gl, true); - GLUniformData ud; - ud = shaderState.getUniform(mgl_ActiveTexture); - if(null!=ud) { - ud.setData(textureUnit); - shaderState.uniform(gl, ud); + /** ES2 supports CullFace implicit + public void glCullFace(int faceName) { + int _cullFace; + switch(faceName) { + case GL.GL_FRONT: + _cullFace = 1; + break; + case GL.GL_BACK: + _cullFace = 2; + break; + case GL.GL_FRONT_AND_BACK: + _cullFace = 3; + break; + default: + throw new GLException("glCullFace invalid faceName: "+toHexString(faceName)); + } + if(0 < _cullFace) { + if(0>cullFace) { + _cullFace *= -1; } - ud = shaderState.getUniform(mgl_ActiveTextureIdx); - if(null!=ud) { - ud.setData(textureUnit); - shaderState.uniform(gl, ud); + if(cullFace != _cullFace) { + cullFace = _cullFace; + cullFaceDirty=true; + } + } + } */ + + public void glAlphaFunc(int func, float ref) { + int _func; + switch(func) { + case GL.GL_NEVER: + _func = 1; + break; + case GL.GL_LESS: + _func = 2; + break; + case GL.GL_EQUAL: + _func = 3; + break; + case GL.GL_LEQUAL: + _func = 4; + break; + case GL.GL_GREATER: + _func = 5; + break; + case GL.GL_NOTEQUAL: + _func = 6; + break; + case GL.GL_GEQUAL: + _func = 7; + break; + case GL.GL_ALWAYS: + _func = 8; + break; + default: + throw new GLException("glAlphaFunc invalid func: "+toHexString(func)); + } + if(0 < _func) { + if(0>alphaTestFunc) { + _func *= -1; + } + if( alphaTestFunc != _func || alphaTestRef != ref ) { + alphaTestFunc = _func; + alphaTestRef = ref; + alphaTestDirty=true; } - activeTextureUnit = textureUnit; - } else { - throw new GLException("glActivateTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit); } } /** - * @return false if digested in regard to GL2ES2 spec, + * @return false if digested in regard to GL2ES2 spec, * eg this call must not be passed to an underlying ES2 implementation. * true if this call shall be passed to an underlying GL2ES2/ES2 implementation as well. */ - public boolean glEnable(GL2ES2 gl, int cap, boolean enable) { + public boolean glEnable(int cap, boolean enable) { switch(cap) { - case GL.GL_TEXTURE_2D: - textureEnabled=enable; + case GL.GL_BLEND: + case GL.GL_DEPTH_TEST: + case GL.GL_DITHER: + case GL.GL_POLYGON_OFFSET_FILL: + case GL.GL_SAMPLE_ALPHA_TO_COVERAGE: + case GL.GL_SAMPLE_COVERAGE: + case GL.GL_SCISSOR_TEST: + case GL.GL_STENCIL_TEST: + return true; + + case GL.GL_CULL_FACE: + /** ES2 supports CullFace implicit + final int _cullFace; + if(0>cullFace && enable || 0<cullFace && !enable) { + _cullFace = cullFace * -1; + } else { + _cullFace = cullFace; + } + if(_cullFace != cullFace) { + cullFaceDirty=true; + cullFace=_cullFace; + } */ return true; + + case GL.GL_TEXTURE_2D: + glEnableTexture(enable, activeTextureUnit); + return false; + case GLLightingFunc.GL_LIGHTING: lightingEnabled=enable; return false; - case GL.GL_CULL_FACE: - cullFace=Math.abs(cullFace); - if(!enable) { - cullFace*=-1; + + case GL2ES1.GL_ALPHA_TEST: + final int _alphaTestFunc; + if(0>alphaTestFunc && enable || 0<alphaTestFunc && !enable) { + _alphaTestFunc = alphaTestFunc * -1; + } else { + _alphaTestFunc = alphaTestFunc; } - return true; + if(_alphaTestFunc != alphaTestFunc) { + alphaTestDirty=true; + alphaTestFunc=_alphaTestFunc; + } + return false; + + case GL2ES1.GL_POINT_SMOOTH: + pointParams.put(1, enable ? 1.0f : 0.0f); + pointParamsDirty = true; + return false; + + case GL2ES1.GL_POINT_SPRITE: + // gl_PointCoord always enabled + return false; } int light = cap - GLLightingFunc.GL_LIGHT0; @@ -299,157 +692,422 @@ public class FixedFuncPipeline { return false; } } - return true; // pass it on .. + System.err.println("FixedFunctionPipeline: "+(enable ? "glEnable" : "glDisable")+" "+toHexString(cap)+" not handled in emulation and not supported in ES2"); + return false; // ignore! } - public void glCullFace(GL2ES2 gl, int faceName) { - switch(faceName) { - case GL.GL_FRONT: - faceName = 1; break; - case GL.GL_BACK: - faceName = 2; break; - case GL.GL_FRONT_AND_BACK: - faceName = 3; break; + // + // Draw + // + + public void glDrawArrays(GL2ES2 gl, int mode, int first, int count) { + switch(mode) { + case GL2.GL_QUAD_STRIP: + mode=GL.GL_TRIANGLE_STRIP; + break; + case GL2.GL_POLYGON: + mode=GL.GL_TRIANGLE_FAN; + break; + case GL2ES1.GL_POINTS: + glDrawPointArrays(gl, first, count); + return; } - if(0>cullFace) { - faceName *= -1; + validate(gl, true); + if ( GL2.GL_QUADS == mode && !gl.isGL2() ) { + for (int j = first; j < count - 3; j += 4) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, j, 4); + } + } else { + gl.glDrawArrays(mode, first, count); } - cullFace = faceName; } + public void glDrawElements(GL2ES2 gl, int mode, int count, int type, java.nio.Buffer indices) { + validate(gl, true); + if ( GL2.GL_QUADS == mode && !gl.isGL2() ) { + final int idx0 = indices.position(); + + if( GL.GL_UNSIGNED_BYTE == type ) { + final ByteBuffer b = (ByteBuffer) indices; + for (int j = 0; j < count; j++) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, (int)(0x000000ff & b.get(idx0+j)), 4); + } + } else if( GL.GL_UNSIGNED_SHORT == type ){ + final ShortBuffer b = (ShortBuffer) indices; + for (int j = 0; j < count; j++) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, (int)(0x0000ffff & b.get(idx0+j)), 4); + } + } else { + final IntBuffer b = (IntBuffer) indices; + for (int j = 0; j < count; j++) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, (int)(0xffffffff & b.get(idx0+j)), 4); + } + } + } else { + // FIXME: Impl. VBO usage .. or unroll (see above)! + if( !gl.getContext().isCPUDataSourcingAvail() ) { + throw new GLException("CPU data sourcing n/a w/ "+gl.getContext()); + } + if( GL2ES1.GL_POINTS != mode ) { + ((GLES2)gl).glDrawElements(mode, count, type, indices); + } else { + // FIXME GL_POINTS ! + ((GLES2)gl).glDrawElements(mode, count, type, indices); + } + } + } + public void glDrawElements(GL2ES2 gl, int mode, int count, int type, long indices_buffer_offset) { + validate(gl, true); + if ( GL2.GL_QUADS == mode && !gl.isGL2() ) { + throw new GLException("Cannot handle indexed QUADS on !GL2 w/ VBO due to lack of CPU index access"); + } else if( GL2ES1.GL_POINTS != mode ) { + // FIXME GL_POINTS ! + gl.glDrawElements(mode, count, type, indices_buffer_offset); + } else { + gl.glDrawElements(mode, count, type, indices_buffer_offset); + } + } + + private final int textureEnabledCount() { + int n=0; + for(int i=MAX_TEXTURE_UNITS-1; i>=0; i--) { + if( 0 != textureEnabled.get(i) ) { + n++; + } + } + return n; + } + + public void validate(GL2ES2 gl, boolean selectShader) { + if( selectShader ) { + if( ShaderSelectionMode.AUTO == requestedShaderSelectionMode) { + final ShaderSelectionMode newMode; + + // pre-validate shader switch + if( 0 != textureEnabledBits ) { + if(lightingEnabled) { + newMode = ShaderSelectionMode.COLOR_TEXTURE8_LIGHT_PER_VERTEX; + } else { + final int n = textureEnabledCount(); + if( 4 < n ) { + newMode = ShaderSelectionMode.COLOR_TEXTURE8; + } else if ( 2 < n ) { + newMode = ShaderSelectionMode.COLOR_TEXTURE4; + } else { + newMode = ShaderSelectionMode.COLOR_TEXTURE2; + } + } + } else { + if(lightingEnabled) { + newMode = ShaderSelectionMode.COLOR_LIGHT_PER_VERTEX; + } else { + newMode = ShaderSelectionMode.COLOR; + } + } + shaderState.attachShaderProgram(gl, selectShaderProgram(gl, newMode), true); // enables shader-program implicit + } else { + shaderState.useProgram(gl, true); + } + } - public void validate(GL2ES2 gl) { - shaderState.useProgram(gl, true); GLUniformData ud; - if(pmvMatrix.update()) { + if( pmvMatrix.update() ) { ud = shaderState.getUniform(mgl_PMVMatrix); if(null!=ud) { + final FloatBuffer m; + if(ShaderSelectionMode.COLOR_TEXTURE8_LIGHT_PER_VERTEX == currentShaderSelectionMode || + ShaderSelectionMode.COLOR_LIGHT_PER_VERTEX== currentShaderSelectionMode ) { + m = pmvMatrix.glGetPMvMvitMatrixf(); + } else { + m = pmvMatrix.glGetPMvMatrixf(); + } + if(m != ud.getBuffer()) { + ud.setData(m); + } // same data object .. shaderState.uniform(gl, ud); } else { throw new GLException("Failed to update: mgl_PMVMatrix"); } } - ud = shaderState.getUniform(mgl_ColorEnabled); - if(null!=ud) { - int ca = (shaderState.isVertexAttribArrayEnabled(GLPointerFuncUtil.mgl_Color)==true)?1:0; - if(ca!=ud.intValue()) { - ud.setData(ca); - shaderState.uniform(gl, ud); + if(colorVAEnabledDirty) { + ud = shaderState.getUniform(mgl_ColorEnabled); + if(null!=ud) { + int ca = true == shaderState.isVertexAttribArrayEnabled(GLPointerFuncUtil.mgl_Color) ? 1 : 0 ; + if(ca!=ud.intValue()) { + ud.setData(ca); + shaderState.uniform(gl, ud); + } + } else { + throw new GLException("Failed to update: mgl_ColorEnabled"); } + colorVAEnabledDirty = false; } - ud = shaderState.getUniform(mgl_CullFace); - if(null!=ud) { - if(cullFace!=ud.intValue()) { + /** ES2 supports CullFace implicit + if(cullFaceDirty) { + ud = shaderState.getUniform(mgl_CullFace); + if(null!=ud) { ud.setData(cullFace); shaderState.uniform(gl, ud); } + cullFaceDirty = false; + } */ + + if(alphaTestDirty) { + ud = shaderState.getUniform(mgl_AlphaTestFunc); + if(null!=ud) { + ud.setData(alphaTestFunc); + shaderState.uniform(gl, ud); + } + ud = shaderState.getUniform(mgl_AlphaTestRef); + if(null!=ud) { + ud.setData(alphaTestRef); + shaderState.uniform(gl, ud); + } + alphaTestDirty = false; + } + if(pointParamsDirty) { + ud = shaderState.getUniform(mgl_PointParams); + if(null!=ud) { + // same data object + shaderState.uniform(gl, ud); + } + pointParamsDirty = false; } if(lightsEnabledDirty) { ud = shaderState.getUniform(mgl_LightsEnabled); if(null!=ud) { - // same data object + // same data object shaderState.uniform(gl, ud); } lightsEnabledDirty=false; } - if(textureCoordsEnabledDirty) { + if(textureCoordEnabledDirty) { ud = shaderState.getUniform(mgl_TexCoordEnabled); if(null!=ud) { - // same data object + // same data object shaderState.uniform(gl, ud); } - textureCoordsEnabledDirty=false; + textureCoordEnabledDirty=false; } - if(textureEnabled) { - if(lightingEnabled) { - shaderState.attachShaderProgram(gl, shaderProgramColorTextureLight, true); - } else { - shaderState.attachShaderProgram(gl, shaderProgramColorTexture, true); + if(textureEnvModeDirty) { + ud = shaderState.getUniform(mgl_TexEnvMode); + if(null!=ud) { + // same data object + shaderState.uniform(gl, ud); } - } else { - if(lightingEnabled) { - shaderState.attachShaderProgram(gl, shaderProgramColorLight, true); - } else { - shaderState.attachShaderProgram(gl, shaderProgramColor, true); + textureEnvModeDirty = false; + } + + if(textureFormatDirty) { + for(int i = 0; i<MAX_TEXTURE_UNITS; i++) { + textureFormat.put(i, texID2Format.get(boundTextureObject[i])); } + ud = shaderState.getUniform(mgl_TexFormat); + if(null!=ud) { + // same data object + shaderState.uniform(gl, ud); + } + textureFormatDirty = false; } - if(DEBUG) { - System.err.println("validate: "+this); + if(textureEnabledDirty) { + ud = shaderState.getUniform(mgl_TextureEnabled); + if(null!=ud) { + // same data object + shaderState.uniform(gl, ud); + } + textureEnabledDirty=false; + } + + if(verbose) { + System.err.println("validate: "+toString(null, DEBUG).toString()); } } - public String toString() { - return "FixedFuncPipeline[pmv: "+pmvMatrix+ - ", textureEnabled: "+textureEnabled+ - ", textureCoordsEnabled: "+textureCoordsEnabled+ - ", lightingEnabled: "+lightingEnabled+ - ", lightsEnabled: "+lightsEnabled+ - "\n\t, shaderProgramColor: "+shaderProgramColor+ - "\n\t, shaderProgramColorTexture: "+shaderProgramColorTexture+ - "\n\t, shaderProgramColorLight: "+shaderProgramColorLight+ - "\n\t, shaderProgramColorTextureLight: "+shaderProgramColorTextureLight+ - "\n\t, ShaderState: "+shaderState+ - "]"; - } - - protected void init(GL2ES2 gl, PMVMatrix pmvMatrix, Class shaderRootClass, String shaderSrcRoot, String shaderBinRoot, - String vertexColorFile, - String vertexColorLightFile, - String fragmentColorFile, - String fragmentColorTextureFile) - { - if(null==pmvMatrix) { - throw new GLException("PMVMatrix is null"); + public StringBuilder toString(StringBuilder sb, boolean alsoUnlocated) { + if(null == sb) { + sb = new StringBuilder(); } - this.pmvMatrix=pmvMatrix; - this.shaderState=new ShaderState(); - this.shaderState.setVerbose(verbose); - ShaderCode vertexColor, vertexColorLight, fragmentColor, fragmentColorTexture; + sb.append("FixedFuncPipeline["); + sb.append(", textureEnabled: "+toHexString(textureEnabledBits)+", "); Buffers.toString(sb, null, textureEnabled); + sb.append("\n\t, textureCoordEnabled: "); Buffers.toString(sb, null, textureCoordEnabled); + sb.append("\n\t lightingEnabled: "+lightingEnabled); + sb.append(", lightsEnabled: "); Buffers.toString(sb, null, lightsEnabled); + sb.append("\n\t, shaderProgramColor: "+shaderProgramColor); + sb.append("\n\t, shaderProgramColorTexture2: "+shaderProgramColorTexture2); + sb.append("\n\t, shaderProgramColorTexture4: "+shaderProgramColorTexture4); + sb.append("\n\t, shaderProgramColorTexture8: "+shaderProgramColorTexture8); + sb.append("\n\t, shaderProgramColorLight: "+shaderProgramColorLight); + sb.append("\n\t, shaderProgramColorTexture8Light: "+shaderProgramColorTexture8Light); + sb.append("\n\t, ShaderState: "); + shaderState.toString(sb, alsoUnlocated); + sb.append("]"); + return sb; + } + @Override + public String toString() { + return toString(null, DEBUG).toString(); + } - vertexColor = ShaderCode.create( gl, gl.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot, - shaderBinRoot, vertexColorFile, false); + private static final String constMaxTextures0 = "#define MAX_TEXTURE_UNITS 0\n"; + private static final String constMaxTextures2 = "#define MAX_TEXTURE_UNITS 2\n"; + private static final String constMaxTextures4 = "#define MAX_TEXTURE_UNITS 4\n"; + private static final String constMaxTextures8 = "#define MAX_TEXTURE_UNITS 8\n"; - vertexColorLight = ShaderCode.create( gl, gl.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot, - shaderBinRoot, vertexColorLightFile, false); + private final void customizeShader(GL2ES2 gl, ShaderCode vp, ShaderCode fp, String maxTextureDefine) { + int rsVpPos = vp.defaultShaderCustomization(gl, true, true); + int rsFpPos = fp.defaultShaderCustomization(gl, true, true); + vp.insertShaderSource(0, rsVpPos, maxTextureDefine); + fp.insertShaderSource(0, rsFpPos, maxTextureDefine); + } - fragmentColor = ShaderCode.create( gl, gl.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot, - shaderBinRoot, fragmentColorFile, false); + private final void loadShaderPoints(GL2ES2 gl) { + if( null != shaderProgramPoints ) { + return; + } - fragmentColorTexture = ShaderCode.create( gl, gl.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot, - shaderBinRoot, fragmentColorTextureFile, false); + final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, shaderPointFileDef, true); + final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, shaderPointFileDef, true); + customizeShader(gl, vp, fp, constMaxTextures2); + shaderProgramPoints = new ShaderProgram(); + shaderProgramPoints.add(vp); + shaderProgramPoints.add(fp); + if(!shaderProgramPoints.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColor program: "+shaderProgramPoints); + } + } - shaderProgramColor = new ShaderProgram(); - shaderProgramColor.add(vertexColor); - shaderProgramColor.add(fragmentColor); - if(!shaderProgramColor.link(gl, System.err)) { - throw new GLException("Couldn't link VertexColor program: "+shaderProgramColor); + private final void loadShader(GL2ES2 gl, ShaderSelectionMode mode) { + final boolean loadColor = ShaderSelectionMode.COLOR == mode; + final boolean loadColorTexture2 = ShaderSelectionMode.COLOR_TEXTURE2 == mode; + final boolean loadColorTexture4 = ShaderSelectionMode.COLOR_TEXTURE4 == mode; + final boolean loadColorTexture8 = ShaderSelectionMode.COLOR_TEXTURE8 == mode; + final boolean loadColorTexture = loadColorTexture2 || loadColorTexture4 || loadColorTexture8 ; + final boolean loadColorLightPerVertex = ShaderSelectionMode.COLOR_LIGHT_PER_VERTEX == mode; + final boolean loadColorTexture8LightPerVertex = ShaderSelectionMode.COLOR_TEXTURE8_LIGHT_PER_VERTEX == mode; + + if( null != shaderProgramColor && loadColor || + null != shaderProgramColorTexture2 && loadColorTexture2 || + null != shaderProgramColorTexture4 && loadColorTexture4 || + null != shaderProgramColorTexture8 && loadColorTexture8 || + null != shaderProgramColorLight && loadColorLightPerVertex || + null != shaderProgramColorTexture8Light && loadColorTexture8LightPerVertex ) { + return; } - shaderProgramColorTexture = new ShaderProgram(); - shaderProgramColorTexture.add(vertexColor); - shaderProgramColorTexture.add(fragmentColorTexture); - if(!shaderProgramColorTexture.link(gl, System.err)) { - throw new GLException("Couldn't link VertexColorTexture program: "+shaderProgramColorTexture); + if( loadColor ) { + final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, vertexColorFile, true); + final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, fragmentColorFile, true); + customizeShader(gl, vp, fp, constMaxTextures0); + shaderProgramColor = new ShaderProgram(); + shaderProgramColor.add(vp); + shaderProgramColor.add(fp); + if(!shaderProgramColor.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColor program: "+shaderProgramColor); + } + } else if( loadColorTexture ) { + final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot, shaderBinRoot, vertexColorFile, true); + final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, fragmentColorTextureFile, true); + + if( loadColorTexture2 ) { + customizeShader(gl, vp, fp, constMaxTextures2); + shaderProgramColorTexture2 = new ShaderProgram(); + shaderProgramColorTexture2.add(vp); + shaderProgramColorTexture2.add(fp); + if(!shaderProgramColorTexture2.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorTexture2 program: "+shaderProgramColorTexture2); + } + } else if( loadColorTexture4 ) { + customizeShader(gl, vp, fp, constMaxTextures4); + shaderProgramColorTexture4 = new ShaderProgram(); + shaderProgramColorTexture4.add(vp); + shaderProgramColorTexture4.add(fp); + if(!shaderProgramColorTexture4.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorTexture4 program: "+shaderProgramColorTexture4); + } + } else if( loadColorTexture8 ) { + customizeShader(gl, vp, fp, constMaxTextures8); + shaderProgramColorTexture8 = new ShaderProgram(); + shaderProgramColorTexture8.add(vp); + shaderProgramColorTexture8.add(fp); + if(!shaderProgramColorTexture8.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorTexture8 program: "+shaderProgramColorTexture8); + } + } + } else if( loadColorLightPerVertex ) { + final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, vertexColorLightFile, true); + final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, fragmentColorFile, true); + customizeShader(gl, vp, fp, constMaxTextures0); + shaderProgramColorLight = new ShaderProgram(); + shaderProgramColorLight.add(vp); + shaderProgramColorLight.add(fp); + if(!shaderProgramColorLight.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorLight); + } + } else if( loadColorTexture8LightPerVertex ) { + final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, vertexColorLightFile, true); + final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot, + shaderBinRoot, fragmentColorTextureFile, true); + customizeShader(gl, vp, fp, constMaxTextures8); + shaderProgramColorTexture8Light = new ShaderProgram(); + shaderProgramColorTexture8Light.add(vp); + shaderProgramColorTexture8Light.add(fp); + if(!shaderProgramColorTexture8Light.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorTexture8Light); + } } + } - shaderProgramColorLight = new ShaderProgram(); - shaderProgramColorLight.add(vertexColorLight); - shaderProgramColorLight.add(fragmentColor); - if(!shaderProgramColorLight.link(gl, System.err)) { - throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorLight); + private ShaderProgram selectShaderProgram(GL2ES2 gl, ShaderSelectionMode newMode) { + if(ShaderSelectionMode.AUTO == newMode) { + newMode = ShaderSelectionMode.COLOR; } + loadShader(gl, newMode); + final ShaderProgram sp; + switch(newMode) { + case COLOR_LIGHT_PER_VERTEX: + sp = shaderProgramColorLight; + break; + case COLOR_TEXTURE2: + sp = shaderProgramColorTexture2; + break; + case COLOR_TEXTURE4: + sp = shaderProgramColorTexture4; + break; + case COLOR_TEXTURE8: + sp = shaderProgramColorTexture8; + break; + case COLOR_TEXTURE8_LIGHT_PER_VERTEX: + sp = shaderProgramColorTexture8Light; + break; + case COLOR: + default: + sp = shaderProgramColor; + } + currentShaderSelectionMode = newMode; + return sp; + } - shaderProgramColorTextureLight = new ShaderProgram(); - shaderProgramColorTextureLight.add(vertexColorLight); - shaderProgramColorTextureLight.add(fragmentColorTexture); - if(!shaderProgramColorTextureLight.link(gl, System.err)) { - throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorTextureLight); + private void init(GL2ES2 gl, ShaderSelectionMode mode, PMVMatrix pmvMatrix) { + if(null==pmvMatrix) { + throw new GLException("PMVMatrix is null"); } + this.pmvMatrix=pmvMatrix; + this.requestedShaderSelectionMode = mode; + this.shaderState=new ShaderState(); + this.shaderState.setVerbose(verbose); - shaderState.attachShaderProgram(gl, shaderProgramColor, true); + shaderState.attachShaderProgram(gl, selectShaderProgram(gl, requestedShaderSelectionMode), true); // mandatory .. if(!shaderState.uniform(gl, new GLUniformData(mgl_PMVMatrix, 4, 4, pmvMatrix.glGetPMvMvitMatrixf()))) { @@ -457,16 +1115,26 @@ public class FixedFuncPipeline { } shaderState.uniform(gl, new GLUniformData(mgl_ColorEnabled, 0)); - shaderState.uniform(gl, new GLUniformData(mgl_ColorStatic, 4, zero4f)); - shaderState.uniform(gl, new GLUniformData(mgl_TexCoordEnabled, 1, textureCoordsEnabled)); - shaderState.uniform(gl, new GLUniformData(mgl_ActiveTexture, activeTextureUnit)); - shaderState.uniform(gl, new GLUniformData(mgl_ActiveTextureIdx, activeTextureUnit)); + shaderState.uniform(gl, new GLUniformData(mgl_ColorStatic, 4, colorStatic)); + + texID2Format.setKeyNotFoundValue(0); + shaderState.uniform(gl, new GLUniformData(mgl_TexCoordEnabled, 1, textureCoordEnabled)); + shaderState.uniform(gl, new GLUniformData(mgl_TexEnvMode, 1, textureEnvMode)); + shaderState.uniform(gl, new GLUniformData(mgl_TexFormat, 1, textureFormat)); + shaderState.uniform(gl, new GLUniformData(mgl_TextureEnabled, 1, textureEnabled)); + for(int i=0; i<MAX_TEXTURE_UNITS; i++) { + shaderState.uniform(gl, new GLUniformData(mgl_Texture+i, i)); + } shaderState.uniform(gl, new GLUniformData(mgl_ShadeModel, 0)); - shaderState.uniform(gl, new GLUniformData(mgl_CullFace, cullFace)); + /** ES2 supports CullFace implicit + shaderState.uniform(gl, new GLUniformData(mgl_CullFace, cullFace)); */ + shaderState.uniform(gl, new GLUniformData(mgl_AlphaTestFunc, alphaTestFunc)); + shaderState.uniform(gl, new GLUniformData(mgl_AlphaTestRef, alphaTestRef)); + shaderState.uniform(gl, new GLUniformData(mgl_PointParams, 4, pointParams)); for(int i=0; i<MAX_LIGHTS; i++) { shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].ambient", 4, defAmbient)); - shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].diffuse", 4, defDiffuse)); - shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].specular", 4, defSpecular)); + shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].diffuse", 4, 0==i ? one4f : defDiffuseN)); + shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].specular", 4, 0==i ? one4f : defSpecularN)); shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].position", 4, defPosition)); shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotDirection", 3, defSpotDir)); shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotExponent", defSpotExponent)); @@ -475,6 +1143,7 @@ public class FixedFuncPipeline { shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].linearAttenuation", defLinearAtten)); shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].quadraticAttenuation", defQuadraticAtten)); } + shaderState.uniform(gl, new GLUniformData(mgl_LightModel+".ambient", 4, defLightModelAmbient)); shaderState.uniform(gl, new GLUniformData(mgl_LightsEnabled, 1, lightsEnabled)); shaderState.uniform(gl, new GLUniformData(mgl_FrontMaterial+".ambient", 4, defMatAmbient)); shaderState.uniform(gl, new GLUniformData(mgl_FrontMaterial+".diffuse", 4, defMatDiffuse)); @@ -483,70 +1152,121 @@ public class FixedFuncPipeline { shaderState.uniform(gl, new GLUniformData(mgl_FrontMaterial+".shininess", defMatShininess)); shaderState.useProgram(gl, false); + if(verbose) { + System.err.println("init: "+toString(null, DEBUG).toString()); + } } - protected static final boolean DEBUG=false; - protected boolean verbose=false; + private String toHexString(int i) { + return "0x"+Integer.toHexString(i); + } + + protected boolean verbose = DEBUG; + + private final FloatBuffer colorStatic = Buffers.copyFloatBuffer(one4f); + + private int activeTextureUnit=0; + private int clientActiveTextureUnit=0; + private final IntIntHashMap texID2Format = new IntIntHashMap(); + private final int[] boundTextureObject = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }; // per unit + private int textureEnabledBits = 0; + private final IntBuffer textureEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); // per unit + private boolean textureEnabledDirty = false; + private final IntBuffer textureCoordEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); // per unit + private boolean textureCoordEnabledDirty = false; + // textureEnvMode: 1 GL_ADD, 2 GL_MODULATE (default), 3 GL_DECAL, 4 GL_BLEND, 5 GL_REPLACE, 6 GL_COMBINE + private final IntBuffer textureEnvMode = Buffers.newDirectIntBuffer(new int[] { 2, 2, 2, 2, 2, 2, 2, 2 }); + private boolean textureEnvModeDirty = false; + private final IntBuffer textureFormat = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); // per unit + private boolean textureFormatDirty = false; + + /** ES2 supports CullFace implicit + private int cullFace=-2; // <=0 disabled, 1 GL_FRONT, 2 GL_BACK (default) and 3 GL_FRONT_AND_BACK + private boolean cullFaceDirty = false; + private static final String mgl_CullFace = "mgl_CullFace"; // 1i (lowp int) */ - protected boolean textureEnabled=false; - protected IntBuffer textureCoordsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); - protected boolean textureCoordsEnabledDirty = false; - protected int activeTextureUnit=0; + private boolean colorVAEnabledDirty = false; + private boolean lightingEnabled=false; + private final IntBuffer lightsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); + private boolean lightsEnabledDirty = false; - protected int cullFace=-2; // <=0 disabled, 1: front, 2: back (default, but disabled), 3: front & back + private boolean alphaTestDirty=false; + private int alphaTestFunc=-8; // <=0 disabled; 1 GL_NEVER, 2 GL_LESS, 3 GL_EQUAL, 4 GL_LEQUAL, 5 GL_GREATER, 6 GL_NOTEQUAL, 7 GL_GEQUAL, and 8 GL_ALWAYS (default) + private float alphaTestRef=0f; - protected boolean lightingEnabled=false; - protected IntBuffer lightsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); - protected boolean lightsEnabledDirty = false; + private boolean pointParamsDirty = false; + /** ( pointSize, pointSmooth, attn. pointMinSize, attn. pointMaxSize ) , ( attenuation coefficients 1f 0f 0f, attenuation fade theshold 1f ) */ + private final FloatBuffer pointParams = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f }); - protected PMVMatrix pmvMatrix; - protected ShaderState shaderState; - protected ShaderProgram shaderProgramColor; - protected ShaderProgram shaderProgramColorTexture; - protected ShaderProgram shaderProgramColorLight; - protected ShaderProgram shaderProgramColorTextureLight; + private PMVMatrix pmvMatrix; + private ShaderState shaderState; + private ShaderProgram shaderProgramColor; + private ShaderProgram shaderProgramColorTexture2, shaderProgramColorTexture4, shaderProgramColorTexture8; + private ShaderProgram shaderProgramColorLight; + private ShaderProgram shaderProgramColorTexture8Light; + private ShaderProgram shaderProgramPoints; + + private ShaderSelectionMode requestedShaderSelectionMode = ShaderSelectionMode.AUTO; + private ShaderSelectionMode currentShaderSelectionMode = requestedShaderSelectionMode; // uniforms .. - protected static final String mgl_PMVMatrix = "mgl_PMVMatrix"; // m4fv[4] - P, Mv, Mvi and Mvit - protected static final String mgl_ColorEnabled = "mgl_ColorEnabled"; // 1i - protected static final String mgl_ColorStatic = "mgl_ColorStatic"; // 4fv - - protected static final String mgl_LightSource = "mgl_LightSource"; // struct mgl_LightSourceParameters[MAX_LIGHTS] - protected static final String mgl_FrontMaterial = "mgl_FrontMaterial"; // struct mgl_MaterialParameters - protected static final String mgl_LightsEnabled = "mgl_LightsEnabled"; // int mgl_LightsEnabled[MAX_LIGHTS]; - - protected static final String mgl_ShadeModel = "mgl_ShadeModel"; // 1i - - protected static final String mgl_TexCoordEnabled = "mgl_TexCoordEnabled"; // int mgl_TexCoordEnabled[MAX_TEXTURE_UNITS]; - protected static final String mgl_ActiveTexture = "mgl_ActiveTexture"; // 1i - protected static final String mgl_ActiveTextureIdx = "mgl_ActiveTextureIdx";// 1i - - protected static final String mgl_CullFace = "mgl_CullFace"; // 1i - - protected static final FloatBuffer zero4f = Buffers.newDirectFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 0.0f }); - - public static final FloatBuffer defAmbient = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f }); - public static final FloatBuffer defDiffuse = zero4f; - public static final FloatBuffer defSpecular= zero4f; - public static final FloatBuffer defPosition= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 1f, 0f }); - public static final FloatBuffer defSpotDir = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, -1f }); - public static final float defSpotExponent = 0f; - public static final float defSpotCutoff = 180f; - public static final float defConstantAtten = 1f; - public static final float defLinearAtten = 0f; - public static final float defQuadraticAtten= 0f; - - public static final FloatBuffer defMatAmbient = Buffers.newDirectFloatBuffer(new float[] { 0.2f, 0.2f, 0.2f, 1.0f }); - public static final FloatBuffer defMatDiffuse = Buffers.newDirectFloatBuffer(new float[] { 0.8f, 0.8f, 0.8f, 1.0f }); - public static final FloatBuffer defMatSpecular= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f}); - public static final FloatBuffer defMatEmission= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f}); + private static final String mgl_PMVMatrix = "mgl_PMVMatrix"; // m4fv[4] - P, Mv, Mvi and Mvit + private static final String mgl_ColorEnabled = "mgl_ColorEnabled"; // 1i + private static final String mgl_ColorStatic = "mgl_ColorStatic"; // 4fv + + private static final String mgl_LightModel = "mgl_LightModel"; // struct mgl_LightModelParameters + private static final String mgl_LightSource = "mgl_LightSource"; // struct mgl_LightSourceParameters[MAX_LIGHTS] + private static final String mgl_FrontMaterial = "mgl_FrontMaterial"; // struct mgl_MaterialParameters + private static final String mgl_LightsEnabled = "mgl_LightsEnabled"; // int mgl_LightsEnabled[MAX_LIGHTS]; + + private static final String mgl_AlphaTestFunc = "mgl_AlphaTestFunc"; // 1i (lowp int) + private static final String mgl_AlphaTestRef = "mgl_AlphaTestRef"; // 1f + private static final String mgl_ShadeModel = "mgl_ShadeModel"; // 1i + private static final String mgl_PointParams = "mgl_PointParams"; // vec4[2]: { (sz, smooth, attnMinSz, attnMaxSz), (attnCoeff(3), attnFadeTs) } + + private static final String mgl_TextureEnabled = "mgl_TextureEnabled"; // int mgl_TextureEnabled[MAX_TEXTURE_UNITS]; + private static final String mgl_Texture = "mgl_Texture"; // sampler2D mgl_Texture<0..7> + private static final String mgl_TexCoordEnabled = "mgl_TexCoordEnabled"; // int mgl_TexCoordEnabled[MAX_TEXTURE_UNITS]; + private static final String mgl_TexEnvMode = "mgl_TexEnvMode"; // int mgl_TexEnvMode[MAX_TEXTURE_UNITS]; + private static final String mgl_TexFormat = "mgl_TexFormat"; // int mgl_TexFormat[MAX_TEXTURE_UNITS]; + + // private static final FloatBuffer zero4f = Buffers.newDirectFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 0.0f }); + private static final FloatBuffer neut4f = Buffers.newDirectFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); + private static final FloatBuffer one4f = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 1.0f, 1.0f, 1.0f }); + + public static final FloatBuffer defAmbient = neut4f; + public static final FloatBuffer defDiffuseN = neut4f; + public static final FloatBuffer defSpecularN = neut4f; + public static final FloatBuffer defPosition = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 1f, 0f }); + public static final FloatBuffer defSpotDir = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, -1f }); + public static final float defSpotExponent = 0f; + public static final float defSpotCutoff = 180f; + public static final float defConstantAtten = 1f; + public static final float defLinearAtten = 0f; + public static final float defQuadraticAtten = 0f; + + public static final FloatBuffer defLightModelAmbient = Buffers.newDirectFloatBuffer(new float[] { 0.2f, 0.2f, 0.2f, 1.0f }); + + public static final FloatBuffer defMatAmbient = Buffers.newDirectFloatBuffer(new float[] { 0.2f, 0.2f, 0.2f, 1.0f }); + public static final FloatBuffer defMatDiffuse = Buffers.newDirectFloatBuffer(new float[] { 0.8f, 0.8f, 0.8f, 1.0f }); + public static final FloatBuffer defMatSpecular = neut4f; + public static final FloatBuffer defMatEmission = neut4f; public static final float defMatShininess = 0f; - protected static final String vertexColorFileDef = "FixedFuncColor"; - protected static final String vertexColorLightFileDef = "FixedFuncColorLight"; - protected static final String fragmentColorFileDef = "FixedFuncColor"; - protected static final String fragmentColorTextureFileDef = "FixedFuncColorTexture"; - protected static final String shaderSrcRootDef = "shaders" ; - protected static final String shaderBinRootDef = "shaders/bin" ; + private static final String vertexColorFileDef = "FixedFuncColor"; + private static final String vertexColorLightFileDef = "FixedFuncColorLight"; + private static final String fragmentColorFileDef = "FixedFuncColor"; + private static final String fragmentColorTextureFileDef = "FixedFuncColorTexture"; + private static final String shaderPointFileDef = "FixedFuncPoints"; + private static final String shaderSrcRootDef = "shaders" ; + private static final String shaderBinRootDef = "shaders/bin" ; + + private final Class<?> shaderRootClass; + private final String shaderSrcRoot; + private final String shaderBinRoot; + private final String vertexColorFile; + private final String vertexColorLightFile; + private final String fragmentColorFile; + private final String fragmentColorTextureFile; } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp index 408ff7251..22dd1e61a 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp @@ -1,16 +1,32 @@ + +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; +#else + #define mgl_FragColor gl_FragColor +#endif + #include es_precision.glsl #include mgl_uniform.glsl #include mgl_varying.glsl +#include mgl_alphatest.fp + void main (void) { - if( mgl_CullFace > 0 && - ( ( mgl_CullFace == 1 && gl_FrontFacing ) || - ( mgl_CullFace == 2 && !gl_FrontFacing ) || - ( mgl_CullFace == 3 ) ) ) { - discard; + vec4 color = frontColor; + + /** ES2 supports CullFace implicit .. + if( mgl_CullFace > 0 && + ( ( MGL_FRONT == mgl_CullFace && gl_FrontFacing ) || + ( MGL_BACK == mgl_CullFace && !gl_FrontFacing ) || + ( MGL_FRONT_AND_BACK == mgl_CullFace ) ) ) { + DISCARD(color); + } */ + if( mgl_AlphaTestFunc > 0 ) { + alphaTest(color); } - gl_FragColor = frontColor; + mgl_FragColor = color; } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp index 346e40196..f39fcfbd0 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp @@ -1,3 +1,9 @@ + +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + #include es_precision.glsl #include mgl_const.glsl diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp index 7ce1eedcf..942a540af 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp @@ -1,3 +1,9 @@ + +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + #include es_precision.glsl #include mgl_lightdef.glsl @@ -50,16 +56,18 @@ void main(void) } } } - ambient *= mgl_FrontMaterial.ambient; - diffuse *= mgl_FrontMaterial.diffuse; - specular *= mgl_FrontMaterial.specular; - if(mgl_ColorEnabled>0) { frontColor=mgl_Color; } else { frontColor=mgl_ColorStatic; } if( lightEnabled ) { + // light-ambient + global-ambient + // ( mgl_LightSource[0..n].ambient * mgl_FrontMaterial.ambient ) + ( mgl_LightModel.ambient * mgl_FrontMaterial.ambient ) + ambient = ( ambient + mgl_LightModel.ambient ) * mgl_FrontMaterial.ambient; + diffuse *= mgl_FrontMaterial.diffuse; + specular *= mgl_FrontMaterial.specular; + frontColor *= ambient + diffuse + specular; } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp index 86e6ace73..130711e19 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp @@ -1,4 +1,13 @@ +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; + #define texture2D texture +#else + #define mgl_FragColor gl_FragColor +#endif + + #include es_precision.glsl #include mgl_lightdef.glsl @@ -6,42 +15,103 @@ #include mgl_uniform.glsl #include mgl_varying.glsl -vec4 getTexColor(in sampler2D tex, in int idx) { - vec4 coord; - if(idx==0) { - coord= mgl_TexCoords[0]; - } else if(idx==1) { - coord= mgl_TexCoords[1]; - } else if(idx==2) { - coord= mgl_TexCoords[2]; - } else if(idx==3) { - coord= mgl_TexCoords[3]; - } else if(idx==4) { - coord= mgl_TexCoords[4]; - } else if(idx==5) { - coord= mgl_TexCoords[5]; - } else if(idx==6) { - coord= mgl_TexCoords[6]; - } else { - coord= mgl_TexCoords[7]; +#include mgl_alphatest.fp + +const float gamma = 1.5; // FIXME +const vec3 igammav = vec3(1.0 / gamma); // FIXME +const vec4 texEnvColor = vec4(0.0); // FIXME + +const vec4 zerov4 = vec4(0.0); +const vec4 onev4 = vec4(1.0); + +void calcTexColor(inout vec4 color, vec4 texColor, in int texFormat, in int texEnvMode) { + if(MGL_MODULATE == texEnvMode) { // default + if( 4 == texFormat ) { + color *= texColor; + } else { + color.rgb *= texColor.rgb; + } + } else if(MGL_REPLACE == texEnvMode) { + if( 4 == texFormat ) { + color = texColor; + } else { + color.rgb = texColor.rgb; + } + } else if(MGL_ADD == texEnvMode) { + if( 4 == texFormat ) { + color += texColor; + } else { + color.rgb += texColor.rgb; + } + } else if(MGL_BLEND == texEnvMode) { + color.rgb = mix(color.rgb, texEnvColor.rgb, texColor.rgb); + if( 4 == texFormat ) { + color.a *= texColor.a; + } + } else if(MGL_DECAL == texEnvMode) { + if( 4 == texFormat ) { + color.rgb = mix(color.rgb, texColor.rgb, texColor.a); + } else { + color.rgb = texColor.rgb; + } } - return texture2D(tex, coord.st); + color = clamp(color, zerov4, onev4); } void main (void) -{ - if( mgl_CullFace > 0 && - ( ( mgl_CullFace == 1 && gl_FrontFacing ) || - ( mgl_CullFace == 2 && !gl_FrontFacing ) || - ( mgl_CullFace == 3 ) ) ) { - discard; - } - - vec4 texColor = getTexColor(mgl_ActiveTexture,mgl_ActiveTextureIdx); - - if(length(texColor.rgb)>0.0) { - gl_FragColor = vec4(frontColor.rgb*texColor.rgb, frontColor.a) ; +{ + vec4 color = frontColor; + + /** ES2 supports CullFace implicit .. + if( mgl_CullFace > 0 && + ( ( MGL_FRONT == mgl_CullFace && gl_FrontFacing ) || + ( MGL_BACK == mgl_CullFace && !gl_FrontFacing ) || + ( MGL_FRONT_AND_BACK == mgl_CullFace ) ) ) { + DISCARD(color); + } else { */ + #if MAX_TEXTURE_UNITS >= 2 + if( 0 != mgl_TextureEnabled[0] ) { + calcTexColor(color, texture2D(mgl_Texture0, mgl_TexCoords[0].st), mgl_TexFormat[0], mgl_TexEnvMode[0]); + } + if( 0 != mgl_TextureEnabled[1] ) { + calcTexColor(color, texture2D(mgl_Texture1, mgl_TexCoords[1].st), mgl_TexFormat[1], mgl_TexEnvMode[1]); + } + #endif + #if MAX_TEXTURE_UNITS >= 4 + if( 0 != mgl_TextureEnabled[2] ) { + calcTexColor(color, texture2D(mgl_Texture2, mgl_TexCoords[2].st), mgl_TexFormat[2], mgl_TexEnvMode[2]); + } + if( 0 != mgl_TextureEnabled[3] ) { + calcTexColor(color, texture2D(mgl_Texture3, mgl_TexCoords[3].st), mgl_TexFormat[3], mgl_TexEnvMode[3]); + } + #endif + #if MAX_TEXTURE_UNITS >= 8 + if( 0 != mgl_TextureEnabled[4] ) { + calcTexColor(color, texture2D(mgl_Texture4, mgl_TexCoords[4].st), mgl_TexFormat[4], mgl_TexEnvMode[4]); + } + if( 0 != mgl_TextureEnabled[5] ) { + calcTexColor(color, texture2D(mgl_Texture5, mgl_TexCoords[5].st), mgl_TexFormat[5], mgl_TexEnvMode[5]); + } + if( 0 != mgl_TextureEnabled[6] ) { + calcTexColor(color, texture2D(mgl_Texture6, mgl_TexCoords[6].st), mgl_TexFormat[6], mgl_TexEnvMode[6]); + } + if( 0 != mgl_TextureEnabled[7] ) { + calcTexColor(color, texture2D(mgl_Texture7, mgl_TexCoords[7].st), mgl_TexFormat[7], mgl_TexEnvMode[7]); + } + #endif + if( mgl_AlphaTestFunc > 0 ) { + alphaTest(color); + } + // } /* CullFace */ + + mgl_FragColor = color; + /** + // simple alpha check + if (color.a != 0.0) { + mgl_FragColor = vec4(pow(color.rgb, igammav), color.a); } else { - gl_FragColor = frontColor; - } + // discard; // freezes NV tegra2 compiler + mgl_FragColor = color; + } */ } + diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.fp new file mode 100644 index 000000000..2d58f2320 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.fp @@ -0,0 +1,47 @@ + +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; +#else + #define mgl_FragColor gl_FragColor +#endif + + +#include es_precision.glsl +#include mgl_lightdef.glsl + +#include mgl_const.glsl +#include mgl_uniform.glsl +#include mgl_varying.glsl + +// #define TEST 1 + +void main (void) +{ + mgl_FragColor = frontColor; + + if( pointSmooth > 0.5 ) { + // smooth (AA) + const float border = 0.90; // take/give 10% for AA + + // origin to 0/0, [-1/-1 .. 1/1] + vec2 pointPos = 2.0 * gl_PointCoord - 1.0 ; + float r = length( pointPos ); // one-circle sqrt(x * x + y * y), range: in-circle [0..1], out >1 + float r1 = 1.0 - ( step(border, r) * 10.0 * ( r - border ) ) ; // [0..1] + #ifndef TEST + if( r1 < 0.0 ) { + discard; + } + #endif + + #ifndef TEST + mgl_FragColor.a *= r1; + #else + mgl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + mgl_FragColor.r = r1 < 0.0 ? 1.0 : 0.0; + mgl_FragColor.g = r > 1.0 ? 1.0 : 0.0; + mgl_FragColor.b = r > border ? 1.0 : 0.0; + #endif + } +} + diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.vp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.vp new file mode 100644 index 000000000..4a5d93a3d --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.vp @@ -0,0 +1,40 @@ + +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + +#include es_precision.glsl + +#include mgl_const.glsl +#include mgl_uniform.glsl +#include mgl_attribute.glsl +#include mgl_varying.glsl + +#include mgl_settexcoord.vp + +void main(void) +{ + if( mgl_ColorEnabled > 0 ) { + frontColor = mgl_Color; + } else { + frontColor = mgl_ColorStatic; + } + + vec4 eyeCoord = mgl_PMVMatrix[1] * mgl_Vertex; + gl_Position = mgl_PMVMatrix[0] * eyeCoord; + + float dist = distance(eyeCoord, vec4(0.0, 0.0, 0.0, 1.0)); + float atten = sqrt( 1.0 / ( pointDistanceConstantAtten + + ( pointDistanceLinearAtten + + pointDistanceQuadraticAtten * dist + ) * dist + ) + ); + float size = clamp(pointSize * atten, pointSizeMin, pointSizeMax); + gl_PointSize = max(size, pointFadeThresholdSize); + + float fade = min(size, pointFadeThresholdSize) / pointFadeThresholdSize; + frontColor.a *= fade * fade; +} + diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_alphatest.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_alphatest.fp new file mode 100644 index 000000000..2b64cdeb8 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_alphatest.fp @@ -0,0 +1,33 @@ + +void alphaTest(inout vec4 color) { + if( MGL_GREATER == mgl_AlphaTestFunc ) { + if ( color.a <= mgl_AlphaTestRef ) { + DISCARD(color); + } + } else if( MGL_LESS == mgl_AlphaTestFunc ) { + if ( color.a >= mgl_AlphaTestRef ) { + DISCARD(color); + } + } else if( MGL_LEQUAL == mgl_AlphaTestFunc ) { + if ( color.a > mgl_AlphaTestRef ) { + DISCARD(color); + } + } else if( MGL_GEQUAL == mgl_AlphaTestFunc ) { + if ( color.a < mgl_AlphaTestRef ) { + DISCARD(color); + } + } else if( MGL_EQUAL == mgl_AlphaTestFunc ) { + if ( abs( color.a - mgl_AlphaTestRef ) > EPSILON ) { + DISCARD(color); + } + } else if( MGL_NOTEQUAL == mgl_AlphaTestFunc ) { + if ( abs( color.a - mgl_AlphaTestRef ) <= EPSILON ) { + DISCARD(color); + } + } else if( MGL_NEVER == mgl_AlphaTestFunc ) { + DISCARD(color); + } /* else if( MGL_ALWAYS == mgl_AlphaTestFunc ) { + // NOP + } */ +} + diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl index 09a11ec95..f670f7b77 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl @@ -4,16 +4,22 @@ #include es_precision.glsl -attribute HIGHP vec4 mgl_Vertex; -attribute HIGHP vec4 mgl_Normal; -attribute HIGHP vec4 mgl_Color; -attribute HIGHP vec4 mgl_MultiTexCoord0; -attribute HIGHP vec4 mgl_MultiTexCoord1; -attribute HIGHP vec4 mgl_MultiTexCoord2; -attribute HIGHP vec4 mgl_MultiTexCoord3; -attribute HIGHP vec4 mgl_MultiTexCoord4; -attribute HIGHP vec4 mgl_MultiTexCoord5; -attribute HIGHP vec4 mgl_MultiTexCoord6; -attribute HIGHP vec4 mgl_MultiTexCoord7; +attribute vec4 mgl_Vertex; +attribute vec4 mgl_Normal; +attribute vec4 mgl_Color; +#if MAX_TEXTURE_UNITS >= 2 +attribute vec4 mgl_MultiTexCoord0; +attribute vec4 mgl_MultiTexCoord1; +#endif +#if MAX_TEXTURE_UNITS >= 4 +attribute vec4 mgl_MultiTexCoord2; +attribute vec4 mgl_MultiTexCoord3; +#endif +#if MAX_TEXTURE_UNITS >= 8 +attribute vec4 mgl_MultiTexCoord4; +attribute vec4 mgl_MultiTexCoord5; +attribute vec4 mgl_MultiTexCoord6; +attribute vec4 mgl_MultiTexCoord7; +#endif #endif // mgl_attribute_glsl diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl index 1a464a1cb..4f97292e3 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl @@ -4,7 +4,36 @@ #include es_precision.glsl -const LOWP int MAX_TEXTURE_UNITS = 8; // <=gl_MaxTextureImageUnits +// will be defined at runtime: MAX_TEXTURE_UNITS [0|2|4|8] const LOWP int MAX_LIGHTS = 8; +const float EPSILON = 0.0000001; // FIXME: determine proper hw-precision + +// discard freezes NV tegra2 compiler (STILL TRUE?) +// #define DISCARD(c) (c.a = 0.0) +#define DISCARD(c) discard + +// Texture Environment / Multi Texturing +#define MGL_ADD 1 +#define MGL_MODULATE 2 +#define MGL_DECAL 3 +#define MGL_BLEND 4 +#define MGL_REPLACE 5 +#define MGL_COMBINE 6 + +// Alpha Test +#define MGL_NEVER 1 +#define MGL_LESS 2 +#define MGL_EQUAL 3 +#define MGL_LEQUAL 4 +#define MGL_GREATER 5 +#define MGL_NOTEQUAL 6 +#define MGL_GEQUAL 7 +#define MGL_ALWAYS 8 + +// Cull Face +#define MGL_FRONT 1 +#define MGL_BACK 2 +#define MGL_FRONT_AND_BACK 3 + #endif // mgl_const_glsl diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl index 98e214139..deaf95408 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl @@ -1,6 +1,9 @@ #ifndef mgl_lightdef_glsl #define mgl_lightdef_glsl +struct mgl_LightModelParameters { + vec4 ambient; +}; struct mgl_LightSourceParameters { vec4 ambient; vec4 diffuse; diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp index 1efe328d0..cbf0db642 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp @@ -22,14 +22,20 @@ void setTexCoord(in vec4 defpos) { mgl_TexCoords[7] = ( 0 != (mgl_TexCoordEnabled & 128) ) ? mgl_MultiTexCoord7 : defpos; */ + #if MAX_TEXTURE_UNITS >= 2 mgl_TexCoords[0] = ( 0 != mgl_TexCoordEnabled[0] ) ? mgl_MultiTexCoord0 : defpos; mgl_TexCoords[1] = ( 0 != mgl_TexCoordEnabled[1] ) ? mgl_MultiTexCoord1 : defpos; + #endif + #if MAX_TEXTURE_UNITS >= 4 mgl_TexCoords[2] = ( 0 != mgl_TexCoordEnabled[2] ) ? mgl_MultiTexCoord2 : defpos; mgl_TexCoords[3] = ( 0 != mgl_TexCoordEnabled[3] ) ? mgl_MultiTexCoord3 : defpos; + #endif + #if MAX_TEXTURE_UNITS >= 8 mgl_TexCoords[4] = ( 0 != mgl_TexCoordEnabled[4] ) ? mgl_MultiTexCoord4 : defpos; mgl_TexCoords[5] = ( 0 != mgl_TexCoordEnabled[5] ) ? mgl_MultiTexCoord5 : defpos; mgl_TexCoords[6] = ( 0 != mgl_TexCoordEnabled[6] ) ? mgl_MultiTexCoord6 : defpos; mgl_TexCoords[7] = ( 0 != mgl_TexCoordEnabled[7] ) ? mgl_MultiTexCoord7 : defpos; + #endif } #endif // mgl_settexcoord_vp diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl index 4c4000dfa..5029e4bd8 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl @@ -6,12 +6,45 @@ #include mgl_const.glsl -uniform HIGHP mat4 mgl_PMVMatrix[4]; // P, Mv, Mvi and Mvit (transpose(inverse(ModelView)) == normalMatrix) +uniform mat4 mgl_PMVMatrix[4]; // P, Mv, Mvi and Mvit (transpose(inverse(ModelView)) == normalMatrix) uniform LOWP int mgl_ColorEnabled; -uniform HIGHP vec4 mgl_ColorStatic; +uniform vec4 mgl_ColorStatic; +uniform LOWP int mgl_AlphaTestFunc; +uniform float mgl_AlphaTestRef; + +// [0].rgba: size, smooth, attnMinSz, attnMaxSz +// [1].rgba: attnCoeff(3), attnFadeTs +uniform MEDIUMP vec4 mgl_PointParams[2]; + +#define pointSize (mgl_PointParams[0].r) +#define pointSmooth (mgl_PointParams[0].g) +#define pointSizeMin (mgl_PointParams[0].b) +#define pointSizeMax (mgl_PointParams[0].a) +#define pointDistanceConstantAtten (mgl_PointParams[1].r) +#define pointDistanceLinearAtten (mgl_PointParams[1].g) +#define pointDistanceQuadraticAtten (mgl_PointParams[1].b) +#define pointFadeThresholdSize (mgl_PointParams[1].a) + +// uniform LOWP int mgl_CullFace; // ES2 supports CullFace implicit .. +#if MAX_TEXTURE_UNITS > 0 +uniform LOWP int mgl_TextureEnabled[MAX_TEXTURE_UNITS]; uniform LOWP int mgl_TexCoordEnabled[MAX_TEXTURE_UNITS]; -uniform sampler2D mgl_ActiveTexture; -uniform LOWP int mgl_ActiveTextureIdx; -uniform LOWP int mgl_CullFace; +uniform LOWP int mgl_TexEnvMode[MAX_TEXTURE_UNITS]; +uniform LOWP int mgl_TexFormat[MAX_TEXTURE_UNITS]; +#if MAX_TEXTURE_UNITS >= 2 +uniform sampler2D mgl_Texture0; +uniform sampler2D mgl_Texture1; +#endif +#if MAX_TEXTURE_UNITS >= 4 +uniform sampler2D mgl_Texture2; +uniform sampler2D mgl_Texture3; +#endif +#if MAX_TEXTURE_UNITS >= 8 +uniform sampler2D mgl_Texture4; +uniform sampler2D mgl_Texture5; +uniform sampler2D mgl_Texture6; +uniform sampler2D mgl_Texture7; +#endif +#endif #endif // mgl_uniform_glsl diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl index 0dedb5d5d..5b34fd9cf 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl @@ -9,6 +9,7 @@ uniform LOWP int mgl_LightsEnabled[MAX_LIGHTS]; +uniform mgl_LightModelParameters mgl_LightModel; uniform mgl_LightSourceParameters mgl_LightSource[MAX_LIGHTS]; uniform mgl_MaterialParameters mgl_FrontMaterial; diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl index fc9f735d1..599ac4a53 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl @@ -7,6 +7,8 @@ #include mgl_const.glsl varying vec4 frontColor; +#if MAX_TEXTURE_UNITS > 0 varying vec4 mgl_TexCoords[MAX_TEXTURE_UNITS]; +#endif #endif // mgl_varying_glsl |