In this tutorial, you will learn how to create a triangle using OpenGL ES.

Output:

Download Source Code: [media-downloader media_id=”1464″ texts=”OpenGLESDemo”]

Download APK: [media-downloader media_id=”1489″ texts=”OpenGLESDemo”]

Wants to Learn Advanced Android Application development from scratch- Beyond Basics

 

Creating New Project – OpenGLDemo

Open your Android Studio & create a new Project, have taken Empty Activity for this project. We kept all the things by default and clicked finish.

Creating MainActivity.java

package com.mytrendin.opengldemo;

import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

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

        //Check if System supports OpenGL ES 2.0
        ActivityManager am= (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        ConfigurationInfo info = am.getDeviceConfigurationInfo();
        boolean supportES2 = (info.reqGlEsVersion >= 0x20000);
        if(supportES2){
            Renderer renderer = new Renderer();
            SurfaceView surfaceView = new SurfaceView(this);
            surfaceView.setEGLContextClientVersion(2);
            surfaceView.setRenderer(renderer);
            this.setContentView(surfaceView);
        }
        else
            Log.e("OpelGLES 2","Your device doesn't support ES2, ("+info.reqGlEsVersion+")");
    }
}

 

First check dynamically if the Device supports OpenGL ES 2.0, it is done using this

ActivityManager am= (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
boolean supportES2 = (info.reqGlEsVersion >= 0x20000);

If the Device supports it then we will set the renderer and get the OpenGL ES 2.0 compatible context.

Related:

Introduction to OpenGL ES

Draw route and calculate distance between two locations in Google Maps Android

Draw route between two locations with Google Maps, using Kotlin, Android

Animation in Unity using 3d models (Part 1)

Animation in Unity using 3d models (Part 2)

Using Prefabs in Unity

Particle Effects – I in Unity

Particle Effects -II in Unity

SurfaceView.java

This class takes care of placing the surface at the correct location on the screen

package com.mytrendin.opengldemo;

import android.content.Context;
import android.opengl.GLSurfaceView;

public class SurfaceView extends GLSurfaceView{
    public SurfaceView(Context context) {
        super(context);
    }
}

Renderer.java

package com.mytrendin.opengldemo;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;

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

public class Renderer implements GLSurfaceView.Renderer {
    Triangle triangle;
    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {

        triangle =new Triangle();
    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int i, int i1) {
    }

    @Override
    public void onDrawFrame(GL10 gl10) {
        GLES20.glClearColor(0.0f,0.8f,0.0f,1.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        triangle.draw();
    }
}

onSurfaceCreated: Called when the surface is created or recreated. So the instance of the Triangle class is created here.

onDrawFrame: Called to draw the current frame.

glClearColor specifies the values used by glClear to clear the color buffers. Values specified by glClearColor are in the range 0 to 1.

GLES20.glClearColor(0.0f,    //red
                    0.8f,    //green
                    0.0f,    //blue
                    1.0f);   //alpha which means Opacity

Using this method the Color is set to Green.

glClear takes a single argument that is bitwise OR of several values indicating which buffer is to be cleared. In this Demo the values are as follows:

GL_COLOR_BUFFER_BIT
Indicates the buffers currently enabled for color writing.
GL_DEPTH_BUFFER_BIT
Indicates the depth buffer.

After writing all the code of drawing triangle just place a call to the draw() method using

triangle.draw();

 

Triangle.java

package com.mytrendin.opengldemo;

import android.opengl.GLES20;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

public class Triangle {
    private FloatBuffer vertexBuffer;
    private float vertices[]=new float[]{
        0.0f, 0.5f,0.0f,
        -0.8f,-0.5f,0.0f,
        0.8f,-0.5f,0.0f
    };
    private float color[]=new float[]{0.0f,0.0f,0.0f,1.0f};
    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";
    private int sharderProgram;
    public  static int loadShader(int type, String shaderCode){
        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader,shaderCode);
        GLES20.glCompileShader(shader);
        return shader;
    }
    public Triangle(){
        ByteBuffer bfr = ByteBuffer.allocateDirect(vertices.length *4);
        bfr.order(ByteOrder.nativeOrder());
        vertexBuffer = bfr.asFloatBuffer();
        vertexBuffer.put(vertices); //put all vertices in new buffer
        vertexBuffer.position(0);    // start reading vertices from beginning
        int vertexShader= loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);

        sharderProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(sharderProgram,vertexShader);
        GLES20.glAttachShader(sharderProgram,fragmentShader);
        GLES20.glLinkProgram(sharderProgram);
    }
    public void draw(){
        GLES20.glUseProgram(sharderProgram);
        int positionAttrib = GLES20.glGetAttribLocation(sharderProgram,"vPosition");
        GLES20.glEnableVertexAttribArray(positionAttrib);
        GLES20.glVertexAttribPointer(positionAttrib,3,GLES20.GL_FLOAT,false,0,vertexBuffer);
        int colorUniform = GLES20.glGetUniformLocation(sharderProgram,"vColor");
        GLES20.glUniform4fv(colorUniform,1,color,0);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,vertices.length / 3);
        GLES20.glDisableVertexAttribArray(positionAttrib);

    }
}

In OpenGL ES we can draw objects using coordinates in 3-dimentional space. A triangle has 3 vertices and for each vertex, we will have to specify its x,y and z co-ordinate. It is defined as follows,

private float vertices[]=new float[]{
        0.0f, 0.5f,0.0f,   //coordinates for vertex 1(Top)
        -0.8f,-0.5f,0.0f,  //vertex 2(Left)
        0.8f,-0.5f,0.0f    //vertex 3(Right)
};

Drawing a defined shape requires us to provide a lot of details to the graphics rendering pipeline. Specifically, you must define the following:

  • Vertex Shader – renders the vertices of a shape.
  • Fragment Shader – renders the face of a shape with colors or textures.
  • Program – It contains the shaders that can be used for drawing one or more shapes.

We need at least one vertex shader to draw a shape and one fragment shader to color that shape. Here is the definition of basic shaders,

private final String vertexShaderCode =
        "attribute vec4 vPosition;" +
        "void main() {" +
        "  gl_Position = vPosition;" +
        "}";

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

In order to draw your shape, you must compile the shader code, To compile this code, create a utility method in your renderer class:

public  static int loadShader(int type, String shaderCode){
        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader,shaderCode);
        GLES20.glCompileShader(shader);
        return shader;
}

We will create an OpenGL program then attach the vertex shader and fragment shader to it then will link it.

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

Now we have drawn our triangle but yet not placed it on screen.

glGetAttribLocation queries the previously linked program object specified by the program for the attribute variable specified by name and returns the index of the generic vertex attribute that is bound to that attribute variable.

glEnableVertexAttribArray enables the generic vertex attribute array

glGetUniformLocation — return the location of a uniform variable

glDrawArrays — render primitives from array data. The first parameter to this method is ‘mode’ which specifies what kind of primitives to render. Various symbolic constants are GL_POINTS, GL_PATCHES, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_LINE_STRIP_ADJACENCY, etc.

glDisableVertexAttribArray disables the generic vertex attribute array specified by index.

If You are Beginner to OpenGL Learn Android application development using OpenGL from the scratch


If you really liked the article, please subscribe to our YouTube Channel for videos related to this article.Please find us on Twitter and Facebook.

If you really liked the article, please subscribe to our YouTube Channel for videos related to this article.Please find us on Twitter and Facebook.

Related Posts