Skip to content
This repository
Browse code

add glbook files

  • Loading branch information...
commit 08c5da62a0cbccd4f4d51987269bd078ab5fd89e 1 parent 3bb7818
Alon Zakai authored

Showing 21 changed files with 4,249 additions and 0 deletions. Show diff stats Hide diff stats

  1. +213 0 tests/glbook/Chapter_10/MultiTexture/MultiTexture.c
  2. BIN  tests/glbook/Chapter_10/MultiTexture/basemap.tga
  3. BIN  tests/glbook/Chapter_10/MultiTexture/lightmap.tga
  4. +302 0 tests/glbook/Chapter_11/Multisample/Multisample.c
  5. +273 0 tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c
  6. +294 0 tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c
  7. BIN  tests/glbook/Chapter_13/ParticleSystem/smoke.tga
  8. +306 0 tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c
  9. +193 0 tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c
  10. +196 0 tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c
  11. +348 0 tests/glbook/Chapter_9/MipMap2D/MipMap2D.c
  12. +199 0 tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c
  13. +227 0 tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c
  14. +257 0 tests/glbook/Chapter_9/TextureWrap/TextureWrap.c
  15. +155 0 tests/glbook/Common/esShader.c
  16. +280 0 tests/glbook/Common/esShapes.c
  17. +213 0 tests/glbook/Common/esTransform.c
  18. +420 0 tests/glbook/Common/esUtil.c
  19. +281 0 tests/glbook/Common/esUtil.h
  20. +60 0 tests/glbook/Makefile
  21. +32 0 tests/glbook/README.linux
213 tests/glbook/Chapter_10/MultiTexture/MultiTexture.c
... ... @@ -0,0 +1,213 @@
  1 +//
  2 +// Book: OpenGL(R) ES 2.0 Programming Guide
  3 +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
  4 +// ISBN-10: 0321502795
  5 +// ISBN-13: 9780321502797
  6 +// Publisher: Addison-Wesley Professional
  7 +// URLs: http://safari.informit.com/9780321563835
  8 +// http://www.opengles-book.com
  9 +//
  10 +
  11 +// MultiTexture.c
  12 +//
  13 +// This is an example that draws a quad with a basemap and
  14 +// lightmap to demonstrate multitexturing.
  15 +//
  16 +#include <stdlib.h>
  17 +#include "esUtil.h"
  18 +
  19 +typedef struct
  20 +{
  21 + // Handle to a program object
  22 + GLuint programObject;
  23 +
  24 + // Attribute locations
  25 + GLint positionLoc;
  26 + GLint texCoordLoc;
  27 +
  28 + // Sampler locations
  29 + GLint baseMapLoc;
  30 + GLint lightMapLoc;
  31 +
  32 + // Texture handle
  33 + GLuint baseMapTexId;
  34 + GLuint lightMapTexId;
  35 +
  36 +} UserData;
  37 +
  38 +
  39 +///
  40 +// Load texture from disk
  41 +//
  42 +GLuint LoadTexture ( char *fileName )
  43 +{
  44 + int width,
  45 + height;
  46 + char *buffer = esLoadTGA ( fileName, &width, &height );
  47 + GLuint texId;
  48 +
  49 + if ( buffer == NULL )
  50 + {
  51 + esLogMessage ( "Error loading (%s) image.\n", fileName );
  52 + return 0;
  53 + }
  54 +
  55 + glGenTextures ( 1, &texId );
  56 + glBindTexture ( GL_TEXTURE_2D, texId );
  57 +
  58 + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
  59 + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  60 + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  61 + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
  62 + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
  63 +
  64 + free ( buffer );
  65 +
  66 + return texId;
  67 +}
  68 +
  69 +
  70 +
  71 +///
  72 +// Initialize the shader and program object
  73 +//
  74 +int Init ( ESContext *esContext )
  75 +{
  76 + UserData *userData = esContext->userData;
  77 + GLbyte vShaderStr[] =
  78 + "attribute vec4 a_position; \n"
  79 + "attribute vec2 a_texCoord; \n"
  80 + "varying vec2 v_texCoord; \n"
  81 + "void main() \n"
  82 + "{ \n"
  83 + " gl_Position = a_position; \n"
  84 + " v_texCoord = a_texCoord; \n"
  85 + "} \n";
  86 +
  87 + GLbyte fShaderStr[] =
  88 + "precision mediump float; \n"
  89 + "varying vec2 v_texCoord; \n"
  90 + "uniform sampler2D s_baseMap; \n"
  91 + "uniform sampler2D s_lightMap; \n"
  92 + "void main() \n"
  93 + "{ \n"
  94 + " vec4 baseColor; \n"
  95 + " vec4 lightColor; \n"
  96 + " \n"
  97 + " baseColor = texture2D( s_baseMap, v_texCoord ); \n"
  98 + " lightColor = texture2D( s_lightMap, v_texCoord ); \n"
  99 + " gl_FragColor = baseColor * (lightColor + 0.25); \n"
  100 + "} \n";
  101 +
  102 + // Load the shaders and get a linked program object
  103 + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
  104 +
  105 + // Get the attribute locations
  106 + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
  107 + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
  108 +
  109 + // Get the sampler location
  110 + userData->baseMapLoc = glGetUniformLocation ( userData->programObject, "s_baseMap" );
  111 + userData->lightMapLoc = glGetUniformLocation ( userData->programObject, "s_lightMap" );
  112 +
  113 + // Load the textures
  114 + userData->baseMapTexId = LoadTexture ( "basemap.tga" );
  115 + userData->lightMapTexId = LoadTexture ( "lightmap.tga" );
  116 +
  117 + if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
  118 + return FALSE;
  119 +
  120 + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
  121 + return TRUE;
  122 +}
  123 +
  124 +///
  125 +// Draw a triangle using the shader pair created in Init()
  126 +//
  127 +void Draw ( ESContext *esContext )
  128 +{
  129 + UserData *userData = esContext->userData;
  130 + GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0
  131 + 0.0f, 0.0f, // TexCoord 0
  132 + -0.5f, -0.5f, 0.0f, // Position 1
  133 + 0.0f, 1.0f, // TexCoord 1
  134 + 0.5f, -0.5f, 0.0f, // Position 2
  135 + 1.0f, 1.0f, // TexCoord 2
  136 + 0.5f, 0.5f, 0.0f, // Position 3
  137 + 1.0f, 0.0f // TexCoord 3
  138 + };
  139 + GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
  140 +
  141 + // Set the viewport
  142 + glViewport ( 0, 0, esContext->width, esContext->height );
  143 +
  144 + // Clear the color buffer
  145 + glClear ( GL_COLOR_BUFFER_BIT );
  146 +
  147 + // Use the program object
  148 + glUseProgram ( userData->programObject );
  149 +
  150 + // Load the vertex position
  151 + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
  152 + GL_FALSE, 5 * sizeof(GLfloat), vVertices );
  153 + // Load the texture coordinate
  154 + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
  155 + GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
  156 +
  157 + glEnableVertexAttribArray ( userData->positionLoc );
  158 + glEnableVertexAttribArray ( userData->texCoordLoc );
  159 +
  160 + // Bind the base map
  161 + glActiveTexture ( GL_TEXTURE0 );
  162 + glBindTexture ( GL_TEXTURE_2D, userData->baseMapTexId );
  163 +
  164 + // Set the base map sampler to texture unit to 0
  165 + glUniform1i ( userData->baseMapLoc, 0 );
  166 +
  167 + // Bind the light map
  168 + glActiveTexture ( GL_TEXTURE1 );
  169 + glBindTexture ( GL_TEXTURE_2D, userData->lightMapTexId );
  170 +
  171 + // Set the light map sampler to texture unit 1
  172 + glUniform1i ( userData->lightMapLoc, 1 );
  173 +
  174 + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
  175 +
  176 + eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
  177 +}
  178 +
  179 +///
  180 +// Cleanup
  181 +//
  182 +void ShutDown ( ESContext *esContext )
  183 +{
  184 + UserData *userData = esContext->userData;
  185 +
  186 + // Delete texture object
  187 + glDeleteTextures ( 1, &userData->baseMapTexId );
  188 + glDeleteTextures ( 1, &userData->lightMapTexId );
  189 +
  190 + // Delete program object
  191 + glDeleteProgram ( userData->programObject );
  192 +}
  193 +
  194 +
  195 +int main ( int argc, char *argv[] )
  196 +{
  197 + ESContext esContext;
  198 + UserData userData;
  199 +
  200 + esInitContext ( &esContext );
  201 + esContext.userData = &userData;
  202 +
  203 + esCreateWindow ( &esContext, "MultiTexture", 320, 240, ES_WINDOW_RGB );
  204 +
  205 + if ( !Init ( &esContext ) )
  206 + return 0;
  207 +
  208 + esRegisterDrawFunc ( &esContext, Draw );
  209 +
  210 + esMainLoop ( &esContext );
  211 +
  212 + ShutDown ( &esContext );
  213 +}
BIN  tests/glbook/Chapter_10/MultiTexture/basemap.tga
Binary file not shown
BIN  tests/glbook/Chapter_10/MultiTexture/lightmap.tga
Binary file not shown
302 tests/glbook/Chapter_11/Multisample/Multisample.c
... ... @@ -0,0 +1,302 @@
  1 +//
  2 +// Book: OpenGL(R) ES 2.0 Programming Guide
  3 +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
  4 +// ISBN-10: 0321502795
  5 +// ISBN-13: 9780321502797
  6 +// Publisher: Addison-Wesley Professional
  7 +// URLs: http://safari.informit.com/9780321563835
  8 +// http://www.opengles-book.com
  9 +//
  10 +
  11 +// Multisample.c
  12 +//
  13 +// This example shows various multi-sampling
  14 +// operations.
  15 +//
  16 +#include <stdlib.h>
  17 +#include <stdio.h>
  18 +#include "esUtil.h"
  19 +
  20 +typedef struct
  21 +{
  22 + // Handle to a program object
  23 + GLuint programObject;
  24 +
  25 + // Attribute locations
  26 + GLint positionLoc;
  27 +
  28 + // Uniform locations
  29 + GLint colorLoc;
  30 +
  31 +} UserData;
  32 +
  33 +///
  34 +// Initialize the shader and program object
  35 +//
  36 +int Init ( ESContext *esContext )
  37 +{
  38 + UserData *userData = esContext->userData;
  39 + GLbyte vShaderStr[] =
  40 + "attribute vec4 a_position; \n"
  41 + "void main() \n"
  42 + "{ \n"
  43 + " gl_Position = a_position; \n"
  44 + "} \n";
  45 +
  46 + GLbyte fShaderStr[] =
  47 + "precision mediump float; \n"
  48 + "uniform vec4 u_color; \n"
  49 + "void main() \n"
  50 + "{ \n"
  51 + " gl_FragColor = u_color; \n"
  52 + "} \n";
  53 +
  54 + // Load the shaders and get a linked program object
  55 + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
  56 +
  57 + // Get the attribute locations
  58 + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
  59 +
  60 + // Get the sampler location
  61 + userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
  62 +
  63 + // Set the clear color
  64 + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
  65 +
  66 + // Set the stencil clear value
  67 + glClearStencil ( 0x1 );
  68 +
  69 + // Set the depth clear value
  70 + glClearDepthf( 0.75f );
  71 +
  72 + // Enable the depth and stencil tests
  73 + glEnable( GL_DEPTH_TEST );
  74 + glEnable( GL_STENCIL_TEST );
  75 +
  76 + return TRUE;
  77 +}
  78 +
  79 +///
  80 +// Initialize the stencil buffer values, and then use those
  81 +// values to control rendering
  82 +//
  83 +void Draw ( ESContext *esContext )
  84 +{
  85 + int i;
  86 +
  87 + UserData *userData = esContext->userData;
  88 +
  89 + GLfloat vVertices[] = {
  90 + -0.75f, 0.25f, 0.50f, // Quad #0
  91 + -0.25f, 0.25f, 0.50f,
  92 + -0.25f, 0.75f, 0.50f,
  93 + -0.75f, 0.75f, 0.50f,
  94 + 0.25f, 0.25f, 0.90f, // Quad #1
  95 + 0.75f, 0.25f, 0.90f,
  96 + 0.75f, 0.75f, 0.90f,
  97 + 0.25f, 0.75f, 0.90f,
  98 + -0.75f, -0.75f, 0.50f, // Quad #2
  99 + -0.25f, -0.75f, 0.50f,
  100 + -0.25f, -0.25f, 0.50f,
  101 + -0.75f, -0.25f, 0.50f,
  102 + 0.25f, -0.75f, 0.50f, // Quad #3
  103 + 0.75f, -0.75f, 0.50f,
  104 + 0.75f, -0.25f, 0.50f,
  105 + 0.25f, -0.25f, 0.50f,
  106 + -1.00f, -1.00f, 0.00f, // Big Quad
  107 + 1.00f, -1.00f, 0.00f,
  108 + 1.00f, 1.00f, 0.00f,
  109 + -1.00f, 1.00f, 0.00f
  110 + };
  111 +
  112 + GLubyte indices[][6] = {
  113 + { 0, 1, 2, 0, 2, 3 }, // Quad #0
  114 + { 4, 5, 6, 4, 6, 7 }, // Quad #1
  115 + { 8, 9, 10, 8, 10, 11 }, // Quad #2
  116 + { 12, 13, 14, 12, 14, 15 }, // Quad #3
  117 + { 16, 17, 18, 16, 18, 19 } // Big Quad
  118 + };
  119 +
  120 +#define NumTests 4
  121 + GLfloat colors[NumTests][4] = {
  122 + { 1.0f, 0.0f, 0.0f, 1.0f },
  123 + { 0.0f, 1.0f, 0.0f, 1.0f },
  124 + { 0.0f, 0.0f, 1.0f, 1.0f },
  125 + { 1.0f, 1.0f, 0.0f, 0.0f }
  126 + };
  127 +
  128 + GLint numStencilBits;
  129 + GLuint stencilValues[NumTests] = {
  130 + 0x7, // Result of test 0
  131 + 0x0, // Result of test 1
  132 + 0x2, // Result of test 2
  133 + 0xff // Result of test 3. We need to fill this
  134 + // value in a run-time
  135 + };
  136 +
  137 + // Set the viewport
  138 + glViewport ( 0, 0, esContext->width, esContext->height );
  139 +
  140 + // Clear the color, depth, and stencil buffers. At this
  141 + // point, the stencil buffer will be 0x1 for all pixels
  142 + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
  143 +
  144 + // Use the program object
  145 + glUseProgram ( userData->programObject );
  146 +
  147 + // Load the vertex position
  148 + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
  149 + GL_FALSE, 0, vVertices );
  150 +
  151 + glEnableVertexAttribArray ( userData->positionLoc );
  152 +
  153 + // Test 0:
  154 + //
  155 + // Initialize upper-left region. In this case, the
  156 + // stencil-buffer values will be replaced because the
  157 + // stencil test for the rendered pixels will fail the
  158 + // stencil test, which is
  159 + //
  160 + // ref mask stencil mask
  161 + // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
  162 + //
  163 + // The value in the stencil buffer for these pixels will
  164 + // be 0x7.
  165 + //
  166 + glStencilFunc( GL_LESS, 0x7, 0x3 );
  167 + glStencilOp( GL_REPLACE, GL_DECR, GL_DECR );
  168 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] );
  169 +
  170 + // Test 1:
  171 + //
  172 + // Initialize the upper-right region. Here, we'll decrement
  173 + // the stencil-buffer values where the stencil test passes
  174 + // but the depth test fails. The stencil test is
  175 + //
  176 + // ref mask stencil mask
  177 + // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
  178 + //
  179 + // but where the geometry fails the depth test. The
  180 + // stencil values for these pixels will be 0x0.
  181 + //
  182 + glStencilFunc( GL_GREATER, 0x3, 0x3 );
  183 + glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
  184 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] );
  185 +
  186 + // Test 2:
  187 + //
  188 + // Initialize the lower-left region. Here we'll increment
  189 + // (with saturation) the stencil value where both the
  190 + // stencil and depth tests pass. The stencil test for
  191 + // these pixels will be
  192 + //
  193 + // ref mask stencil mask
  194 + // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
  195 + //
  196 + // The stencil values for these pixels will be 0x2.
  197 + //
  198 + glStencilFunc( GL_EQUAL, 0x1, 0x3 );
  199 + glStencilOp( GL_KEEP, GL_INCR, GL_INCR );
  200 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] );
  201 +
  202 + // Test 3:
  203 + //
  204 + // Finally, initialize the lower-right region. We'll invert
  205 + // the stencil value where the stencil tests fails. The
  206 + // stencil test for these pixels will be
  207 + //
  208 + // ref mask stencil mask
  209 + // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
  210 + //
  211 + // The stencil value here will be set to ~((2^s-1) & 0x1),
  212 + // (with the 0x1 being from the stencil clear value),
  213 + // where 's' is the number of bits in the stencil buffer
  214 + //
  215 + glStencilFunc( GL_EQUAL, 0x2, 0x1 );
  216 + glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP );
  217 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] );
  218 +
  219 + // Since we don't know at compile time how many stecil bits are present,
  220 + // we'll query, and update the value correct value in the
  221 + // stencilValues arrays for the fourth tests. We'll use this value
  222 + // later in rendering.
  223 + glGetIntegerv( GL_STENCIL_BITS, &numStencilBits );
  224 +
  225 + stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff;
  226 +
  227 + // Use the stencil buffer for controlling where rendering will
  228 + // occur. We diable writing to the stencil buffer so we
  229 + // can test against them without modifying the values we
  230 + // generated.
  231 + glStencilMask( 0x0 );
  232 +
  233 + for ( i = 0; i < NumTests; ++i )
  234 + {
  235 + glStencilFunc( GL_EQUAL, stencilValues[i], 0xff );
  236 + glUniform4fv( userData->colorLoc, 1, colors[i] );
  237 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] );
  238 + }
  239 +
  240 + //eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
  241 +}
  242 +
  243 +
  244 +///
  245 +// Cleanup
  246 +//
  247 +void ShutDown ( ESContext *esContext )
  248 +{
  249 + UserData *userData = esContext->userData;
  250 +
  251 + // Delete program object
  252 + glDeleteProgram ( userData->programObject );
  253 +}
  254 +
  255 +
  256 +///
  257 +// Handle keyboard input
  258 +//
  259 +void Key ( ESContext *esContext, unsigned char key, int x, int y)
  260 +{
  261 + switch ( key )
  262 + {
  263 + case 'm':
  264 + printf( "Saw an 'm'\n" );
  265 + break;
  266 +
  267 + case 'a':
  268 + printf( "Saw an 'a'\n" );
  269 + break;
  270 +
  271 + case '1':
  272 + printf( "Saw a '1'\n" );
  273 + break;
  274 +
  275 + case 033: // ASCII Escape Key
  276 + ShutDown( esContext );
  277 + exit( 0 );
  278 + break;
  279 + }
  280 +}
  281 +
  282 +
  283 +int main ( int argc, char *argv[] )
  284 +{
  285 + ESContext esContext;
  286 + UserData userData;
  287 +
  288 + esInitContext ( &esContext );
  289 + esContext.userData = &userData;
  290 +
  291 + esCreateWindow ( &esContext, "Multi-sampling", 320, 240, ES_WINDOW_RGB );
  292 +
  293 + if ( !Init ( &esContext ) )
  294 + return 0;
  295 +
  296 + esRegisterDrawFunc ( &esContext, Draw );
  297 + esRegisterKeyFunc( &esContext, Key );
  298 +
  299 + esMainLoop ( &esContext );
  300 +
  301 + ShutDown ( &esContext );
  302 +}
273 tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c
... ... @@ -0,0 +1,273 @@
  1 +//
  2 +// Book: OpenGL(R) ES 2.0 Programming Guide
  3 +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
  4 +// ISBN-10: 0321502795
  5 +// ISBN-13: 9780321502797
  6 +// Publisher: Addison-Wesley Professional
  7 +// URLs: http://safari.informit.com/9780321563835
  8 +// http://www.opengles-book.com
  9 +//
  10 +
  11 +// Stencil_Test.c
  12 +//
  13 +// This example shows various stencil buffer
  14 +// operations.
  15 +//
  16 +#include <stdlib.h>
  17 +#include "esUtil.h"
  18 +
  19 +typedef struct
  20 +{
  21 + // Handle to a program object
  22 + GLuint programObject;
  23 +
  24 + // Attribute locations
  25 + GLint positionLoc;
  26 +
  27 + // Uniform locations
  28 + GLint colorLoc;
  29 +
  30 +} UserData;
  31 +
  32 +///
  33 +// Initialize the shader and program object
  34 +//
  35 +int Init ( ESContext *esContext )
  36 +{
  37 + UserData *userData = esContext->userData;
  38 + GLbyte vShaderStr[] =
  39 + "attribute vec4 a_position; \n"
  40 + "void main() \n"
  41 + "{ \n"
  42 + " gl_Position = a_position; \n"
  43 + "} \n";
  44 +
  45 + GLbyte fShaderStr[] =
  46 + "precision mediump float; \n"
  47 + "uniform vec4 u_color; \n"
  48 + "void main() \n"
  49 + "{ \n"
  50 + " gl_FragColor = u_color; \n"
  51 + "} \n";
  52 +
  53 + // Load the shaders and get a linked program object
  54 + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
  55 +
  56 + // Get the attribute locations
  57 + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
  58 +
  59 + // Get the sampler location
  60 + userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
  61 +
  62 + // Set the clear color
  63 + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
  64 +
  65 + // Set the stencil clear value
  66 + glClearStencil ( 0x1 );
  67 +
  68 + // Set the depth clear value
  69 + glClearDepthf( 0.75f );
  70 +
  71 + // Enable the depth and stencil tests
  72 + glEnable( GL_DEPTH_TEST );
  73 + glEnable( GL_STENCIL_TEST );
  74 +
  75 + return TRUE;
  76 +}
  77 +
  78 +///
  79 +// Initialize the stencil buffer values, and then use those
  80 +// values to control rendering
  81 +//
  82 +void Draw ( ESContext *esContext )
  83 +{
  84 + int i;
  85 +
  86 + UserData *userData = esContext->userData;
  87 +
  88 + GLfloat vVertices[] = {
  89 + -0.75f, 0.25f, 0.50f, // Quad #0
  90 + -0.25f, 0.25f, 0.50f,
  91 + -0.25f, 0.75f, 0.50f,
  92 + -0.75f, 0.75f, 0.50f,
  93 + 0.25f, 0.25f, 0.90f, // Quad #1
  94 + 0.75f, 0.25f, 0.90f,
  95 + 0.75f, 0.75f, 0.90f,
  96 + 0.25f, 0.75f, 0.90f,
  97 + -0.75f, -0.75f, 0.50f, // Quad #2
  98 + -0.25f, -0.75f, 0.50f,
  99 + -0.25f, -0.25f, 0.50f,
  100 + -0.75f, -0.25f, 0.50f,
  101 + 0.25f, -0.75f, 0.50f, // Quad #3
  102 + 0.75f, -0.75f, 0.50f,
  103 + 0.75f, -0.25f, 0.50f,
  104 + 0.25f, -0.25f, 0.50f,
  105 + -1.00f, -1.00f, 0.00f, // Big Quad
  106 + 1.00f, -1.00f, 0.00f,
  107 + 1.00f, 1.00f, 0.00f,
  108 + -1.00f, 1.00f, 0.00f
  109 + };
  110 +
  111 + GLubyte indices[][6] = {
  112 + { 0, 1, 2, 0, 2, 3 }, // Quad #0
  113 + { 4, 5, 6, 4, 6, 7 }, // Quad #1
  114 + { 8, 9, 10, 8, 10, 11 }, // Quad #2
  115 + { 12, 13, 14, 12, 14, 15 }, // Quad #3
  116 + { 16, 17, 18, 16, 18, 19 } // Big Quad
  117 + };
  118 +
  119 +#define NumTests 4
  120 + GLfloat colors[NumTests][4] = {
  121 + { 1.0f, 0.0f, 0.0f, 1.0f },
  122 + { 0.0f, 1.0f, 0.0f, 1.0f },
  123 + { 0.0f, 0.0f, 1.0f, 1.0f },
  124 + { 1.0f, 1.0f, 0.0f, 0.0f }
  125 + };
  126 +
  127 + GLint numStencilBits;
  128 + GLuint stencilValues[NumTests] = {
  129 + 0x7, // Result of test 0
  130 + 0x0, // Result of test 1
  131 + 0x2, // Result of test 2
  132 + 0xff // Result of test 3. We need to fill this
  133 + // value in a run-time
  134 + };
  135 +
  136 + // Set the viewport
  137 + glViewport ( 0, 0, esContext->width, esContext->height );
  138 +
  139 + // Clear the color, depth, and stencil buffers. At this
  140 + // point, the stencil buffer will be 0x1 for all pixels
  141 + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
  142 +
  143 + // Use the program object
  144 + glUseProgram ( userData->programObject );
  145 +
  146 + // Load the vertex position
  147 + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
  148 + GL_FALSE, 0, vVertices );
  149 +
  150 + glEnableVertexAttribArray ( userData->positionLoc );
  151 +
  152 + // Test 0:
  153 + //
  154 + // Initialize upper-left region. In this case, the
  155 + // stencil-buffer values will be replaced because the
  156 + // stencil test for the rendered pixels will fail the
  157 + // stencil test, which is
  158 + //
  159 + // ref mask stencil mask
  160 + // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
  161 + //
  162 + // The value in the stencil buffer for these pixels will
  163 + // be 0x7.
  164 + //
  165 + glStencilFunc( GL_LESS, 0x7, 0x3 );
  166 + glStencilOp( GL_REPLACE, GL_DECR, GL_DECR );
  167 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] );
  168 +
  169 + // Test 1:
  170 + //
  171 + // Initialize the upper-right region. Here, we'll decrement
  172 + // the stencil-buffer values where the stencil test passes
  173 + // but the depth test fails. The stencil test is
  174 + //
  175 + // ref mask stencil mask
  176 + // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
  177 + //
  178 + // but where the geometry fails the depth test. The
  179 + // stencil values for these pixels will be 0x0.
  180 + //
  181 + glStencilFunc( GL_GREATER, 0x3, 0x3 );
  182 + glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
  183 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] );
  184 +
  185 + // Test 2:
  186 + //
  187 + // Initialize the lower-left region. Here we'll increment
  188 + // (with saturation) the stencil value where both the
  189 + // stencil and depth tests pass. The stencil test for
  190 + // these pixels will be
  191 + //
  192 + // ref mask stencil mask
  193 + // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
  194 + //
  195 + // The stencil values for these pixels will be 0x2.
  196 + //
  197 + glStencilFunc( GL_EQUAL, 0x1, 0x3 );
  198 + glStencilOp( GL_KEEP, GL_INCR, GL_INCR );
  199 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] );
  200 +
  201 + // Test 3:
  202 + //
  203 + // Finally, initialize the lower-right region. We'll invert
  204 + // the stencil value where the stencil tests fails. The
  205 + // stencil test for these pixels will be
  206 + //
  207 + // ref mask stencil mask
  208 + // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
  209 + //
  210 + // The stencil value here will be set to ~((2^s-1) & 0x1),
  211 + // (with the 0x1 being from the stencil clear value),
  212 + // where 's' is the number of bits in the stencil buffer
  213 + //
  214 + glStencilFunc( GL_EQUAL, 0x2, 0x1 );
  215 + glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP );
  216 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] );
  217 +
  218 + // Since we don't know at compile time how many stecil bits are present,
  219 + // we'll query, and update the value correct value in the
  220 + // stencilValues arrays for the fourth tests. We'll use this value
  221 + // later in rendering.
  222 + glGetIntegerv( GL_STENCIL_BITS, &numStencilBits );
  223 +
  224 + stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff;
  225 +
  226 + // Use the stencil buffer for controlling where rendering will
  227 + // occur. We diable writing to the stencil buffer so we
  228 + // can test against them without modifying the values we
  229 + // generated.
  230 + glStencilMask( 0x0 );
  231 +
  232 + for ( i = 0; i < NumTests; ++i )
  233 + {
  234 + glStencilFunc( GL_EQUAL, stencilValues[i], 0xff );
  235 + glUniform4fv( userData->colorLoc, 1, colors[i] );
  236 + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] );
  237 + }
  238 +
  239 + eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
  240 +}
  241 +
  242 +///
  243 +// Cleanup
  244 +//
  245 +void ShutDown ( ESContext *esContext )
  246 +{
  247 + UserData *userData = esContext->userData;
  248 +
  249 + // Delete program object
  250 + glDeleteProgram ( userData->programObject );
  251 +}
  252 +
  253 +
  254 +int main ( int argc, char *argv[] )
  255 +{
  256 + ESContext esContext;
  257 + UserData userData;
  258 +
  259 + esInitContext ( &esContext );
  260 + esContext.userData = &userData;
  261 +
  262 + esCreateWindow ( &esContext, "Stencil Test", 320, 240,
  263 + ES_WINDOW_RGB | ES_WINDOW_DEPTH | ES_WINDOW_STENCIL );
  264 +
  265 + if ( !Init ( &esContext ) )
  266 + return 0;
  267 +
  268 + esRegisterDrawFunc ( &esContext, Draw );
  269 +
  270 + esMainLoop ( &esContext );
  271 +
  272 + ShutDown ( &esContext );
  273 +}
294 tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c
... ... @@ -0,0 +1,294 @@
  1 +//
  2 +// Book: OpenGL(R) ES 2.0 Programming Guide
  3 +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
  4 +// ISBN-10: 0321502795
  5 +// ISBN-13: 9780321502797
  6 +// Publisher: Addison-Wesley Professional
  7 +// URLs: http://safari.informit.com/9780321563835
  8 +// http://www.opengles-book.com
  9 +//
  10 +
  11 +// ParticleSystem.c
  12 +//
  13 +// This is an example that demonstrates rendering a particle system
  14 +// using a vertex shader and point sprites.
  15 +//
  16 +#include <stdlib.h>
  17 +#include <math.h>
  18 +#include "esUtil.h"
  19 +
  20 +#define NUM_PARTICLES 1000
  21 +#define PARTICLE_SIZE 7
  22 +
  23 +typedef struct
  24 +{
  25 + // Handle to a program object
  26 + GLuint programObject;
  27 +
  28 + // Attribute locations
  29 + GLint lifetimeLoc;
  30 + GLint startPositionLoc;
  31 + GLint endPositionLoc;
  32 +
  33 + // Uniform location
  34 + GLint timeLoc;
  35 + GLint colorLoc;
  36 + GLint centerPositionLoc;
  37 + GLint samplerLoc;
  38 +
  39 + // Texture handle
  40 + GLuint textureId;
  41 +
  42 + // Particle vertex data
  43 + float particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
  44 +
  45 + // Current time
  46 + float time;
  47 +
  48 +} UserData;
  49 +
  50 +///
  51 +// Load texture from disk
  52 +//
  53 +GLuint LoadTexture ( char *fileName )
  54 +{
  55 + int width,
  56 + height;
  57 + char *buffer = esLoadTGA ( fileName, &width, &height );
  58 + GLuint texId;
  59 +
  60 + if ( buffer == NULL )
  61 + {
  62 + esLogMessage ( "Error loading (%s) image.\n", fileName );
  63 + return 0;
  64 + }
  65 +
  66 + glGenTextures ( 1, &texId );
  67 + glBindTexture ( GL_TEXTURE_2D, texId );
  68 +
  69 + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
  70 + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  71 + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  72 + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
  73 + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
  74 +
  75 + free ( buffer );
  76 +
  77 + return texId;
  78 +}
  79 +
  80 +
  81 +///
  82 +// Initialize the shader and program object
  83 +//
  84 +int Init ( ESContext *esContext )
  85 +{
  86 + UserData *userData = esContext->userData;
  87 + int i;
  88 +
  89 + GLbyte vShaderStr[] =
  90 + "uniform float u_time; \n"
  91 + "uniform vec3 u_centerPosition; \n"
  92 + "attribute float a_lifetime; \n"
  93 + "attribute vec3 a_startPosition; \n"
  94 + "attribute vec3 a_endPosition; \n"
  95 + "varying float v_lifetime; \n"
  96 + "void main() \n"
  97 + "{ \n"
  98 + " if ( u_time <= a_lifetime ) \n"
  99 + " { \n"
  100 + " gl_Position.xyz = a_startPosition + \n"
  101 + " (u_time * a_endPosition); \n"
  102 + " gl_Position.xyz += u_centerPosition; \n"
  103 + " gl_Position.w = 1.0; \n"
  104 + " } \n"
  105 + " else \n"
  106 + " gl_Position = vec4( -1000, -1000, 0, 0 ); \n"
  107 + " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n"
  108 + " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n"
  109 + " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
  110 + "}";
  111 +
  112 + GLbyte fShaderStr[] =
  113 + "precision mediump float; \n"
  114 + "uniform vec4 u_color; \n"
  115 + "varying float v_lifetime; \n"
  116 + "uniform sampler2D s_texture; \n"
  117 + "void main() \n"
  118 + "{ \n"
  119 + " vec4 texColor; \n"
  120 + " texColor = texture2D( s_texture, gl_PointCoord ); \n"
  121 + " gl_FragColor = vec4( u_color ) * texColor; \n"
  122 + " gl_FragColor.a *= v_lifetime; \n"
  123 + "} \n";
  124 +
  125 + // Load the shaders and get a linked program object
  126 + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
  127 +
  128 + // Get the attribute locations
  129 + userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
  130 + userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
  131 + userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
  132 +
  133 + // Get the uniform locations
  134 + userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
  135 + userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
  136 + userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
  137 + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
  138 +
  139 + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
  140 +
  141 + // Fill in particle data array
  142 + srand ( 0 );
  143 + for ( i = 0; i < NUM_PARTICLES; i++ )
  144 + {
  145 + float *particleData = &userData->particleData[i * PARTICLE_SIZE];
  146 +
  147 + // Lifetime of particle
  148 + (*particleData++) = ( (float)(rand() % 10000) / 10000.0f );
  149 +
  150 + // End position of particle
  151 + (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
  152 + (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
  153 + (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
  154 +
  155 + // Start position of particle
  156 + (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
  157 + (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
  158 + (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
  159 +
  160 + }
  161 +
  162 + // Initialize time to cause reset on first update
  163 + userData->time = 1.0f;
  164 +
  165 + userData->textureId = LoadTexture ( "smoke.tga" );
  166 + if ( userData->textureId <= 0 )
  167 + {
  168 + return FALSE;
  169 + }
  170 +
  171 + return TRUE;
  172 +}
  173 +
  174 +///
  175 +// Update time-based variables
  176 +//
  177 +void Update ( ESContext *esContext, float deltaTime )
  178 +{
  179 + UserData *userData = esContext->userData;
  180 +
  181 + userData->time += deltaTime;
  182 +
  183 + if ( userData->time >= 1.0f )
  184 + {
  185 + float centerPos[3];
  186 + float color[4];
  187 +
  188 + userData->time = 0.0f;
  189 +
  190 + // Pick a new start location and color
  191 + centerPos[0] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
  192 + centerPos[1] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
  193 + centerPos[2] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
  194 +
  195 + glUniform3fv ( userData->centerPositionLoc, 1, &centerPos[0] );
  196 +
  197 + // Random color
  198 + color[0] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
  199 + color[1] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
  200 + color[2] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
  201 + color[3] = 0.5;
  202 +
  203 + glUniform4fv ( userData->colorLoc, 1, &color[0] );
  204 + }
  205 +
  206 + // Load uniform time variable
  207 + glUniform1f ( userData->timeLoc, userData->time );
  208 +}
  209 +
  210 +///
  211 +// Draw a triangle using the shader pair created in Init()
  212 +//
  213 +void Draw ( ESContext *esContext )
  214 +{
  215 + UserData *userData = esContext->userData;
  216 +
  217 + // Set the viewport
  218 + glViewport ( 0, 0, esContext->width, esContext->height );
  219 +
  220 + // Clear the color buffer
  221 + glClear ( GL_COLOR_BUFFER_BIT );
  222 +
  223 + // Use the program object
  224 + glUseProgram ( userData->programObject );
  225 +
  226 + // Load the vertex attributes
  227 + glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
  228 + GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
  229 + userData->particleData );
  230 +
  231 + glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
  232 + GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
  233 + &userData->particleData[1] );
  234 +
  235 + glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
  236 + GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
  237 + &userData->particleData[4] );
  238 +
  239 +
  240 + glEnableVertexAttribArray ( userData->lifetimeLoc );
  241 + glEnableVertexAttribArray ( userData->endPositionLoc );
  242 + glEnableVertexAttribArray ( userData->startPositionLoc );
  243 + // Blend particles
  244 + glEnable ( GL_BLEND );
  245 + glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
  246 +
  247 + // Bind the texture
  248 + glActiveTexture ( GL_TEXTURE0 );
  249 + glBindTexture ( GL_TEXTURE_2D, userData->textureId );
  250 + glEnable ( GL_TEXTURE_2D );
  251 +
  252 + // Set the sampler texture unit to 0
  253 + glUniform1i ( userData->samplerLoc, 0 );
  254 +
  255 + glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
  256 +
  257 + eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
  258 +}
  259 +
  260 +///
  261 +// Cleanup
  262 +//
  263 +void ShutDown ( ESContext *esContext )
  264 +{
  265 + UserData *userData = esContext->userData;
  266 +
  267 + // Delete texture object
  268 + glDeleteTextures ( 1, &userData->textureId );
  269 +
  270 + // Delete program object
  271 + glDeleteProgram ( userData->programObject );
  272 +}
  273 +
  274 +
  275 +int main ( int argc, char *argv[] )
  276 +{
  277 + ESContext esContext;
  278 + UserData userData;
  279 +
  280 + esInitContext ( &esContext );
  281 + esContext.userData = &userData;
  282 +
  283 + esCreateWindow ( &esContext, "ParticleSystem", 640, 480, ES_WINDOW_RGB );
  284 +
  285 + if ( !Init ( &esContext ) )
  286 + return 0;
  287 +
  288 + esRegisterDrawFunc ( &esContext, Draw );
  289 + esRegisterUpdateFunc ( &esContext, Update );
  290 +
  291 + esMainLoop ( &esContext );
  292 +