Android OpenGL ES 2.0仅部分绘图

时间:2017-09-10 00:57:37

标签: android opengl-es opengl-es-2.0

我最近开始研究Android上的OpenGL。在T尝试使用WebGL之后,我尝试在Android上使用它,遇到了一个奇怪的问题,经过数小时的谷歌搜索和试用后,我无法解决。

我的代码应该绘制一个立方体。但是,它似乎没有正确使用我的元素缓冲区并始终绘制黑色/绿色三角形。即使我删除了一些索引,它仍会绘制相同的黑色/绿色三角形,这暗示我OpenGL会提取错误的数据。

我已经阅读了谷歌代码教程,该代码在每次绘制调用之前写入缓冲区,但由于内存开销,我真的想避免这种情况。

这是我的渲染器的代码。我希望我的错误在这里:

package test.slikey.opengl_test;

import android.opengl.GLSurfaceView;
import android.opengl.Matrix;

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

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

import static android.opengl.GLES20.*;

public class OpenGLRenderer implements GLSurfaceView.Renderer {

    private final String vertexShaderCode = "" +
            "precision mediump float;" +
            "" +
            "attribute vec3 aVertexPosition;" +
            "attribute vec4 aVertexColor;" +
            "" +
            "uniform mat4 uMatWorld;" +
            "uniform mat4 uMatView;" +
            "uniform mat4 uMatProj;" +
            "" +
            "varying vec4 vFragColor;" +
            "" +
            "void main()" +
            "{" +
            "  gl_Position = uMatProj * uMatView * uMatWorld * vec4(aVertexPosition, 1.0);" +
            "  vFragColor = aVertexColor;" +
            "}";

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

    private final float[] positions = new float[]{
            -1.0f, -1.0f, -1.0f,     0.0f, 1.0f, 0.0f, 1.0f,
             1.0f, -1.0f, -1.0f,     0.0f, 1.0f, 0.0f, 1.0f,
             1.0f,  1.0f, -1.0f,     1.0f, 0.5f, 0.0f, 1.0f,
            -1.0f,  1.0f, -1.0f,     1.0f, 0.5f, 0.0f, 1.0f,
            -1.0f, -1.0f,  1.0f,     1.0f, 0.0f, 0.0f, 1.0f,
             1.0f, -1.0f,  1.0f,     1.0f, 0.0f, 0.0f, 1.0f,
             1.0f,  1.0f,  1.0f,     0.0f, 0.0f, 1.0f, 1.0f,
            -1.0f,  1.0f,  1.0f,     1.0f, 0.0f, 1.0f, 1.0f
    };

    private final byte[] indices = new byte[]{
            0, 4, 5,
            0, 5, 1,
            1, 5, 6,
            1, 6, 2,
            2, 6, 7,
            2, 7, 3,
            3, 7, 4,
            3, 4, 0,
            4, 7, 6,
            4, 6, 5,
            3, 0, 1,
            3, 1, 2
    };

    private int shaderProgram;
    private int attribVertexPosition;
    private int attribVertexColor;
    private int uniformMatWorld;
    private int uniformMatView;
    private int uniformMatProj;

    private float[] matrixWorld;
    private float[] matrixView;
    private float[] matrixProj;

    private int vertexBufferPointer;
    private int indexBufferPointer;

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        glClearColor(0.2f, 0.6f, 0.8f, 1.0f);

        shaderProgram = initShaderProgram();

        attribVertexPosition = glGetAttribLocation(shaderProgram, "aVertexPosition");
        attribVertexColor = glGetAttribLocation(shaderProgram, "aVertexColor");
        uniformMatWorld = glGetUniformLocation(shaderProgram, "uMatWorld");
        uniformMatView = glGetUniformLocation(shaderProgram, "uMatView");
        uniformMatProj = glGetUniformLocation(shaderProgram, "uMatProj");

        matrixWorld = new float[16];
        matrixView = new float[16];
        matrixProj = new float[16];

        initBuffers();
    }

    private int initShaderProgram() {
        int vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);

        int program = glCreateProgram();
        glAttachShader(program, vertexShader);
        glAttachShader(program, fragmentShader);

        glLinkProgram(program);

        int[] linkStatus = new int[1];
        glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
        if (linkStatus[0] != GL_TRUE) {
            glDeleteProgram(program);
            throw new RuntimeException("Could not link program: "
                    + glGetProgramInfoLog(program));
        }

        return program;
    }

    private int loadShader(int type, String shaderCode) {
        int shader = glCreateShader(type);

        glShaderSource(shader, shaderCode);
        glCompileShader(shader);

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

        return shader;
    }

    private void initBuffers() {
        int[] buffers = new int[2];
        glGenBuffers(2, buffers, 0);

        vertexBufferPointer = buffers[0];
        indexBufferPointer = buffers[1];

        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferPointer);
        glBufferData(GL_ARRAY_BUFFER, positions.length, ByteBuffer.allocateDirect(positions.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(positions).position(0), GL_STATIC_DRAW);

        glVertexAttribPointer(attribVertexPosition, 3, GL_FLOAT, false, 7 * 4, 0);
        glVertexAttribPointer(attribVertexColor, 4, GL_FLOAT, false, 7 * 4, 3 * 4);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferPointer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.length, ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder()).put(indices).position(0), GL_STATIC_DRAW);

        glEnableVertexAttribArray(attribVertexPosition);
        glEnableVertexAttribArray(attribVertexColor);
    }

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

        Matrix.perspectiveM(matrixProj, 0, 45, (float) width / height, 0.01f, 1000.0f);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        glUseProgram(shaderProgram);

        Matrix.setIdentityM(matrixWorld, 0);
        Matrix.setLookAtM(matrixView, 0,
                0, 0, -8,
                0, 0, 0,
                0, 1, 0
        );

        glUniformMatrix4fv(uniformMatWorld, 1, false, matrixWorld, 0);
        glUniformMatrix4fv(uniformMatView, 1, false, matrixView, 0);
        glUniformMatrix4fv(uniformMatProj, 1, false, matrixProj, 0);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_BYTE, 0);
    }
}

我希望它是一个非常小的东西,比如我缺少的默认设置,这是特定于Android的。一个类似的代码适用于WebGL。 希望有人有个主意。

谢谢!

0 个答案:

没有答案