Search code examples
androidopengl-esrenderpartial

Using glScissor in android OpenGL


I want to render only a party of my screen according to my internal app logic. But i am facing issues giving parameters to glScissor.

This is my onDrawFrame method:

@Override
public void onDrawFrame(GL10 gl) {
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();

    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    gl.glShadeModel(GL10.GL_FLAT);
    gl.glEnable(GL10.GL_TEXTURE_2D);

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glPushMatrix();
    gl.glScissor(250,250,300,300);

    gl.glEnable(GL10.GL_SCISSOR_TEST);

    gl.glViewport(250,250,300,300);

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

    attack.draw(gl);

    gl.glDisable(GL10.GL_SCISSOR_TEST);

    gl.glPopMatrix();
}

250,250,300,300 are just values i gave for testing... But the screen content is drawn at multiple places of the screen repetitively....

I am mapping my screen cordinates to OpenGL cordinates in my attact.draw (attack is the object of one of my class) using 2*x/width-1 , 2*y/height-1

Can someone tell me what mistake i am doing using glScissor and guide me through to the correct way of doing it.


Solution

  • The problem is most likely that you're not clearing the whole rendering surface. In general (not considering extensions that can change the behavior), you need to either clear the whole surface, or make sure that you cover all the pixels during your rendering, each time you redraw. Any parts of the frame that are not cleared/rendered will be undefined. What looks like repetitive drawing could be just undefined content.

    The reason you're not clearing the whole surface is that the scissor test applies to glClear(). So with the scissor test enabled, and a scissor rectangle set, only that rectangle will be cleared.

    To fix this, you can simply change the order of the calls to:

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    
    gl.glScissor(250, 250, 300, 300);
    gl.glEnable(GL10.GL_SCISSOR_TEST);
    

    With this order, the scissor test will not be enabled when glClear() is called, and the whole surface will be cleared.