diff options
Diffstat (limited to 'src/classes/javax/media/opengl/util/glsl')
3 files changed, 906 insertions, 0 deletions
diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderCode.java b/src/classes/javax/media/opengl/util/glsl/ShaderCode.java new file mode 100644 index 000000000..46ead1b30 --- /dev/null +++ b/src/classes/javax/media/opengl/util/glsl/ShaderCode.java @@ -0,0 +1,122 @@ + +package javax.media.opengl.util.glsl; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; + +import java.nio.*; +import java.io.PrintStream; + +public class ShaderCode { + public ShaderCode(int type, int number, + int binFormat, Buffer binary, String[][] source) { + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + case GL2ES2.GL_FRAGMENT_SHADER: + break; + default: + throw new GLException("Unknown shader type: "+type); + } + shaderSource = source; + shaderBinaryFormat = binFormat; + shaderBinary = binary; + shaderType = type; + shader = BufferUtil.newIntBuffer(number); + id = getNextID(); + } + + /** + * returns the uniq shader id as an integer + * @see #key() + */ + public int id() { return id.intValue(); } + + /** + * returns the uniq shader id as an Integer + * + * @see #id() + */ + public Integer key() { return id; } + + public int shaderType() { return shaderType; } + public String shaderTypeStr() { return shaderTypeStr(shaderType); } + + public static String shaderTypeStr(int type) { + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + return "VERTEX_SHADER"; + case GL2ES2.GL_FRAGMENT_SHADER: + return "FRAGMENT_SHADER"; + } + return "UNKNOWN_SHADER"; + } + + public int shaderBinaryFormat() { return shaderBinaryFormat; } + public Buffer shaderBinary() { return shaderBinary; } + public String[][] shaderSource() { return shaderSource; } + + public boolean isValid() { return valid; } + + public IntBuffer shader() { return shader; } + + public boolean compile(GL2ES2 gl) { + return compile(gl, null); + } + public boolean compile(GL2ES2 gl, PrintStream verboseOut) { + if(isValid()) return true; + + // Create & Compile the vertex/fragment shader objects + valid=gl.glCreateCompileShader(shader, shaderType, + shaderBinaryFormat, shaderBinary, + shaderSource, verboseOut); + shader.clear(); + return valid; + } + + public void release(GL2ES2 gl) { + if(isValid()) { + gl.glDeleteShader(shader()); + valid=false; + } + } + + public boolean equals(Object obj) { + if(this==obj) return true; + if(obj instanceof ShaderCode) { + return id()==((ShaderCode)obj).id(); + } + return false; + } + public int hashCode() { + return id.intValue(); + } + public String toString() { + StringBuffer buf = new StringBuffer("ShaderCode [id="+id+", type="+shaderTypeStr()+", valid="+valid); + /* + if(shaderSource!=null) { + for(int i=0; i<shaderSource.length; i++) { + for(int j=0; j<shaderSource[i].length; j++) { + buf.append("\n\t, ShaderSource["+i+"]["+j+"]:\n"); + buf.append(shaderSource[i][j]); + } + } + } */ + buf.append("]"); + return buf.toString(); + } + + protected String[][] shaderSource = null; + protected Buffer shaderBinary = null; + protected int shaderBinaryFormat = -1; + protected IntBuffer shader = null; + protected int shaderType = -1; + protected Integer id = null; + + protected boolean valid=false; + + private static synchronized Integer getNextID() { + return new Integer(nextID++); + } + protected static int nextID = 1; +} + diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java b/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java new file mode 100644 index 000000000..5628f3332 --- /dev/null +++ b/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java @@ -0,0 +1,201 @@ + +package javax.media.opengl.util.glsl; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; + +import java.util.HashMap; +import java.util.Iterator; +import java.nio.*; +import java.io.PrintStream; + +public class ShaderProgram { + public ShaderProgram() { + id = getNextID(); + } + + public boolean linked() { + return programLinked; + } + + public boolean inUse() { + return programInUse; + } + + public int program() { return shaderProgram; } + + /** + * returns the uniq shader id as an integer + * @see #key() + */ + public int id() { return id.intValue(); } + + /** + * returns the uniq shader id as an Integer + * + * @see #id() + */ + public Integer key() { return id; } + + /** + * @see #glReleaseAllVertexAttributes + */ + public synchronized void release(GL2ES2 gl) { + release(gl, false); + } + + /** + * @see #glReleaseAllVertexAttributes + */ + public synchronized void release(GL2ES2 gl, boolean releaseShaderToo) { + glUseProgram(gl, false); + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + ShaderCode shaderCode = (ShaderCode) iter.next(); + gl.glDetachShader(shaderProgram, shaderCode.shader()); + if(releaseShaderToo) { + shaderCode.release(gl); + } + } + shaderMap.clear(); + gl.glDeleteProgram(shaderProgram); + shaderProgram=-1; + } + + // + // ShaderCode handling + // + + /** + * Adds a new shader to a this non running program. + * + * @return false if the program is in use, or the shader already exist, + * otherwise true. + */ + public synchronized boolean add(ShaderCode shaderCode) { + if(shaderMap.containsKey(shaderCode.key())) return false; + shaderMap.put(shaderCode.key(), shaderCode); + return true; + } + + public synchronized ShaderCode getShader(int id) { + return (ShaderCode) shaderMap.get(new Integer(id)); + } + + // + // Program handling + // + + /** + * Replace a shader in a 'running' program. + * Refetches all previously bin/get attribute names + * and resets all attribute data as well + * + * @see getAttribLocation + * @param gl + * @param oldShaderID the to be replace Shader + * @param newShader the new ShaderCode + * @param verboseOut the optional verbose outputstream + * @throws GLException is the program is not linked + * + * @see #glRefetchAttribLocations + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public synchronized boolean glReplaceShader(GL2ES2 gl, int oldShaderID, ShaderCode newShader, PrintStream verboseOut) { + if(!programLinked) throw new GLException("Program is not linked"); + boolean shaderWasInUse = programInUse; + glUseProgram(gl, false); + if(!newShader.compile(gl, verboseOut)) { + return false; + } + if(oldShaderID>=0) { + ShaderCode oldShader = (ShaderCode) shaderMap.remove(new Integer(oldShaderID)); + if(null!=oldShader) { + gl.glDetachShader(shaderProgram, oldShader.shader()); + } + } + add(newShader); + + gl.glAttachShader(shaderProgram, newShader.shader()); + gl.glLinkProgram(shaderProgram); + if ( ! gl.glIsProgramValid(shaderProgram, System.err) ) { + return false; + } + + if(shaderWasInUse) { + glUseProgram(gl, true); + } + return true; + } + + public synchronized boolean link(GL2ES2 gl, PrintStream verboseOut) { + if(programLinked) throw new GLException("Program is already linked"); + + if(0>shaderProgram) { + shaderProgram = gl.glCreateProgram(); + } + + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + ShaderCode shaderCode = (ShaderCode) iter.next(); + if(!shaderCode.compile(gl, verboseOut)) { + return false; + } + gl.glAttachShader(shaderProgram, shaderCode.shader()); + } + + // Link the program + gl.glLinkProgram(shaderProgram); + + if ( ! gl.glIsProgramValid(shaderProgram, System.err) ) { + return false; + } + programLinked=true; + + return true; + } + + public boolean equals(Object obj) { + if(this==obj) return true; + if(obj instanceof ShaderCode) { + return id()==((ShaderCode)obj).id(); + } + return false; + } + public int hashCode() { + return id.intValue(); + } + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("ShaderProgram[id="+id); + buf.append(", linked="+programLinked+", inUse="+programInUse+", program: "+shaderProgram+", ["); + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + buf.append((ShaderCode) iter.next()); + buf.append(" "); + } + buf.append("]"); + return buf.toString(); + } + + protected synchronized void glUseProgram(GL2ES2 gl, boolean on) { + if(!programLinked) throw new GLException("Program is not linked"); + if(programInUse==on) return; + gl.glUseProgram(on?shaderProgram:0); + programInUse = on; + + //Throwable tX = new Throwable("Info: ShaderProgram.glUseProgram: "+on); + //tX.printStackTrace(); + + } + + protected boolean programLinked = false; + protected boolean programInUse = false; + protected int shaderProgram=-1; + protected HashMap shaderMap = new HashMap(); + protected Integer id = null; + + private static synchronized Integer getNextID() { + return new Integer(nextID++); + } + protected static int nextID = 1; +} + diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderState.java b/src/classes/javax/media/opengl/util/glsl/ShaderState.java new file mode 100644 index 000000000..7f917cc07 --- /dev/null +++ b/src/classes/javax/media/opengl/util/glsl/ShaderState.java @@ -0,0 +1,583 @@ + +package javax.media.opengl.util.glsl; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.nio.*; +import java.io.PrintStream; + +public class ShaderState { + + public ShaderState() { + } + + public boolean verbose() { return verbose; } + + public void setVerbose(boolean v) { verbose=v; } + + /** + * Fetches the current shader state + * + * @see javax.media.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see javax.media.opengl.util.glsl.ShaderState#getCurrent() + */ + public static synchronized ShaderState getCurrent() { return currentShaderState; } + + /** + * Turns the shader program on + * and set this ShaderState to current if on equals true + * + * @see javax.media.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see javax.media.opengl.util.glsl.ShaderState#getCurrent() + */ + public synchronized void glUseProgram(GL2ES2 gl, boolean on) { + if(on) { + if(null!=shaderProgram) { + shaderProgram.glUseProgram(gl, true); + } else { + throw new GLException("No program is attached"); + } + if(currentShaderState!=this) { + currentShaderState = this; + } + } else if(null!=shaderProgram) { + shaderProgram.glUseProgram(gl, false); + } + } + + public boolean linked() { + return (null!=shaderProgram)?shaderProgram.linked():false; + } + + public boolean inUse() { + return (null!=shaderProgram)?shaderProgram.inUse():false; + } + + /** + * Attach or switch a shader program + * + * Attaching a shader program the first time, + * as well as switching to another program on the fly, + * while managing all attribute and uniform data. + */ + public synchronized void attachShaderProgram(GL2ES2 gl, ShaderProgram prog) { + boolean prgInUse = false; // earmarked state + + if(null!=shaderProgram) { + if(shaderProgram.equals(prog)) { + // nothing to do .. + if(DEBUG) { + System.err.println("Info: attachShaderProgram: NOP: equal id: "+shaderProgram.id()); + } + return; + } + prgInUse = shaderProgram.inUse(); + } + if(DEBUG) { + Throwable tX = new Throwable("Info: attachShaderProgram: BEGIN "+shaderProgram+" -> "+prog); + tX.printStackTrace(); + } + + // register new one + shaderProgram = prog; + + if(null!=shaderProgram) { + // reinstall all data .. + shaderProgram.glUseProgram(gl, true); + glResetAllVertexAttributes(gl); + glResetAllUniforms(gl); + if(!prgInUse) { + shaderProgram.glUseProgram(gl, false); + } + } + if(DEBUG) { + System.err.println("Info: attachShaderProgram: END"); + } + } + + public ShaderProgram shaderProgram() { return shaderProgram; } + + /** + * @see #glReleaseAllVertexAttributes + * @see #glReleaseAllUniforms + */ + public synchronized void release(GL2ES2 gl) { + release(gl, false, false); + } + + public synchronized void release(GL2ES2 gl, boolean releaseProgramToo, boolean releaseShaderToo) { + boolean prgInUse = false; + if(null!=shaderProgram) { + prgInUse = shaderProgram.inUse(); + if(!prgInUse) { + shaderProgram.glUseProgram(gl, true); + } + } + glReleaseAllVertexAttributes(gl); + glReleaseAllUniforms(gl); + if(null!=shaderProgram) { + if(releaseProgramToo) { + shaderProgram.release(gl, releaseShaderToo); + } else if(!prgInUse) { + shaderProgram.glUseProgram(gl, false); + } + } + } + + // + // Shader attribute handling + // + + /** + * Binds an attribute to the shader. + * This must be done before the program is linked ! + * n name - 1 idx, where name is a uniq key + * + * @throws GLException is the program is already linked + * + * @see #glBindAttribLocation + * @see javax.media.opengl.GL2ES2#glBindAttribLocation + * @see #glGetAttribLocation + * @see javax.media.opengl.GL2ES2#glGetAttribLocation + * @see #getAttribLocation + * @see #glReplaceShader + */ + public void glBindAttribLocation(GL2ES2 gl, int index, String name) { + if(null==shaderProgram) throw new GLException("No program is attached"); + if(shaderProgram.linked()) throw new GLException("Program is already linked"); + Integer idx = new Integer(index); + if(!attribMap2Idx.containsKey(name)) { + attribMap2Idx.put(name, idx); + gl.glBindAttribLocation(shaderProgram.program(), index, name); + } + } + + /** + * Gets the index of a shader attribute. + * This must be done after the program is linked ! + * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + * @throws GLException is the program is not linked + * + * @see #glBindAttribLocation + * @see javax.media.opengl.GL2ES2#glBindAttribLocation + * @see #glGetAttribLocation + * @see javax.media.opengl.GL2ES2#glGetAttribLocation + * @see #getAttribLocation + * @see #glReplaceShader + */ + public int glGetAttribLocation(GL2ES2 gl, String name) { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); + int index = getAttribLocation(name); + if(0>index) { + index = gl.glGetAttribLocation(shaderProgram.program(), name); + if(0<=index) { + Integer idx = new Integer(index); + attribMap2Idx.put(name, idx); + } else if(verbose) { + Throwable tX = new Throwable("Info: glGetAttribLocation failed, no location for: "+name+", index: "+index); + tX.printStackTrace(); + } + } + return index; + } + + protected int getAttribLocation(String name) { + Integer idx = (Integer) attribMap2Idx.get(name); + return (null!=idx)?idx.intValue():-1; + } + + + // + // Enabled Vertex Arrays and its data + // + + /** + * Enable a vertex attribute array + * + * Even if the attribute is not found in the current shader, + * it is stored in this state. + * + * @returns false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public boolean glEnableVertexAttribArray(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + enabledVertexAttribArraySet.add(name); + int index = glGetAttribLocation(gl, name); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glEnableVertexAttribArray failed, no index for: "+name); + tX.printStackTrace(); + } + return false; + } + if(DEBUG) { + System.err.println("Info: glEnableVertexAttribArray: "+name); + } + gl.glEnableVertexAttribArray(index); + return true; + } + + public boolean isVertexAttribArrayEnabled(String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + return enabledVertexAttribArraySet.contains(name); + } + + /** + * Disables a vertex attribute array + * + * Even if the attribute is not found in the current shader, + * it is removed from this state. + * + * @returns false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public boolean glDisableVertexAttribArray(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + enabledVertexAttribArraySet.remove(name); + int index = glGetAttribLocation(gl, name); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glDisableVertexAttribArray failed, no index for: "+name); + tX.printStackTrace(); + } + return false; + } + if(DEBUG) { + System.err.println("Info: glDisableVertexAttribArray: "+name); + } + gl.glDisableVertexAttribArray(index); + return true; + } + + /** + * Set the vertex attribute data. + * Enable the attribute, if it is not enabled yet. + * + * Even if the attribute is not found in the current shader, + * it is stored in this state. + * + * @arg data the GLArrayData's name must match the attributes one, + * it's index will be set with the attribute's location, + * if found. + * + * @returns false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public boolean glVertexAttribPointer(GL2ES2 gl, GLArrayData data) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + if(!enabledVertexAttribArraySet.contains(data.getName())) { + if(!glEnableVertexAttribArray(gl, data.getName())) { + if(verbose) { + Throwable tX = new Throwable("Info: glVertexAttribPointer: couldn't enable: "+data); + tX.printStackTrace(); + } + } + } + int index = getAttribLocation(data.getName()); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glVertexAttribPointer failed, no index for: "+data); + tX.printStackTrace(); + } + } + data.setLocation(index); + vertexAttribMap2Data.put(data.getName(), data); + if(0<=index) { + // only pass the data, if the attribute exists in the current shader + if(DEBUG) { + System.err.println("Info: glVertexAttribPointer: "+data); + } + gl.glVertexAttribPointer(data); + return true; + } + return false; + } + + /** + * Get the vertex attribute data, previously set. + * + * @returns the GLArrayData object, null if not previously set. + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public GLArrayData getVertexAttribPointer(String name) { + return (GLArrayData) vertexAttribMap2Data.get(name); + } + + /** + * Releases all mapped vertex attribute data, + * disables all enabled attributes and loses all indices + * + * @throws GLException is the program is not in use but the shaderProgram is set + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public void glReleaseAllVertexAttributes(GL2ES2 gl) { + if(null!=shaderProgram) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + for(Iterator iter = vertexAttribMap2Data.keySet().iterator(); iter.hasNext(); ) { + if(!glDisableVertexAttribArray(gl, (String) iter.next())) { + throw new GLException("Internal Error: mapped vertex attribute couldn't be disabled"); + } + } + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + if(!glDisableVertexAttribArray(gl, (String) iter.next())) { + throw new GLException("Internal Error: prev enabled vertex attribute couldn't be disabled"); + } + } + } + vertexAttribMap2Data.clear(); + enabledVertexAttribArraySet.clear(); + attribMap2Idx.clear(); + } + + /** + * Disables all vertex attribute arrays. + * + * Their enabled stated will be removed from this state only + * if 'removeFromState' is true. + * + * This method purpose is more for debugging. + * + * @throws GLException is the program is not in use but the shaderProgram is set + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public void glDisableAllVertexAttributeArrays(GL2ES2 gl, boolean removeFromState) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + String name = (String) iter.next(); + if(removeFromState) { + enabledVertexAttribArraySet.remove(name); + } + int index = glGetAttribLocation(gl, name); + if(0<=index) { + gl.glDisableVertexAttribArray(index); + } + } + } + + /** + * Reset all previously mapped vertex attribute data, + * incl enabling them + * + * @throws GLException is the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public void glResetAllVertexAttributes(GL2ES2 gl) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + attribMap2Idx.clear(); + + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + glEnableVertexAttribArray(gl, (String) iter.next()); + } + + for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + glVertexAttribPointer(gl, (GLArrayData) iter.next()); + } + } + + // + // Shader Uniform handling + // + + /** + * Gets the index of a shader uniform. + * This must be done when the program is in use ! + * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + + * @throws GLException is the program is not linked + * + * @see #glGetUniformLocation + * @see javax.media.opengl.GL2ES2#glGetUniformLocation + * @see #getUniformLocation + * @see #glReplaceShader + */ + protected int glGetUniformLocation(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + int index = getUniformLocation(name); + if(0>index) { + index = gl.glGetUniformLocation(shaderProgram.program(), name); + if(0<=index) { + Integer idx = new Integer(index); + uniformMap2Idx.put(name, idx); + } else if(verbose) { + Throwable tX = new Throwable("Info: glUniform failed, no location for: "+name+", index: "+index); + tX.printStackTrace(); + } + } + return index; + } + + protected int getUniformLocation(String name) { + Integer idx = (Integer) uniformMap2Idx.get(name); + return (null!=idx)?idx.intValue():-1; + } + + /** + * Set the uniform data. + * + * Even if the uniform is not found in the current shader, + * it is stored in this state. + * + * @arg data the GLUniforms's name must match the uniform one, + * it's index will be set with the uniforms's location, + * if found. + * + * + * @returns false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glGetUniformLocation + * @see javax.media.opengl.GL2ES2#glGetUniformLocation + * @see #getUniformLocation + * @see #glReplaceShader + */ + public boolean glUniform(GL2ES2 gl, GLUniformData data) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + int location = glGetUniformLocation(gl, data.getName()); + data.setLocation(location); + uniformMap2Data.put(data.getName(), data); + if(0<=location) { + // only pass the data, if the uniform exists in the current shader + if(DEBUG) { + System.err.println("Info: glUniform: "+data); + } + gl.glUniform(data); + } + return true; + } + + /** + * Get the uniform data, previously set. + * + * @returns the GLUniformData object, null if not previously set. + */ + public GLUniformData getUniform(String name) { + return (GLUniformData) uniformMap2Data.get(name); + } + + /** + * Releases all mapped uniform data + * and loses all indices + * + * @throws GLException is the program is not in use + */ + public void glReleaseAllUniforms(GL2ES2 gl) { + uniformMap2Data.clear(); + uniformMap2Idx.clear(); + } + + /** + * Reset all previously mapped uniform data + * + * @throws GLException is the program is not in use + */ + public void glResetAllUniforms(GL2ES2 gl) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + uniformMap2Idx.clear(); + for(Iterator iter = uniformMap2Data.values().iterator(); iter.hasNext(); ) { + glUniform(gl, (GLUniformData) iter.next()); + } + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("ShaderState["); + buf.append(shaderProgram.toString()); + buf.append(",EnabledStates: ["); + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + buf.append("\n "); + buf.append((String)iter.next()); + } + buf.append("], ["); + for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + buf.append("\n "); + buf.append((GLArrayData) iter.next()); + } + buf.append("], ["); + for(Iterator iter=uniformMap2Data.values().iterator(); iter.hasNext(); ) { + buf.append("\n "); + buf.append((GLUniformData) iter.next()); + } + buf.append("]"); + return buf.toString(); + } + + protected static final boolean DEBUG = false; + protected boolean verbose = false; + protected ShaderProgram shaderProgram=null; + protected HashMap attribMap2Idx = new HashMap(); + protected HashSet enabledVertexAttribArraySet = new HashSet(); + protected HashMap vertexAttribMap2Data = new HashMap(); + protected HashMap uniformMap2Idx = new HashMap(); + protected HashMap uniformMap2Data = new HashMap(); + protected static ShaderState currentShaderState = null; + +} + |