2D openGL and clipping window

I make a 2D game right now. I draw the background, sprites then the interface.
For the interface, i want to define a drawable zone for some animation. I did some search and it seems that i have to use stencil buffer (that i never used) :


      // How i init openGL
      GL11.glViewport(0,0,800,600);
      GL11.glMatrixMode(GL11.GL_PROJECTION);
      GL11.glLoadIdentity();
      GLU.gluOrtho2D(0.0f, 800, 0.0f, 600);
      GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
      GL11.glLoadIdentity();
      
      GL11.glDisable(GL11.GL_LIGHTING);
      GL11.glDisable(GL11.GL_DEPTH_TEST);
      GL11.glEnable(GL11.GL_TEXTURE_2D);
      GL11.glEnable(GL11.GL_BLEND);
      GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE_MINUS_SRC_ALPHA);
      
      GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);


       ...

      // Where i want to do the clipping window

      Sprite sp1 = sprites[items[selected]];
      Sprite sp2 = sprites[items[next]];
                 
      GL11.glClearStencil(0);
      GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
      GL11.glEnable(GL11.GL_STENCIL_TEST);
      GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
      GL11.glStencilOp(GL11.GL_REPLACE,GL11.GL_REPLACE,GL11.GL_REPLACE);
      GL11.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
      GL11.glDisable(GL11.GL_TEXTURE_2D);
      GL11.glBegin(GL11.GL_QUADS);
        GL11.glVertex2f(800-48, 600-48);
        GL11.glVertex2f(800-16, 600-48);
        GL11.glVertex2f(800-16, 600-16);
        GL11.glVertex2f(800-48, 600-16);
      GL11.glEnd();
      
      GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1);
      GL11.glStencilOp(GL11.GL_KEEP,GL11.GL_KEEP,GL11.GL_KEEP);
      
      GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
      GL11.glEnable(GL11.GL_TEXTURE_2D);
      
      if(sp1 != null)
      {
        sp1.draw(800-48-dir*compt*2,600-48,false,false);
      }
      
      if(sp2 != null)
      {
        sp2.draw(800-48-dir*compt*2+dir*32,600-48,false,false);
      }
      
      GL11.glDisable(GL11.GL_STENCIL_TEST);

There is a red scare where i want to setup my cliping window. Sprites show inside and outside the cliping window.
It must be a stupid mistake…

You need to turn off colour writing when you draw your red square to set your stencil region. IIRC it’s glColorMask(false, false, false, false).

Alternatively, if you only want rectangular clipping regions then glScissor is much easier to use.

Thanks for the reply.

I was looking for the glScissor function ;D. With it, it work.
But i didn’t manage to make it work with stencil :’(


      Sprite sp1 = sprites[items[selected]];
      Sprite sp2 = sprites[items[next]];
      
      GL11.glEnable(GL11.GL_STENCIL_TEST);
      GL11.glClearStencil(0);
      GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
      GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
      GL11.glStencilOp(GL11.GL_KEEP,GL11.GL_KEEP,GL11.GL_REPLACE);
      GL11.glColorMask(false,false,false,false);
      GL11.glDisable(GL11.GL_TEXTURE_2D);
      GL11.glBegin(GL11.GL_QUADS);
        GL11.glVertex2f(800-48, 600-48);
        GL11.glVertex2f(800-16, 600-48);
        GL11.glVertex2f(800-16, 600-16);
        GL11.glVertex2f(800-48, 600-16);
      GL11.glEnd();
      
      GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1);
      GL11.glStencilOp(GL11.GL_KEEP,GL11.GL_KEEP,GL11.GL_KEEP);
      GL11.glColorMask(true,true,true,true);
      GL11.glEnable(GL11.GL_TEXTURE_2D);
      
    /*  GL11.glEnable(GL11.GL_SCISSOR_TEST);
      GL11.glScissor(800-48, 600-48, 32, 32);*/
      
      if(sp1 != null)
      {
        sp1.draw(800-48-dir*compt*2,600-48,false,false);
      }
      
      if(sp2 != null)
      {
        sp2.draw(800-48-dir*compt*2+dir*32,600-48,false,false);
      }
      
      //GL11.glDisable(GL11.GL_SCISSOR_TEST);
      
      GL11.glDisable(GL11.GL_STENCIL_TEST);

Is stencil buffer on all graphic card ? I try to look for something about stencil in opengl capabilities but I didn’t find it.

You also need to specify that you want a stencil buffer when creating your display, but I forget how to do that with Jogl. Try glGet(GL_STENCIL_BITS) and make sure it’s >0.

Yes !!! ;D


      PixelFormat pixelFormat = new PixelFormat();

      int depth = pixelFormat.getDepthBits();
      int alpha = pixelFormat.getAlphaBits();
      int stencil = 1;
      
      pixelFormat = new PixelFormat(alpha,depth,stencil);

      Display.create(pixelFormat);

It create a display with a stencil buffer and it works fine.

Thanks :wink: