Android Open Source - ExpertAndroid E S20 Abstract Renderer






From Project

Back to project page ExpertAndroid.

License

The source code is released under:

MIT License

If you think the Android project ExpertAndroid 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

package com.iuriio.demos.expertandroid.ch9openglexperiments;
/*from  w w w  . j  av a2s .c  o  m*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.content.res.AssetManager;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.Matrix;
import android.util.Log;

//filename: ES20AbstractRenderer.java
/*
 * Responsibilities
 * *****************
 * 1. Load vertex and shader programs
 * 2. Provide model transformations
 * 3. provide default vertex/shader programs
 * 4. Provide default frustum and camera settings
 * 
 * Abstract features
 * ******************
 * 1. allow derived shader programs
 * 2. allow derived draw
 * 3. allow derived figures
 * 4. allow derived frustum/viewing volume settings
 * 5. Act as a base class, if needed, for abstracting textures
 */
public abstract class ES20AbstractRenderer implements Renderer
{
   public static String TAG = "ES20AbstractRenderer";

   //Class level or global variables are usually 
   //unhealthy. Try to minimize them!!
   
   //The target matrix that holds the end result
   //of all model transformations
   private float[] mCurrentModelMatrix = new float[16];

   //A matrix that is a result of setting the camera/eye
   private float[] mVMatrix = new float[16];
   
   //A matrix that is the result of setting the frustum
   private float[] mProjMatrix = new float[16];
   
   //A matrix that is a multiple of current model, view, 
   //and projection matrices.
   private float[] mMVPMatrix = new float[16];

   //GLSL program object with both the shaders compiled, 
   //linked, and attached.
   private int mProgram;
   
   //A handle for the uniform variable identifying the MVP matrix
   private int muMVPMatrixHandle;
   
   //An attribute handle in the vertex shader
   //for passing the vertex arrays.
   private int maPositionHandle;
   
   //Name of the default vertex shader 
   //source code file in the asset directory.
   private static final String DEF_VERTEX_SHADER_FILENAME 
       = "def_vertex_shader.txt";
   
   //Name of the default fragment shader 
   //source code file in the asset directory.
   private static final String DEF_FRAGMENT_SHADER_FILENAME 
       = "def_fragment_shader.txt";
   
   /*
    * This class relies on virtual methods to specialize.
    * Doesn't use construction arguments for specialization. 
    */
   public ES20AbstractRenderer()
   {
     initializeMatrices();
   }
   
   public void initializeMatrices()
   {
    //Set the model matrix to identity
      //Subsequent scaling, rotation, etc will update this
      //in a stateful manner. So starting state matters.
    Matrix.setIdentityM(this.mCurrentModelMatrix, 0);
    
    //Although we use this matrix only once, 
    //it is good to start with a known state.
    Matrix.setIdentityM(mMVPMatrix, 0);
   }
   
   //@Override the interface method of Renderer
   //JDK 1.5 doesn't allow this override tag on ab
   public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) 
   {
        prepareSurface(gl,eglConfig);
   }
   /**
    * 1. Create the GLSL program object by passing vertex
    * and shader code. Derived classes can supply their own shader programs. 
    * 2. Get vertex position hanndle
    * 3. get the uniform mvp matrix handle
    */
   public void prepareSurface(GL10 gl, EGLConfig eglConfig) 
   {
     Log.d(TAG,"preparing surface");
       mProgram = createProgram(
           this.getVertexShaderCodeString(), 
           this.getFragmentShaderCodeString());
       if (mProgram == 0) {
           return;
       }
     Log.d(TAG,"Getting position handle:aPosition");
       //maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
       maPositionHandle = getAttributeHandle("aPosition", "Getting Position Handle");
       
     Log.d(TAG,"Getting matrix handle:uMVPMatrix");
       //muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
       muMVPMatrixHandle = getUniformHandle("uMVPMatrix", "Getting MVP uniform matrix handle");
   }
   
    //Override this method to specify your 
    //your own frustum or the dimensions of a viewing volume.
    protected FrustumDimensions getFrustumDimensions()
    {
      //Get default dimensions in this base class
      return FrustumDimensions.getDefault();
    }
    
    //@Override the interface method of Renderer
    //JDK 1.5 doesn't allow this override tag on absolute methods
    //Based on width and height of the window set the 
    //viewport and the frustum.
    public void onSurfaceChanged(GL10 gl, int w, int h) 
    {
      Log.d(TAG,"surface changed. Setting matrix frustum: projection matrix");
      GLES20.glViewport(0, 0, w, h);
        float ratio = (float) w / h;
        FrustumDimensions fd = this.getFrustumDimensions();
      //Matrix.setIdentityM(mProjMatrix, 0);
        Matrix.frustumM(mProjMatrix, 0, ratio * fd.bottom, ratio * fd.top, 
            fd.bottom, fd.top, fd.near, fd.far);
    }
    
    //@Override the interface method of Renderer
    //JDK 1.5 doesn't allow this override tag on absolute methods
    //1. Set your camera. You can place this method while creating
    //the surface or changing the surface. Or you can choose to
    //vary it during the draw method.
    //2. Do basic drawing methods like clear the pallet
    //3. Use the shader program that is setup before
    public void onDrawFrame(GL10 gl) 
    {
         Log.d(TAG,"set look at matrix: view matrix");
      //Matrix.setIdentityM(mVMatrix, 0);
      Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
      
        Log.d(TAG,"base drawframe");
        GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
        GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
        
        GLES20.glUseProgram(mProgram);
        checkGlError("glUseProgram");
        
        //Allow a derived class to setup drawing
        //for further down the chain.
        //the default doesn't do anything.
        preDraw(gl,this.maPositionHandle);
        
        //Real abstract method
        draw(gl,this.maPositionHandle);
    }
    
    
    /*
     * 1. Load vertex shader
     * 2. load fragment shader
     * 3. create program
     * 4. attach shaders
     * 5. link program and return it
     * 6. returns 0 if the program cannot be created
     */
    private int createProgram(String vertexSource, String fragmentSource) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {
            return 0;
        }
         Log.d(TAG,"vertex shader created");
        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (pixelShader == 0) {
            return 0;
        }
        Log.d(TAG,"fragment shader created");
        int program = GLES20.glCreateProgram();
        if (program == 0) {
          checkGlError("Error Creating the program");
          return 0;
        }
       Log.d(TAG,"program created");
        GLES20.glAttachShader(program, vertexShader);
        checkGlError("glAttachShader");
        
        GLES20.glAttachShader(program, pixelShader);
        checkGlError("glAttachShader");
        
        GLES20.glLinkProgram(program);
        int[] linkStatus = new int[1];
        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
        
        if (linkStatus[0] == GLES20.GL_TRUE) {
          Log.d(TAG,"Program successfuly linked");
          return program;
        }
        Log.e(TAG, "Could not link program: ");
        Log.e(TAG, GLES20.glGetProgramInfoLog(program));
        GLES20.glDeleteProgram(program);
        return 0;
    }
    /*
     * Load a given type of shader and check for any errors
     */
    private int loadShader(int shaderType, String source) {
        int shader = GLES20.glCreateShader(shaderType);
        if (shader == 0){
          checkGlError("Cannot create shader:" 
              + getShaderTypeAsString(shaderType));
          return 0;
        }
        //Associaate shader id to source
        GLES20.glShaderSource(shader, source);
        //Compile source
        GLES20.glCompileShader(shader);
        //Check if there is an error
        int[] compiled = new int[1];
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
        //Return if there is no error
        if (compiled[0] == GLES20.GL_TRUE) {
          Log.d(TAG, getShaderTypeAsString(shaderType) 
              + " successfully compiled");
          return shader;
        }
        
        //report error if there is one and return 0
        Log.e(TAG, "Could not compile shader " 
            + getShaderTypeAsString(shaderType));
        Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
        GLES20.glDeleteShader(shader);
        return 0;
    }
    public String getShaderTypeAsString(int shaderType)
    {
      if (shaderType == GLES20.GL_VERTEX_SHADER){
        return "Vertex Shader";
      }
      else if (shaderType == GLES20.GL_FRAGMENT_SHADER){
        return "Fragment Shader";
      }
      else { return new String("Unknown Shader Type Value");}
    }
    //Use this method to check and log GL errors 
    protected void checkGlError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(TAG, op + ": glError " + error);
            throw new RuntimeException(op + ": glError " + error);
        }
    }

    /*
     * The following three methods update the mCurrentModelMatrix
     * with the given model transformation.
     * These are stateful accumulative methods.
     */
    public void trnslate(float x, float y, float z)
    {
      float[] tempModelMatrix = new float[16];      
      Matrix.setIdentityM(tempModelMatrix, 0);
      Matrix.translateM(tempModelMatrix,0,x,y,z);
        Matrix.multiplyMM(this.mCurrentModelMatrix, 0, 
            tempModelMatrix, 0, this.mCurrentModelMatrix, 0);
    }
    public void rotate(float angle, float x, float y, float z)
    {
      float[] tempModelMatrix = new float[16];      
      Matrix.setIdentityM(tempModelMatrix, 0);
      Matrix.rotateM(tempModelMatrix,0,angle,x,y,z);
        Matrix.multiplyMM(this.mCurrentModelMatrix, 0, 
            tempModelMatrix, 0, this.mCurrentModelMatrix, 0);
    }
    public void scale(float xFactor, float yFactor, float zFactor)
    {
      float[] tempModelMatrix = new float[16];      
      Matrix.setIdentityM(tempModelMatrix, 0);
      Matrix.scaleM(tempModelMatrix,0,xFactor,yFactor,zFactor);
        Matrix.multiplyMM(this.mCurrentModelMatrix, 0, 
            tempModelMatrix, 0, this.mCurrentModelMatrix, 0);
    }
    
    /*
     * Calculaute the final model view matrix
     * 1. Order of matrix multiplication is important
     * 2. MVPmatrix = proj * view * model;
     * 3. Setup the MVP matrix in the vertex shader memory
     */
    protected void setupMatrices()
    {
      float[] tempModelMatrix = new float[16];
      Matrix.setIdentityM(tempModelMatrix, 0);
      
        //translate the model combo next
        Matrix.multiplyMM(mMVPMatrix, 0, //matrix and offset 
            mCurrentModelMatrix, 0, 
            tempModelMatrix, 0);
      
      //translate eye coordinates first
        Matrix.multiplyMM(mMVPMatrix, 0, 
            this.mVMatrix, 0, 
            mMVPMatrix, 0);
        
        //Project it: screen coordinates
        Matrix.multiplyMM(mMVPMatrix, 0, 
            mProjMatrix, 0, 
            mMVPMatrix, 0);
        
        //Set the vertex uniform handler representing the MVP matrix
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, //uniform handle 
            1, //number of uniforms. 1 if it is not an array
            false, //transpose: must be false
            mMVPMatrix, //client matrix memory pointer
            0); //offset
    }
    
    //Override this method to continue the onDrawframe callback
    //from the renderer.
    protected abstract void draw(GL10 gl, int positionHandle);
    
    //Override this to implement preDraw
    //useful for derived classes to specialize pre-draws
    protected void preDraw(GL10 gl, int positionHandle)
    {
      //none for this class
    }

    //Use this method if your intent is to return
    //a default vertex shader.
    public String getDefaultVertexShaderCodeString()
    {
      return this.getStringFromAssetFile(DEF_VERTEX_SHADER_FILENAME);
    }
    
    //Use this method if your intent is to return
    //a default fragment shader.
    public String getDefaultFragmentShaderCodeString()
    {
      return this.getStringFromAssetFile(DEF_FRAGMENT_SHADER_FILENAME);
    }
    
    //Override this method if you want to provide
    //a different vertex shader program.
    protected String getVertexShaderCodeString()
    {
        String vertexShader =
            "uniform mat4 uMVPMatrix;\n" +
            "attribute vec4 aPosition;\n" +
            "void main() {\n" +
            "  gl_Position = uMVPMatrix * aPosition;\n" +
            "}\n";
        return vertexShader;
    }
    
    //Override this method if you want to provide
    //a different vertex shader program.
    //In a derived method call getStringFromAssetFile(filename)
    //to read as string to be returned from here.
    protected String getFragmentShaderCodeString()
    {
        String fragmentShader =
            "void main() {\n" +
            "  gl_FragColor = vec4(0.5, 0.25, 0.5, 1.0);\n" +
            "}\n";
        return fragmentShader;
    }
    
    //How to to read a text file from an asset
    //directory. In this approach you will need to 
    //create your application object and provide a static
    //variable to create the context.
    //See MyApplication implementation to see how this works.
    //Or see http://androidbook.com/item/4224
    public String getStringFromAssetFile(String filename)
    {
      Context ctx = MyApplication.m_appContext; 
      if ( ctx == null)
      {
        throw new RuntimeException("Sorry your app context is null");
      }
      try
      {
      AssetManager am = ctx.getAssets();
      InputStream is = am.open(filename);
      String s = convertStreamToString(is);
      is.close();
      return s;
      }
      catch (IOException x)
      {
        throw new RuntimeException("Sorry not able to read filename:" + filename,x);
      }
    }
    
    //Converting a file stream to a string
    //Optimize as you see fit. This may not be an efficient read
    private String convertStreamToString(InputStream is)
    throws IOException
    {   
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      int i = is.read();
      while (i != -1)
      {
        baos.write(i);
        i = is.read();
      }
      return baos.toString();
    }
    
    //Use this if you need to use a program object
    //directly. Make sure you call this after the 
    //surface is created and prepared in this base class.
    //otherwise it will be null.
    public int getGLSProgramObjectReference() 
    {
      return this.mProgram;
    }
    //Use this method to get a handle to any 
    //named attribute. It is a utility method.
    //It uses the program object that is in effect.
    //Ensure program object is valid before calling this.
    public int getAttributeHandle(String GLSLAttributeName, String comment)
    {
       String logComment = comment + ":" + GLSLAttributeName;
      Log.d(TAG,comment);
       int attributeHandle = 
         GLES20.glGetAttribLocation(mProgram, GLSLAttributeName);
        checkGlError(logComment);
        if (attributeHandle == -1) {
            throw new RuntimeException(logComment);
        }
      return attributeHandle;
    }
    public int getUniformHandle(String GLSLUniformName, String comment)
    {
       String logComment = comment + ":" + GLSLUniformName;
      Log.d(TAG,comment);
       int uniformHandle = 
         GLES20.glGetUniformLocation(mProgram, GLSLUniformName);
        checkGlError(logComment);
        if (uniformHandle == -1) {
            throw new RuntimeException(logComment);
        }
      return uniformHandle;
    }
}




Java Source Code List

com.androidbook.notebad.NoteEditor.java
com.androidbook.notebad.NotePadProvider.java
com.androidbook.notebad.NotePad.java
com.androidbook.notebad.NotesList.java
com.androidbook.notebad.TitleEditor.java
com.androidbook.parse.BaseActivity.java
com.androidbook.parse.BaseListActivity.java
com.androidbook.parse.CreateAMeaningActivity.java
com.androidbook.parse.CreateAWordActivity.java
com.androidbook.parse.Field.java
com.androidbook.parse.FormActivity.java
com.androidbook.parse.IReportBack.java
com.androidbook.parse.IValidator.java
com.androidbook.parse.IValueValidator.java
com.androidbook.parse.LoginActivity.java
com.androidbook.parse.ParseApplication.java
com.androidbook.parse.ParseObjectWrapperOld1.java
com.androidbook.parse.ParseObjectWrapper.java
com.androidbook.parse.ParseStarterProjectActivity.java
com.androidbook.parse.PasswordFieldRule.java
com.androidbook.parse.PasswordResetActivity.java
com.androidbook.parse.PasswordResetSuccessActivity.java
com.androidbook.parse.SignupActivity.java
com.androidbook.parse.SignupSuccessActivity.java
com.androidbook.parse.StringUtils.java
com.androidbook.parse.UserListActivity.java
com.androidbook.parse.WelcomeActivity.java
com.androidbook.parse.WordListActivity.java
com.androidbook.parse.WordListAdapter.java
com.androidbook.parse.WordMeaningListAdapter.java
com.androidbook.parse.WordMeaning.java
com.androidbook.parse.WordMeaningsListActivity.java
com.androidbook.parse.Word.java
com.iuriio.demos.expertandroid.ch10search.MainActivity.java
com.iuriio.demos.expertandroid.ch10search.SearchActivity.java
com.iuriio.demos.expertandroid.ch11searchprovider.MainActivity.java
com.iuriio.demos.expertandroid.ch11searchprovider.SearchActivity.java
com.iuriio.demos.expertandroid.ch11searchprovider.SimpleSuggestionProvider.java
com.iuriio.demos.expertandroid.ch11searchprovider.SuggestUrlProvider.java
com.iuriio.demos.expertandroid.ch13parsesimple.BaseActivity.java
com.iuriio.demos.expertandroid.ch13parsesimple.LoginActivity.java
com.iuriio.demos.expertandroid.ch13parsesimple.MainActivity.java
com.iuriio.demos.expertandroid.ch13parsesimple.ParseApp.java
com.iuriio.demos.expertandroid.ch13parsesimple.ParseObjectWrapper.java
com.iuriio.demos.expertandroid.ch13parsesimple.ParseStarterProjectActivity.java
com.iuriio.demos.expertandroid.ch13parsesimple.PasswordResetSuccessActivity.java
com.iuriio.demos.expertandroid.ch13parsesimple.ResetPasswordActivity.java
com.iuriio.demos.expertandroid.ch13parsesimple.SignupActivity.java
com.iuriio.demos.expertandroid.ch13parsesimple.StringUtils.java
com.iuriio.demos.expertandroid.ch13parsesimple.WordListActivity.java
com.iuriio.demos.expertandroid.ch13parsesimple.Word.java
com.iuriio.demos.expertandroid.ch1circleview.AbstractBaseView.java
com.iuriio.demos.expertandroid.ch1circleview.CircleView.java
com.iuriio.demos.expertandroid.ch1circleview.MainActivity.java
com.iuriio.demos.expertandroid.ch2durationcontrol.DatePickerFragment.java
com.iuriio.demos.expertandroid.ch2durationcontrol.DurationControl.java
com.iuriio.demos.expertandroid.ch2durationcontrol.MainActivity.java
com.iuriio.demos.expertandroid.ch3flowlayout.FlowLayout.java
com.iuriio.demos.expertandroid.ch3flowlayout.MainActivity.java
com.iuriio.demos.expertandroid.ch4gsonserialization.ChildObject.java
com.iuriio.demos.expertandroid.ch4gsonserialization.MainActivity.java
com.iuriio.demos.expertandroid.ch4gsonserialization.MainObject.java
com.iuriio.demos.expertandroid.ch6forms.BaseActivity.java
com.iuriio.demos.expertandroid.ch6forms.Field.java
com.iuriio.demos.expertandroid.ch6forms.FormActivity.java
com.iuriio.demos.expertandroid.ch6forms.IValidator.java
com.iuriio.demos.expertandroid.ch6forms.IValueValidator.java
com.iuriio.demos.expertandroid.ch6forms.MainActivity.java
com.iuriio.demos.expertandroid.ch6forms.PasswordFieldRule.java
com.iuriio.demos.expertandroid.ch6forms.StringUtils.java
com.iuriio.demos.expertandroid.ch6forms.WelcomeActivity.java
com.iuriio.demos.expertandroid.ch9openglexperiments.AbstractRenderer.java
com.iuriio.demos.expertandroid.ch9openglexperiments.AnimatedSimpleTriangleRenderer.java
com.iuriio.demos.expertandroid.ch9openglexperiments.ES20AbstractRenderer.java
com.iuriio.demos.expertandroid.ch9openglexperiments.ES20ControlledAnimatedTexturedCubeRenderer.java
com.iuriio.demos.expertandroid.ch9openglexperiments.ES20SimpleTriangleRenderer.java
com.iuriio.demos.expertandroid.ch9openglexperiments.ES20SingleTextureAbstractRenderer.java
com.iuriio.demos.expertandroid.ch9openglexperiments.FrustumDimensions.java
com.iuriio.demos.expertandroid.ch9openglexperiments.MainActivity.java
com.iuriio.demos.expertandroid.ch9openglexperiments.MyApplication.java
com.iuriio.demos.expertandroid.ch9openglexperiments.OpenGLES10Activity.java
com.iuriio.demos.expertandroid.ch9openglexperiments.OpenGLES20Activity.java
com.iuriio.demos.expertandroid.ch9openglexperiments.PolygonRenderer.java
com.iuriio.demos.expertandroid.ch9openglexperiments.RegularPolygon.java
com.iuriio.demos.expertandroid.ch9openglexperiments.Shape.java
com.iuriio.demos.expertandroid.ch9openglexperiments.SimpleTriangleRenderer.java
converters.FieldTransporter.java
converters.IFieldTransport.java
converters.IntegerFieldTransport.java
converters.ParseObjectEssentials.java
converters.StringFieldTransport.java
converters.User.java
converters.ValueField.java