summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2007-04-03 02:51:23 +0000
committerKenneth Russel <[email protected]>2007-04-03 02:51:23 +0000
commitd31a93e255019a5dc177a1caf91da174bd313b82 (patch)
tree749fbadc2fcac89d21d9b397efe5743018f86a61
parent340ef879cdeaebdce644351cfddf90c032cf5d56 (diff)
Checked in code from Chris Campbell for abstracting shader support and
adding it to MSG -- thanks very much. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/joglutils/trunk@55 83d24430-9974-4f80-8418-2cc3294053b9
-rw-r--r--src/net/java/joglutils/msg/elements/GLShaderElement.java92
-rw-r--r--src/net/java/joglutils/msg/elements/ShaderElement.java99
-rw-r--r--src/net/java/joglutils/msg/misc/Shader.java508
-rw-r--r--src/net/java/joglutils/msg/nodes/ShaderNode.java115
4 files changed, 814 insertions, 0 deletions
diff --git a/src/net/java/joglutils/msg/elements/GLShaderElement.java b/src/net/java/joglutils/msg/elements/GLShaderElement.java
new file mode 100644
index 0000000..a7abbc6
--- /dev/null
+++ b/src/net/java/joglutils/msg/elements/GLShaderElement.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+package net.java.joglutils.msg.elements;
+
+import javax.media.opengl.*;
+import javax.media.opengl.glu.*;
+
+import net.java.joglutils.msg.misc.*;
+import net.java.joglutils.msg.nodes.*;
+
+/** Represents the current shader, which is applied to any drawn
+ geometry, and performs side-effects in OpenGL. */
+
+public class GLShaderElement extends ShaderElement {
+ // Boilerplate for concrete element subclasses
+ public Element newInstance() {
+ return new GLShaderElement();
+ }
+ public static GLShaderElement getInstance(State state) {
+ return (GLShaderElement) ShaderElement.getInstance(state);
+ }
+ public static void enable(State defaultState) {
+ Element tmp = new GLShaderElement();
+ defaultState.setElement(tmp.getStateIndex(), tmp);
+ }
+
+ public void pop(State state, Element previousTopElement) {
+ // Put things back the way they were
+ switchShaders(((GLShaderElement) previousTopElement).shader, shader);
+ }
+
+ public void setElt(ShaderNode shader) {
+ ShaderNode prev = this.shader;
+ super.setElt(shader);
+ switchShaders(prev, shader);
+ }
+
+ private void switchShaders(ShaderNode prev, ShaderNode shader) {
+ GL gl = GLU.getCurrentGL();
+ Shader prevShader = null;
+ Shader curShader = null;
+ if (prev != null) {
+ prevShader = prev.getShader();
+ }
+ if (shader != null) {
+ curShader = shader.getShader();
+ }
+
+ // FIXME: should be smarter about this; if the target is the same
+ // for the previous and current shaders, just bind the new one
+ if (prevShader != null) {
+ prevShader.disable();
+ }
+ if (curShader != null) {
+ curShader.enable();
+ }
+ }
+}
diff --git a/src/net/java/joglutils/msg/elements/ShaderElement.java b/src/net/java/joglutils/msg/elements/ShaderElement.java
new file mode 100644
index 0000000..8b1a3fe
--- /dev/null
+++ b/src/net/java/joglutils/msg/elements/ShaderElement.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.elements;
+
+import net.java.joglutils.msg.misc.*;
+import net.java.joglutils.msg.nodes.*;
+
+/** Represents the current vertex/fragment shader, which is applied to
+ any drawn geometry. */
+
+public class ShaderElement extends Element {
+ // Boilerplate
+ private static StateIndex index = State.registerElementType();
+ public StateIndex getStateIndex() { return index; }
+ public Element newInstance() {
+ return new ShaderElement();
+ }
+ /** Returns the instance of this element in the passed State. */
+ public static ShaderElement getInstance(State state) {
+ return (ShaderElement) state.getElement(index);
+ }
+ /** Enables this element in the passed state, which should be the
+ default for a given action. */
+ public static void enable(State defaultState) {
+ ShaderElement tmp = new ShaderElement();
+ defaultState.setElement(tmp.getStateIndex(), tmp);
+ }
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
+
+ // This particular element refers to the ShaderNode directly.
+ // Having it refer to the Shader object doesn't really make sense,
+ // because the Shader object implicitly relies on OpenGL and the
+ // intent is to make the base element class not reliant on GL.
+
+ // The ShaderNode
+ protected ShaderNode shader;
+
+ /** Sets the shader in the given state. */
+ public static void set(State state, ShaderNode shader) {
+ getInstance(state).setElt(shader);
+ }
+
+ /** Returns the current shader in the state. */
+ public static ShaderNode get(State state) {
+ return getInstance(state).shader;
+ }
+
+ public void push(State state) {
+ ShaderElement prev = (ShaderElement) getNextInStack();
+ if (prev != null) {
+ // Pull down the shader from the previous element
+ shader = prev.shader;
+ }
+ }
+
+ /** Sets the shader in this element. */
+ public void setElt(ShaderNode shader) {
+ this.shader = shader;
+ }
+}
diff --git a/src/net/java/joglutils/msg/misc/Shader.java b/src/net/java/joglutils/msg/misc/Shader.java
new file mode 100644
index 0000000..c816629
--- /dev/null
+++ b/src/net/java/joglutils/msg/misc/Shader.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+package net.java.joglutils.msg.misc;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLException;
+import javax.media.opengl.glu.GLU;
+import static javax.media.opengl.GL.*;
+
+/**
+ * Represents an OpenGL shader program object, which can be constructed from
+ * the source code for a vertex shader, a fragment shader, or both.
+ * Contains convenience methods for enabling/disabling shader state.
+ * <p>
+ * Usage example:
+ * <pre>
+ * String source =
+ * "uniform sampler2D myTex;" +
+ * "void main(void)" +
+ * "{" +
+ * " vec4 src = texture2D(myTex, gl_TexCoord[0].st);" +
+ * " gl_FragColor = src.bgra;" + // swizzle!
+ * "}";
+ * Shader shader = new Shader(source);
+ * shader.setUniform("myTex", 0); // myTex will be on texture unit 0
+ * ...
+ * shader.enable();
+ * texture.enable();
+ * texture.bind();
+ * ...
+ * texture.disable();
+ * shader.disable();
+ * };
+ * </pre>
+ *
+ * @author Chris Campbell
+ */
+public class Shader {
+
+ /**
+ * The handle to the OpenGL fragment program object.
+ */
+ private int id;
+
+ /**
+ * Creates a new shader program object and compiles/links the provided
+ * fragment shader code into that object.
+ *
+ * @param fragmentCode a {@code String} representing the fragment shader
+ * source code to be compiled and linked
+ *
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public Shader(String fragmentCode)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ id = createProgram(gl, null, fragmentCode);
+ }
+
+ /**
+ * Creates a new shader program object and compiles/links the provided
+ * vertex shader and fragment shader code into that object.
+ *
+ * @param vertexCode a {@code String} representing the vertex shader
+ * source code to be compiled and linked; this may be null if only a
+ * fragment shader is going to be needed
+ * @param fragmentCode a {@code String} representing the fragment shader
+ * source code to be compiled and linked; this may be null if only a
+ * vertex shader is going to be needed
+ *
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public Shader(String vertexCode, String fragmentCode)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ id = createProgram(gl, vertexCode, fragmentCode);
+ }
+
+ /**
+ * Compiles and links a new shader program using the given sources. If
+ * successful, this function returns a handle to the newly created shader
+ * program; otherwise returns 0.
+ *
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ private static int createProgram(GL gl,
+ String vertexShaderSource,
+ String fragmentShaderSource)
+ throws GLException
+ {
+ if (vertexShaderSource == null && fragmentShaderSource == null) {
+ throw new GLException(
+ "Either vertexShaderSource or fragmentShaderSource " +
+ "must be specified");
+ }
+
+ int shaderProgram;
+ int vertexShader = 0;
+ int fragmentShader = 0;
+ int[] success = new int[1];
+ int[] infoLogLength = new int[1];
+
+ if (vertexShaderSource != null) {
+ vertexShader = compileShader(gl, vertexShaderSource, true);
+ if (vertexShader == 0) {
+ return 0;
+ }
+ }
+
+ if (fragmentShaderSource != null) {
+ fragmentShader = compileShader(gl, fragmentShaderSource, false);
+ if (fragmentShader == 0) {
+ if (vertexShader != 0) {
+ gl.glDeleteObjectARB(vertexShader);
+ }
+ return 0;
+ }
+ }
+
+ // create the program object and attach it to the shader
+ shaderProgram = gl.glCreateProgramObjectARB();
+ if (vertexShader != 0) {
+ gl.glAttachObjectARB(shaderProgram, vertexShader);
+ // it is now safe to delete the shader object
+ gl.glDeleteObjectARB(vertexShader);
+ }
+ if (fragmentShader != 0) {
+ gl.glAttachObjectARB(shaderProgram, fragmentShader);
+ // it is now safe to delete the shader object
+ gl.glDeleteObjectARB(fragmentShader);
+ }
+
+ // link the program
+ gl.glLinkProgramARB(shaderProgram);
+ gl.glGetObjectParameterivARB(shaderProgram,
+ GL_OBJECT_LINK_STATUS_ARB,
+ success, 0);
+
+ // print the linker messages, if necessary
+ gl.glGetObjectParameterivARB(shaderProgram,
+ GL_OBJECT_INFO_LOG_LENGTH_ARB,
+ infoLogLength, 0);
+ if (infoLogLength[0] > 1) {
+ byte[] infoLog = new byte[1024];
+ gl.glGetInfoLogARB(shaderProgram, 1024, null, 0, infoLog, 0);
+ System.err.println("Linker message: " +
+ new String(infoLog));
+ }
+
+ if (success[0] == 0) {
+ gl.glDeleteObjectARB(shaderProgram);
+ return 0;
+ }
+
+ return shaderProgram;
+ }
+
+ /**
+ * Compiles the given shader program. If successful, this function returns
+ * a handle to the newly created shader object; otherwise returns 0.
+ *
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ private static int compileShader(GL gl, String shaderSource, boolean vertex)
+ throws GLException
+ {
+ int kind = vertex ? GL_VERTEX_SHADER_ARB : GL_FRAGMENT_SHADER_ARB;
+ int shader;
+ int[] success = new int[1];
+ int[] infoLogLength = new int[1];
+
+ // create the shader object and compile the shader source code
+ shader = gl.glCreateShaderObjectARB(kind);
+ gl.glShaderSourceARB(shader, 1, new String[] { shaderSource }, null, 0);
+ gl.glCompileShaderARB(shader);
+ gl.glGetObjectParameterivARB(shader,
+ GL_OBJECT_COMPILE_STATUS_ARB,
+ success, 0);
+
+ // print the compiler messages, if necessary
+ gl.glGetObjectParameterivARB(shader,
+ GL_OBJECT_INFO_LOG_LENGTH_ARB,
+ infoLogLength, 0);
+ if (infoLogLength[0] > 1) {
+ byte[] infoLog = new byte[1024];
+ gl.glGetInfoLogARB(shader, 1024, null, 0, infoLog, 0);
+ System.err.println((vertex ? "Vertex" : "Fragment") +
+ " compile message: " +
+ new String(infoLog));
+ }
+
+ if (success[0] == 0) {
+ gl.glDeleteObjectARB(shader);
+ return 0;
+ }
+
+ return shader;
+ }
+
+ /**
+ * Returns the underlying OpenGL program object handle for this fragment
+ * shader. Most applications will not need to access this, since it is
+ * handled automatically by the enable() and dispose() methods.
+ *
+ * @return the OpenGL program object handle for this fragment shader
+ */
+ public int getProgramObject() {
+ return id;
+ }
+
+ /**
+ * Enables this shader program in the current GL context's state.
+ *
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void enable() throws GLException {
+ GL gl = GLU.getCurrentGL();
+ gl.glUseProgramObjectARB(id);
+ }
+
+ /**
+ * Disables this shader program in the current GL context's state.
+ *
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void disable() throws GLException {
+ GL gl = GLU.getCurrentGL();
+ gl.glUseProgramObjectARB(0);
+ }
+
+ /**
+ * Disposes the native resources used by this program object.
+ *
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void dispose() throws GLException {
+ GL gl = GLU.getCurrentGL();
+ gl.glDeleteObjectARB(id);
+ id = 0;
+ }
+
+ /**
+ * 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
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void setUniform(String name, int i0)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform1iARB(loc, i0);
+ }
+
+ /**
+ * Sets the uniform variable of the given name with the provided
+ * integer values.
+ *
+ * @param name the name of the uniform variable to be set
+ * @param i0 the first uniform parameter
+ * @param i1 the second uniform parameter
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void setUniform(String name, int i0, int i1)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform2iARB(loc, i0, i1);
+ }
+
+ /**
+ * Sets the uniform variable of the given name with the provided
+ * integer values.
+ *
+ * @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
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void setUniform(String name, int i0, int i1, int i2)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform3iARB(loc, i0, i1, i2);
+ }
+
+ /**
+ * Sets the uniform variable of the given name with the provided
+ * integer values.
+ *
+ * @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
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void setUniform(String name, int i0, int i1, int i2, int i3)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform4iARB(loc, i0, i1, i2, i3);
+ }
+
+ /**
+ * Sets the uniform variable of the given name with the provided
+ * float value.
+ *
+ * @param name the name of the uniform variable to be set
+ * @param f0 the first uniform parameter
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void setUniform(String name, float f0)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform1fARB(loc, f0);
+ }
+
+ /**
+ * Sets the uniform variable of the given name with the provided
+ * float values.
+ *
+ * @param name the name of the uniform variable to be set
+ * @param f0 the first uniform parameter
+ * @param f1 the second uniform parameter
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void setUniform(String name, float f0, float f1)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform2fARB(loc, f0, f1);
+ }
+
+ /**
+ * Sets the uniform variable of the given name with the provided
+ * float values.
+ *
+ * @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
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void setUniform(String name, float f0, float f1, float f2)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform3fARB(loc, f0, f1, f2);
+ }
+
+ /**
+ * Sets the uniform variable of the given name with the provided
+ * float values.
+ *
+ * @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
+ * @throws GLException if no OpenGL context was current or if any
+ * OpenGL-related errors occurred
+ */
+ public void setUniform(String name, float f0, float f1, float f2, float f3)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform4fARB(loc, f0, f1, f2, f3);
+ }
+
+ /**
+ * Sets the uniform array variable of the given name with the provided
+ * float array values.
+ *
+ * @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
+ * @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)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform1fvARB(loc, count, vals, off);
+ }
+
+ /**
+ * Sets the uniform array variable of the given name with the provided
+ * float array values.
+ *
+ * @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
+ * @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)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform2fvARB(loc, count, vals, off);
+ }
+
+ /**
+ * Sets the uniform array variable of the given name with the provided
+ * float array values.
+ *
+ * @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
+ * @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)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform3fvARB(loc, count, vals, off);
+ }
+
+ /**
+ * Sets the uniform array variable of the given name with the provided
+ * float array values.
+ *
+ * @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)
+ throws GLException
+ {
+ GL gl = GLU.getCurrentGL();
+ int loc = gl.glGetUniformLocationARB(id, name);
+ gl.glUniform4fvARB(loc, count, vals, off);
+ }
+}
diff --git a/src/net/java/joglutils/msg/nodes/ShaderNode.java b/src/net/java/joglutils/msg/nodes/ShaderNode.java
new file mode 100644
index 0000000..73154ee
--- /dev/null
+++ b/src/net/java/joglutils/msg/nodes/ShaderNode.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+package net.java.joglutils.msg.nodes;
+
+import java.awt.image.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import javax.media.opengl.*;
+
+import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
+import net.java.joglutils.msg.misc.*;
+
+/** Represents a vertex/fragment shader. */
+public class ShaderNode extends Node {
+
+ private String vertexShaderCode;
+ private String fragmentShaderCode;
+ private Shader shader;
+ private List<Shader> disposedShaders = new ArrayList<Shader>();
+
+ static {
+ // Enable the elements this node affects for known actions
+ GLShaderElement.enable(GLRenderAction.getDefaultState());
+ }
+
+ /** Initializes this shader from the given String. No OpenGL work is
+ done during this call; it is done lazily when the Shader is
+ fetched. */
+ public void setShader(String fragmentShaderCode) {
+ disposeShader();
+ this.vertexShaderCode = null;
+ this.fragmentShaderCode = fragmentShaderCode;
+ }
+
+ /** Initializes this shader from the given String. No OpenGL work is
+ done during this call; it is done lazily when the Shader is
+ fetched. */
+ public void setShader(String vertexShaderCode, String fragmentShaderCode) {
+ disposeShader();
+ this.vertexShaderCode = vertexShaderCode;
+ this.fragmentShaderCode = fragmentShaderCode;
+ }
+
+ /** Fetches the Shader object associated with this ShaderNode.
+ It is required to call this each frame during rendering.
+ An OpenGL context must be current at the time this method is
+ called or a GLException will be thrown. */
+ public Shader getShader() throws GLException {
+ lazyDispose();
+ if (shader == null) {
+ this.shader = new Shader(vertexShaderCode, fragmentShaderCode);
+ }
+ return shader;
+ }
+
+ public void doAction(Action action) {
+ if (ShaderElement.isEnabled(action.getState())) {
+ ShaderElement.set(action.getState(), this);
+ }
+ }
+
+ private synchronized void disposeShader() {
+ if (shader != null) {
+ disposedShaders.add(shader);
+ shader = null;
+ }
+ }
+
+ private void lazyDispose() {
+ while (!disposedShaders.isEmpty()) {
+ Shader s = null;
+ synchronized (this) {
+ s = disposedShaders.remove(disposedShaders.size() - 1);
+ }
+ s.dispose();
+ }
+ }
+}