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.
And also the minimum SDK and target SDK will set to 18.
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,
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,
Complete source code can be found at https://github.com/trsquarelab/glexamples/tree/master/android/gles_3_helloworld
<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,
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,
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