/* * 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.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 com.jogamp.common.util.IntIntHashMap; import com.jogamp.common.util.PropertyAccess; 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; static { Debug.initSingleton(); DEBUG = PropertyAccess.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(final GL2ES2 gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix) { shaderRootClass = FixedFuncPipeline.class; shaderSrcRoot = shaderSrcRootDef; shaderBinRoot = shaderBinRootDef; vertexColorFile = vertexColorFileDef; vertexColorLightFile = vertexColorLightFileDef; fragmentColorFile = fragmentColorFileDef; fragmentColorTextureFile = fragmentColorTextureFileDef; init(gl, mode, pmvMatrix); } public FixedFuncPipeline(final GL2ES2 gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix, final Class shaderRootClass, final String shaderSrcRoot, final String shaderBinRoot, final String vertexColorFile, final String vertexColorLightFile, final String fragmentColorFile, final 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(final ShaderSelectionMode mode) { requestedShaderSelectionMode=mode; } public ShaderSelectionMode getCurrentShaderSelectionMode() { return currentShaderSelectionMode; } public boolean verbose() { return verbose; } public void setVerbose(final boolean v) { verbose = DEBUG || v; } public boolean isValid() { return shaderState.linked(); } public ShaderState getShaderState() { return shaderState; } public int getActiveTextureUnit() { return activeTextureUnit; } public void destroy(final 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(final GL2ES2 gl, final float red, final float green, final float blue, final 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(final GL2ES2 gl, final int glArrayIndex) { glToggleClientState(gl, glArrayIndex, true); } public void glDisableClientState(final GL2ES2 gl, final int glArrayIndex) { glToggleClientState(gl, glArrayIndex, false); } private void glToggleClientState(final GL2ES2 gl, final int glArrayIndex, final 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(final GL2ES2 gl, final GLArrayData data) { shaderState.useProgram(gl, true); shaderState.vertexAttribPointer(gl, data); } public void glColorPointer(final GL2ES2 gl, final GLArrayData data) { shaderState.useProgram(gl, true); shaderState.vertexAttribPointer(gl, data); } public void glNormalPointer(final GL2ES2 gl, final 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(final boolean enable, final 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(final int target, final int pname, final 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 GL.GL_BLEND: mode = 4; break; case GL.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(final int value) { if( value != textureEnvMode.get(activeTextureUnit) ) { textureEnvMode.put(activeTextureUnit, value); textureEnvModeDirty = true; } } public void glGetTexEnviv(final int target, final int pname, final IntBuffer params) { // FIXME System.err.println("FixedFuncPipeline: Unimplemented glGetTexEnviv: target "+toHexString(target)+", pname "+toHexString(pname)); } public void glGetTexEnviv(final int target, final int pname, final int[] params, final int params_offset) { // FIXME System.err.println("FixedFuncPipeline: Unimplemented glGetTexEnviv: target "+toHexString(target)+", pname "+toHexString(pname)); } // // Point Sprites // public void glPointSize(final float size) { pointParams.put(0, size); pointParamsDirty = true; } public void glPointParameterf(final int pname, final 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 GL.GL_POINT_FADE_THRESHOLD_SIZE: pointParams.put(4+3, param); break; } pointParamsDirty = true; } public void glPointParameterfv(final int pname, final float[] params, final 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(final int pname, final 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(final GL2ES2 gl, final GLRunnable2 glDrawAction, final 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(final GL gl, final Object args) { final int[] _args = (int[])args; gl.glDrawArrays(GL.GL_POINTS, _args[0], _args[1]); return null; } }; private final void glDrawPointArrays(final GL2ES2 gl, final int first, final int count) { glDrawPoints(gl, glDrawArraysAction, new int[] { first, count }); } // // Lighting // public void glLightfv(final GL2ES2 gl, int light, final int pname, final 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(final GL2ES2 gl, final int face, final int pname, final 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(final GL2ES2 gl, final int mode) { shaderState.useProgram(gl, true); final 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(final int func, final 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(final int cap, final 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(final GL2ES2 gl, final 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) { final 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; }