多维数据集未在Android上的OpenGL ES 3.0中绘制

时间:2016-07-22 18:13:19

标签: java android opengl-es

我想在Android设备上的opengl es 3.0中渲染一个简单的多维数据集,但它不会渲染。这是我的SurfaceView设置:

public GLContextView(Context context){
    super(context);

    setEGLContextClientVersion(3);

    setRenderer(renderer);
}

呈现代码:

public void onSurfaceCreated(javax.microedition.khronos.opengles.GL10 unused, javax.microedition.khronos.egl.EGLConfig p2){
    GLES30.glEnable(GLES30.GL_DEPTH_TEST);
    GLES30.glEnable(GLES30.GL_BLEND);
    GLES30.glEnable(GLES30.GL_CULL_FACE);
    GLES30.glDepthFunc(GLES30.GL_LEQUAL);
    GLES30.glCullFace(GLES30.GL_BACK);

    GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    cubeProgram = RenderHelper.createShaderProgram(Shader.CubeVertexShader, Shader.CubeFragmentShader);

    int[] array = new int[2];
    GLES30.glGenVertexArrays(1, array, 0);
    vaId = array[0];
    GLES30.glBindVertexArray(vaId);


    GLES30.glGenBuffers(2, array, 0);
    vbId = array[0];
    ibId = array[1];

    GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbId);
    GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, RenderCube.vertices.length * 4, RenderCube.vBuffer, GLES30.GL_STATIC_DRAW);
    GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, 0);
    GLES30.glEnableVertexAttribArray(positionHandle);

    GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, ibId);
    GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, RenderCube.indices.length * 4, RenderCube.iBuffer, GLES30.GL_STATIC_DRAW);

    colorHandle = GLES30.glGetUniformLocation(cubeProgram, "in_color");

    GLES30.glBindVertexArray(0);
}

public void onDrawFrame(GL10 p1){
    GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);

    GLES30.glUseProgram(cubeProgram);

    GLES30.glBindVertexArray(vaId);

    GLES30.glUniform4f(colorHandle, 1.0f, 1.0f, 1.0f, 1.0f);

    GLES30.glDrawElements(GLES30.GL_TRIANGLES, RenderCube.indices.length, GLES30.GL_UNSIGNED_INT, 0);

}


public void onSurfaceChanged(GL10 p1, int p2, int p3){
    GLES30.glViewport(0, 0, p2, p3);
}

具有顶点和索引数据的RenderCube类:

class RenderCube{
    public static float[] vertices = {
        0.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 1.0f,

        0.0f, 1.0f, 0.0f,
        1.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
    };

    public static int[] indices = {
        0, 3, 1, 0, 2, 3, //Bottom
        4, 7, 5, 4, 6, 7, //Top
        0, 5, 1, 0, 4, 5, //Back
        2, 7, 3, 2, 6, 7, //Front
        0, 6, 2, 0, 4, 6, //Left
        1, 7, 3, 1, 5, 7  //Right
    };

    public static FloatBuffer vBuffer = RenderHelper.createFloatBuffer(vertices.length * 4, vertices);
    public static IntBuffer iBuffer = RenderHelper.createIntBuffer(indices.length * 4, indices);

};

着色器:

final class Shader{

    public static final String CubeVertexShader =
    "#version 300 es\n" +
    "layout (location = 0) in vec3 pos;" +
    "void main(){" +
    "   gl_Position = vec4(pos, 1.0f);" +
    "}";

    public static final String CubeFragmentShader =
    "#version 300 es\n" +
    "precision mediump float;" +
    "uniform vec4 in_color;" +
    "out vec4 color;" +
    "void main(){" +
    "   color = in_color;" +
    "}";
}

编译正常,不会打印出opengl错误。我做错了什么?

1 个答案:

答案 0 :(得分:1)

我认为你根本没有可见的三角形。

底部,顶部,左侧和右侧的三角形是不可见的,因为它们与观察平面正交。因此,您正在查看它们的边缘,它们最终会变为退化三角形(即面积为零的三角形)。

您定义它们的方式,背面和正面的三角形都具有顺时针缠绕顺序。扩展这4个三角形的索引,并仅显示相应顶点的x和y坐标:

0, 5, 1 -> (0.0f, 0.0f), (1.0f, 1.0f), (1.0f, 0.0f)
0, 4, 5 -> (0.0f, 0.0f), (0.0f, 1.0f), (1.0f, 1.0f)
2, 7, 3 -> (0.0f, 0.0f), (1.0f, 1.0f), (1.0f, 0.0f)
2, 6, 7 -> (0.0f, 0.0f), (0.0f, 1.0f), (1.0f, 1.0f)

如您所见,这些三角形都是顺时针方向。由于您选择启用背面剔除:

GLES30.glEnable(GLES30.GL_CULL_FACE);
GLES30.glCullFace(GLES30.GL_BACK);

并且正面的默认缠绕顺序是逆时针方向,这意味着背面的缠绕是顺时针方向,所有这些三角形都将被剔除。

此外,由于正面位于z = 1.0,因此它也正好位于前剪裁平面上。我读取规范的方式,正好在裁剪平面上的几何应该仍然可见。但是将它清楚地放在剪辑音量中可能更安全。