Pages

getteammates.com

Friday, 27 March 2015

OpenGL ES 3.0 Programming in Android


Android introduced OpenGL ES 3.0 support from API level 18, Android 4.3 (JELLY_BEAN_MR2).

OpenGL ES 3.0 is a super set of OpenGL ES 2.0.

We will be creating an Android application which draw a simple rectangle using OpenGL ES 3.0.


Updating AndroidManifest.xml file

We will make sure that the application is installed on device which supports OpenGL ES 3.0 using uses-feature tag.

<uses-feature android:glEsVersion="0x00030000" android:required="true" />

And also the minimum SDK and target SDK will set to 18.

<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="18" />

Main Activity implementation


Now lets create the Activity implementation. We will create a GLSurfaceView implementation and set it 
as the content view.

Our Activity class implementation is shown below,

    1 import android.app.Activity;
    2 import android.os.Bundle;
    3 
    4 public class MainActivity extends Activity {
    5     private GLES3View mView;
    6 
    7     @Override
    8     protected void onCreate(Bundle savedInstanceState) {
    9         super.onCreate(savedInstanceState);
   10         mView = new GLES3View(getApplication());
   11         setContentView(mView);
   12     }
   13 
   14     @Override
   15     protected void onPause() {
   16         super.onPause();
   17         mView.onPause();
   18     }
   19 
   20     @Override
   21     protected void onResume() {
   22         super.onResume();
   23         mView.onResume();
   24     }   
   25 }

View implementation

So far so good. Now lets go to the actual OpenGL ES 3.0 rendering.

What we will be doing is drawing a simple rectangle. Lets look at the vertex shader,
    1 #version 300 es
    2 layout(location = 0) in vec4 aPosition;
    3 void main()
    4 {
    5     gl_Position = aPosition;
    6 }

First line tells that we are going to use GLSL version 3.0. Next we declare our attribute variable. layout(location = 0) specifies the attribute index. See that we are not required to have glBindAttribLocation​ any more.
Rest of the statement is same as OpenGL ES 2.0 shader.

Now lets look at the fragment shader,

    1 #version 300 es
    2 precision mediump float;
    3 out vec4 fragColor;
    4 void main()
    5 {
    6     fragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);
    7 }

fragColor is out put variable. The value written to this variable is what will be written out into the color buffer. Here we will have an yellow rectangle.

Rest of the source code is almost similar to that of OpenGL ES 2.0 rendering, please note that we will be using android.opengl.GLES30 instead of android.opengl.GLES20.

Complete source code is given below,

    1 import java.nio.ByteBuffer;
    2 import java.nio.ByteOrder;
    3 import java.nio.FloatBuffer;
    4 
    5 import javax.microedition.khronos.egl.EGLConfig;
    6 import javax.microedition.khronos.opengles.GL10;
    7 
    8 import android.content.Context;
    9 import android.opengl.GLES30;
   10 import android.opengl.GLSurfaceView;
   11 import android.util.Log;
   12 
   13 public class GLES3View extends GLSurfaceView implements GLSurfaceView.Renderer {
   14 
   15     private static final String TAG = "GLES_3_HELLOWORLD";
   16     
   17     private static final String VertexShader = 
   18             "#version 300 es                               \n" +
   19             "layout(location = 0) in vec4 aPosition;       \n" +
   20             "void main()                                   \n" +
   21             "{                                             \n" +
   22             "    gl_Position = aPosition;                  \n" +
   23             "}                                             \n" +
   24             "                                              \n";
   25 
   26     private static final String FragmentShader = 
   27             "#version 300 es                               \n" +
   28             "precision mediump float;                      \n" +
   29             "out vec4 fragColor;                           \n" +
   30             "void main()                                   \n" +
   31             "{                                             \n" +
   32             "    fragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f); \n" +
   33             "}                                             \n" +
   34             "";
   35 
   36     final int mPosLoc = 0;
   37 
   38     int mProgram;
   39 
   40     FloatBuffer mVerticesBuffer;
   41 
   42     public GLES3View(Context context) {
   43         super(context);
   44         
   45         // setup EGL configurations
   46         setEGLConfigChooser(8, 8, 8, 8, 16, 0);
   47         setEGLContextClientVersion(2);
   48         
   49         setRenderer(this);
   50     }
   51 
   52     private void init() {
   53         GLES30.glClearColor(0.5f, 0.5f, 0.5f, 1f);
   54         
   55         mProgram = createProgram(VertexShader, FragmentShader);
   56         
   57         // vertices
   58         float vertices[] = {
   59                 -0.75f, -0.75f,
   60                 0.75f, -0.75f,
   61                 0.75f, 0.75f,
   62                 -0.75f, 0.75f                
   63         };
   64         
   65         // create the float buffer
   66         ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
   67         vbb.order(ByteOrder.nativeOrder()); 
   68         mVerticesBuffer = vbb.asFloatBuffer();
   69         mVerticesBuffer.put(vertices);
   70         mVerticesBuffer.position(0);
   71     }
   72 
   73     private void draw() {
   74         GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
   75         
   76         GLES30.glUseProgram(mProgram);
   77         
   78         GLES30.glVertexAttribPointer(mPosLoc, 2, GLES30.GL_FLOAT,
   79                                              false, 0, mVerticesBuffer);
   80         GLES30.glEnableVertexAttribArray(mPosLoc);
   81         
   82         GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, 4);
   83     }
   84 
   85     private int loadShader(int shaderType, String source) {
   86         Log.d(TAG, source);
   87         
   88         int shader = GLES30.glCreateShader(shaderType);
   89         if (shader != 0) {
   90             // compile the shader
   91             GLES30.glShaderSource(shader, source);
   92             GLES30.glCompileShader(shader);
   93             
   94             int[] compiled = new int[1];
   95             GLES30.glGetShaderiv(shader, GLES30.GL_COMPILE_STATUS, compiled, 0);
   96             if (compiled[0] == 0) {
   97                 Log.e(TAG, GLES30.glGetShaderInfoLog(shader));
   98                 GLES30.glDeleteShader(shader);
   99                 shader = 0;
  100             }
  101         }
  102         
  103         return shader;
  104     }
  105 
  106     private int createProgram(String vertexSource, String fragmentSource) {
  107         int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexSource);
  108         if (vertexShader == 0) {
  109             return 0;
  110         }
  111 
  112         int pixelShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentSource);
  113         if (pixelShader == 0) {
  114             return 0;
  115         }
  116 
  117         int program = GLES30.glCreateProgram();
  118         if (program != 0) {
  119             GLES30.glAttachShader(program, vertexShader);
  120             GLES30.glAttachShader(program, pixelShader);
  121             GLES30.glLinkProgram(program);
  122             int []linkStatus = {0};
  123             GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, linkStatus, 0);
  124             if (linkStatus[0] != 1) {
  125                 Log.e(TAG, GLES30.glGetProgramInfoLog(program));
  126                 GLES30.glDeleteProgram(program);
  127                 program = 0;
  128             }
  129         }
  130         return program;
  131     }
  132     
  133     public void onDrawFrame(GL10 gl) {
  134         draw();
  135     }
  136 
  137     public void onSurfaceChanged(GL10 gl, int width, int height) {
  138         GLES30.glViewport(0, 0, width, height);
  139     }
  140 
  141     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
  142         init();
  143     }
  144 }

Complete source code can be found at https://github.com/trsquarelab/glexamples/tree/master/android/gles_3_helloworld

No comments:

Post a Comment