Android Open Source - Schooner-3D Material






From Project

Back to project page Schooner-3D.

License

The source code is released under:

Apache License

If you think the Android project Schooner-3D 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 2012 Dan Mercer/*w  ww .jav a 2  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.supermercerbros.gameengine.engine.shaders;

import java.nio.ByteOrder;

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

import com.supermercerbros.gameengine.objects.GameObject;
import com.supermercerbros.gameengine.objects.Metadata;
import com.supermercerbros.gameengine.shaders.ProgramSource;
import com.supermercerbros.gameengine.util.GLES2;

/**
 * Superclass for materials to be used when rendering 3D objects.
 */
public abstract class Material {
  private static final boolean NATIVE_ORDER_IS_BIG_ENDIAN = ByteOrder
      .nativeOrder() == ByteOrder.BIG_ENDIAN;
  
  public static final String VAR_A_POS = "attribute vec3 a_pos; \n";
  public static final String VAR_A_NORMAL = "attribute vec3 a_normal; \n";
  public static final String VAR_U_VIEWPROJ = "uniform mat4 u_viewProj;\n";
  public static final String VAR_U_MODEL = "uniform mat4 u_model;\n";
  
  public static final String VARS_U_LIGHT = "uniform vec3 u_lightVec;\n"
      + "uniform vec3 u_lightColor;\n";
  
  /**
   * Contains the OpenGL shader program used by this Material.
   */
  protected Program program;
  
  /**
   * Contains the handle to the <code>a_pos</code> attribute in the shader,
   * the attribute used to store vertex position. This handle is initialized
   * during {@link #attachAttribs(Metadata, int, float[])}.
   */
  protected int a_pos = -2;
  /**
   * Contains the handle to the <code>a_normal</code> attribute in the shader,
   * the attribute used to store vertex normals. This handle is initialized
   * during {@link #attachAttribs(Metadata, int, float[])}.
   */
  protected int a_normal;
  /**
   * Contains the handle to the <code>a_mtl</code> attribute in the shader,
   * the attribute used to store vertex-specific material data, such as colors
   * or uv-coordinates. This handle is initialized during
   * {@link #attachAttribs(Metadata, int, float[])}.
   */
  protected int a_mtl;
  
  /**
   * Contains the handle to the <code>u_model</code> uniform in the shader,
   * the uniform used to store the object-specific tranformation matrix. This
   * handle is initialized during
   * {@link #attachAttribs(Metadata, int, float[])}.
   */
  private int u_model;
  /**
   * Contains the handle to the <code>u_matrices</code> uniform in the shader,
   * which is the uniform used to store extra matrices for the object. This
   * handle is initialized during
   * {@link #attachAttribs(Metadata, int, float[])}.
   */
  private int u_matrices;
  
  /**
   * The loading offset for the VBO.
   */
  private int inPos = 0;
  /**
   * The unloading offset for the VBO.
   */
  private int outPos = 0;
  
  /**
   * The stride of this Material
   */
  private int stride;
  private int byteStride;
  
  private VertexModifier modifier;
  
  public void setVertexModifier(VertexModifier mod) {
    if (program != null) {
      throw new IllegalStateException("Program has already been set.");
    }
    modifier = mod;
  }
  
  protected void setProgram(ProgramSource source, int stride) {
    if (program != null) {
      throw new IllegalStateException("Program has already been set.");
    }
    
    final String vertex;
    final String fragment;
    if (modifier != null) {
      StringBuilder vertSB = new StringBuilder(source.vertPrecision);
      
      // variables
      vertSB.append(source.vertVars);
      modifier.getVars(vertSB);
      vertSB.append(source.varyings);
      
      // methods
      vertSB.append(source.vertMethods);
      modifier.getMethods(vertSB);
      
      vertSB.append(ProgramSource.MAIN_HEADER);
      modifier.getCode(vertSB);
      vertSB.append(source.vertMain.replaceAll("\\ba_pos\\b", "mod_pos")
          .replaceAll("\\ba_normal\\b", "mod_normal"));
      vertSB.append(ProgramSource.MAIN_FOOTER);
      vertex = vertSB.toString();
      
      //@formatter:off
      fragment =
          source.fragPrecision +
          source.fragVars +
          source.varyings +
          source.fragMethods +
          ProgramSource.MAIN_HEADER +
          source.fragMain +
          ProgramSource.MAIN_FOOTER;
      //@formatter:on
      this.stride = stride + modifier.getStride();
    } else {
      //@formatter:off
      vertex =
          source.vertPrecision +
          source.vertVars +
          source.varyings +
          ProgramSource.MAIN_HEADER +
          source.vertMain +
          ProgramSource.MAIN_FOOTER +
          source.vertMethods;
      
      fragment = 
          source.fragPrecision +
          source.fragVars +
          source.varyings +
          ProgramSource.MAIN_HEADER +
          source.fragMain +
          ProgramSource.MAIN_FOOTER +
          source.fragMethods;
      //@formatter:on
      this.stride = stride;
    }
    
    this.byteStride = this.stride * 4;
    
//    Log.d("Vertex Shader", vertex);
//    Log.d("Fragment Shader", fragment);
    this.program = ShaderLib.newProgram(vertex, fragment);
  }
  
  /**
   * Called by the renderer to attach the vertex attributes.
   * 
   * @param primitive
   *            The Metadata about the primitive to load
   * @param vboOffset
   *            The offset into the VBO where the vertex data is stored
   * @param matrices
   *            A float array containing the matrices for this primitve,
   *            starting with the model matrix.
   */
  public void attachAttribs(Metadata primitive, int vboOffset,
      float[] matrices) {
    if (a_pos == -2) {
      a_pos = program.getAttribLocation(ShaderLib.A_POS);
      a_normal = program.getAttribLocation(ShaderLib.A_NORMAL);
      a_mtl = program.getAttribLocation(ShaderLib.A_MTL);
      u_model = program.getUniformLocation(ShaderLib.U_MODEL);
      u_matrices = program.getUniformLocation(ShaderLib.U_MATRICES);
    }
    
    if (u_model != -1) {
      GLES20.glUniformMatrix4fv(u_model, 1, false, matrices, 0);
    }
    
    if (u_matrices != -1 && matrices.length != 16) {
      GLES20.glUniformMatrix4fv(u_matrices, (matrices.length - 16) / 16,
          false, matrices, 16);
    }
    
    outPos = vboOffset;
    
    onAttachAttribs();
    if (modifier != null) {
      modifier.onAttachAttribs(this, program);
    }
  }
  
  /**
   * @return The OpenGL geometry type. Usually {@link GLES20#GL_TRIANGLES}.
   *         Override this to use a different geometry type.
   */
  public int getGeometryType() {
    return GLES20.GL_TRIANGLES;
  }
  
  /**
   * @return The number of floats per vertex
   */
  public int getStride() {
    return stride;
  }
  
  /**
   * Called by the Engine thread to load a GameObject's data to the VBO array.
   * 
   * @param obj
   *            The GameObject to load
   * @param vbo
   *            The vertex buffer array
   * @param offset
   *            The offset into vbo to load the data at
   * @return The size of the object's data in the vbo (
   *         <code>obj.info.count * stride</code>)
   */
  public int loadObjectToVBO(GameObject obj, float[] vbo, int offset) {
    inPos = offset;
    final int vertCount = obj.info.count;
    onLoadObject(obj, vbo, vertCount);
    if (modifier != null) {
      modifier.onLoadObject(this, obj, vbo);
    }
    return vertCount * stride;
  }
  
  protected abstract void onLoadObject(GameObject obj, float[] vbo,
      int vertCount);
  
  /**
   * Called by {@link #attachAttribs(Metadata, int, float[])} to set
   * material-specific attributes. The <code>u_model</code> and
   * <code>a_matrices</code> attributes have already been set.
   */
  protected abstract void onAttachAttribs();
  
  /**
   * Called after a VertexModifier has been set if necessary. Subclasses
   * should call {@link #setProgram(ProgramSource, int)} in their
   * implementation of this method.
   */
  public abstract void makeProgram();
  
  /**
   * @param data
   *            The array of vertex data to load (such as obj.verts)
   * @param vbo
   *            The vertex buffer array to load to
   * @param size
   *            The number of values for each vertex
   * @param count
   *            The number of vertices represented
   */
  public void loadArrayToVbo(float[] data, float[] vbo, int size, int count) {
    for (int i = 0; i < count; i++) {
      System.arraycopy(data, i * size, vbo, inPos + i * stride, size);
    }
    inPos += size;
  }
  
  /**
   * Loads byte vertex attribute data to the VBO array.
   * 
   * @param data
   *            The data to load
   * @param vbo
   *            The VBO array to load to
   * @param size
   *            The number of bytes per vertex
   * @param count
   *            The number of vertices represented
   */
  public void loadArrayToVbo(byte[] data, float[] vbo, int size, int count) {
    
    // The number of ints per vertex (can only put ints or floats into vbo)
    final int intSize = (size + 3) / 4;
    
    for (int i = 0; i < count; i++) { // for each vertex
      // Convert bytes to ints
      for (int intCount = 0; intCount < intSize; intCount++) { // for each int in the attribute
        final int intIndex = inPos + i * stride + intCount;
        int byteIndex = i * size + (intCount * 4);
        
        // Convert 4 bytes to int
        int value = 0;
        if (NATIVE_ORDER_IS_BIG_ENDIAN) {
          for (int counter = size - 1; counter >= 0; counter--) {
            value |= data[byteIndex++] << (8 * counter);
            // First byte is most significant
          }
        } else {
          for (int counter = 0; counter < size; counter++) {
            value |= data[byteIndex++] << (8 * counter);
            // First byte is least significant
          }
        }
        vbo[intIndex] = Float.intBitsToFloat(value);
      }
    }
    inPos += intSize;
  }
  
  /**
   * Attaches the given float attribute to the GPU.
   * 
   * @param attrib
   *            The index of the attribute to attach.
   * @param size
   *            The size of the attribute.
   */
  public void attachAttrib(int attrib, int size) {
    GLES2.glEnableVertexAttribArray(attrib);
    GLES2.glVertexAttribPointer(attrib, size, GLES20.GL_FLOAT, false,
        byteStride, outPos);
    outPos += size * 4;
  }
  
  /**
   * Attaches the given attribute to the GPU.
   * 
   * @param attrib
   *            The index of the attribute to attach.
   * @param size
   *            The number of elements in the attribute.
   * @param glType
   *            the GL_ enum describing the data type
   */
  public void attachAttrib(int attrib, int size, int glType) {
    GLES2.glEnableVertexAttribArray(attrib);
    GLES2.glVertexAttribPointer(attrib, size, glType, false, byteStride,
        outPos);
    if (glType == GLES20.GL_BYTE || glType == GLES20.GL_UNSIGNED_BYTE) {
      size = (size + 3) / 4;
    } else if (glType == GLES20.GL_SHORT
        || glType == GLES20.GL_UNSIGNED_SHORT) {
      size = (size + 1) / 2;
    }
    outPos += size * 4;
  }
  
  /**
   * Attaches a generic (constant) vertex attribute.
   * 
   * @param attrib
   *            The index of the attribute.
   * @param value
   *            The value(s) of the attribute. Must be 1 to 4 values.
   */
  public void attachAttrib(int attrib, float... value) {
    if (attrib < 0) {
      return;
    }
    if (value.length == 0) {
      throw new IllegalArgumentException("No value supplied.");
    }
    if (value.length > 4) {
      throw new IllegalArgumentException(
          "Cannot attach more than 4 values.");
    }
    
    GLES2.glDisableVertexAttribArray(attrib);
    switch (value.length) {
    case 1:
      GLES2.glVertexAttrib1fv(attrib, value, 0);
      break;
    case 2:
      GLES2.glVertexAttrib2fv(attrib, value, 0);
      break;
    case 3:
      GLES2.glVertexAttrib3fv(attrib, value, 0);
      break;
    case 4:
      GLES2.glVertexAttrib4fv(attrib, value, 0);
      break;
    default:
    }
  }
  
  protected void setUniform(int location, float... args) {
    if (args.length == 1) {
      GLES2.glUniform1fv(location, 1, args, 0);
    } else if (args.length == 2) {
      GLES2.glUniform2fv(location, 1, args, 0);
    } else if (args.length == 3) {
      GLES2.glUniform3fv(location, 1, args, 0);
    } else if (args.length == 4) {
      GLES2.glUniform4fv(location, 1, args, 0);
    } else {
      throw new UnsupportedOperationException(
          "args must have 1 to 4 elements.");
    }
  }
  
  protected void setUniform(String name, float... args) {
    setUniform(program.getUniformLocation(name), args);
  }
  
  public Program getProgram() {
    return program;
  }
}




Java Source Code List

com.supermercerbros.gameengine.GameActivity.java
com.supermercerbros.gameengine.GameView.java
com.supermercerbros.gameengine.Schooner3D.java
com.supermercerbros.gameengine.TestActivity.java
com.supermercerbros.gameengine.TestMaterials.java
com.supermercerbros.gameengine.TestObjects.java
com.supermercerbros.gameengine.animation.AnimationData.java
com.supermercerbros.gameengine.animation.Keyframe.java
com.supermercerbros.gameengine.animation.MeshAnimation.java
com.supermercerbros.gameengine.armature.ActionData.java
com.supermercerbros.gameengine.armature.Action.java
com.supermercerbros.gameengine.armature.BinarySkeletalVertexModifier.java
com.supermercerbros.gameengine.armature.Bone.java
com.supermercerbros.gameengine.armature.SkeletalVertexModifier.java
com.supermercerbros.gameengine.armature.Skeleton.java
com.supermercerbros.gameengine.collision.Bounds.java
com.supermercerbros.gameengine.collision.Collider.java
com.supermercerbros.gameengine.collision.CollisionDetector.java
com.supermercerbros.gameengine.collision.Collision.java
com.supermercerbros.gameengine.collision.DebugListener.java
com.supermercerbros.gameengine.collision.Edge.java
com.supermercerbros.gameengine.collision.Face.java
com.supermercerbros.gameengine.collision.Feature.java
com.supermercerbros.gameengine.collision.Intersection.java
com.supermercerbros.gameengine.collision.Line.java
com.supermercerbros.gameengine.collision.LocalDistMinimum.java
com.supermercerbros.gameengine.collision.Matrix.java
com.supermercerbros.gameengine.collision.OnCollisionCheckFinishedListener.java
com.supermercerbros.gameengine.collision.Plane.java
com.supermercerbros.gameengine.collision.Point.java
com.supermercerbros.gameengine.collision.Polyhedron.java
com.supermercerbros.gameengine.collision.SphereBounds.java
com.supermercerbros.gameengine.collision.Vector.java
com.supermercerbros.gameengine.collision.Vertex.java
com.supermercerbros.gameengine.debug.JankCatcher.java
com.supermercerbros.gameengine.debug.LoopLog.java
com.supermercerbros.gameengine.engine.Camera.java
com.supermercerbros.gameengine.engine.DataPipe.java
com.supermercerbros.gameengine.engine.EGLContextLostHandler.java
com.supermercerbros.gameengine.engine.Engine.java
com.supermercerbros.gameengine.engine.GameRenderer.java
com.supermercerbros.gameengine.engine.Light.java
com.supermercerbros.gameengine.engine.Normals.java
com.supermercerbros.gameengine.engine.RenderData.java
com.supermercerbros.gameengine.engine.Scene.java
com.supermercerbros.gameengine.engine.Time.java
com.supermercerbros.gameengine.engine.shaders.Material.java
com.supermercerbros.gameengine.engine.shaders.Program.java
com.supermercerbros.gameengine.engine.shaders.ShaderLib.java
com.supermercerbros.gameengine.engine.shaders.Shader.java
com.supermercerbros.gameengine.engine.shaders.VertexModifier.java
com.supermercerbros.gameengine.handlers.OnAnimationCompleteDispatcher.java
com.supermercerbros.gameengine.handlers.OnAnimationCompleteListener.java
com.supermercerbros.gameengine.hud.CoordsConverter.java
com.supermercerbros.gameengine.hud.GameHud.java
com.supermercerbros.gameengine.hud.HudElement.java
com.supermercerbros.gameengine.material.CelShadedMaterial.java
com.supermercerbros.gameengine.material.TexturedMaterial.java
com.supermercerbros.gameengine.math.BezierCurve.java
com.supermercerbros.gameengine.math.Curve.java
com.supermercerbros.gameengine.math.MatrixUtils.java
com.supermercerbros.gameengine.math.Quaternion.java
com.supermercerbros.gameengine.motion.CurveMovement.java
com.supermercerbros.gameengine.motion.MovementData.java
com.supermercerbros.gameengine.motion.Movement.java
com.supermercerbros.gameengine.objects.AnimatedMeshObject.java
com.supermercerbros.gameengine.objects.BasicMaterial.java
com.supermercerbros.gameengine.objects.BonedObject.java
com.supermercerbros.gameengine.objects.GameObject.java
com.supermercerbros.gameengine.objects.Metadata.java
com.supermercerbros.gameengine.parsers.ConstantCurve.java
com.supermercerbros.gameengine.parsers.GameFactory.java
com.supermercerbros.gameengine.parsers.PreBoneData.java
com.supermercerbros.gameengine.parsers.PreObjectData.java
com.supermercerbros.gameengine.parsers.Sch3D.java
com.supermercerbros.gameengine.render.Compositor.java
com.supermercerbros.gameengine.shaders.ProgramSource.java
com.supermercerbros.gameengine.texture.BitmapTexture.java
com.supermercerbros.gameengine.texture.ETC1CompressedTexture.java
com.supermercerbros.gameengine.texture.Texture.java
com.supermercerbros.gameengine.util.BetterDataInputStream.java
com.supermercerbros.gameengine.util.DelayedRunnable.java
com.supermercerbros.gameengine.util.GLES2.java
com.supermercerbros.gameengine.util.IPO.java
com.supermercerbros.gameengine.util.LoopingThread.java
com.supermercerbros.gameengine.util.Toggle.java
com.supermercerbros.gameengine.util.Utils.java