OpenGL:使用VBO渲染点云并不起作用

时间:2018-04-04 10:05:59

标签: android opengl-es point-clouds

我在OpenGL中使用Android来可视化数组中的大型数据集点云。首先,我想在屏幕上显示一些点来检查管道是否正确。我使用VBO来渲染它,但它只显示屏幕中间的一个点。我已经实现了以下在互联网here中找到的代码。

这是我的PointRenderer班级

public class PointRenderer implements GLSurfaceView.Renderer {
private float[] mModelMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] mProjectionMatrix = new float[16];
private float[] mMVPMatrix = new float[16];
private int mMVPMatrixHandle;
private int mPositionHandle;

float[] vertices = {
        0.0f,  0.5f, 0.0f,
        -100.5f, -100.5f, 0.0f,
        100.5f, -100.5f, 0.0f
};
FloatBuffer vertexBuf;

@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
    vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
    vertexBuf.put(vertices).position(0);

    // Set the background clear color to gray.
    GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);

    float eyeX = 0.0f;
    float eyeY = 0.0f;
    float eyeZ = 0.0f;

    float centerX = 0.0f;
    float centerY = 0.0f;
    float centerZ = -5.0f;

    float upX = 0.0f;
    float upY = 1.0f;
    float upZ = 0.0f;

    // Set the view matrix. This matrix can be said to represent the camera position.
    // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
    // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
    Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);

    final String vertexShader =
            "uniform mat4 u_MVPMatrix;      \n"
                    + "attribute vec4 a_Position;     \n"
                    + "void main()                    \n"
                    + "{                              \n"
                    + "   gl_Position = u_MVPMatrix   \n"
                    + "               * a_Position;   \n"
                    + "   gl_PointSize = 10.0;       \n"
                    + "}                              \n";

    final String fragmentShader =
            "precision mediump float;       \n"
                    + "void main()                    \n"
                    + "{                              \n"
                    + "   gl_FragColor = vec4(1.0,    \n"
                    + "   1.0, 1.0, 1.0);             \n"
                    + "}                              \n";

    // Load in the vertex shader.
    int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);

    if (vertexShaderHandle != 0) {
        // Pass in the shader source.
        GLES20.glShaderSource(vertexShaderHandle, vertexShader);

        // Compile the shader.
        GLES20.glCompileShader(vertexShaderHandle);

        // Get the compilation status.
        final int[] compileStatus = new int[1];
        GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

        // If the compilation failed, delete the shader.
        if (compileStatus[0] == 0) {
            GLES20.glDeleteShader(vertexShaderHandle);
            vertexShaderHandle = 0;
        }
    }

    if (vertexShaderHandle == 0) {
        throw new RuntimeException("Error creating vertex shader.");
    }

    // Load in the fragment shader shader.
    int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);

    if (fragmentShaderHandle != 0) {
        // Pass in the shader source.
        GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);

        // Compile the shader.
        GLES20.glCompileShader(fragmentShaderHandle);

        // Get the compilation status.
        final int[] compileStatus = new int[1];
        GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

        // If the compilation failed, delete the shader.
        if (compileStatus[0] == 0) {
            GLES20.glDeleteShader(fragmentShaderHandle);
            fragmentShaderHandle = 0;
        }
    }

    if (fragmentShaderHandle == 0) {
        throw new RuntimeException("Error creating fragment shader.");
    }

    // Create a program object and store the handle to it.
    int programHandle = GLES20.glCreateProgram();

    if (programHandle != 0) {
        // Bind the vertex shader to the program.
        GLES20.glAttachShader(programHandle, vertexShaderHandle);
        // Bind the fragment shader to the program.
        GLES20.glAttachShader(programHandle, fragmentShaderHandle);
        // Bind attributes
        GLES20.glBindAttribLocation(programHandle, 0, "a_Position");
        // Link the two shaders together into a program.
        GLES20.glLinkProgram(programHandle);
        // Get the link status.
        final int[] linkStatus = new int[1];
        GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
        // If the link failed, delete the program.
        if (linkStatus[0] == 0) {
            GLES20.glDeleteProgram(programHandle);
            programHandle = 0;
        }
    }

    if (programHandle == 0) {
        throw new RuntimeException("Error creating program.");
    }

    // Set program handles. These will later be used to pass in values to the program.
    mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
    mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");

    // Tell OpenGL to use this program when rendering.
    GLES20.glUseProgram(programHandle);
}

@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
    // Set the OpenGL viewport to the same size as the surface.
    GLES20.glViewport(0, 0, width, height);

    // Create a new perspective projection matrix. The height will stay the same
    // while the width will vary as per aspect ratio.
    final float ratio = (float) width / height;
    final float left = -ratio;
    final float right = ratio;
    final float bottom = -1.0f;
    final float top = 1.0f;
    final float near = 1.0f;
    final float far = 100.0f;

    Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}

@Override
public void onDrawFrame(GL10 glUnused) {
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

    Matrix.setIdentityM(mModelMatrix, 0);
    //Push to the distance - note this will have no effect on a point size
    Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
    Matrix.multiplyMV(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
    Matrix.multiplyMV(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);

    //Send the vertex
    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuf);
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    //Draw the point
    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertices.length/3);

    }
}

2 个答案:

答案 0 :(得分:0)

我怀疑你的两个点的坐标是在可见平截头体之外。尝试用较小的内容替换100.5-100.5,看看是否有帮助。

答案 1 :(得分:0)

您必须同时启用顶点属性和纹理坐标属性

GLES20.glEnableVertexAttribArray(mVertexAttrib)
GLES20.glEnableVertexAttribArray(mTexCoordAttrib)