androidopengl-esglsurfaceview

glBufferSubData not working in GLSurfaceView.Renderer.onDrawFrame


I use GLSurfaceView to draw three points in native code, it worked great until I tried changed the point's position in GLSurfaceView.Renderer.onDrawFrame method.

Instead of changing the position of the point, glBufferSubData method caused the point to be lost, the glMapBufferRange causes the same problem.

The render class of my GLSurfaceView code:

private static class Renderer implements GLSurfaceView.Renderer {

    private final GLSurfaceView glSurfaceView;

    private Renderer(GLSurfaceView glSurfaceView) {
        this.glSurfaceView = glSurfaceView;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        NativeMethod.nSurfaceCreated(glSurfaceView.getContext().getAssets());
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        NativeMethod.nSurfaceChanged(width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        NativeMethod.nDrawFrame();
    }
}

And in native code:

JNIEXPORT void JNICALL
Java_xxx_NativeMethod_nSurfaceCreated(JNIEnv *env, jclass clazz, jobject asset_manager) {
    renderer = create_program_from_assets(env, asset_manager, "vertex_shader.glsl", "fragment_shader.glsl");

    glUseProgram(renderer);
    glClearColor(1.0F, 1.0F, 1.0F, 1.0F);

    glGenVertexArrays(1, vao);
    glBindVertexArray(vao[0]);

    glGenBuffers(1, vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vao[0]);
    float vertices[] = {
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            0.0f, 0.5f, 0.0f
    };
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *) 0);
    glEnableVertexAttribArray(0);
}

JNIEXPORT void JNICALL
Java_xxx_NativeMethod_nSurfaceChanged(JNIEnv *env, jclass clazz, jint width, jint height) {
    glViewport(0, 0, width, height);
}

JNIEXPORT void JNICALL
Java_xxx_NativeMethod_nDrawFrame(JNIEnv *env, jclass clazz) {
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawArrays(GL_POINTS, 0, 3);
}

The code is simple and works well. It can display three points on the screen:

three points on the screen

But when I changed the point's position using glBufferSubData, the point will be lost:

JNIEXPORT void JNICALL
Java_xxx_NativeMethod_nDrawFrame(JNIEnv *env, jclass clazz) {
    glClear(GL_COLOR_BUFFER_BIT);
    float vertex_fr[] = {0.0F, 0.0F, 10.0F};
    glBufferSubData(GL_ARRAY_BUFFER, 0 , sizeof(vertex_fr), vertex_fr);
    glDrawArrays(GL_POINTS, 0, 3);
}

As you can see, the first point should be placed in the center of screen, But what happened is that the first point is missing:

only two points left I have tried some code, I found that if I tried to changed a point, the point will be lost, and this problem alse happened with glMapBufferRange.

Is the buffer cannot be changed in GLSurfaceView.Renderer.onDrawFrame? or is there some wrong with my code?

thanks.


Solution

  • You do not set a projection matrix, so the near plane is 1 and the far plane is -1. The Z coordinate must be between the near and far planes, otherwise the geometry will be clipped. Change. the Z coordinate:

    float vertex_fr[] = {0.0F, 0.0F, 10.0F};

    float vertex_fr[] = {0.0f, 0.0f, 0.5f};