diff options
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
10 files changed, 880 insertions, 298 deletions
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 804678fb4..abf71ba41 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java @@ -29,48 +29,82 @@ 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.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; - - public FixedFuncHook (GL2ES2 gl) { - this(gl, null); - } + protected FixedFuncPipeline fixedFunction; + protected PMVMatrix pmvMatrix; + protected boolean ownsPMVMatrix; + protected GL2ES2 gl; - 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) { this.gl = gl; - pmvMatrix = (null!=matrix)?matrix:new PMVMatrix(); - - fixedFunction = new FixedFuncPipeline(gl, pmvMatrix); + 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, - Class<?> shaderRootClass, String shaderSrcRoot, String shaderBinRoot, - String vertexColorFile, - String vertexColorLightFile, - String fragmentColorFile, - String fragmentColorTextureFile) { + /** + * @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 = matrix; + if(null != pmvMatrix) { + this.ownsPMVMatrix = false; + this.pmvMatrix = pmvMatrix; + } else { + this.ownsPMVMatrix = true; + this.pmvMatrix = new PMVMatrix(); + } - fixedFunction = new FixedFuncPipeline(gl, pmvMatrix, - shaderRootClass, shaderSrcRoot, shaderBinRoot, - vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile); + fixedFunction = new FixedFuncPipeline(this.gl, mode, this.pmvMatrix, shaderRootClass, shaderSrcRoot, + shaderBinRoot, vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile); } + public boolean verbose() { return fixedFunction.verbose(); } + + 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; } @@ -92,24 +126,19 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } 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); - } - + } public void glGetFloatv(int pname, java.nio.FloatBuffer params) { if(PMVMatrix.isMatrixGetName(pname)) { pmvMatrix.glGetFloatv(pname, params); @@ -138,7 +167,35 @@ 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) { + 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) { + 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 arg0) { + // NOP - FIXME ? + } + // // MatrixIf // @@ -178,9 +235,15 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun 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); + } 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); + } public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar) { pmvMatrix.glFrustumf(left, right, bottom, top, zNear, zFar); } @@ -207,13 +270,27 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun public void glMaterialf(int face, int pname, float param) { glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(new float[] { param })); } + + // + // Misc Simple States + // public void glShadeModel(int mode) { fixedFunction.glShadeModel(gl, mode); + } + public void glAlphaFunc(int func, float ref) { + fixedFunction.glAlphaFunc(func, ref); } - + public void glCullFace(int faceName) { + fixedFunction.glCullFace(faceName); + gl.glCullFace(faceName); + } + // // PointerIf // + public void glClientActiveTexture(int textureUnit) { + fixedFunction.glClientActiveTexture(textureUnit); + } public void glEnableClientState(int glArrayIndex) { fixedFunction.glEnableClientState(gl, glArrayIndex); } 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 40fc119d2..be9fe8c34 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,61 @@ package jogamp.opengl.util.glsl.fixedfunc; -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 java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +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.GLLightingFunc; +import javax.media.opengl.fixedfunc.GLPointerFunc; +import javax.media.opengl.fixedfunc.GLPointerFuncUtil; +import jogamp.opengl.Debug; + +import com.jogamp.common.nio.Buffers; +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 = Debug.isPropertyDefined("jogl.debug.FixedFuncPipeline", true); 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) { + init(gl, mode, pmvMatrix, FixedFuncPipeline.class, shaderSrcRootDef, + shaderBinRootDef, vertexColorFileDef, vertexColorLightFileDef, fragmentColorFileDef, fragmentColorTextureFileDef); } - public FixedFuncPipeline(GL2ES2 gl, PMVMatrix pmvMatrix, Class<?> shaderRootClass, String shaderSrcRoot, String shaderBinRoot, + public FixedFuncPipeline(GL2ES2 gl, ShaderSelectionMode mode, 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); + String fragmentColorFile, String fragmentColorTextureFile) { + init(gl, mode, pmvMatrix, shaderRootClass, shaderSrcRoot, + shaderBinRoot, vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile); } + + public ShaderSelectionMode getShaderSelectionMode() { return shaderSelectionMode; } + public void setShaderSelectionMode(ShaderSelectionMode mode) { shaderSelectionMode=mode; } 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,19 +97,6 @@ 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); @@ -90,28 +105,58 @@ public class FixedFuncPipeline { shaderState.destroy(gl); } - public void glEnableClientState(GL2ES2 gl, int glArrayIndex) { + // + // Simple Globals + // + + public void glColor4fv(GL2ES2 gl, FloatBuffer data ) { shaderState.useProgram(gl, true); - - shaderState.enableVertexAttribArray(gl, getArrayIndexName(glArrayIndex)); - // textureCoordsEnabled |= (1 << activeTextureUnit); - if ( textureCoordsEnabled.get(activeTextureUnit) != 1 ) { - textureCoordsEnabled.put(activeTextureUnit, 1); - textureCoordsEnabledDirty = true; + GLUniformData ud = shaderState.getUniform(mgl_ColorStatic); + if(null!=ud) { + ud.setData(data); + shaderState.uniform(gl, ud); } } + // + // 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; } } - + public void glVertexPointer(GL2ES2 gl, GLArrayData data) { shaderState.useProgram(gl, true); shaderState.vertexAttribPointer(gl, data); @@ -122,27 +167,142 @@ public class FixedFuncPipeline { shaderState.vertexAttribPointer(gl, data); } - public void glColor4fv(GL2ES2 gl, FloatBuffer data ) { - shaderState.useProgram(gl, true); - GLUniformData ud = shaderState.getUniform(mgl_ColorStatic); - if(null!=ud) { - ud.setData(data); - shaderState.uniform(gl, ud); - } - } - public void glNormalPointer(GL2ES2 gl, GLArrayData data) { shaderState.useProgram(gl, true); shaderState.vertexAttribPointer(gl, data); } + + // + // MULTI-TEXTURE + // + + 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)); + } + + // + // Lighting + // - public void glLightfv(GL2ES2 gl, int light, int pname, java.nio.FloatBuffer params) { + public void glLightfv(GL2ES2 gl, int light, int pname, java.nio.FloatBuffer params) { shaderState.useProgram(gl, true); light -=GLLightingFunc.GL_LIGHT0; if(0 <= light && light < MAX_LIGHTS) { @@ -179,17 +339,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 +358,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 +369,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 +390,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 +413,134 @@ 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); + 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; } - activeTextureUnit = textureUnit; - } else { - throw new GLException("glActivateTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit); } } + 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; + } + } + } + /** * @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: + 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: + final boolean isEnabled = 0 != ( textureEnabledBits & ( 1 << activeTextureUnit ) ); + if( isEnabled != enable ) { + if(enable) { + textureEnabledBits |= ( 1 << activeTextureUnit ); + textureEnabled.put(activeTextureUnit, 1); + } else { + textureEnabledBits &= ~( 1 << activeTextureUnit ); + textureEnabled.put(activeTextureUnit, 0); + } + textureEnabledDirty=true; + } + 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; } int light = cap - GLLightingFunc.GL_LIGHT0; @@ -299,26 +551,33 @@ public class FixedFuncPipeline { return false; } } - return true; // pass it on .. - } - - 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; - } - if(0>cullFace) { - faceName *= -1; - } - cullFace = faceName; + System.err.println("FixedFunctionPipeline: "+(enable ? "glEnable" : "glDisable")+" "+toHexString(cap)+" not handled in emulation and not supported in ES2"); + return false; // ignore! } public void validate(GL2ES2 gl) { - shaderState.useProgram(gl, true); + if( ShaderSelectionMode.AUTO == shaderSelectionMode) { + final ShaderSelectionMode newMode; + + // pre-validate shader switch + if( 0 != textureEnabledBits ) { + if(lightingEnabled) { + newMode = ShaderSelectionMode.COLOR_TEXTURE_LIGHT_PER_VERTEX; + } else { + newMode = ShaderSelectionMode.COLOR_TEXTURE; + } + } 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); + } + GLUniformData ud; if( pmvMatrix.update() ) { ud = shaderState.getUniform(mgl_PMVMatrix); @@ -329,22 +588,39 @@ public class FixedFuncPipeline { 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 = (shaderState.isVertexAttribArrayEnabled(GLPointerFuncUtil.mgl_Color)==true)?1:0; + if(ca!=ud.intValue()) { + ud.setData(ca); + shaderState.uniform(gl, ud); + } } + colorVAEnabledDirty = false; } - ud = shaderState.getUniform(mgl_CullFace); - if(null!=ud) { - if(cullFace!=ud.intValue()) { + 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(lightsEnabledDirty) { ud = shaderState.getUniform(mgl_LightsEnabled); if(null!=ud) { @@ -354,57 +630,102 @@ public class FixedFuncPipeline { lightsEnabledDirty=false; } - if(textureCoordsEnabledDirty) { + if(textureCoordEnabledDirty) { ud = shaderState.getUniform(mgl_TexCoordEnabled); if(null!=ud) { // 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(textureEnabledDirty) { + ud = shaderState.getUniform(mgl_TextureEnabled); + if(null!=ud) { + // same data object + shaderState.uniform(gl, ud); + } + textureEnabledDirty=false; } - if(DEBUG) { - System.err.println("validate: "+this); + + if(verbose) { + System.err.println("validate: "+toString(null, DEBUG).toString()); } } + public StringBuilder toString(StringBuilder sb, boolean alsoUnlocated) { + if(null == sb) { + sb = new StringBuilder(); + } + 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, shaderProgramColorTexture: "+shaderProgramColorTexture); + sb.append("\n\t, shaderProgramColorLight: "+shaderProgramColorLight); + sb.append("\n\t, shaderProgramColorTextureLight: "+shaderProgramColorTextureLight); + sb.append("\n\t, ShaderState: "); + shaderState.toString(sb, alsoUnlocated); + sb.append("]"); + return sb; + } 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) + return toString(null, DEBUG).toString(); + } + + private ShaderProgram selectShaderProgram(GL2ES2 gl, ShaderSelectionMode mode) { + final ShaderProgram sp; + switch(mode) { + case COLOR_LIGHT_PER_VERTEX: + sp = shaderProgramColorLight; + break; + case COLOR_TEXTURE: + sp = shaderProgramColorTexture; + break; + case COLOR_TEXTURE_LIGHT_PER_VERTEX: + sp = shaderProgramColorTextureLight; + break; + case AUTO: + case COLOR: + default: + sp = shaderProgramColor; + } + return sp; + } + + private void init(GL2ES2 gl, ShaderSelectionMode mode, 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"); } this.pmvMatrix=pmvMatrix; + this.shaderSelectionMode = mode; this.shaderState=new ShaderState(); this.shaderState.setVerbose(verbose); ShaderCode vertexColor, vertexColorLight, fragmentColor, fragmentColorTexture; @@ -449,7 +770,7 @@ public class FixedFuncPipeline { throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorTextureLight); } - shaderState.attachShaderProgram(gl, shaderProgramColor, true); + shaderState.attachShaderProgram(gl, selectShaderProgram(gl, shaderSelectionMode), true); // mandatory .. if(!shaderState.uniform(gl, new GLUniformData(mgl_PMVMatrix, 4, 4, pmvMatrix.glGetPMvMvitMatrixf()))) { @@ -457,16 +778,24 @@ 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, one4f)); + + 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)); + shaderState.uniform(gl, new GLUniformData(mgl_AlphaTestFunc, alphaTestFunc)); + shaderState.uniform(gl, new GLUniformData(mgl_AlphaTestRef, alphaTestRef)); 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)); @@ -474,7 +803,8 @@ public class FixedFuncPipeline { shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].constantAttenuation", defConstantAtten)); 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 +813,102 @@ 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; - - 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; - - protected int cullFace=-2; // <=0 disabled, 1: front, 2: back (default, but disabled), 3: front & back - - protected boolean lightingEnabled=false; - protected IntBuffer lightsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); - protected boolean lightsEnabledDirty = false; - - protected PMVMatrix pmvMatrix; - protected ShaderState shaderState; - protected ShaderProgram shaderProgramColor; - protected ShaderProgram shaderProgramColorTexture; - protected ShaderProgram shaderProgramColorLight; - protected ShaderProgram shaderProgramColorTextureLight; + private String toHexString(int i) { + return "0x"+Integer.toHexString(i); + } + + protected boolean verbose = DEBUG; + + 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; + + private int cullFace=-2; // <=0 disabled, 1 GL_FRONT, 2 GL_BACK (default) and 3 GL_FRONT_AND_BACK + private boolean cullFaceDirty = false; + + 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; + + 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; + + private PMVMatrix pmvMatrix; + private ShaderState shaderState; + private ShaderProgram shaderProgramColor; + private ShaderProgram shaderProgramColorTexture; + private ShaderProgram shaderProgramColorLight; + private ShaderProgram shaderProgramColorTextureLight; + + private ShaderSelectionMode shaderSelectionMode = ShaderSelectionMode.AUTO; // 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_CullFace = "mgl_CullFace"; // 1i (lowp int) + 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_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 shaderSrcRootDef = "shaders" ; + private static final String shaderBinRootDef = "shaders/bin" ; } 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..bd7f2bdb2 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 @@ -3,14 +3,21 @@ #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; + HIGHP vec4 color = frontColor; + + 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; + gl_FragColor = color; } 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..0b5519355 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 @@ -50,16 +50,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..edaa00a57 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 @@ -6,42 +6,98 @@ #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 HIGHP float gamma = 1.5; // FIXME +const HIGHP vec3 igammav = vec3(1.0 / gamma); // FIXME +const vec4 texEnvColor = vec4(0.0); // FIXME + +const HIGHP vec4 zerov4 = vec4(0.0); +const HIGHP 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); +{ + HIGHP vec4 color = frontColor; - if(length(texColor.rgb)>0.0) { - gl_FragColor = vec4(frontColor.rgb*texColor.rgb, frontColor.a) ; + 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 { - gl_FragColor = frontColor; + int texEnv = 0; + + 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]); + } + 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]); + } + 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]); + } + if( mgl_AlphaTestFunc > 0 ) { + alphaTest(color); + } } + + gl_FragColor = color; + /** + // simple alpha check + if (color.a != 0.0) { + gl_FragColor = vec4(pow(color.rgb, igammav), color.a); + } else { + // discard; // freezes NV tegra2 compiler + gl_FragColor = color; + } */ } + 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_const.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl index 1a464a1cb..d45b593e2 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 @@ -7,4 +7,33 @@ const LOWP int MAX_TEXTURE_UNITS = 8; // <=gl_MaxTextureImageUnits const LOWP int MAX_LIGHTS = 8; +const HIGHP 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_uniform.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl index 4c4000dfa..aeaa1314d 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 @@ -9,9 +9,21 @@ uniform HIGHP mat4 mgl_PMVMatrix[4]; // P, Mv, Mvi and Mvit (transpose(inverse(ModelView)) == normalMatrix) uniform LOWP int mgl_ColorEnabled; uniform HIGHP vec4 mgl_ColorStatic; +uniform LOWP int mgl_AlphaTestFunc; +uniform HIGHP float mgl_AlphaTestRef; +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_TexEnvMode[MAX_TEXTURE_UNITS]; +uniform LOWP int mgl_TexFormat[MAX_TEXTURE_UNITS]; +uniform sampler2D mgl_Texture0; +uniform sampler2D mgl_Texture1; +uniform sampler2D mgl_Texture2; +uniform sampler2D mgl_Texture3; +uniform sampler2D mgl_Texture4; +uniform sampler2D mgl_Texture5; +uniform sampler2D mgl_Texture6; +uniform sampler2D mgl_Texture7; +uniform sampler2D mgl_Texture8; uniform LOWP int mgl_CullFace; #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; |