2
votes

I have an array containing the the height of the vertices of a terrain map. When I first draw the terrain it looks fine:

enter image description here

But as I rotate it across the z-axis, parts of the shape seem to be projected behind vertices on the back:

90 degree rotation (z-axis):

90 degreee rotation

~180 degree rotation (z-axis):

enter image description here

Besides my implementation of the map, my code is fairly simple:

Vertex Shader:

attribute vec4 position;
attribute vec4 color;

uniform mat4 matrix;
varying vec4 interpolated_color;

void main() {
    gl_Position = matrix * position;
    interpolated_color = color;
}

Fragment_shader:

precision mediump float;

varying vec4 interpolated_color;

void main(){
   gl_FragColor = interpolated_color;
}

Renderer:

public class MapRenderer implements GLSurfaceView.Renderer {

    ...

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(1.0f, 0.0f,0.0f, 1.0f);
        map = mapGen.composeMap(); //gets array with vertices heights
        mapView = new MapView(context, map, mapGen);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        float aspect_ratio = (float) width/height;
        Matrix.perspectiveM(projectionMatrix, 0, 45, aspect_ratio, 1f, 10f);
    }


    @Override
    public void onDrawFrame(GL10 gl) {
        float[] scratch = new float[16];

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        Matrix.setIdentityM(modelMatrix, 0);

        Matrix.translateM(modelMatrix, 0, 0, 0, -4);
        Matrix.rotateM(modelMatrix, 0, -cameraAngle, 1, 0, 0); //cameraAngle initialized at 0 changes with user input
        Matrix.rotateM(modelMatrix, 0, mapAngle, 0, 0, 1); //mapAngle initialized at 0 changes with user input

        Matrix.multiplyMM(scratch, 0, projectionMatrix, 0, modelMatrix, 0);

        mapView.draw(scratch);
    }
}

MapView Class:

    public void draw(float[] mvpMatrix){
        int matrix = GLES20.glGetUniformLocation(program, "matrix");

        GLES20.glUniformMatrix4fv(matrix, 1, false, mvpMatrix, 0);

        //nFaces and facesBuffer are class variables
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, nFaces*3, GLES20.GL_UNSIGNED_SHORT, facesBuffer);
    }

I tried to turn on and off face culling to see if any differences occurred but none did. Changing the projection matrix also did not seem to have any effects besides changing the angle the error starts to occur. It seems to happen at ~90 degrees and up to ~270 degrees when using Matrix.perspectiveM and exactly at 90 and 270 when using Matrix.orthoM.

I also checked if OpenGL returned any errors by the glGetErrors() method and did not get anything.

My vertices are sorted in the buffer sequentially from the one located at (-1, 1, 0) to the last one located at (1, -1, 0). I don't know if that could cause this issue or, even if that was the case, how I could solve this in OpenGL ES 2 to support rotation accross the z-axis.

1

1 Answers

2
votes

Depth Test needs to be enabled in order for OpenGL take distance into consideration.

On the Renderer:

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(1.0f, 0.0f,0.0f, 1.0f);

        GLES20.glEnable(GLES20.GL_DEPTH_TEST);

        map = mapGen.composeMap(); //gets array with vertices heights
        mapView = new MapView(context, map, mapGen);
    }