/* * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2010 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.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.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 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; /** * *

* 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). *

*/ public class FixedFuncPipeline { protected static final boolean 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, 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, 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 = DEBUG || v; } public boolean isValid() { return shaderState.linked(); } public ShaderState getShaderState() { return shaderState; } public int getActiveTextureUnit() { return activeTextureUnit; } public void destroy(GL2ES2 gl) { 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); } // // 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.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) { glToggleClientState(gl, glArrayIndex, false); } 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); } public void glColorPointer(GL2ES2 gl, GLArrayData data) { shaderState.useProgram(gl, true); shaderState.vertexAttribPointer(gl, data); } public void glNormalPointer(GL2ES2 gl, GLArrayData data) { shaderState.useProgram(gl, true); 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 glClientActiveTexture(int textureUnit) { textureUnit -= GL.GL_TEXTURE0; if(0 <= textureUnit && textureUnit "+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 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 glDrawArraysAction = new GLRunnable2() { @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; if(0 <= light && light < MAX_LIGHTS) { GLUniformData ud = null; switch(pname) { case GLLightingFunc.GL_AMBIENT: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].ambient"); break; case GLLightingFunc.GL_DIFFUSE: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].diffuse"); break; case GLLightingFunc.GL_SPECULAR: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].specular"); break; case GLLightingFunc.GL_POSITION: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].position"); break; case GLLightingFunc.GL_SPOT_DIRECTION: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotDirection"); break; case GLLightingFunc.GL_SPOT_EXPONENT: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotExponent"); break; case GLLightingFunc.GL_SPOT_CUTOFF: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotCutoff"); break; case GLLightingFunc.GL_CONSTANT_ATTENUATION: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].constantAttenuation"); break; case GLLightingFunc.GL_LINEAR_ATTENUATION: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].linearAttenuation"); break; case GLLightingFunc.GL_QUADRATIC_ATTENUATION: ud = shaderState.getUniform(mgl_LightSource+"["+light+"].quadraticAttenuation"); break; default: throw new GLException("glLightfv invalid pname: "+toHexString(pname)); } if(null!=ud) { ud.setData(params); shaderState.uniform(gl, ud); } } else { throw new GLException("glLightfv light not within [0.."+MAX_LIGHTS+"]: "+light); } } public void glMaterialfv(GL2ES2 gl, int face, int pname, java.nio.FloatBuffer params) { shaderState.useProgram(gl, true); switch (face) { case GL.GL_FRONT: case GL.GL_FRONT_AND_BACK: break; case GL.GL_BACK: System.err.println("FixedFuncPipeline: Unimplemented glMaterialfv GL_BACK face"); return; default: } GLUniformData ud = null; switch(pname) { case GLLightingFunc.GL_AMBIENT: ud = shaderState.getUniform(mgl_FrontMaterial+".ambient"); break; case GLLightingFunc.GL_AMBIENT_AND_DIFFUSE: { 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"); break; case GLLightingFunc.GL_SPECULAR: ud = shaderState.getUniform(mgl_FrontMaterial+".specular"); break; case GLLightingFunc.GL_EMISSION: ud = shaderState.getUniform(mgl_FrontMaterial+".emission"); break; case GLLightingFunc.GL_SHININESS: ud = shaderState.getUniform(mgl_FrontMaterial+".shininess"); break; default: 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); if(null!=ud) { ud.setData(mode); 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; } 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; } } } /** * @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(int cap, boolean enable) { switch(cap) { 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 || 0alphaTestFunc && enable || 0=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); } } GLUniformData ud; 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"); } } 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; } /** 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 shaderState.uniform(gl, ud); } lightsEnabledDirty=false; } if(textureCoordEnabledDirty) { ud = shaderState.getUniform(mgl_TexCoordEnabled); if(null!=ud) { // same data object shaderState.uniform(gl, ud); } textureCoordEnabledDirty=false; } if(textureEnvModeDirty) { ud = shaderState.getUniform(mgl_TexEnvMode); if(null!=ud) { // same data object shaderState.uniform(gl, ud); } textureEnvModeDirty = false; } if(textureFormatDirty) { for(int i = 0; i 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; 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; }