Package mdesl.graphics.glutils

Source Code of mdesl.graphics.glutils.ShaderProgram$Attrib

/**
* Copyright (c) 2012, Matt DesLauriers All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions are met:
*
*  * Redistributions of source code must retain the above copyright notice, this
*    list of conditions and the following disclaimer.
*
*  * Redistributions in binary
*    form must reproduce the above copyright notice, this list of conditions and
*    the following disclaimer in the documentation and/or other materials provided
*    with the distribution.
*
*  * Neither the name of the Matt DesLauriers nor the names
*    of his contributors may be used to endorse or promote products derived from
*    this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
*  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
*  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
*  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
*  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
*  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*/
package mdesl.graphics.glutils;

import static org.lwjgl.opengl.GL20.GL_ACTIVE_ATTRIBUTES;
import static org.lwjgl.opengl.GL20.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH;
import static org.lwjgl.opengl.GL20.GL_ACTIVE_UNIFORMS;
import static org.lwjgl.opengl.GL20.GL_ACTIVE_UNIFORM_MAX_LENGTH;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glBindAttribLocation;
import static org.lwjgl.opengl.GL20.glCompileShader;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glCreateShader;
import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glDeleteShader;
import static org.lwjgl.opengl.GL20.glDetachShader;
import static org.lwjgl.opengl.GL20.glGetActiveAttrib;
import static org.lwjgl.opengl.GL20.glGetActiveAttribSize;
import static org.lwjgl.opengl.GL20.glGetActiveAttribType;
import static org.lwjgl.opengl.GL20.glGetActiveUniform;
import static org.lwjgl.opengl.GL20.glGetAttribLocation;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL20.glGetUniform;
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.glShaderSource;
import static org.lwjgl.opengl.GL20.glUniform1f;
import static org.lwjgl.opengl.GL20.glUniform1i;
import static org.lwjgl.opengl.GL20.glUniform2f;
import static org.lwjgl.opengl.GL20.glUniform2i;
import static org.lwjgl.opengl.GL20.glUniform3f;
import static org.lwjgl.opengl.GL20.glUniform3i;
import static org.lwjgl.opengl.GL20.glUniform4f;
import static org.lwjgl.opengl.GL20.glUniform4i;
import static org.lwjgl.opengl.GL20.glUniformMatrix3;
import static org.lwjgl.opengl.GL20.glUniformMatrix4;
import static org.lwjgl.opengl.GL20.glUseProgram;
import static org.lwjgl.opengl.GL32.GL_GEOMETRY_SHADER;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.List;

import mdesl.test.Util;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.ContextCapabilities;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.vector.Matrix3f;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;

/** A complete ShaderProgram utility wrapper.
*
* @author davedes */
public class ShaderProgram {

  private static FloatBuffer fbuf16;
  private static IntBuffer ibuf4;
 
  // a simple struct for attrib data; ideally we should find the
  // component count to utilize our VertexAttrib class
  protected static class Attrib {
    String name = null;
    int type = -1;
    int size = 0; // for arrays
    int location = -1;
  }

  /** The vertex shader type (GL_VERTEX_SHADER). */
  public static final int VERTEX_SHADER = GL_VERTEX_SHADER;
  /** The fragment shader type (GL_FRAGMENT_SHADER). */
  public static final int FRAGMENT_SHADER = GL_FRAGMENT_SHADER;
  private static boolean strict = false;

  /** Returns true if the extensions GL_ARB_shader_objects,
   * GL_ARB_vertex_shader, and GL_ARB_fragment shader are present.
   *
   * @return true if shaders are supported */
  public static boolean isSupported() {
    ContextCapabilities c = GLContext.getCapabilities();
    return c.GL_ARB_shader_objects && c.GL_ARB_vertex_shader && c.GL_ARB_fragment_shader;
    // return c.OpenGL20;
  }

  /** Whether shader programs are to use "strict" uniform/attribute name
   * checking (default: disabled). That is, when strict mode is enabled,
   * trying to modify or retrieve uniform/attribute data by name will fail and
   * throw an IllegalArgumentException if there exists no 'active'
   * uniforms/attributes by the given name. (In GLSL, declared uniforms might
   * still be "inactive" if they are not used.) If strict mode is disabled,
   * getting/setting uniform/attribute data will fail silently if the name is
   * not found.
   *
   * @param enabled true to enable strict mode */
  public static void setStrictMode(boolean enabled) {
    strict = enabled;
  }

  /** Returns <tt>true</tt> if shader programs are to use "strict"
   * uniform/attribute name checking (default: disabled). That is, when strict
   * mode is enabled, trying to modify or retrieve uniform/attribute data by
   * name will fail and throw an IllegalArgumentException if there exists no
   * 'active' uniforms/attributes by the given name. (In GLSL, declared
   * uniforms might still be "inactive" if they are not used.) If strict mode
   * is disabled, getting/setting uniform/attribute data will fail silently if
   * the name is not found.
   *
   * @return true if strict mode is enabled */
  public static boolean isStrictMode() {
    return strict;
  }

  /** The OpenGL handle for this shader program object. */
  protected int program;
  /** The log for this program. */
  protected String log = "";
  /** A map of uniforms by <name, int>. */
  protected HashMap<String, Integer> uniforms = new HashMap<String, Integer>();
  /** A list of attribute data. */
  protected Attrib[] attributes;

  /** The vertex shader source. */
  protected String vertShaderSource;
  /** The fragment shader source. */
  protected String fragShaderSource;
  /** The OpenGL handle for this program's vertex shader object. */
  protected int vert;
  /** The OpenGL handle for this program's fragment shader object. */
  protected int frag;


  /** Creates a new shader program with the given vertex and fragment shader
   * source code. The given source code is compiled, then the shaders attached
   * and linked.
   *
   * If shaders are not supported on this system (isSupported returns false),
   * a LWJGLException will be thrown.
   *
   * If one of the shaders does not compile successfully, a LWJGLException
   * will be thrown.
   *
   * If there was a problem in linking the shaders to the program, a
   * LWJGLException will be thrown and the program will be deleted.
   *
   * Before linking, the specified attribLocations will be bound using
   * glBindAttribLocation.
   *
   * @param vertexShaderSource the shader code to compile, attach and link
   * @param fragShaderSource the frag code to compile, attach and link
   * @param attribLocations the attribute locations to bind
   * @throws LWJGLException if there was an issue
   * @throws IllegalArgumentException if there was an issue */
  public ShaderProgram(String vertexShaderSource, String fragShaderSource,
      List<VertexAttrib> attribLocations) throws LWJGLException {
    if (vertexShaderSource == null || fragShaderSource == null)
      throw new IllegalArgumentException("shader source must be non-null");
    if (!isSupported())
      throw new LWJGLException("no shader support found; shaders require OpenGL 2.0");
    this.vertShaderSource = vertexShaderSource;
    this.fragShaderSource = fragShaderSource;
    vert = compileShader(VERTEX_SHADER, vertexShaderSource);
    frag = compileShader(FRAGMENT_SHADER, fragShaderSource);
    program = createProgram();
    try {
      linkProgram(attribLocations);
    } catch (LWJGLException e) {
      dispose();
      throw e;
    }
    //TODO: for convenience it might be nice to warn non-critical errors in a log
    //but ideally the user should do that himself
//    if (log != null && log.length() != 0)
//      Util.warn(log);
  }

  /** Creates a new shader program with the given vertex and fragment shader
   * source code. The given source code is compiled, then the shaders attached
   * and linked.
   *
   * If shaders are not supported on this system (isSupported returns false),
   * a LWJGLException will be thrown.
   *
   * If one of the shaders does not compile successfully, a LWJGLException
   * will be thrown.
   *
   * If there was a problem in linking the shaders to the program, a
   * LWJGLException will be thrown and the program will be deleted.
   *
   * @param vertexShaderSource the shader code to compile, attach and link
   * @param fragShaderSource the frag code to compile, attach and link
   * @throws LWJGLException if there was an issue
   * @throws IllegalArgumentException if there was an issue */
  public ShaderProgram(String vertexShaderSource, String fragShaderSource) throws LWJGLException {
    this(vertexShaderSource, fragShaderSource, null);
  }

  /** Subclasses may wish to implement this to manually handle program/shader
   * creation, compiling, and linking. This constructor does nothing; users
   * will need to call compileShader, createProgram and linkProgram manually.
   *
   * @throws SlimException */
  protected ShaderProgram() {
  }

  /** Creates a shader program and returns its OpenGL handle. If the result is
   * zero, an exception will be thrown.
   *
   * @return the OpenGL handle for the newly created shader program
   * @throws SlimException if the result is zero */
  protected int createProgram() throws LWJGLException {
    int program = glCreateProgram();
    if (program == 0)
      throw new LWJGLException("could not create program; check ShaderProgram.isSupported()");
    return program;
  }

  /** Used only for clearer debug messages. */
  private String shaderTypeString(int type) {
    if (type == FRAGMENT_SHADER)
      return "FRAGMENT_SHADER";
    else if (type == VERTEX_SHADER)
      return "VERTEX_SHADER";
    else if (type == GL_GEOMETRY_SHADER)
      return "GEOMETRY_SHADER";
    else
      return "shader";
  }

  /** Compiles a shader from source and returns its handle. If the compilation
   * failed, a SlimException will be thrown. If the compilation had error,
   * info or warnings messages, they will be appended to this program's log.
   *
   * @param type the type to use in compilation
   * @param source the source code to compile
   * @return the resulting ID
   * @throws SlimException if compilation was unsuccessful */
  protected int compileShader(int type, String source) throws LWJGLException {
    int shader = glCreateShader(type);
    if (shader == 0)
      throw new LWJGLException(
          "could not create shader object; check ShaderProgram.isSupported()");
    glShaderSource(shader, source);
    glCompileShader(shader);

    int comp = glGetShaderi(shader, GL_COMPILE_STATUS);
    int len = glGetShaderi(shader, GL_INFO_LOG_LENGTH);
    String t = shaderTypeString(type);
    String err = glGetShaderInfoLog(shader, len);
    if (err != null && err.length() != 0)
      log += t + " compile log:\n" + err + "\n";
    if (comp == GL11.GL_FALSE)
      throw new LWJGLException(log.length()!=0 ? log : "Could not compile "+shaderTypeString(type));
    return shader;
  }

  /** Called to attach vertex and fragment; users may override this for more
   * specific purposes. */
  protected void attachShaders() {
    glAttachShader(getID(), vert);
    glAttachShader(getID(), frag);
  }

  /** Tries to bind the given attributes by location, then calls
   * attachShaders() and links the program.
   *
   * @param attribs tries to bind the given attributes in their order of
   * appearance
   * @throws SlimException if this program is invalid (released) or if the
   * link was unsuccessful */
  protected void linkProgram(List<VertexAttrib> attribLocations) throws LWJGLException {
    if (!valid())
      throw new LWJGLException("trying to link an invalid (i.e. released) program");

    uniforms.clear();

    // bind user-defined attribute locations
    if (attribLocations != null) {
      for (VertexAttrib a : attribLocations) {
        if (a != null)
          glBindAttribLocation(program, a.location, a.name);
      }
    }

    attachShaders();
    glLinkProgram(program);
    int comp = glGetProgrami(program, GL_LINK_STATUS);
    int len = glGetProgrami(program, GL_INFO_LOG_LENGTH);
    String err = glGetProgramInfoLog(program, len);
    if (err != null && err.length() != 0)
      log = err + "\n" + log;
    if (log != null)
      log = log.trim();
    if (comp == GL11.GL_FALSE)
      throw new LWJGLException(log.length()!=0 ? log : "Could not link program");

    fetchUniforms();
    fetchAttributes();
  }

  /** Returns the full log of compiling/linking errors, info, warnings, etc.
   *
   * @return the full log of this ShaderProgram */
  public String getLog() {
    return log;
  }

  /** Enables this shader for use -- only one shader can be bound at a time.
   * Calling bind() when another program is bound will simply make this object
   * the active program.
   *
   * @throw IllegalStateException if this program is invalid */
  public void use() {
    if (!valid())
      throw new IllegalStateException("trying to enable a program that is not valid");
    glUseProgram(program);
  }

  /** Detaches and releases the shaders
   * associated with this program. This can be called after linking a program
   * in order to free up memory (as the shaders are no longer needed),
   * however, since it is not a commonly used feature and thus not well tested
   * on all drivers, it should be used with caution. Shaders shouldn't be used
   * after being released. */
  public void disposeShaders() {
    if (vert != 0) {
      glDetachShader(getID(), vert);
      glDeleteShader(vert);
      vert = 0;
    }
    if (frag != 0) {
      glDetachShader(getID(), frag);
      glDeleteShader(frag);
      frag = 0;
    }
  }

  /** If this program has not yet been released, this will releases
   * this program and its shaders. To only release the
   * shaders (not the program itself), call disposeShaders(). Programs will be
   * considered "invalid" after being released, and should no longer be used. */
  public void dispose() {
    if (program != 0) {
      disposeShaders();
      glDeleteProgram(program);
      program = 0;
    }
  }

  /** Returns the OpenGL handle for this program's vertex shader.
   *
   * @return the vertex ID */
  public int getVertexShaderID() {
    return vert;
  }

  /** Returns the OpenGL handle for this program's fragment shader.
   *
   * @return the fragment ID */
  public int getFragmentShaderID() {
    return frag;
  }

  /** Returns the source code for the vertex shader.
   *
   * @return the source code */
  public String getVertexShaderSource() {
    return vertShaderSource;
  }

  /** Returns the source code for the fragment shader.
   *
   * @return the source code */
  public String getFragmentShaderSource() {
    return fragShaderSource;
  }

  /** Returns the OpenGL handle for this shader program
   *
   * @return the program ID */
  public int getID() {
    return program;
  }

  /** A shader program is "valid" if it's ID is not zero. Upon releasing a
   * program, the ID will be set to zero.
   *
   * @return whether this program is valid */
  public boolean valid() {
    return program != 0;
  }

  private void fetchUniforms() {
    int len = glGetProgrami(program, GL_ACTIVE_UNIFORMS);
    // max length of all uniforms stored in program
    int strLen = glGetProgrami(program, GL_ACTIVE_UNIFORM_MAX_LENGTH);

    for (int i = 0; i < len; i++) {
      String name = glGetActiveUniform(program, i, strLen);
      int id = glGetUniformLocation(program, name);
      uniforms.put(name, id);
    }
  }

  private void fetchAttributes() {
    int len = glGetProgrami(program, GL_ACTIVE_ATTRIBUTES);
    // max length of all uniforms stored in program
    int strLen = glGetProgrami(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH);

    attributes = new Attrib[len];
    for (int i = 0; i < len; i++) {
      Attrib a = new Attrib();
      // TODO: use proper FloatBuffer method instead of these convenience
      // methods
      a.name = glGetActiveAttrib(program, i, strLen);
      a.size = glGetActiveAttribSize(program, i);
      a.type = glGetActiveAttribType(program, i);
      a.location = glGetAttribLocation(program, a.name);
      attributes[i] = a;
    }
  }

  /** Returns the location of the uniform by name. If the uniform is not found
   * and we are in strict mode, an IllegalArgumentException will be thrown,
   * otherwise -1 will be returned if no active uniform by that name exists.
   *
   * @param name the uniform name
   * @return the ID (location) in the shader program */
  public int getUniformLocation(String name) {
    int location = -1;
    Integer locI = uniforms.get(name);
    if (locI == null) { // maybe it's not yet cached?
      location = glGetUniformLocation(program, name);
      uniforms.put(name, location);
    } else
      location = locI.intValue();
    // throw an exception if not found...
    if (location == -1 && strict)
      throw new IllegalArgumentException("no active uniform by name '" + name + "' "
          + "(disable strict compiling to suppress warnings)");
    return location;
  }

  Attrib attrib(String name) {
    for (int i = 0; i < attributes.length; i++) {
      if (name.equals(attributes[i].name))
        return attributes[i];
    }
    // throw an exception if not found...
    if (strict)
      throw new IllegalArgumentException("no active attribute by name '" + name + "' "
          + "(disable strict compiling to suppress warnings)");
    return null;
  }

  /** Returns the location of the attribute by name. If the attribute is not
   * found and we are in strict mode, an IllegalArgumentException will be
   * thrown, otherwise -1 will be returned if no active attribute by that name
   * exists.
   *
   * @param name the attribute name
   * @return the ID (location) in the shader program */
  public int getAttributeLocation(String name) {
    Attrib a = attrib(name);
    return a != null ? a.location : -1;
  }

  /** Returns the type of the attribute by name. If the attribute is not found
   * and we are in strict mode, an IllegalArgumentException will be thrown,
   * otherwise -1 will be returned if no active attribute by that name exists.
   *
   * @param name the attribute name
   * @return the ID (location) in the shader program */
  public int getAttributeType(String name) {
    Attrib a = attrib(name);
    return a != null ? a.type : -1;
  }

  /** Returns the size of the attribute by name (i.e. for arrays). If the
   * attribute is not found and we are in strict mode, an
   * IllegalArgumentException will be thrown, otherwise -1 will be returned if
   * no active attribute by that name exists.
   *
   * @param name the attribute name
   * @return the ID (location) in the shader program */
  public int getAttributeSize(String name) {
    Attrib a = attrib(name);
    return a != null ? a.size : -1;
  }

  /** Creates and returns an array for all active attributes that were found
   * when linking the program.
   *
   * @return an array list of active uniform names */
  public String[] getAttributeNames() {
    String[] s = new String[attributes.length];
    for (int i = 0; i < attributes.length; i++) {
      s[i] = attributes[i].name;
    }
    return s;
  }

  /** Creates and returns an array for all active uniforms that were found when
   * linking the program.
   *
   * @return an array list of active uniform names */
  public String[] getUniformNames() {
    return uniforms.keySet().toArray(new String[uniforms.size()]);
  }

  /** Returns true if an active uniform by the given name was found when
   * linking.
   *
   * @param name the active uniform name
   * @return true if the uniform was found */
  public boolean hasUniform(String name) {
    return uniforms.containsKey(name);
  }

  /** Returns true if an active attribute by the given name was found when
   * linking.
   *
   * @param name the active attribute name
   * @return true if the attribute was found */
  public boolean hasAttribute(String name) {
    for (int i = 0; i < attributes.length; i++)
      if (name.equals(attributes[i].name))
        return true;
    return false;
  }

  /** ----- UNIFORM GETTERS ----- */

  private FloatBuffer uniformf(int loc) {
    if (fbuf16 == null)
      fbuf16 = BufferUtils.createFloatBuffer(16);
    fbuf16.clear();
    if (loc == -1)
      return fbuf16;
    getUniform(loc, fbuf16);
    return fbuf16;
  }

  private IntBuffer uniformi(int loc) {
    if (ibuf4 == null)
      ibuf4 = BufferUtils.createIntBuffer(4);
    ibuf4.clear();
    if (loc == -1)
      return ibuf4;
    getUniform(loc, ibuf4);
    return ibuf4;
  }


  /** Retrieves data from a uniform and places it in the given buffer.
   *
   * @param loc the location of the uniform
   * @param buf the buffer to place the data */
  public void getUniform(int loc, FloatBuffer buf) {
    glGetUniform(program, loc, buf);
  }

  /** Retrieves data from a uniform and places it in the given buffer.
   *
   * @param loc the location of the uniform
   * @param buf the buffer to place the data */
  public void getUniform(int loc, IntBuffer buf) {
    glGetUniform(program, loc, buf);
  }

  /** Retrieves data from a uniform and places it in the given buffer. If
   * strict mode is enabled, this will throw an IllegalArgumentException if
   * the given uniform is not 'active' -- i.e. if GLSL determined that the
   * shader isn't using it. If strict mode is disabled, this method will
   * return <tt>true</tt> if the uniform was found, and <tt>false</tt>
   * otherwise.
   *
   * @param name the name of the uniform
   * @param buf the buffer to place the data
   * @return true if the uniform was found, false if there is no active
   * uniform by that name */
  public boolean getUniform(String name, FloatBuffer buf) {
    int id = getUniformLocation(name);
    if (id == -1)
      return false;
    getUniform(id, buf);
    return true;
  }

  /** Retrieves data from a uniform and places it in the given buffer. If
   * strict mode is enabled, this will throw an IllegalArgumentException if
   * the given uniform is not 'active' -- i.e. if GLSL determined that the
   * shader isn't using it. If strict mode is disabled, this method will
   * return <tt>true</tt> if the uniform was found, and <tt>false</tt>
   * otherwise.
   *
   * @param name the name of the uniform
   * @param buf the buffer to place the data
   * @return true if the uniform was found, false if there is no active
   * uniform by that name */
  public boolean getUniform(String name, IntBuffer buf) {
    int id = getUniformLocation(name);
    if (id == -1)
      return false;
    getUniform(id, buf);
    return true;
  }

  /** A convenience method to retrieve an integer/sampler2D uniform. The return
   * values are undefined if the uniform is not found.
   *
   * @param loc the uniform location
   * @return the value */
  public int getUniform1i(int loc) {
    return uniformi(loc).get(0);
  }

  /** A convenience method to retrieve an integer/sampler2D uniform. The return
   * values are undefined if the uniform is not found.
   *
   * @param name the uniform location
   * @return the value */
  public int getUniform1i(String name) {
    return getUniform1i(getUniformLocation(name));
  }

  /** A convenience method to retrieve an ivec2 uniform; for maximum
   * performance and memory efficiency you should use getUniform(int,
   * IntBuffer) with a shared buffer.
   *
   * @param loc the uniform location
   * @return a newly created int[] array with 2 elements; e.g. (x, y) */
  public int[] getUniform2i(int loc) {
    IntBuffer buf = uniformi(loc);
    return new int[] { buf.get(0), buf.get(1) };
  }

  /** A convenience method to retrieve an ivec2 uniform; for maximum
   * performance and memory efficiency you should use getUniform(int,
   * IntBuffer) with a shared buffer. The return values are undefined if the
   * uniform is not found.
   *
   * @param name the uniform name
   * @return a newly created int[] array with 2 elements; e.g. (x, y) */
  public int[] getUniform2i(String name) {
    return getUniform2i(getUniformLocation(name));
  }

  /** A convenience method to retrieve an ivec3 uniform; for maximum
   * performance and memory efficiency you should use getUniform(String,
   * IntBuffer) with a shared buffer.
   *
   * @param loc the name of the uniform
   * @return a newly created int[] array with 3 elements; e.g. (x, y, z) */
  public int[] getUniform3i(int loc) {
    IntBuffer buf = uniformi(loc);
    return new int[] { buf.get(0), buf.get(1), buf.get(2) };
  }

  /** A convenience method to retrieve an ivec3 uniform; for maximum
   * performance and memory efficiency you should use getUniform(String,
   * IntBuffer) with a shared buffer. The return values are undefined if the
   * uniform is not found.
   *
   * @param name the name of the uniform
   * @return a newly created int[] array with 3 elements; e.g. (x, y, z) */
  public int[] getUniform3i(String name) {
    return getUniform3i(getUniformLocation(name));
  }

  /** A convenience method to retrieve an ivec4 uniform; for maximum
   * performance and memory efficiency you should use getUniform(String,
   * IntBuffer) with a shared buffer.
   *
   * @param loc the location of the uniform
   * @return a newly created int[] array with 2 elements; e.g. (r, g, b, a) */
  public int[] getUniform4i(int loc) {
    IntBuffer buf = uniformi(loc);
    return new int[] { buf.get(0), buf.get(1), buf.get(2), buf.get(3) };
  }
 
  /** A convenience method to retrieve an ivec4 uniform; for maximum
   * performance and memory efficiency you should use getUniform(String,
   * IntBuffer) with a shared buffer. The return values are undefined if the
   * uniform is not found.
   *
   * @param name the name of the uniform
   * @return a newly created int[] array with 2 elements; e.g. (r, g, b, a) */
  public int[] getUniform4i(String name) {
    return getUniform4i(getUniformLocation(name));
  }
 
  /** A convenience method to retrieve a float uniform.
   *
   * @param location the location of the uniform
   * @return the value */
  public float getUniform1f(int loc) {
    return uniformf(loc).get(0);
  }

  /** A convenience method to retrieve a float uniform. The return values are undefined if the
   * uniform is not found.
   *
   * @param name the uniform name
   * @return the value */
  public float getUniform1f(String name) {
    return getUniform1f(getUniformLocation(name));
  }

  /** A convenience method to retrieve a vec2 uniform; for maximum performance
   * and memory efficiency you should use getUniform(String, FloatBuffer) with
   * a shared buffer.
   *
   * @param location the location of the uniform
   * @return a newly created float[] array with 2 elements; e.g. (x, y) */
  public float[] getUniform2f(int loc) {
    FloatBuffer buf = uniformf(loc);
    return new float[] { buf.get(0), buf.get(1) };
  }

  /** A convenience method to retrieve a vec2 uniform; for maximum performance
   * and memory efficiency you should use getUniform(String, FloatBuffer) with
   * a shared buffer. The return values are undefined if the
   * uniform is not found.
   *
   * @param name the name of the uniform
   * @return a newly created float[] array with 2 elements; e.g. (x, y) */
  public float[] getUniform2f(String name) {
    return getUniform2f(getUniformLocation(name));
  }

  /** A convenience method to retrieve a vec3 uniform; for maximum performance
   * and memory efficiency you should use getUniform(String, FloatBuffer) with
   * a shared buffer.
   *
   * @param location the location of the uniform
   * @return a newly created float[] array with 3 elements; e.g. (x, y, z) */
  public float[] getUniform3f(int loc) {
    FloatBuffer buf = uniformf(loc);
    return new float[] { buf.get(0), buf.get(1), buf.get(2) };
  }
 
  /** A convenience method to retrieve a vec3 uniform; for maximum performance
   * and memory efficiency you should use getUniform(String, FloatBuffer) with
   * a shared buffer. The return values are undefined if the
   * uniform is not found.
   *
   * @param name the name of the uniform
   * @return a newly created float[] array with 3 elements; e.g. (x, y, z) */
  public float[] getUniform3f(String name) {
    return getUniform3f(getUniformLocation(name));
  }

  /** A convenience method to retrieve a vec4 uniform; for maximum performance
   * and memory efficiency you should use getUniform(String, FloatBuffer) with
   * a shared buffer.
   *
   * @param location the location of the uniform
   * @return a newly created float[] array with 4 elements; e.g. (r, g, b, a) */
  public float[] getUniform4f(int loc) {
    FloatBuffer buf = uniformf(loc);
    return new float[] { buf.get(0), buf.get(1), buf.get(2), buf.get(3) };
  }
 
  /** A convenience method to retrieve a vec4 uniform; for maximum performance
   * and memory efficiency you should use getUniform(String, FloatBuffer) with
   * a shared buffer. The return values are undefined if the
   * uniform is not found.
   *
   * @param name the name of the uniform
   * @return a newly created float[] array with 4 elements; e.g. (r, g, b, a) */
  public float[] getUniform4f(String name) {
    return getUniform4f(getUniformLocation(name));
  }

  /** ----- UNIFORM LOCATION SETTERS ----- */
 
  /**
   * Sets the value of a float uniform.
   * @param loc the location of the uniform
   * @param f the float value
   */
  public void setUniformf(int loc, float f) {
    if (loc==-1) return;
    glUniform1f(loc, f);
  }
 
  /**
   * Sets the value of a vec2 uniform.
   * @param loc the location of the uniform
   * @param a vec.x / tex.s
   * @param b vec.y / tex.t
   */
  public void setUniformf(int loc, float a, float b) {
    if (loc==-1) return;
    glUniform2f(loc, a, b);
  }
 
  /**
   * Sets the value of a vec3 uniform.
   * @param loc the location of the uniform
   * @param a vec.x / color.r / tex.s
   * @param b vec.y / color.g / tex.t
   * @param c vec.z / color.b / tex.p
   */
  public void setUniformf(int loc, float a, float b, float c) {
    if (loc==-1) return;
    glUniform3f(loc, a, b, c);
  }

  /**
   * Sets the value of a vec4 uniform.
   * @param loc the location of the uniform
   * @param a vec.x / color.r
   * @param b vec.y / color.g
   * @param c vec.z / color.b
   * @param d vec.w / color.a
   */
  public void setUniformf(int loc, float a, float b, float c, float d) {
    if (loc==-1) return;
    glUniform4f(loc, a, b, c, d);
  }

  /**
   * Sets the value of an int or sampler2D uniform.
   * @param loc the location of the uniform
   * @param i the integer / active texture (e.g. 0 for TEXTURE0)
   */
  public void setUniformi(int loc, int i) {
    if (loc==-1) return;
    glUniform1i(loc, i);
  }
 
  /**
   * Sets the value of a ivec2 uniform.
   * @param loc the location of the uniform
   * @param a vec.x / tex.s
   * @param b vec.y / tex.t
   */
  public void setUniformi(int loc, int a, int b) {
    if (loc==-1) return;
    glUniform2i(loc, a, b);
  }

  /**
   * Sets the value of a ivec3 uniform.
   * @param loc the location of the uniform
   * @param a vec.x / color.r
   * @param b vec.y / color.g
   * @param c vec.z / color.b
   */
  public void setUniformi(int loc, int a, int b, int c) {
    if (loc==-1) return;
    glUniform3i(loc, a, b, c);
  }
 
  /**
   * Sets the value of a ivec4 uniform.
   * @param loc the location of the uniform
   * @param a vec.x / color.r
   * @param b vec.y / color.g
   * @param c vec.z / color.b
   * @param d vec.w / color.a
   */
  public void setUniformi(int loc, int a, int b, int c, int d) {
    if (loc==-1) return;
    glUniform4i(loc, a, b, c, d);
  }
 
 
  /** ----- UNIFORM STRING SETTERS ----- */

  /**
   * Sets the value of a float uniform.
   * @param name the name of the uniform
   * @param f the float value
   */
  public void setUniformf(String name, float f) {
    setUniformf(getUniformLocation(name), f);
  }
 
  /**
   * Sets the value of a vec2 uniform.
   * @param name the name of the uniform
   * @param a vec.x / tex.s
   * @param b vec.y / tex.t
   */
  public void setUniformf(String name, float a, float b) {
    setUniformf(getUniformLocation(name), a, b);
  }
 
  /**
   * Sets the value of a vec3 uniform.
   * @param name the name of the uniform
   * @param a vec.x / color.r / tex.s
   * @param b vec.y / color.g / tex.t
   * @param c vec.z / color.b / tex.p
   */
  public void setUniformf(String name, float a, float b, float c) {
    setUniformf(getUniformLocation(name), a, b, c);
  }

  /**
   * Sets the value of a vec4 uniform.
   * @param name the name of the uniform
   * @param a vec.x / color.r
   * @param b vec.y / color.g
   * @param c vec.z / color.b
   * @param d vec.w / color.a
   */
  public void setUniformf(String name, float a, float b, float c, float d) {
    setUniformf(getUniformLocation(name), a, b, c, d);
  }

  /**
   * Sets the value of an int or sampler2D uniform.
   * @param name the name of the uniform
   * @param i the integer / active texture (e.g. 0 for TEXTURE0)
   */
  public void setUniformi(String name, int i) {
    setUniformi(getUniformLocation(name), i);
  }
 
  /**
   * Sets the value of a ivec2 uniform.
   * @param name the name of the uniform
   * @param a vec.x / tex.s
   * @param b vec.y / tex.t
   */
  public void setUniformi(String name, int a, int b) {
    setUniformi(getUniformLocation(name), a, b);
  }

  /**
   * Sets the value of a ivec3 uniform.
   * @param name the name of the uniform
   * @param a vec.x / color.r
   * @param b vec.y / color.g
   * @param c vec.z / color.b
   */
  public void setUniformi(String name, int a, int b, int c) {
    setUniformi(getUniformLocation(name), a, b, c);
  }
 
  /**
   * Sets the value of a ivec4 uniform.
   * @param name the name of the uniform
   * @param a vec.x / color.r
   * @param b vec.y / color.g
   * @param c vec.z / color.b
   * @param d vec.w / color.a
   */
  public void setUniformi(String name, int a, int b, int c, int d) {
    setUniformi(getUniformLocation(name), a, b, c, d);
  }
 

  /** ----- MATRIX SETTERS ----- */
 
  public void setUniformMatrix(String name, boolean transpose, Matrix3f m) {
    setUniformMatrix(getUniformLocation(name), transpose, m);
  }
 
  public void setUniformMatrix(String name, boolean transpose, Matrix4f m) {
    setUniformMatrix(getUniformLocation(name), transpose, m);
  }
 
  public void setUniformMatrix(int loc, boolean transpose, Matrix3f m) {
    if (loc==-1) return;
    if (fbuf16==null)
      fbuf16 = BufferUtils.createFloatBuffer(16);
    fbuf16.clear();
    m.store(fbuf16);
    fbuf16.flip();
    glUniformMatrix3(loc, transpose, fbuf16);
  }
 
  public void setUniformMatrix(int loc, boolean transpose, Matrix4f m) {
    if (loc==-1) return;
    if (fbuf16==null)
      fbuf16 = BufferUtils.createFloatBuffer(16);
    fbuf16.clear();
    m.store(fbuf16);
    fbuf16.flip();
    glUniformMatrix4(loc, transpose, fbuf16);
  }
 
 
  /** ----- VECTOR SETTERS ----- */
   
  public void setUniformf(String name, Vector2f v) {
    setUniformf(getUniformLocation(name), v);
  }
 
  public void setUniformf(String name, Vector3f v) {
    setUniformf(getUniformLocation(name), v);
  }
 
  public void setUniformf(String name, Vector4f v) {
    setUniformf(getUniformLocation(name), v);
  }
 
  public void setUniformf(int loc, Vector2f v) {
    if (loc==-1) return;
    setUniformf(loc, v.x, v.y);
  }
 
  public void setUniformf(int loc, Vector3f v) {
    if (loc==-1) return;
    setUniformf(loc, v.x, v.y, v.z);
  }
 
  public void setUniformf(int loc, Vector4f v) {
    if (loc==-1) return;
    setUniformf(loc, v.x, v.y, v.z, v.w);
  }
}
TOP

Related Classes of mdesl.graphics.glutils.ShaderProgram$Attrib

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.