Android Open Source - droidengine2d Shader Program






From Project

Back to project page droidengine2d.

License

The source code is released under:

Apache License

If you think the Android project droidengine2d listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*   Copyright 2013-2014 Miguel Vicente Linares
 *//www.j  a v a2 s  .  c o  m
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.miviclin.droidengine2d.graphics.shader;

import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.opengl.GLES20;
import android.util.Log;

import com.miviclin.droidengine2d.graphics.GLDebugger;

/**
 * ShaderProgram contains a vertex shader and a fragment shader.
 * 
 * @author Miguel Vicente Linares
 * 
 */
public class ShaderProgram {

  private String vertexShaderSource;
  private String fragmentShaderSource;
  private HashMap<String, Integer> attributesLocations;
  private HashMap<String, Integer> uniformsLocations;
  private int programId;
  private boolean linked;

  /**
   * Creates a ShaderProgram.
   */
  public ShaderProgram() {
    this.vertexShaderSource = "";
    this.fragmentShaderSource = "";
    this.attributesLocations = new HashMap<String, Integer>();
    this.uniformsLocations = new HashMap<String, Integer>();
    this.linked = false;
  }

  /**
   * Returns a string containing the GLSL code of the vertex shader.
   * 
   * @return GLSL code of the vertex shader
   */
  public String getVertexShaderSource() {
    return vertexShaderSource;
  }

  /**
   * Returns a string containing the GLSL code of the fragment shader.
   * 
   * @return GLSL code of the fragment shader
   */
  public String getFragmentShaderSource() {
    return fragmentShaderSource;
  }

  /**
   * Returns the location of the specified attribute in the shader.
   * 
   * @param attributeName Name of the attribute.
   * @return Location of the attribute
   */
  public int getAttributeLocation(String attributeName) {
    int attributeLocation = attributesLocations.get(attributeName).intValue();
    if (attributeLocation == -1) {
      throw new IllegalArgumentException("The specified attribute is not linked: " + attributeName);
    }
    return attributeLocation;
  }

  /**
   * Returns the location of the specified uniform in the shader.
   * 
   * @param uniformName Name of the uniform.
   * @return Location of the uniform
   */
  public int getUniformLocation(String uniformName) {
    int uniformLocation = uniformsLocations.get(uniformName).intValue();
    if (uniformLocation == -1) {
      throw new IllegalArgumentException("The specified uniform is not linked: " + uniformName);
    }
    return uniformLocation;
  }

  /**
   * Installs this shader program as part of the current rendering state.
   */
  public void use() {
    GLES20.glUseProgram(programId);
  }

  /**
   * Returns the ID (used by the OpenGL context) of this program.
   * 
   * @return the ID of this program
   */
  public int getProgramId() {
    return programId;
  }

  /**
   * Sets the ID (used by the OpenGL context) of this program.<br>
   * This method should only be called to set the ID generated by OpenGL where the shaders are compiled and the OpenGL
   * program is created.
   * 
   * @param programId ID.
   */
  protected void setProgramId(int programId) {
    this.programId = programId;
  }

  /**
   * Returns true if the attributes of the shaders are linked to the program.
   * 
   * @return true if the attributes of the shaders are linked to the program, false otherwise.
   */
  public boolean isLinked() {
    return linked;
  }

  /**
   * Sets the linked flag to true.<br>
   * This method should be called only when the attributes of the shaders are linked to the program, usually from
   * {@link #compileAndLink()}.
   */
  protected void setLinked() {
    this.linked = true;
  }

  /**
   * Sets the vertex and fragment shaders of this program. This method should be called from {@link #compileAndLink()}
   * .
   * 
   * @param vertexShaderSource GLSL code of the vertex shader.
   * @param fragmentShaderSource GLSL code of the fragment shader.
   * @param attributes List of attributes of the shader program.
   * @param uniforms List of uniforms of the shader program.
   */
  public void setShaders(String vertexShaderSource, String fragmentShaderSource, ArrayList<String> attributes,
      ArrayList<String> uniforms) {

    this.vertexShaderSource = vertexShaderSource;
    this.fragmentShaderSource = fragmentShaderSource;

    for (int i = 0; i < attributes.size(); i++) {
      attributesLocations.put(attributes.get(i), -1);
    }

    for (int i = 0; i < uniforms.size(); i++) {
      uniformsLocations.put(uniforms.get(i), -1);
    }
  }

  /**
   * 1) Compiles the shaders, generating the ID of this program.<br>
   * 2) Sets the ID of this program with setProgram(programId).<br>
   * 3) Links the attributes of the shaders to this program and calls {@link #setLinked()}.
   */
  public void compileAndLink() {
    if (vertexShaderSource.equals("") || fragmentShaderSource.equals("")) {
      throw new ShaderProgramException("The source code of the shaders is not loaded.\n" +
          "Ensure setShaders(...) has been called before trying to compile the shader program.");
    }
    int programId = ShaderProgram.createProgram(vertexShaderSource, fragmentShaderSource);
    if (programId == 0) {
      return;
    }
    setProgramId(programId);
    link(programId);
    setLinked();
  }

  /**
   * Links the attributes of the shaders to this program.<br>
   * This method is called from {@link #compileAndLink()}.
   * 
   * @param programId The ID (used by the OpenGL context) of this program.
   */
  protected void link(int programId) {
    String variableName;
    int location;
    for (Map.Entry<String, Integer> entry : attributesLocations.entrySet()) {
      variableName = entry.getKey();
      location = GLES20.glGetAttribLocation(programId, variableName);
      GLDebugger.getInstance().passiveCheckGLError();
      if (location == -1) {
        throw new RuntimeException("Could not get attribute location for " + variableName);
      }
      entry.setValue(location);
    }
    for (Map.Entry<String, Integer> entry : uniformsLocations.entrySet()) {
      variableName = entry.getKey();
      location = GLES20.glGetUniformLocation(programId, variableName);
      GLDebugger.getInstance().passiveCheckGLError();
      if (location == -1) {
        throw new RuntimeException("Could not get uniform location for " + variableName);
      }
      entry.setValue(location);
    }
  }

  /**
   * Sets the specified attribute's values for each vertex that will be sent to the vertex shader.
   * 
   * @param attributeName Name of the attribute.
   * @param size Number of components of the specified vertex attribute (For example: position (x, y, z) => size=3).
   * @param strideBytes Byte offset between consecutive generic vertex attributes.
   * @param dataBuffer Buffer where vertices are stored.
   * @param dataOffset Offset of the first component of the first attribute with the specified attributeName in the
   *            dataBuffer.
   */
  public void setAttribute(String attributeName, int size, int strideBytes, FloatBuffer dataBuffer, int dataOffset) {
    int attributeLocation = getAttributeLocation(attributeName);

    GLES20.glEnableVertexAttribArray(attributeLocation);
    GLDebugger.getInstance().passiveCheckGLError();

    dataBuffer.position(dataOffset);
    GLES20.glVertexAttribPointer(attributeLocation, size, GLES20.GL_FLOAT, false, strideBytes, dataBuffer);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 1-component uniform of this shader program.
   * 
   * @param uniformName Name of the uniform.
   * @param x Value of the uniform.
   */
  public void setUniform1f(String uniformName, float x) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniform1f(uniformLocation, x);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 1-component uniform array of this shader program.
   * 
   * @param uniformName Name of the uniform.
   * @param count Number of elements of the uniform array.
   * @param data Array where the value of the uniform array is stored.
   * @param dataOffset Offset of the first element of the uniform in the specified array.
   */
  public void setUniform1fv(String uniformName, int count, float[] data, int dataOffset) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniform1fv(uniformLocation, count, data, dataOffset);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 2-component uniform of this shader program.
   * 
   * @param uniformName Name of the uniform.
   * @param x First component of the uniform.
   * @param y Second component of the uniform.
   */
  public void setUniform1f(String uniformName, float x, float y) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniform2f(uniformLocation, x, y);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 2-component uniform of this shader program.
   * 
   * @param uniformName Name of the uniform.
   * @param count Number of elements of the uniform array.
   * @param data Array where the value of the uniform array is stored.
   * @param dataOffset Offset of the first element of the uniform in the specified array.
   */
  public void setUniform2fv(String uniformName, int count, float[] data, int dataOffset) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniform2fv(uniformLocation, count, data, dataOffset);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 3-component uniform of this shader program.
   * 
   * @param uniformName Name of the uniform.
   * @param x First component of the uniform.
   * @param y Second component of the uniform.
   * @param z Third component of the uniform.
   */
  public void setUniform3f(String uniformName, float x, float y, float z) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniform3f(uniformLocation, x, y, z);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 3-component uniform of this shader program.
   * 
   * @param uniformName Name of the uniform.
   * @param count Number of elements of the uniform array.
   * @param data Array where the value of the uniform array is stored.
   * @param dataOffset Offset of the first element of the uniform in the specified array.
   */
  public void setUniform3fv(String uniformName, int count, float[] data, int dataOffset) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniform3fv(uniformLocation, count, data, dataOffset);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 4-component uniform of this shader program.
   * 
   * @param uniformName Name of the uniform.
   * @param x First component of the uniform.
   * @param y Second component of the uniform.
   * @param z Third component of the uniform.
   * @param w Fourth component of the uniform.
   */
  public void setUniform4f(String uniformName, float x, float y, float z, float w) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniform4f(uniformLocation, x, y, z, w);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 4-component uniform of this shader program.
   * 
   * @param uniformName Name of the uniform.
   * @param count Number of elements of the uniform array.
   * @param data Array where the value of the uniform array is stored.
   * @param dataOffset Offset of the first element of the uniform in the specified array.
   */
  public void setUniform4fv(String uniformName, int count, float[] data, int dataOffset) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniform4fv(uniformLocation, count, data, dataOffset);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 2x2 matrix uniform of this shader program.
   * 
   * @param numMatrices Number of matrices in the uniform array.
   * @param data Data of the matrices we want to send, in the same array.
   * @param dataOffset Offset of the first element of the first matrix.
   */
  public void setUniformMatrix2fv(String uniformName, int numMatrices, float[] data, int dataOffset) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniformMatrix2fv(uniformLocation, numMatrices, false, data, dataOffset);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 3x3 matrix uniform of this shader program.
   * 
   * @param numMatrices Number of matrices in the uniform array.
   * @param data Data of the matrices we want to send, in the same array.
   * @param dataOffset Offset of the first element of the first matrix.
   */
  public void setUniformMatrix3fv(String uniformName, int numMatrices, float[] data, int dataOffset) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniformMatrix3fv(uniformLocation, numMatrices, false, data, dataOffset);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Specifies the value of the specified 4x4 matrix uniform of this shader program.
   * 
   * @param numMatrices Number of matrices in the uniform array.
   * @param data Data of the matrices we want to send, in the same array.
   * @param dataOffset Offset of the first element of the first matrix.
   */
  public void setUniformMatrix4fv(String uniformName, int numMatrices, float[] data, int dataOffset) {
    int uniformLocation = getUniformLocation(uniformName);
    GLES20.glUniformMatrix4fv(uniformLocation, numMatrices, false, data, dataOffset);
    GLDebugger.getInstance().passiveCheckGLError();
  }

  /**
   * Creates a GLSL shader program from the specified vertex and fragment shaders.
   * 
   * @param vertexSource GLSL code of the vertex shader.
   * @param fragmentSource GLSL code of the fragment shader.
   * @return the ID of the compiled program generated by OpenGL ES 2.0. Or 0 if an error occurred.
   */
  protected static int createProgram(String vertexSource, String fragmentSource) {
    int vertexShader, fragmentShader, program;

    vertexShader = compileShader(GLES20.GL_VERTEX_SHADER, vertexSource);
    if (vertexShader == 0) {
      return 0;
    }
    fragmentShader = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
    if (fragmentShader == 0) {
      return 0;
    }
    program = GLES20.glCreateProgram();
    if (program != 0) {
      GLES20.glAttachShader(program, vertexShader);
      GLDebugger.getInstance().passiveCheckGLError();
      GLES20.glAttachShader(program, fragmentShader);
      GLDebugger.getInstance().passiveCheckGLError();
      GLES20.glLinkProgram(program);
      int[] linkStatus = new int[1];
      GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
      if (linkStatus[0] != GLES20.GL_TRUE) {
        Log.e(ShaderProgram.class.getSimpleName(), "Could not link program: ");
        Log.e(ShaderProgram.class.getSimpleName(), GLES20.glGetProgramInfoLog(program));
        GLES20.glDeleteProgram(program);
        program = 0;
      }
    }
    return program;
  }

  /**
   * Compiles the shader.
   * 
   * @param shaderType Type of the shader. Use {@link GLES20#GL_VERTEX_SHADER } or {@link GLES20#GL_FRAGMENT_SHADER }.
   * @param source GLSL code of the shader.
   * @return the ID of the compiled shader generated by OpenGL ES 2.0
   */
  private static int compileShader(int shaderType, String source) {
    int shader = GLES20.glCreateShader(shaderType);
    if (shader != 0) {
      GLES20.glShaderSource(shader, source);
      GLES20.glCompileShader(shader);
      int[] compiled = new int[1];
      GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
      if (compiled[0] == 0) {
        Log.e(ShaderProgram.class.getSimpleName(), "Could not compile shader " + shaderType + ":");
        Log.e(ShaderProgram.class.getSimpleName(), GLES20.glGetShaderInfoLog(shader));
        GLES20.glDeleteShader(shader);
        shader = 0;
      }
    }
    return shader;
  }

  @Override
  public String toString() {
    return vertexShaderSource + "\n\n" + fragmentShaderSource;
  }

}




Java Source Code List

com.miviclin.droidengine2d.AbstractGame.java
com.miviclin.droidengine2d.EngineActivity.java
com.miviclin.droidengine2d.EngineLock.java
com.miviclin.droidengine2d.Engine.java
com.miviclin.droidengine2d.GameThread.java
com.miviclin.droidengine2d.Game.java
com.miviclin.droidengine2d.audio.MusicPlayer.java
com.miviclin.droidengine2d.audio.SoundManager.java
com.miviclin.droidengine2d.gamestate.GameStateAdapter.java
com.miviclin.droidengine2d.gamestate.GameStateManager.java
com.miviclin.droidengine2d.gamestate.GameStateNotRegisteredException.java
com.miviclin.droidengine2d.gamestate.GameState.java
com.miviclin.droidengine2d.gamestate.OnGameStateChangeListener.java
com.miviclin.droidengine2d.graphics.Color.java
com.miviclin.droidengine2d.graphics.DefaultRenderer.java
com.miviclin.droidengine2d.graphics.EngineRenderer.java
com.miviclin.droidengine2d.graphics.GLDebugger.java
com.miviclin.droidengine2d.graphics.GLRenderer.java
com.miviclin.droidengine2d.graphics.GLView.java
com.miviclin.droidengine2d.graphics.Graphics.java
com.miviclin.droidengine2d.graphics.animation.AnimationFrame.java
com.miviclin.droidengine2d.graphics.animation.AnimationStateAdapter.java
com.miviclin.droidengine2d.graphics.animation.AnimationStateListener.java
com.miviclin.droidengine2d.graphics.animation.Animation.java
com.miviclin.droidengine2d.graphics.cameras.Camera.java
com.miviclin.droidengine2d.graphics.cameras.OrthographicCamera.java
com.miviclin.droidengine2d.graphics.material.BlendingOptions.java
com.miviclin.droidengine2d.graphics.material.ColorMaterial.java
com.miviclin.droidengine2d.graphics.material.Material.java
com.miviclin.droidengine2d.graphics.material.TextureColorMaterial.java
com.miviclin.droidengine2d.graphics.material.TextureHsvMaterial.java
com.miviclin.droidengine2d.graphics.material.TextureMaterial.java
com.miviclin.droidengine2d.graphics.material.TransparentTextureMaterial.java
com.miviclin.droidengine2d.graphics.material.UnsupportedMaterialException.java
com.miviclin.droidengine2d.graphics.mesh.ColorMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.Geometry.java
com.miviclin.droidengine2d.graphics.mesh.GraphicsBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.RectangleBatchGeometry.java
com.miviclin.droidengine2d.graphics.mesh.RectangleBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.TextureColorMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.TextureHsvMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.TextureMaterialBatchRendererBase.java
com.miviclin.droidengine2d.graphics.mesh.TextureMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.mesh.TransparentTextureMaterialBatchRenderer.java
com.miviclin.droidengine2d.graphics.shader.ShaderProgramException.java
com.miviclin.droidengine2d.graphics.shader.ShaderProgram.java
com.miviclin.droidengine2d.graphics.shader.ShaderVars.java
com.miviclin.droidengine2d.graphics.text.BitmapFont.java
com.miviclin.droidengine2d.graphics.text.FontChar.java
com.miviclin.droidengine2d.graphics.text.Font.java
com.miviclin.droidengine2d.graphics.text.UndefinedCharacterException.java
com.miviclin.droidengine2d.graphics.texture.TextureAtlas.java
com.miviclin.droidengine2d.graphics.texture.TextureManager.java
com.miviclin.droidengine2d.graphics.texture.TexturePackerAtlas.java
com.miviclin.droidengine2d.graphics.texture.TextureRegion.java
com.miviclin.droidengine2d.graphics.texture.Texture.java
com.miviclin.droidengine2d.input.DefaultKeyEventProcessor.java
com.miviclin.droidengine2d.input.GameInputManager.java
com.miviclin.droidengine2d.input.GameStateInputManager.java
com.miviclin.droidengine2d.input.KeyEventInfo.java
com.miviclin.droidengine2d.input.KeyEventProcessor.java
com.miviclin.droidengine2d.input.KeyProcessor.java
com.miviclin.droidengine2d.input.MotionEventProcessor.java
com.miviclin.droidengine2d.input.TouchProcessor.java
com.miviclin.droidengine2d.input.sensor.AccelerometerValuesListener.java
com.miviclin.droidengine2d.input.sensor.Accelerometer.java
com.miviclin.droidengine2d.input.sensor.SensorUtilities.java
com.miviclin.droidengine2d.resources.AssetsLoader.java
com.miviclin.droidengine2d.util.ActivityUtilities.java
com.miviclin.droidengine2d.util.MutexLock.java
com.miviclin.droidengine2d.util.PrimitiveTypeSize.java
com.miviclin.droidengine2d.util.TransformUtilities.java
com.miviclin.droidengine2d.util.Transform.java
com.miviclin.droidengine2d.util.math.Matrix4.java
com.miviclin.droidengine2d.util.math.MatrixFix.java
com.miviclin.droidengine2d.util.math.Vector2.java
com.miviclin.droidengine2d.util.math.Vector3.java
com.miviclin.droidengine2d.util.time.TimeConstants.java
com.miviclin.droidengine2d.util.time.TimeCounter.java