Android OpenGL ES 2,绘制方块

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11806690/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:55:27  来源:igfitidea点击:

Android OpenGL ES 2, Drawing squares

androidopengl-es-2.0

提问by Jon W

EDIT: Problem solved!So I've been going through the official OpenGL ES 2 tutorials for Android, and I've gotten to the part that involves drawing shapes, but I can't seem to get a square to work. It draws a right triangle instead.

编辑:问题解决了!因此,我一直在阅读适用于 Android 的官方 OpenGL ES 2 教程,并且已经了解了涉及绘制形状的部分,但我似乎无法让正方形起作用。相反,它绘制了一个直角三角形。

I've included the code that I'm using to define and draw the shape, which is copied almost exactly from the tutorial. The Renderer class simply creates an instance of this shape and calls the draw method.

我已经包含了用于定义和绘制形状的代码,该代码几乎完全从教程中复制而来。Renderer 类只是创建此形状的一个实例并调用 draw 方法。

For some reason, the tutorial does not give the values/declaration for vertexStride and vertexCount, so the ones I have in there are educated guesses. I've tried several values for vertexCount (1 thru 12), and none work.

出于某种原因,本教程没有给出 vertexStride 和 vertexCount 的值/声明,所以我在那里的那些是有根据的猜测。我已经为 vertexCount (1 到 12) 尝试了几个值,但没有一个工作。

Thanks in advance.

提前致谢。

            public class Square {

                private FloatBuffer vertexBuffer;
                private ShortBuffer drawListBuffer;

                // number of coordinates per vertex in this array
                static final int COORDS_PER_VERTEX = 3;
                static float squareCoords[] = { -0.5f,  0.5f, 0.0f,   // top left
                                                -0.5f, -0.5f, 0.0f,   // bottom left
                                                 0.5f, -0.5f, 0.0f,   // bottom right
                                                 0.5f,  0.5f, 0.0f }; // top right

                private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
                float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };


                private final String vertexShaderCode =
                        "attribute vec4 vPosition;" +
                        "void main() {" +
                        "  gl_Position = vPosition;" +
                        "}";

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

                int mProgram;

                static final int vertexStride = COORDS_PER_VERTEX * 4;
                static final int vertexCount = 4;

                public Square() {
                    // initialize vertex byte buffer for shape coordinates
                    ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); // (# of coordinate values * 4 bytes per float)
                    bb.order(ByteOrder.nativeOrder());
                    vertexBuffer = bb.asFloatBuffer();
                    vertexBuffer.put(squareCoords);
                    vertexBuffer.position(0);

                    // initialize byte buffer for the draw list
                    ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2); // (# of coordinate values * 2 bytes per short)
                    dlb.order(ByteOrder.nativeOrder());
                    drawListBuffer = dlb.asShortBuffer();
                    drawListBuffer.put(drawOrder);
                    drawListBuffer.position(0);


                    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
                    int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

                    mProgram = GLES20.glCreateProgram();             // create empty OpenGL ES Program
                    GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
                    GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
                    GLES20.glLinkProgram(mProgram);                  // creates OpenGL ES program executables
                }

                public static int loadShader(int type, String shaderCode){

                    // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
                    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
                    int shader = GLES20.glCreateShader(type);

                    // add the source code to the shader and compile it
                    GLES20.glShaderSource(shader, shaderCode);
                    GLES20.glCompileShader(shader);

                    return shader;
                }

                public void draw() {
                    // Add program to OpenGL ES environment
                    GLES20.glUseProgram(mProgram);

                    // get handle to vertex shader's vPosition member
                    int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

                    // Enable a handle to the triangle vertices
                    GLES20.glEnableVertexAttribArray(mPositionHandle);

                    // Prepare the triangle coordinate data
                    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                                                 GLES20.GL_FLOAT, false,
                                                 vertexStride, vertexBuffer);

                    // get handle to fragment shader's vColor member
                    int mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

                    // Set color for drawing the triangle
                    GLES20.glUniform4fv(mColorHandle, 1, color, 0);

                    // Draw the triangle
                    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

                    // Disable vertex array
                    GLES20.glDisableVertexAttribArray(mPositionHandle);
                }
            }

回答by Nate-Wilkins

vertexCount = squareCoords.length/COORDS_PER_VERTEX; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z) 
vertexStride = COORDS_PER_VERTEX * 4;                //4 are how many bytes in a float

Let me know if that worked out for you, good luck.

如果这对你有用,请告诉我,祝你好运。

I think your also missing the ModelViewProjectionMatrix used to convert 3D space to 2D screen space. mvpMatrix should be passed in by the draw function draw(float[] mvpMatrix)Forgot to mention you also should use DrawElements(...)(used in example) if you do there's no need for the count or stride, just the length of an idicies array and a drawing buffer.

我认为您还缺少ModelViewProjection用于将 3D 空间转换为 2D 屏幕空间的矩阵。mvpMatrix 应该由 draw 函数传入draw(float[] mvpMatrix)忘记提到你也应该使用DrawElements(...)(在示例中使用)如果你不需要计数或步幅,只需要一个 idicies 数组和一个绘图缓冲区的长度。

    // Get handle to shape's transformation matrix
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

    // Apply the projection and view transformation
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

    // Draw the square
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
                          GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

回答by mrfelis

The tutorial is missing some steps: the final code for the square is here.

该教程缺少一些步骤:方块的最终代码在这里

The example was intended to use glDrawElementsinstead of glDrawArrayswhich is indicated by the presence of the line: private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices.

该示例旨在使用以下行glDrawElements来代替glDrawArrayswhich :private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices

This array specifies the desired vertices of 2 triangles. 0, 1 and 2 for the first. Then 0, 2 and 3 for the second. GL_TRANGLE_FANjust happens to work because it will draw the next triangle using the first vertex in the buffer, the last vertex used in previous triangle and the next vertex. For the second triangle this is 0, 2 and 3. Then 0, 3 and 4, etc. Had vertex 2 been 5, 5 and vertex 3 been -5, 5, the resulting fan would not have been a square.

此数组指定 2 个三角形的所需顶点。第一个为 0、1 和 2。然后是第二个 0、2 和 3。GL_TRANGLE_FAN恰好可以工作,因为它将使用缓冲区中的第一个顶点、前一个三角形中使用的最后一个顶点和下一个顶点绘制下一个三角形。对于第二个三角形,这是 0、2 和 3。然后是 0、3 和 4,依此类推。如果顶点 2 是 5、5 并且顶点 3 是 -5、5,则生成的扇形不会是正方形。

Replace these lines:

替换这些行:

// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

With these:

用这些:

// Draw the square
GLES20.glDrawElements(
    GLES20.GL_TRIANGLES, drawOrder.length,
    GLES20.GL_UNSIGNED_SHORT, drawListBuffer);