• Skip to main content
  • Skip to primary sidebar

Anastasios Chondrogiannis

Software developer with a focus on iOS

Android OpenGL ES – Part 1: Basic Setup

February 14, 2020 by Anastasios Chondrogiannis Leave a Comment

1. Create a new Android Project with C/C++ support

In order to create a new Android project with C/C++ support, click here and follow the instructions.

The only difference is that you will use a different API level:

Minimum API level: API 21: Android 5.0 (Lollipop)

2. Add a new Activity

  • Right click the package name
  • Select New -> Kotlin File/Class.
  • Fill in the following information:
    • Name: MainActivity
    • Kind: Class
  • Click OK.
  • Add the following code:
package dev.anastasioscho.glestriangle

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity: AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
   }
}
  • Open the AndroidManifest.xml file.
  • Add the following in the application tag:
<activity android:name=".MainActivity">
   <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
</activity>

At this point you can build and run your app.

3. Declare the OpenGL Requirement

We will use OpenGL ES 3.1 which adds the ability to do general purpose compute. That’s why we picked Android 5.0 (API Level 21) in the first place.

  • Open the AndroidManifest.xml file.
  • Add the following:
<uses-feature android:glEsVersion="0x00030001" android:required="true" />

4. Setup the GLSurfaceView

A GLSurfaceView is a specialised view where you can draw OpenGL ES graphics. The actual drawing is done in an GLSurfaceView.Renderer object.

  • Right click the package name.
  • Select New -> Kotlin File/Class.
  • Fill in the following information:
    • Name: CustomGLSurfaceView
    • Kind: class
  • Add the following code:
package dev.anastasioscho.glestriangle

import android.content.Context
import android.opengl.GLSurfaceView
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class CustomGLSurfaceView(context: Context): GLSurfaceView(context) {
   private val customGLRenderer = CustomGLRenderer()

   init {
      setEGLContextClientVersion(3)
      setRenderer(customGLRenderer)
   }

   inner class CustomGLRenderer: Renderer {
      override fun onDrawFrame(gl: GL10?) {}
      override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {}
      override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {}
   }
}
  • Open the MainActivity.kt file.
  • Make the following changes:
package dev.anastasioscho.glestriangle

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity: AppCompatActivity() {
   private lateinit var customGLSurfaceView: GLSurfaceView

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)

      customGLSurfaceView = CustomGLSurfaceView(this)
      setContentView(customGLSurfaceView)
   }
}

5. Create an XML Layout (Optional)

You can also use your CustomGLSurfaceView in an XML layout:

  • Right click the res folder.
  • Select New -> Android Resource File.
  • Provide the following information:
    • File name: activity_main
    • Resource type: Layout
    • Root element: LinearLayout
    • Source set: main
    • Directory name: layout
    • Chosen qualifiers: Leave it empty
  • Add the following code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

   <dev.anastasioscho.glestriangle.CustomGLSurfaceView
      android:id="@+id/customGLSurfaceView"
      android:layout_width="match_parent"
      android:layout_height="match_parent" />

</LinearLayout>
  • Open the MainActivity.kt file.
  • Make the following changes:
package dev.anastasioscho.glestriangle

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity: AppCompatActivity() {
   private lateinit var customGLSurfaceView: GLSurfaceView

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)

      setContentView(R.layout.activity_main)

      customGLSurfaceView = findViewById(R.id.customGLSurfaceView)
   }
}
  • Open the CustomGLSurfaceView.kt file.
  • Make the following changes:
package dev.anastasioscho.glestriangle

import android.content.Context
import android.opengl.GLSurfaceView
import android.util.AttributeSet
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class CustomGLSurfaceView(context: Context, attrs: AttributeSet): GLSurfaceView(context, attrs) {
   private val customGLRenderer = CustomGLRenderer()

   init {
      setEGLContextClientVersion(3)
      setRenderer(customGLRenderer)
   }

   inner class CustomGLRenderer: Renderer {
      override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {}
      override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {}
      override fun onDrawFrame(gl: GL10?) {}
   }
}

6. Test the app

You will use OpenGL to paint the screen green.

6.1 Link the OpenGL library

  • Open the CMakeLists.txt file.
  • Add the following code:
cmake_minimum_required(VERSION 3.6.0)

add_library(native-library SHARED main.cpp)

find_library(opengl-lib GLESv3)

target_link_libraries(native-library ${opengl-lib})
  • Save the file and click Sync Now.

6.2 Create the NativeLibrary class

The purpose of this class is to load your native library and encapsulate the native functions.

  • Right click the package name.
  • Select New -> Kotlin File/Class.
  • Provide the following information:
    • Name: NativeLibrary
    • Kind: Class
  • Add the following code:
package dev.anastasioscho.glestriangle

class NativeLibrary {
   companion object {
      init {
         System.loadLibrary("native-library")
      }
   }

   external fun nOnSurfaceCreated()
   external fun nOnSurfaceChanged(width: Int, height: Int)
   external fun nOnDrawFrame()
}

6.3 Implement the native functions

  • Open the main.cpp file.
  • Add the following code:
#include <jni.h>
#include <GLES3/gl31.h>

extern "C" JNIEXPORT void JNICALL Java_dev_anastasioscho_glestriangle_NativeLibrary_nOnSurfaceCreated(JNIEnv * env, jobject obj) {
   glClearColor(0.0, 1.0, 0.0, 1.0);

   return;
}

extern "C" JNIEXPORT void JNICALL Java_dev_anastasioscho_glestriangle_NativeLibrary_nOnSurfaceChanged(JNIEnv * env, jobject obj, jint width, jint height) {
   glViewport(0, 0, width, height);

   return;
}

extern "C" JNIEXPORT void JNICALL Java_dev_anastasioscho_glestriangle_NativeLibrary_nOnDrawFrame(JNIEnv * env, jobject obj) {
   glClear(GL_COLOR_BUFFER_BIT);

   return;
}

Warning

You must replace the dev_anastasios_glestriangle portion of the above functions with the appropriate components of your package name. So for example, if your package name is my.package.name then replace it with my_package_name.

6.4 Call the native functions

  • Open the CustomGLSurface.kt file.
  • Add the following code:
package dev.anastasioscho.glestriangle

import android.content.Context
import android.opengl.GLSurfaceView
import android.util.AttributeSet
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class CustomGLSurfaceView(context: Context, attrs: AttributeSet): GLSurfaceView(context, attrs) {
   private val customGLRenderer = CustomGLRenderer()
   private val nativeLibrary = NativeLibrary()

   init {
      setEGLContextClientVersion(3)
      setRenderer(customGLRenderer)
   }

   inner class CustomGLRenderer: Renderer {
      override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
         nativeLibrary.nOnSurfaceCreated()
      }

      override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
         nativeLibrary.nOnSurfaceChanged(width, height)
      }

      override fun onDrawFrame(gl: GL10?) {
         nativeLibrary.nOnDrawFrame()
      }
   }
}

References

  • https://developer.android.com/guide/topics/graphics/opengl
  • https://developer.android.com/studio/projects/configure-cmake
  • https://www.khronos.org/opengles/
  • https://developer.android.com/training/custom-views/create-view
  • https://developer.android.com/ndk/guides/stable_apis

Filed Under: Android Development

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Let’s connect!

  • Facebook
  • Instagram
  • LinkedIn
  • Twitter

Recent Posts

  • Android OpenGL ES – Part 10: Specular lighting
  • Android OpenGL ES – Part 9: Diffuse lighting
  • Android OpenGL ES – Part 8: Ambient Lighting
  • Android OpenGL ES – Part 7: Textures
  • Android OpenGL ES – Part 6: Camera View

Archives

  • March 2020
  • February 2020
  • November 2019
  • October 2019
  • July 2019

Categories

  • Android Development
  • Machine Learning

Copyright © 2025 · Genesis Sample on Genesis Framework · WordPress · Log in