From 3e839104e21ff5010f3b4751db9408f5c3386c5d Mon Sep 17 00:00:00 2001 From: Christopher Campbell Date: Mon, 9 Apr 2007 06:48:12 +0000 Subject: Added setUniformMatrices*() methods to Shader. Fleshed out setUniform*() methods in ShaderNode. The setUniform*() methods can be called from any thread; they store the parameters so that the next time getShader() is called from the GL thread, the parameters will be passed down to OpenGL. These two classes should be pretty close to "feature complete" now. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/joglutils/trunk@64 83d24430-9974-4f80-8418-2cc3294053b9 --- .../joglutils/msg/elements/GLShaderElement.java | 11 - src/net/java/joglutils/msg/misc/Shader.java | 157 ++++++- src/net/java/joglutils/msg/nodes/ShaderNode.java | 477 ++++++++++++++++++++- 3 files changed, 625 insertions(+), 20 deletions(-) diff --git a/src/net/java/joglutils/msg/elements/GLShaderElement.java b/src/net/java/joglutils/msg/elements/GLShaderElement.java index cf28c97..178a8f2 100644 --- a/src/net/java/joglutils/msg/elements/GLShaderElement.java +++ b/src/net/java/joglutils/msg/elements/GLShaderElement.java @@ -90,17 +90,6 @@ public class GLShaderElement extends ShaderElement { } if (curShader != null) { curShader.enable(); - - // FIXME: the following is a big hack... - Map fMap = shader.getUniformfMap(); - if (!fMap.isEmpty()) { - for (String name : fMap.keySet()) { - Vec4f val = fMap.get(name); - //curShader.setUniform(name, val.x(), val.y(), val.z(), val.w()); - curShader.setUniform(name, val.x()); - fMap.clear(); - } - } } } } diff --git a/src/net/java/joglutils/msg/misc/Shader.java b/src/net/java/joglutils/msg/misc/Shader.java index c816629..ab25f78 100644 --- a/src/net/java/joglutils/msg/misc/Shader.java +++ b/src/net/java/joglutils/msg/misc/Shader.java @@ -430,6 +430,82 @@ public class Shader { gl.glUniform4fARB(loc, f0, f1, f2, f3); } + /** + * Sets the uniform array variable of the given name with the provided + * int array values. + * + * @param name the name of the uniform variable to be set + * @param count the number of int elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setUniformArray1i(String name, int count, int[] vals, int off) + throws GLException + { + GL gl = GLU.getCurrentGL(); + int loc = gl.glGetUniformLocationARB(id, name); + gl.glUniform1ivARB(loc, count, vals, off); + } + + /** + * Sets the uniform array variable of the given name with the provided + * int array values. + * + * @param name the name of the uniform variable to be set + * @param count the number of ivec2 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setUniformArray2i(String name, int count, int[] vals, int off) + throws GLException + { + GL gl = GLU.getCurrentGL(); + int loc = gl.glGetUniformLocationARB(id, name); + gl.glUniform2ivARB(loc, count, vals, off); + } + + /** + * Sets the uniform array variable of the given name with the provided + * int array values. + * + * @param name the name of the uniform variable to be set + * @param count the number of ivec3 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setUniformArray3i(String name, int count, int[] vals, int off) + throws GLException + { + GL gl = GLU.getCurrentGL(); + int loc = gl.glGetUniformLocationARB(id, name); + gl.glUniform3ivARB(loc, count, vals, off); + } + + /** + * Sets the uniform array variable of the given name with the provided + * int array values. + * + * @param name the name of the uniform variable to be set + * @param count the number of ivec4 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setUniformArray4i(String name, int count, int[] vals, int off) + throws GLException + { + GL gl = GLU.getCurrentGL(); + int loc = gl.glGetUniformLocationARB(id, name); + gl.glUniform4ivARB(loc, count, vals, off); + } + /** * Sets the uniform array variable of the given name with the provided * float array values. @@ -441,7 +517,8 @@ public class Shader { * @throws GLException if no OpenGL context was current or if any * OpenGL-related errors occurred */ - public void setUniformArray1f(String name, int count, float[] vals, int off) + public void setUniformArray1f(String name, + int count, float[] vals, int off) throws GLException { GL gl = GLU.getCurrentGL(); @@ -460,7 +537,8 @@ public class Shader { * @throws GLException if no OpenGL context was current or if any * OpenGL-related errors occurred */ - public void setUniformArray2f(String name, int count, float[] vals, int off) + public void setUniformArray2f(String name, + int count, float[] vals, int off) throws GLException { GL gl = GLU.getCurrentGL(); @@ -479,7 +557,8 @@ public class Shader { * @throws GLException if no OpenGL context was current or if any * OpenGL-related errors occurred */ - public void setUniformArray3f(String name, int count, float[] vals, int off) + public void setUniformArray3f(String name, + int count, float[] vals, int off) throws GLException { GL gl = GLU.getCurrentGL(); @@ -498,11 +577,81 @@ public class Shader { * @throws GLException if no OpenGL context was current or if any * OpenGL-related errors occurred */ - public void setUniformArray4f(String name, int count, float[] vals, int off) + public void setUniformArray4f(String name, + int count, float[] vals, int off) throws GLException { GL gl = GLU.getCurrentGL(); int loc = gl.glGetUniformLocationARB(id, name); gl.glUniform4fvARB(loc, count, vals, off); } + + /** + * Sets the uniform matrix (or matrix array) variable of the given name + * with the provided matrix values. + * + * @param name the name of the uniform variable to be set + * @param count the number of 2x2 matrices (mat2 elements) in the array + * @param transpose if false, each matrix is assumed to be suppplied in + * column major order; otherwise assumed to be supplied in row major order + * @param vals the matrix values to be set + * @param off the offset into the vals array + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setUniformMatrices2f(String name, + int count, boolean transpose, + float[] vals, int off) + throws GLException + { + GL gl = GLU.getCurrentGL(); + int loc = gl.glGetUniformLocationARB(id, name); + gl.glUniformMatrix2fvARB(loc, count, transpose, vals, off); + } + + /** + * Sets the uniform matrix (or matrix array) variable of the given name + * with the provided matrix values. + * + * @param name the name of the uniform variable to be set + * @param count the number of 3x3 matrices (mat3 elements) in the array + * @param transpose if false, each matrix is assumed to be suppplied in + * column major order; otherwise assumed to be supplied in row major order + * @param vals the matrix values to be set + * @param off the offset into the vals array + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setUniformMatrices3f(String name, + int count, boolean transpose, + float[] vals, int off) + throws GLException + { + GL gl = GLU.getCurrentGL(); + int loc = gl.glGetUniformLocationARB(id, name); + gl.glUniformMatrix3fvARB(loc, count, transpose, vals, off); + } + + /** + * Sets the uniform matrix (or matrix array) variable of the given name + * with the provided matrix values. + * + * @param name the name of the uniform variable to be set + * @param count the number of 4x4 matrices (mat4 elements) in the array + * @param transpose if false, each matrix is assumed to be suppplied in + * column major order; otherwise assumed to be supplied in row major order + * @param vals the matrix values to be set + * @param off the offset into the vals array + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setUniformMatrices4f(String name, + int count, boolean transpose, + float[] vals, int off) + throws GLException + { + GL gl = GLU.getCurrentGL(); + int loc = gl.glGetUniformLocationARB(id, name); + gl.glUniformMatrix4fvARB(loc, count, transpose, vals, off); + } } diff --git a/src/net/java/joglutils/msg/nodes/ShaderNode.java b/src/net/java/joglutils/msg/nodes/ShaderNode.java index ab9ea60..676838e 100644 --- a/src/net/java/joglutils/msg/nodes/ShaderNode.java +++ b/src/net/java/joglutils/msg/nodes/ShaderNode.java @@ -55,6 +55,7 @@ public class ShaderNode extends Node { private String fragmentShaderCode; private Shader shader; private List disposedShaders = new ArrayList(); + private Map paramMap = new HashMap(); static { // Enable the elements this node affects for known actions @@ -79,12 +80,346 @@ public class ShaderNode extends Node { this.fragmentShaderCode = fragmentShaderCode; } - private Map fMap = new HashMap(); - public void setUniform(String name, float val) { - fMap.put(name, new Vec4f(val, val, val, val)); + /** + * Sets the uniform variable of the given name with the provided + * integer value. + * + * @param name the name of the uniform variable to be set + * @param i0 the first uniform parameter + */ + public void setUniform(String name, int i0) { + int[] iArr = new int[] { i0 }; + paramMap.put(name, new Params(iArr, 1)); } - public Map getUniformfMap() { - return fMap; + + /** + * Sets the uniform variable of the given name with the provided + * integer values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param i0 the first uniform parameter + * @param i1 the second uniform parameter + */ + public void setUniform(String name, int i0, int i1) { + int[] iArr = new int[] { i0, i1 }; + paramMap.put(name, new Params(iArr, 2)); + } + + /** + * Sets the uniform variable of the given name with the provided + * integer values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param i0 the first uniform parameter + * @param i1 the second uniform parameter + * @param i2 the third uniform parameter + */ + public void setUniform(String name, int i0, int i1, int i2) { + int[] iArr = new int[] { i0, i1, i2 }; + paramMap.put(name, new Params(iArr, 3)); + } + + /** + * Sets the uniform variable of the given name with the provided + * integer values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param i0 the first uniform parameter + * @param i1 the second uniform parameter + * @param i2 the third uniform parameter + * @param i3 the fourth uniform parameter + */ + public void setUniform(String name, + int i0, int i1, int i2, int i3) + { + int[] iArr = new int[] { i0, i1, i2, i3 }; + paramMap.put(name, new Params(iArr, 4)); + } + + /** + * Sets the uniform variable of the given name with the provided + * float value. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param f0 the first uniform parameter + */ + public void setUniform(String name, float f0) { + float[] fArr = new float[] { f0 }; + paramMap.put(name, new Params(fArr, 1)); + } + + /** + * Sets the uniform variable of the given name with the provided + * float values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param f0 the first uniform parameter + * @param f1 the second uniform parameter + */ + public void setUniform(String name, float f0, float f1) { + float[] fArr = new float[] { f0, f1 }; + paramMap.put(name, new Params(fArr, 2)); + } + + /** + * Sets the uniform variable of the given name with the provided + * float values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param f0 the first uniform parameter + * @param f1 the second uniform parameter + * @param f2 the third uniform parameter + */ + public void setUniform(String name, float f0, float f1, float f2) { + float[] fArr = new float[] { f0, f1, f2 }; + paramMap.put(name, new Params(fArr, 3)); + } + + /** + * Sets the uniform variable of the given name with the provided + * float values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param f0 the first uniform parameter + * @param f1 the second uniform parameter + * @param f2 the third uniform parameter + * @param f3 the fourth uniform parameter + */ + public void setUniform(String name, + float f0, float f1, float f2, float f3) + { + float[] fArr = new float[] { f0, f1, f2, f3 }; + paramMap.put(name, new Params(fArr, 4)); + } + + /** + * Sets the uniform array variable of the given name with the provided + * int array values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of int elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + */ + public void setUniformArray1i(String name, + int count, int[] vals, int off) + { + paramMap.put(name, new Params(vals, 1, count, off)); + } + + /** + * Sets the uniform array variable of the given name with the provided + * int array values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of ivec2 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + */ + public void setUniformArray2i(String name, + int count, int[] vals, int off) + { + paramMap.put(name, new Params(vals, 2, count, off)); + } + + /** + * Sets the uniform array variable of the given name with the provided + * int array values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of ivec3 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + */ + public void setUniformArray3i(String name, + int count, int[] vals, int off) + { + paramMap.put(name, new Params(vals, 3, count, off)); + } + + /** + * Sets the uniform array variable of the given name with the provided + * int array values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of ivec4 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + */ + public void setUniformArray4i(String name, + int count, int[] vals, int off) + { + paramMap.put(name, new Params(vals, 4, count, off)); + } + + /** + * Sets the uniform array variable of the given name with the provided + * float array values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of float elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + */ + public void setUniformArray1f(String name, + int count, float[] vals, int off) + { + paramMap.put(name, new Params(vals, 1, count, off)); + } + + /** + * Sets the uniform array variable of the given name with the provided + * float array values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of vec2 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + */ + public void setUniformArray2f(String name, + int count, float[] vals, int off) + { + paramMap.put(name, new Params(vals, 2, count, off)); + } + + /** + * Sets the uniform array variable of the given name with the provided + * float array values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of vec3 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + */ + public void setUniformArray3f(String name, + int count, float[] vals, int off) + { + paramMap.put(name, new Params(vals, 3, count, off)); + } + + /** + * Sets the uniform array variable of the given name with the provided + * float array values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of vec4 elements in the array + * @param vals the array values to be set + * @param off the offset into the vals array + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setUniformArray4f(String name, + int count, float[] vals, int off) + { + paramMap.put(name, new Params(vals, 4, count, off)); + } + + /** + * Sets the uniform matrix (or matrix array) variable of the given name + * with the provided matrix values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of 2x2 matrices (mat2 elements) in the array + * @param transpose if false, each matrix is assumed to be suppplied in + * column major order; otherwise assumed to be supplied in row major order + * @param vals the matrix values to be set + * @param off the offset into the vals array + */ + public void setUniformMatrices2f(String name, + int count, boolean transpose, + float[] vals, int off) + { + paramMap.put(name, new Params(vals, 2, count, off, true, transpose)); + } + + /** + * Sets the uniform matrix (or matrix array) variable of the given name + * with the provided matrix values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of 3x3 matrices (mat3 elements) in the array + * @param transpose if false, each matrix is assumed to be suppplied in + * column major order; otherwise assumed to be supplied in row major order + * @param vals the matrix values to be set + * @param off the offset into the vals array + */ + public void setUniformMatrices3f(String name, + int count, boolean transpose, + float[] vals, int off) + { + paramMap.put(name, new Params(vals, 3, count, off, true, transpose)); + } + + /** + * Sets the uniform matrix (or matrix array) variable of the given name + * with the provided matrix values. + *

+ * No OpenGL work is done during this call; it is done lazily when + * the Shader is fetched. + * + * @param name the name of the uniform variable to be set + * @param count the number of 4x4 matrices (mat4 elements) in the array + * @param transpose if false, each matrix is assumed to be suppplied in + * column major order; otherwise assumed to be supplied in row major order + * @param vals the matrix values to be set + * @param off the offset into the vals array + */ + public void setUniformMatrices4f(String name, + int count, boolean transpose, + float[] vals, int off) + { + paramMap.put(name, new Params(vals, 4, count, off, true, transpose)); } /** Fetches the Shader object associated with this ShaderNode. @@ -96,6 +431,7 @@ public class ShaderNode extends Node { if (shader == null) { this.shader = new Shader(vertexShaderCode, fragmentShaderCode); } + sendParams(); return shader; } @@ -121,4 +457,135 @@ public class ShaderNode extends Node { s.dispose(); } } + + /** + * Sends the stored uniform parameters down to GL. + * An OpenGL context must be current at the time this method is + * called or a GLException will be thrown. + */ + private void sendParams() { + if (!paramMap.isEmpty()) { + // FIXME: the shader needs to be enabled prior to setting uniforms, + // but doing so here may lead to too many enable/disable calls + shader.enable(); + for (String name : paramMap.keySet()) { + Params params = paramMap.get(name); + if (params.isMatrix) { + switch (params.vecSize) { + case 2: + shader.setUniformMatrices2f(name, params.numElems, + params.transpose, + params.fArr, + params.offset); + break; + case 3: + shader.setUniformMatrices3f(name, params.numElems, + params.transpose, + params.fArr, + params.offset); + break; + case 4: + shader.setUniformMatrices4f(name, params.numElems, + params.transpose, + params.fArr, + params.offset); + break; + default: + continue; + } + } else if (params.fArr != null) { + switch (params.vecSize) { + case 1: + shader.setUniformArray1f(name, params.numElems, + params.fArr, params.offset); + break; + case 2: + shader.setUniformArray2f(name, params.numElems, + params.fArr, params.offset); + break; + case 3: + shader.setUniformArray3f(name, params.numElems, + params.fArr, params.offset); + break; + case 4: + shader.setUniformArray4f(name, params.numElems, + params.fArr, params.offset); + break; + default: + continue; + } + } else if (params.iArr != null) { + switch (params.vecSize) { + case 1: + shader.setUniformArray1i(name, params.numElems, + params.iArr, params.offset); + break; + case 2: + shader.setUniformArray2i(name, params.numElems, + params.iArr, params.offset); + break; + case 3: + shader.setUniformArray3i(name, params.numElems, + params.iArr, params.offset); + break; + case 4: + shader.setUniformArray4i(name, params.numElems, + params.iArr, params.offset); + break; + default: + continue; + } + } + } + // FIXME: see above... + shader.disable(); + paramMap.clear(); + } + } + + /** + * A small class to encapsulate int or float data passed in through + * the various setUniform*() methods. + */ + private static class Params { + private float[] fArr; + private int[] iArr; + private int vecSize; // 1, 2, 3, or 4 + private int numElems; + private int offset; + private boolean isMatrix; + private boolean transpose; + + Params(float[] fArr, int vecSize) { + this(fArr, vecSize, 1, 0); + } + + Params(float[] fArr, int vecSize, int numElems, int offset) { + this(fArr, vecSize, numElems, offset, false, false); + } + + Params(float[] fArr, int vecSize, int numElems, int offset, + boolean isMatrix, boolean transpose) + { + this.fArr = fArr; + this.vecSize = vecSize; + this.numElems = numElems; + this.offset = offset; + this.isMatrix = isMatrix; + this.transpose = transpose; + } + + Params(int[] iArr, int vecSize) { + this(iArr, vecSize, 1, 0); + } + + Params(int[] iArr, int vecSize, int numElems, int offset) { + this.iArr = iArr; + this.vecSize = vecSize; + this.numElems = numElems; + this.offset = offset; + this.isMatrix = false; + this.transpose = false; + } + } } -- cgit v1.2.3