#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glut.h>


void Draw(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

  glStencilFunc(GL_ALWAYS, 1, 1);
  glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
                                   ^
                                   |    
                     /* lo stencil test passa sempre e ha successo anche il depth buffer
                        quindi viene caricato ad 1 il valore dello Stencil Buffer nel triangolo rosso*/

  /* red triangle */
  glColor3ub(200, 0, 0);
  glBegin(GL_POLYGON);
  glVertex3i(-4, -4, 0);
  glVertex3i(4, -4, 0);
  glVertex3i(0, 4, 0);
  glEnd();

  glStencilFunc(GL_EQUAL, 1, 1);



         /* nella zona esterna al triangolo rosso il test fallisce e lo Stencil Buffer viene
            incrementato dove viene specificato il rettangolo verde*/    
                 ^
                 |
  glStencilOp(GL_INCR, GL_KEEP, GL_DECR);
                                   ^
                                   |    
         /* lo stencil test passa nella regione dove prima e' stato disegnato il triangolo
            rosso e in questa regione viene disegnato il quadrato verde e lo Stencil buffer 
            viene decrementato*/

  /* green square */
  glColor3ub(0, 200, 0);
  glBegin(GL_POLYGON);
  glVertex3i(3, 3, 0);
  glVertex3i(-3, 3, 0);
  glVertex3i(-3, -3, 0);
  glVertex3i(3, -3, 0);
  glEnd();

  glStencilFunc(GL_EQUAL, 1, 1);
  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
                                   ^
                                   |    
         /* lo stencil test passa nella regione esterna al triangolo rosso e interna al quadrato
            verde, in questa zona viene disegnato il quadrato blu*/

  // blue square 
  glColor3ub(0, 0, 200);
  glBegin(GL_POLYGON);
  glVertex3i(3, 3, 0);
  glVertex3i(-3, 3, 0);
  glVertex3i(-3, -3, 0);
  glVertex3i(3, -3, 0);
  glEnd();

  
  glFlush();
}



int main(int argc, char **argv)
{
  GLenum type;

  glutInit(&argc, argv);
  
  type = GLUT_RGB | GLUT_STENCIL;
  glutInitDisplayMode(type);
  glutCreateWindow("Stencil Test");

  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClearStencil(0);
  glStencilMask(1);
  glEnable(GL_STENCIL_TEST);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0);
  glMatrixMode(GL_MODELVIEW);

  glutDisplayFunc(Draw);
  glutMainLoop();
  return 0;             /* ANSI C requires main to return int. */
}