Edit

kc3-lang/angle/samples/gles2_book/Stencil_Test

Branch :

  • Show log

    Commit

  • Author : Geoff Lang
    Date : 2013-10-07 17:18:14
    Hash : 7c697201
    Message : Deleted manually maintained visual studio projects and replaced them with gyp generated ones.

  • Stencil_Test.c
  • //
    // Book:      OpenGL(R) ES 2.0 Programming Guide
    // Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
    // ISBN-10:   0321502795
    // ISBN-13:   9780321502797
    // Publisher: Addison-Wesley Professional
    // URLs:      http://safari.informit.com/9780321563835
    //            http://www.opengles-book.com
    //
    
    // Stencil_Test.c
    //
    //    This example shows various stencil buffer
    //    operations.
    //
    #include <stdlib.h>
    #include "esUtil.h"
    
    typedef struct
    {
       // Handle to a program object
       GLuint programObject;
    
       // Attribute locations
       GLint  positionLoc;
    
       // Uniform locations
       GLint  colorLoc;
    
    } UserData;
    
    ///
    // Initialize the shader and program object
    //
    int Init ( ESContext *esContext )
    {
       UserData *userData = esContext->userData;
       GLbyte vShaderStr[] =  
          "attribute vec4 a_position;   \n"
          "void main()                  \n"
          "{                            \n"
          "   gl_Position = a_position; \n"
          "}                            \n";
       
       GLbyte fShaderStr[] =  
          "precision mediump float;  \n"
          "uniform vec4  u_color;    \n"
          "void main()               \n"
          "{                         \n"
          "  gl_FragColor = u_color; \n"
          "}                         \n";
    
       // Load the shaders and get a linked program object
       userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
    
       // Get the attribute locations
       userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
       
       // Get the sampler location
       userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
    
       // Set the clear color
       glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
       
       // Set the stencil clear value
       glClearStencil ( 0x1 );
    
       // Set the depth clear value
       glClearDepthf( 0.75f );
    
       // Enable the depth and stencil tests
       glEnable( GL_DEPTH_TEST );
       glEnable( GL_STENCIL_TEST );
    
       return TRUE;
    }
    
    ///
    // Initialize the stencil buffer values, and then use those
    //   values to control rendering
    //
    void Draw ( ESContext *esContext )
    {
       int  i;
    
       UserData *userData = esContext->userData;
    
       GLfloat vVertices[] = { 
           -0.75f,  0.25f,  0.50f, // Quad #0
           -0.25f,  0.25f,  0.50f,
           -0.25f,  0.75f,  0.50f,
           -0.75f,  0.75f,  0.50f,
    	    0.25f,  0.25f,  0.90f, // Quad #1
    		0.75f,  0.25f,  0.90f,
    		0.75f,  0.75f,  0.90f,
    		0.25f,  0.75f,  0.90f,
    	   -0.75f, -0.75f,  0.50f, // Quad #2
           -0.25f, -0.75f,  0.50f,
           -0.25f, -0.25f,  0.50f,
           -0.75f, -0.25f,  0.50f,
            0.25f, -0.75f,  0.50f, // Quad #3
            0.75f, -0.75f,  0.50f,
            0.75f, -0.25f,  0.50f,
            0.25f, -0.25f,  0.50f,
           -1.00f, -1.00f,  0.00f, // Big Quad
            1.00f, -1.00f,  0.00f,
            1.00f,  1.00f,  0.00f,
           -1.00f,  1.00f,  0.00f
       };
    
       GLubyte indices[][6] = { 
           {  0,  1,  2,  0,  2,  3 }, // Quad #0
           {  4,  5,  6,  4,  6,  7 }, // Quad #1
           {  8,  9, 10,  8, 10, 11 }, // Quad #2
           { 12, 13, 14, 12, 14, 15 }, // Quad #3
           { 16, 17, 18, 16, 18, 19 }  // Big Quad
       };
       
    #define NumTests  4
       GLfloat  colors[NumTests][4] = { 
           { 1.0f, 0.0f, 0.0f, 1.0f },
           { 0.0f, 1.0f, 0.0f, 1.0f },
           { 0.0f, 0.0f, 1.0f, 1.0f },
           { 1.0f, 1.0f, 0.0f, 0.0f }
       };
    
       GLint   numStencilBits;
       GLuint  stencilValues[NumTests] = { 
          0x7, // Result of test 0
          0x0, // Result of test 1
          0x2, // Result of test 2
          0xff // Result of test 3.  We need to fill this
               //  value in a run-time
       };
    
       // Set the viewport
       glViewport ( 0, 0, esContext->width, esContext->height );
       
       // Clear the color, depth, and stencil buffers.  At this
       //   point, the stencil buffer will be 0x1 for all pixels
       glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
    
       // Use the program object
       glUseProgram ( userData->programObject );
    
       // Load the vertex position
       glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 
                               GL_FALSE, 0, vVertices );
      
       glEnableVertexAttribArray ( userData->positionLoc );
    
       // Test 0:
       //
       // Initialize upper-left region.  In this case, the
       //   stencil-buffer values will be replaced because the
       //   stencil test for the rendered pixels will fail the
       //   stencil test, which is
       //
       //        ref   mask   stencil  mask
       //      ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
       //
       //   The value in the stencil buffer for these pixels will
       //   be 0x7.
       //
       glStencilFunc( GL_LESS, 0x7, 0x3 );
       glStencilOp( GL_REPLACE, GL_DECR, GL_DECR );
       glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] );
     
       // Test 1:
       //
       // Initialize the upper-right region.  Here, we'll decrement
       //   the stencil-buffer values where the stencil test passes
       //   but the depth test fails.  The stencil test is
       //
       //        ref  mask    stencil  mask
       //      ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
       //
       //    but where the geometry fails the depth test.  The
       //    stencil values for these pixels will be 0x0.
       //
       glStencilFunc( GL_GREATER, 0x3, 0x3 );
       glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
       glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] );
    
       // Test 2:
       //
       // Initialize the lower-left region.  Here we'll increment 
       //   (with saturation) the stencil value where both the
       //   stencil and depth tests pass.  The stencil test for
       //   these pixels will be
       //
       //        ref  mask     stencil  mask
       //      ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
       //
       //   The stencil values for these pixels will be 0x2.
       //
       glStencilFunc( GL_EQUAL, 0x1, 0x3 );
       glStencilOp( GL_KEEP, GL_INCR, GL_INCR );
       glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] );
    
       // Test 3:
       //
       // Finally, initialize the lower-right region.  We'll invert
       //   the stencil value where the stencil tests fails.  The
       //   stencil test for these pixels will be
       //
       //        ref   mask    stencil  mask
       //      ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
       //
       //   The stencil value here will be set to ~((2^s-1) & 0x1),
       //   (with the 0x1 being from the stencil clear value),
       //   where 's' is the number of bits in the stencil buffer
       //
       glStencilFunc( GL_EQUAL, 0x2, 0x1 );
       glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP );
       glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] );
       
       // Since we don't know at compile time how many stecil bits are present,
       //   we'll query, and update the value correct value in the
       //   stencilValues arrays for the fourth tests.  We'll use this value
       //   later in rendering.
       glGetIntegerv( GL_STENCIL_BITS, &numStencilBits );
       
       stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff;
    
       // Use the stencil buffer for controlling where rendering will
       //   occur.  We diable writing to the stencil buffer so we
       //   can test against them without modifying the values we
       //   generated.
       glStencilMask( 0x0 );
       
       for ( i = 0; i < NumTests; ++i )
       {
          glStencilFunc( GL_EQUAL, stencilValues[i], 0xff );
          glUniform4fv( userData->colorLoc, 1, colors[i] );
          glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] );
       }
    
       eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
    }
    
    ///
    // Cleanup
    //
    void ShutDown ( ESContext *esContext )
    {
       UserData *userData = esContext->userData;
    
       // Delete program object
       glDeleteProgram ( userData->programObject );
    }
    
    
    int main ( int argc, char *argv[] )
    {
       ESContext esContext;
       UserData  userData;
    
       esInitContext ( &esContext );
       esContext.userData = &userData;
    
       esCreateWindow ( &esContext, TEXT("Stencil Test"), 320, 240,
                        ES_WINDOW_RGB | ES_WINDOW_DEPTH | ES_WINDOW_STENCIL );
       
       if ( !Init ( &esContext ) )
          return 0;
    
       esRegisterDrawFunc ( &esContext, Draw );
       
       esMainLoop ( &esContext );
    
       ShutDown ( &esContext );
    }