简体   繁体   中英

OpenGL ES draw a square on android

I tried, to draw a square in OpenGL ES for android, but for some reason my code crashes, or does only show the clearColor. I'm sure, that the project setup with the renderer and GLSurfaceView class is correct, and that the function to import the vertex and the fragment shader from a file works. This is the code, to draw the square (the constructor is called in onSurfaceCreated on the draw method in onDrawFrame method of my renderer class):

import android.content.Context;
import android.opengl.GLES20;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

public class Square {
    int ShaderProgramID;
    private FloatBuffer vertexBuffer;
    private int vertexBufferID;
    private int vertexCount;
    private int vertexStride;
    static final int COORDS_PER_VERTEX = 3;
    static final int COLORS_PER_VERTEX = 4;
    static final int SIZE_OF_FLOAT = 4;
    static final float coords[] = {
          //x:    y:     z:            r:    g:    b:    a:
            -0.5f, 0.5f, 0.0f,         1.0f, 0.0f, 0.0f, 1.0f,
            -0.5f,-0.5f, 0.0f,         0.0f, 1.0f, 0.0f, 1.0f,
             0.5f,-0.5f, 0.0f,         0.0f, 0.0f, 1.0f, 1.0f,
            -0.5f, 0.5f, 0.0f,         1.0f, 0.0f, 0.0f, 1.0f,
             0.5f,-0.5f, 0.0f,         0.0f, 0.0f, 1.0f, 1.0f,
             0.5f, 0.5f, 0.0f,         1.0f, 1.0f, 1.0f, 1.0f,

    };
    public Square(Context context)  {
        String vertexShaderSrc = ReadFromfile("defaultVertexShader.glsl", context);
        String fragmentShaderSrc = ReadFromfile("defaultFragmentShader.glsl", context);

        int vertexID = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        GLES20.glShaderSource(vertexID, vertexShaderSrc);
        GLES20.glCompileShader(vertexID);

        int fragmetID = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(fragmetID, fragmentShaderSrc);
        GLES20.glCompileShader(fragmetID);

        ShaderProgramID = GLES20.glCreateProgram();
        GLES20.glAttachShader(ShaderProgramID, vertexID);
        GLES20.glAttachShader(ShaderProgramID, fragmetID);
        GLES20.glBindAttribLocation(ShaderProgramID, 0, "aPos");
        GLES20.glBindAttribLocation(ShaderProgramID, 1, "aColor");
        GLES20.glLinkProgram(ShaderProgramID);

        positionHandle = GLES20.glGetAttribLocation(ShaderProgramID, "a_Position");
        colorHandle = GLES20.glGetAttribLocation(ShaderProgramID, "a_Color");

        vertexBuffer = FloatBuffer.allocate(coords.length);
        vertexBuffer.put(coords);
        vertexBuffer.position(0);
        IntBuffer buffer = IntBuffer.allocate(1);
        GLES20.glGenBuffers(1, buffer);
        vertexBufferID = buffer.get(0);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferID);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, coords.length * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);

        vertexCount = coords.length / (COORDS_PER_VERTEX + COLORS_PER_VERTEX);
        vertexStride = (COORDS_PER_VERTEX + COLORS_PER_VERTEX) * 4;
    }
    private int positionHandle;
    private int colorHandle;
    public void draw() {
        GLES20.glUseProgram(ShaderProgramID);


        vertexBuffer.position(0);
        GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
        GLES20.glEnableVertexAttribArray(positionHandle);


        vertexBuffer.position(3);
        GLES20.glVertexAttribPointer(colorHandle, COLORS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
        GLES20.glEnableVertexAttribArray(colorHandle);


        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.glDisableVertexAttribArray(colorHandle);

    }

    public String ReadFromfile(String fileName, Context context) {
        StringBuilder ReturnString = new StringBuilder();
        InputStream fIn = null;
        InputStreamReader isr = null;
        BufferedReader input = null;
        try {
            fIn = context.getResources().getAssets()
                    .open(fileName);
            isr = new InputStreamReader(fIn);
            input = new BufferedReader(isr);
            String line = "";
            while ((line = input.readLine()) != null) {
                ReturnString.append(line + "\n");
            }
        } catch (Exception e) {
            e.getMessage();
        } finally {
            try {
                if (isr != null)
                    isr.close();
                if (fIn != null)
                    fIn.close();
                if (input != null)
                    input.close();
            } catch (Exception e2) {
                e2.getMessage();
            }
        }
        return ReturnString.toString();
    }
}

this is the VertexShaderCode:

attribute vec4 aPos;
attribute vec4 aColor;

varying vec4 v_Color;

void main()
{
    v_Color = a_Color;
    gl_Position = a_Position;
}

and this is the FragmentShaderCode

precision mediump float;
varying vec4 v_Color;
void main()
{
    gl_FragColor = v_Color;
}

In vertex shader:

attribute vec4 aPos;

position is 4-component vector, but in "vertexBuffer" position is written as 3-component vector. So try to improve shader:

attribute vec3 aPos;

Also "a_Position" used, but not declared anywhere, make this:

gl_Position = vec4(a_Pos,1.0);

and improve here:

positionHandle = GLES20.glGetAttribLocation(ShaderProgramID, "a_Pos");

This code can show if shader compiled or not, and an error.

int[] compiled = new int[1];
        GLES31.glGetShaderiv(shader, GLES31.GL_COMPILE_STATUS, compiled, 0);
        if (compiled[0] == 0) {
            GLES31.glDeleteShader(shader);
            throw new RuntimeException("Could not compile program: "
                    + GLES31.glGetShaderInfoLog(shader) + " | ");
        }

This is the correct way to prepare float buffer:

ByteBuffer bb = ByteBuffer.allocateDirect(coords.length*4);
bb.order(ByteOrder.nativeOrder());

FloatBuffer vertexBuffer = bb.asFloatBuffer();

THis is the current code:

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLES31;
import android.util.Log;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;


public class Square {
int ShaderProgramID;
private FloatBuffer vertexBuffer;
private int vertexBufferID;
private int vertexCount;
private int vertexStride;
static final int COORDS_PER_VERTEX = 3;
static final int COLORS_PER_VERTEX = 4;
static final int SIZE_OF_FLOAT = 4;
static final float coords[] = {
        //x:    y:     z:            r:    g:    b:    a:
        -0.5f, 0.5f, 0.0f,         1.0f, 0.0f, 0.0f, 1.0f,
        -0.5f,-0.5f, 0.0f,         0.0f, 1.0f, 0.0f, 1.0f,
         0.5f,-0.5f, 0.0f,         0.0f, 0.0f, 1.0f, 1.0f,
        -0.5f, 0.5f, 0.0f,         1.0f, 0.0f, 0.0f, 1.0f,
         0.5f,-0.5f, 0.0f,         0.0f, 0.0f, 1.0f, 1.0f,
         0.5f, 0.5f, 0.0f,         1.0f, 1.0f, 1.0f, 1.0f,

};
public Square(Context context)  {
    String vertexShaderSrc = ReadFromfile("defaultVertexShader.glsl", context);
    String fragmentShaderSrc = ReadFromfile("defaultFragmentShader.glsl", context);

    int vertexID = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
    GLES20.glShaderSource(vertexID, vertexShaderSrc);
    GLES20.glCompileShader(vertexID);

    int fragmetID = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
    GLES20.glShaderSource(fragmetID, fragmentShaderSrc);
    GLES20.glCompileShader(fragmetID);

    ShaderProgramID = GLES20.glCreateProgram();
    GLES20.glAttachShader(ShaderProgramID, vertexID);
    GLES20.glAttachShader(ShaderProgramID, fragmetID);
    GLES20.glBindAttribLocation(ShaderProgramID, 0, "aPos");
    GLES20.glBindAttribLocation(ShaderProgramID, 1, "aColor");
    GLES20.glLinkProgram(ShaderProgramID);

    positionHandle = GLES20.glGetAttribLocation(ShaderProgramID, "aPos");
    colorHandle = GLES20.glGetAttribLocation(ShaderProgramID, "aColor");

    vertexBuffer = FloatBuffer.allocate(coords.length);
    vertexBuffer.put(coords);
    vertexBuffer.position(0);
    IntBuffer buffer = IntBuffer.allocate(1);
    GLES20.glGenBuffers(1, buffer);
    vertexBufferID = buffer.get(0);
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferID);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, coords.length * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);

    vertexCount = coords.length / (COORDS_PER_VERTEX + COLORS_PER_VERTEX);
    vertexStride = (COORDS_PER_VERTEX + COLORS_PER_VERTEX) * 4;
}
private int positionHandle;
private int colorHandle;
public void draw() {
    GLES20.glUseProgram(ShaderProgramID);

    vertexBuffer.position(0);
    GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, 0);
    GLES20.glEnableVertexAttribArray(positionHandle);


    vertexBuffer.position(3);
    GLES20.glVertexAttribPointer(colorHandle, COLORS_PER_VERTEX, GLES20.GL_FLOAT,        false, vertexStride, 3);
    GLES20.glEnableVertexAttribArray(colorHandle);


    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
    GLES20.glDisableVertexAttribArray(positionHandle);
    GLES20.glDisableVertexAttribArray(colorHandle);

}

public String ReadFromfile(String fileName, Context context) {
    StringBuilder ReturnString = new StringBuilder();
    InputStream fIn = null;
    InputStreamReader isr = null;
    BufferedReader input = null;
    try {
        fIn = context.getResources().getAssets()
                .open(fileName);
        isr = new InputStreamReader(fIn);
        input = new BufferedReader(isr);
        String line = "";
        while ((line = input.readLine()) != null) {
            ReturnString.append(line + "\n");
        }
    } catch (Exception e) {
        e.getMessage();
    } finally {
        try {
            if (isr != null)
                isr.close();
            if (fIn != null)
                fIn.close();
            if (input != null)
                input.close();
        } catch (Exception e2) {
            e2.getMessage();
        }
    }
    return ReturnString.toString();
}
}

Fragment:

#version 310 es
precision mediump float;
in vec4 vColor;
void main()
{
gl_FragColor = vColor;
}

Vertex:

#version 310 es
attribute vec3 aPos;
attribute vec4 aColor;
out vec4 vColor;

void main()
{
vColor = aColor;
gl_Position = vec4(aPos,1.0);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM