Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/223.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在OpenGL ES 2.0中,如何从数组中读取4个以上的顶点数据?_Java_Android_Opengl Es_Glsl_Opengl Es 2.0 - Fatal编程技术网

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

Java 在OpenGL ES 2.0中,如何从数组中读取4个以上的顶点数据?,java,android,opengl-es,glsl,opengl-es-2.0,Java,Android,Opengl Es,Glsl,Opengl Es 2.0,我试图在OpenGL ES 2.0中从浮点数组缓冲区中为顶点位置和颜色绘制一个挨着一个的点,但每次绘制只能接受4个顶点。当我添加更多,然后告诉它绘制更多,那么它将只绘制阵列中的2个非相邻顶点。为什么会这样?为什么我不能在一个实例中绘制超过4个顶点?如果可以,怎么做 这里有一个例子。 当我有3*4数组数据时,它会这样绘制它们: ,这是正确完成的 例如,如果我设置3*6数组数据,它不会绘制6个点,它会绘制如下内容: 我的大部分代码都来自opengles课程项目,我仍在学习,不太了解onSurf

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


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

,这是正确完成的

例如,如果我设置
3*6
数组数据,它不会绘制6个点,它会绘制如下内容:


我的大部分代码都来自
opengles
课程项目,我仍在学习,不太了解
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);

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

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

GLES20.glvertexattributepointer(mPositionHandle,3,GLES20.GL_FLOAT,false,3*4,mVertexPos);
GLES20.GlenableVertexAttributeArray(mPositionHandle);
GLES20.glvertexattributepointer(mColorHandle,4,GLES20.GL_FLOAT,false,4*4,mVertexColor);
GLES20.GlenableVertexAttributeArray(mColorHandle);
由于顶点紧密排列,因此步幅可以设置为0。这是由
glvertexattributepointer
提供的特殊情况。当步幅为0时,将通过“大小和类型”参数自动计算步幅

GLES20.glvertexattributepointer(mPositionHandle,3,GLES20.GL_FLOAT,false,0,mVertexPos);
GLES20.GlenableVertexAttributeArray(mPositionHandle);
GLES20.glvertexattributepointer(mColorHandle,4,GLES20.GL_FLOAT,false,0,mVertexColor);
GLES20.GlenableVertexAttributeArray(mColorHandle);
请注意,如果有4个属性,则缓冲区中的元素数(浮点值数)将与连续通用顶点属性之间的字节偏移量一致。因此,4个顶点同时工作,但6个顶点失败。

缓冲区的大小从未明确设置。调用
glDrawArrays
时,启用的顶点属性必须引用一个缓冲区,该缓冲区足够大,可以提供所需的属性。

谢谢!我很高兴接受这个答案,因为它解决了我的问题。非常感谢你用这种方法总结了跨步的实际意义。在
ByteBuffer.allocateDirect
方法中,乘以源数组的长度基本相同。