Monday, September 26, 2016

Working with 3D - OpenGl ES

Hi .... Dear All ....  Today I am uploading a superb example of OpenGL ES.
In this example i am drawing a Triangle using OpenGL ES.
What is OpenGL ES???
•       Android provides many tools for creating handy and great looking user interface for the applications.
•       The OpenGL ES APIs, which comes as part of Android, has many helper classes and methods that assist in displaying high-end and animated graphics.
•       Most of the android phones come with a dedicated Graphical Processing Unit (GPU); hence the compositing and rendering can be accelerated using this additional hardware. 

Let us now see how to use OpenGL ES APIs to define and draw shapes.
Steps to use the APIs:
  1. Define shapes that will be rendered on screen – Eg: Triangle, Rectangle.
  2. Create our renderer android.opengl.GLSurfaceView.Renderer to render the shape on Surface View.
  3. Extend the android.opengl.GLSurfaceView to create our own surface on which the shapes will be composed.
  4. Finally create an Activity that will show these Graphic shapes by using above View. 
Lets start with step 1 
     package com.exam.ravi.graphicsex2;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;

/** * A two-dimensional triangle for use as a drawn object in OpenGL ES 2.0. */

public class Triangle {

    private final String shaderCode =
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "}";

    private final String fragShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    private final FloatBuffer vertexBuffer;
    private final int anInt;
    private int mpositionhandle;
    private int mcolorhandle;
    private int mmvpmatrixhandle;

    static final int COORDS_PER_VERTEX = 3;
    static float triangleCoords[] = {
            0.0f,  0.622008459f, 0.0f,   // top    
                -0.5f, -0.311004243f, 0.0f,   // bottom left 
                0.5f, -0.311004243f, 0.0f    // bottom right    };
         private final int vertexcount = triangleCoords.length / COORDS_PER_VERTEX;
    private final int vertexstride = COORDS_PER_VERTEX * 4;  // 4 bytes per vertex
    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f };
    public Triangle() {
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(
                triangleCoords.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());

        vertexBuffer = byteBuffer.asFloatBuffer();
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);

        int vertexShader = MyRenderer.loadShader(
                GLES20.GL_VERTEX_SHADER, shaderCode);
        int fragmentShader = MyRenderer.loadShader(
                GLES20.GL_FRAGMENT_SHADER, fragShaderCode);

        anInt = GLES20.glCreateProgram();          
        GLES20.glAttachShader(anInt, vertexShader);   
        GLES20.glAttachShader(anInt, fragmentShader); 
        GLES20.glLinkProgram(anInt);                  

    }

    /**     * Encapsulates the OpenGL ES instructions for drawing this shape.     *   
               * @param mvpMatrix - The Model View Project matrix in which to draw   
                 * this shape.     */    public void draw(float[] mvpMatrix) {
     
        GLES20.glUseProgram(anInt);
        mpositionhandle = GLES20.glGetAttribLocation(anInt, "vPosition");
        GLES20.glEnableVertexAttribArray(mpositionhandle);
        GLES20.glVertexAttribPointer(
                mpositionhandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexstride, vertexBuffer);

        mcolorhandle = GLES20.glGetUniformLocation(anInt, "vColor");

        GLES20.glUniform4fv(mcolorhandle, 1, color, 0);

        mmvpmatrixhandle = GLES20.glGetUniformLocation(anInt, "uMVPMatrix");
        MyRenderer.checkGlError("glGetUniformLocation");
        GLES20.glUniformMatrix4fv(mmvpmatrixhandle, 1, false, mvpMatrix, 0);
        MyRenderer.checkGlError("glUniformMatrix4fv");

        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexcount);

        GLES20.glDisableVertexAttribArray(mpositionhandle);
    }

}

Step II 
     package com.exam.ravi.graphicsex2;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

public class MyRenderer implements GLSurfaceView.Renderer {

    private static final String TAG = "MyRenderer";
    private Triangle mTriangle;
    private final float[] mMVPMatrix = new float[16];
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];
    private final float[] mRotationMatrix = new float[16];

    private float mAngle;

    @Override   
           public void onSurfaceCreated(GL10 unused, EGLConfig config) {

        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        mTriangle = new Triangle();
    }

    @Override   
             public void onDrawFrame(GL10 unused) {
        float[] scratch = new float[16];
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);


        Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, 1.0f);

        Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

        mTriangle.draw(scratch);
    }

    @Override    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);

        float ratio = (float) width / height;

        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);

    }

    /**     * Utility method for compiling a OpenGL shader.    
          *     * <p><strong>Note:</strong> When developing shaders, use the checkGlError()  
                * method to debug shader coding errors.</p>
     *     * @param type - Vertex or fragment shader type.    
                 * @param shaderCode - String containing the shader code.   
               * @return - Returns an id for the shader.     */   
           public static int loadShader(int type, String shaderCode){

        int shader = GLES20.glCreateShader(type);

        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        return shader;
    }

    /**     * Utility method for debugging OpenGL calls. Provide the name of the call 
                 * just after making it:     *     * <pre>
     
            * mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");   
                 * MyRenderer.checkGlError("glGetUniformLocation");</pre>
 
       *       * If the operation is not successful, the check throws an error.     *   
                * @param glOperation - Name of the OpenGL call to check.     */    
         public static void checkGlError(String glOperation) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(TAG, glOperation + ": glError " + error);
            throw new RuntimeException(glOperation + ": glError " + error);
        }
    }

    /**     * Returns the rotation angle of the triangle shape (mTriangle).     *    
                 * @return - A float representing the rotation angle.     */   
        public float getAngle() {
        return mAngle;
    }

    public void setAngle(float angle) {
        mAngle = angle;
    }
}

Step III
     package com.exam.ravi.graphicsex2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.opengl.GLSurfaceView;

public class MainActivity extends AppCompatActivity {

    private GLSurfaceView glSurfaceView;

    @Override    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        glSurfaceView = new MySurfaceView(this);
        setContentView(glSurfaceView);
    }

    @Override    protected void onPause() {
        super.onPause();
        glSurfaceView.onPause();
    }

    @Override    protected void onResume() {
        super.onResume();
        glSurfaceView.onResume();
    }
}

Step IV

     package com.exam.ravi.graphicsex2;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;

public class MySurfaceView extends GLSurfaceView {

    private final MyRenderer mRenderer;

    public MySurfaceView(Context context) {
        super(context);
        setEGLContextClientVersion(2);

        mRenderer = new MyRenderer();
        setRenderer(mRenderer);

        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }
}

Output will be like 



No comments:

Post a Comment