OpenGL ES 3 Android

Hi guys.
I am trying to set up a simple demo application with OpenGL ES 3 on Android and testing with my new Android device. For now, I just want to draw a simple line and can’t figure out what the heck I am missing. :melting_face:

Here my code for the activity:

package de.banaworks.shiftingpillars;

import static android.opengl.GLES10.glDrawArrays;
import static android.opengl.GLES10.glViewport;
import static android.opengl.GLES11.GL_ARRAY_BUFFER;
import static android.opengl.GLES11.GL_STATIC_DRAW;
import static android.opengl.GLES11.glBindBuffer;
import static android.opengl.GLES11.glBufferData;
import static android.opengl.GLES11.glGenBuffers;
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
import static android.opengl.GLES20.GL_LINES;
import static android.opengl.GLES20.GL_VERTEX_SHADER;
import static android.opengl.GLES20.glAttachShader;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glCompileShader;
import static android.opengl.GLES20.glCreateProgram;
import static android.opengl.GLES20.glCreateShader;
import static android.opengl.GLES20.glDisableVertexAttribArray;
import static android.opengl.GLES20.glEnableVertexAttribArray;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetProgramInfoLog;
import static android.opengl.GLES20.glGetShaderInfoLog;
import static android.opengl.GLES20.glLinkProgram;
import static android.opengl.GLES20.glShaderSource;
import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glVertexAttribPointer;
import static android.opengl.GLES30.GL_MAP_WRITE_BIT;
import static android.opengl.GLES30.glMapBufferRange;
import static android.opengl.GLES30.glUnmapBuffer;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;

import java.io.IOException;
import java.nio.ByteBuffer;

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

public class GameActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final var view = new GLSurfaceView(this) {

        };
        view.setEGLContextClientVersion(3);
        view.setRenderer(new Renderer() {
            private final int vertexSize = 4 * 4;

            private final int vertexCount = 2;

            private final int bufferSize = vertexCount * vertexSize;

            private int triangle;

            private int shaderProgram;

            @Override
            public void onSurfaceCreated(GL10 gl, EGLConfig config) {
                glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
                loadTriangle();
                loadShaderProgram();
            }

            private void loadTriangle() {
                triangle = createBuffer();
                glBindBuffer(GL_ARRAY_BUFFER, triangle);
                glBufferData(GL_ARRAY_BUFFER, bufferSize, null, GL_STATIC_DRAW);
                writeTriangleToArrayBuffer();
            }

            private int createBuffer() {
                final var buffers = new int[1];
                glGenBuffers(1, buffers, 0);
                return buffers[0];
            }

            private void writeTriangleToArrayBuffer() {
                final var buffer = (ByteBuffer) glMapBufferRange(GL_ARRAY_BUFFER, 0, bufferSize, GL_MAP_WRITE_BIT);
                putVertex(1.0f, 0.0f, 0.0f, 1.0f, buffer);
                putVertex(-1.0f, 0.0f, 0.0f, 1.0f, buffer);
                glUnmapBuffer(GL_ARRAY_BUFFER);
            }

            private void putVertex(float x, float y, float z, float w, ByteBuffer buffer) {
                buffer.putFloat(x).putFloat(y).putFloat(z).putFloat(w);
            }

            private void loadShaderProgram() {
                shaderProgram = glCreateProgram();
                glAttachShader(shaderProgram, loadShader(GL_VERTEX_SHADER, R.raw.vertex_shader));
                glAttachShader(shaderProgram, loadShader(GL_FRAGMENT_SHADER, R.raw.fragment_shader));
                glLinkProgram(shaderProgram);
                checkShaderProgramState();
            }

            private int loadShader(int type, int file) {
                final var shader = glCreateShader(type);
                final var code = new String(loadResource(file));
                glShaderSource(shader, code);
                glCompileShader(shader);
                checkShaderState(shader, code);
                return shader;
            }

            private byte[] loadResource(int file) {
                try (final var input = getResources().openRawResource(file)) {
                    return input.readAllBytes();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            private void checkShaderState(int shader, String code) {
                final var error = glGetShaderInfoLog(shader);
                if (error == null) {
                    throw new RuntimeException(String.format("Compiling shader code:%n%s%nproduced error:%n%s", code, error));
                }
            }

            private void checkShaderProgramState() {
                final var error = glGetProgramInfoLog(shaderProgram);
                if (error != null && !error.isEmpty()) {
                    throw new RuntimeException("Linking shader program produced error: " + error);
                }
            }

            @Override
            public void onSurfaceChanged(GL10 gl, int width, int height) {
                glViewport(0, 0, width, height);
            }

            @Override
            public void onDrawFrame(GL10 gl) {
                glClear(GL_COLOR_BUFFER_BIT);
                glUseProgram(shaderProgram);
                final var positionHandle = glGetAttribLocation(shaderProgram, "position");
                glEnableVertexAttribArray(positionHandle);
                glVertexAttribPointer(positionHandle, 4, GL_FLOAT, false, vertexSize, 0);
                glDrawArrays(GL_LINES, 0, vertexCount);
                glDisableVertexAttribArray(0);
                glUseProgram(0);
            }
        });
        setContentView(view);
    }
}

Here my two shaders:

attribute vec4 position;

void main() {
    gl_Position = position;
}

void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

The black screen works but I see no line. What am I missing? I am not entirely sure if I configured the OpenGL ES versions correctly. Also I am not entirely sure if the binding between buffer and shader variable is proper. Any help appreciated! :slight_smile:

Found the mistake. I forgot to adjust the byte order in the buffer. :smiling_face_with_tear:

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.