summaryrefslogtreecommitdiffstats
path: root/src/net/java/joglutils/msg/misc/Shader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/joglutils/msg/misc/Shader.java')
-rw-r--r--src/net/java/joglutils/msg/misc/Shader.java508
1 files changed, 508 insertions, 0 deletions
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);
+ }
+}