简体   繁体   中英

OpenGL shape drawing inverted around y axis?

Well this is awkward,

I'm trying to follow the simple guide from google to draw using openGL. Now I slightly modified the code there to see how and what's happening, and that immediately "errored out" on me. The code does work fine and display well - but not quite the display I expect it to have.

I'm trying to draw a triangle with the following coordinates (0, 0.75, 0) (-0.5, 0, 0) (0, 0, 0). This should be a triangle with a vertical long side, and a short horizontal side. And the diagonal should go from bottom left to top "right".

As said: I am seeing a triangle: however the second coordinate seems to be "flipped" around the y axis: is a negative x value really "to the right"?

The renderer code:

public class MyGLRenderer implements GLSurfaceView.Renderer {
    private Triangle mTriangle;
    // mMVPMatrix is an abbreviation for "Model View Projection Matrix"
    private final float[] mMVPMatrix = new float[16];
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];    

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        // Set the background frame color
        GLES20.glClearColor(0f, 0f, 0f, 1.0f);
        // initialize a triangle
        float triangleCoords[] = {
                0.0f,  0.75f, 0.0f, // top
                -0.5f, 0f, 0.0f, // bottom left
                0.0f, 0.0f, 0.0f  // bottom right
        };
        mTriangle = new Triangle(triangleCoords);
    }

    public void onDrawFrame(GL10 unused) {
        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        // Set the camera position (View matrix)
        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        // Calculate the projection and view transformation
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

        // Draw shape
        mTriangle.draw(mMVPMatrix);
    }


    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);

        float ratio = (float) width / height;

        // this projection matrix is applied to object coordinates
        // in the onDrawFrame() method
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 2.99f, 7);
    }

    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;
    }
}

And for completeness sake the Triangle class:

public class Triangle {

    private FloatBuffer vertexBuffer;
    // number of coordinates per vertex in this array
    private static final int COORDS_PER_VERTEX = 3;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    private int vertexCount;


    // Set color with red, green, blue and alpha (opacity) values
    private static final float colorDefault[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

    public Triangle(float[] sizes) {

        this.vertexCount = sizes.length / COORDS_PER_VERTEX;
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                sizes.length * 4);
        // use the device hardware's native byte order
        bb.order(ByteOrder.nativeOrder());

        // create a floating point buffer from the ByteBuffer
        vertexBuffer = bb.asFloatBuffer();
        // add the coordinates to the FloatBuffer
        vertexBuffer.put(sizes);
        // set the buffer to read the first coordinate
        vertexBuffer.position(0);

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

        // create empty OpenGL ES Program
        mProgram = GLES20.glCreateProgram();

        // add the vertex shader to program
        GLES20.glAttachShader(mProgram, vertexShader);

        // add the fragment shader to program
        GLES20.glAttachShader(mProgram, fragmentShader);

        // creates OpenGL ES program executables
        GLES20.glLinkProgram(mProgram);
    }




    private final int mProgram;
    private final String vertexShaderCode =
            "uniform mat4 uMVPMatrix;" +
            "attribute vec4 vSizes;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vSizes;" +
                    "}";

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




    public void draw(float[] mvpMatrix) {
        int mSizesHandle;
        int mColorHandle;
        int mMVPMatrixHandle;
        // Add program to OpenGL ES environment
        GLES20.glUseProgram(mProgram);

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

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

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



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

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


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

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


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

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

}

Based on your Matrix code, it looks like you're building a View Matrix that looks at <-3,0,0> from <0,0,0>, and given that your triangle lies flat on the xy plane, it's actually rather miraculous that you're seeing anything at all. So you need to revise how you construct your viewing matrix. I'd also advise that you color the triangle by-vertex so that it's easier to tell where your triangle's vertices are ending up after transformation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM