有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在OpenGL ES 2.0中从数组中读取4个以上的顶点数据?

我试图从浮点数组缓冲区中为顶点位置和颜色在OpenGL ES 2.0中一个接一个地绘制点,但每次绘制只能接受4个顶点。当我添加更多,然后告诉它绘制更多,那么它将只绘制阵列中的2个非相邻顶点。为什么会这样?为什么我不能在一个实例中绘制超过4个顶点?如果可以,怎么做


这里有一个例子。 当我有3*4数组数据时,它会这样绘制它们:

. . . .,这是正确的

例如,如果我设置3*6数组数据,它不会画6个点,它画的是这样的:

. .


我的大部分代码来自OpenGL ES课程项目,我仍在学习,不太了解onSurfaceCreated中的事情是如何完成的

以下是我的OpenGLRenderer类:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    ...

    final String vertexShader =
            "uniform mat4 u_MVPMatrix;      \n"                 // A constant representing the combined model/view/projection matrix.

                    + "attribute vec4 a_Position;     \n"       // Per-vertex position information we will pass in.
                    + "attribute vec4 a_Color;        \n"       // Per-vertex color information we will pass in.

                    + "varying vec4 v_Color;          \n"       // This will be passed into the fragment shader.

                    + "void main()                    \n"       // The entry point for our vertex shader.
                    + "{                              \n"
                    + "   v_Color = a_Color;          \n"       // Pass the color through to the fragment shader.
                                                                // It will be interpolated across the triangle.
                    + "   gl_Position = u_MVPMatrix   \n"       // gl_Position is a special variable used to store the final position.
                    + "               * a_Position;   \n"       // Multiply the vertex by the matrix to get the final point in
                    + "}                              \n";      // normalized screen coordinates.

    final String fragmentShader =
            "precision mediump float;       \n"                 // Set the default precision to medium. We don't need as high of a
                                                                // precision in the fragment shader.
                    + "varying vec4 v_Color;          \n"       // This is the color from the vertex shader interpolated across the
                                                                // triangle per fragment.
                    + "void main()                    \n"       // The entry point for our fragment shader.
                    + "{                              \n"
                    + "   gl_FragColor = v_Color;     \n"       // Pass the color directly through the pipeline.
                    + "}                              \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");
        GLES20.glBindAttribLocation(programHandle, 1, "a_Color");

        // 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");
    mColorHandle = GLES20.glGetAttribLocation(programHandle, "a_Color");

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

}

指出要点:

@Override
public void onDrawFrame(GL10 gl) {

    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

    Matrix.setIdentityM(mModelMatrix, 0);

    drawPoints();

}

// Like I said, 4 and below works without any issue
private final int vertexesToDraw = 6;

// x, y, z (z being upwards)
private final float[] vertexPosData = {
        0.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f,
        2.0f, 0.0f, 0.0f,
        3.0f, 0.0f, 0.0f,
        4.0f, 0.0f, 0.0f,
        5.0f, 0.0f, 0.0f
};

// red, green, blue, alpha
private final float[] vertexColorData = {
        1.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f
};

FloatBuffer mVertexPos, mVertexColor;

// this gets initialized first
private void setupPoints() {

    mVertexPos = ByteBuffer.allocateDirect(vertexPosData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
    mVertexPos.put(vertexPosData).position(0);
    mVertexPos.position(0);

    mVertexColor = ByteBuffer.allocateDirect(vertexColorData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
    mVertexColor.put(vertexColorData).position(0);
    mVertexColor.position(0);

}

private void drawPoints() {

    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * vertexesToDraw, mVertexPos);
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, 4 * vertexesToDraw, mVertexColor);
    GLES20.glEnableVertexAttribArray(mColorHandle);

    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);

    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexesToDraw);

}

共 (1) 个答案

  1. # 1 楼答案

    ^{}的第五个参数是连续通用顶点属性(stride)之间的字节偏移量,而不是缓冲区中的元素数

    这意味着,对于类型为float(float的大小为4字节)且元组大小为3(例如x、y、z坐标)的属性,步长参数必须为4*3=12
    对于元组大小为4(RGBA颜色)的属性,步幅参数必须为4*4=16

    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, mVertexPos);
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    
    GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, 4 * 4, mVertexColor);
    GLES20.glEnableVertexAttribArray(mColorHandle);
    

    由于顶点紧密排列,步长可以设置为0。这是一个特例,由glVertexAttribPointer提供。当步幅为0时,则由大小类型参数自动计算

    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, mVertexPos);
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    
    GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, 0, mVertexColor);
    GLES20.glEnableVertexAttribArray(mColorHandle);
    

    请注意,如果有4个属性,则缓冲区中的元素数(浮点值数)与连续通用顶点属性之间的字节偏移量一致。因此,4个顶点同时工作,但6个顶点失败
    缓冲区的大小从未明确设置。调用glDrawArrays时,启用的顶点属性必须引用一个缓冲区,该缓冲区足够大,可以提供所需的属性