diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-03-31 18:09:04 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-03-31 18:09:04 -0700 |
commit | 08c5da62a0cbccd4f4d51987269bd078ab5fd89e (patch) | |
tree | 95f639b61a80f309762593fe704274c5e4682c44 | |
parent | 3bb7818644872f82a59140a39e92303fdcf6bf23 (diff) |
add glbook files
21 files changed, 4249 insertions, 0 deletions
diff --git a/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c b/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c new file mode 100644 index 00000000..5324ad92 --- /dev/null +++ b/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c @@ -0,0 +1,213 @@ +//
+// 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
+//
+
+// MultiTexture.c
+//
+// This is an example that draws a quad with a basemap and
+// lightmap to demonstrate multitexturing.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler locations
+ GLint baseMapLoc;
+ GLint lightMapLoc;
+
+ // Texture handle
+ GLuint baseMapTexId;
+ GLuint lightMapTexId;
+
+} UserData;
+
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_baseMap; \n"
+ "uniform sampler2D s_lightMap; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 baseColor; \n"
+ " vec4 lightColor; \n"
+ " \n"
+ " baseColor = texture2D( s_baseMap, v_texCoord ); \n"
+ " lightColor = texture2D( s_lightMap, v_texCoord ); \n"
+ " gl_FragColor = baseColor * (lightColor + 0.25); \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" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->baseMapLoc = glGetUniformLocation ( userData->programObject, "s_baseMap" );
+ userData->lightMapLoc = glGetUniformLocation ( userData->programObject, "s_lightMap" );
+
+ // Load the textures
+ userData->baseMapTexId = LoadTexture ( "basemap.tga" );
+ userData->lightMapTexId = LoadTexture ( "lightmap.tga" );
+
+ if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
+ return FALSE;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -0.5f, -0.5f, 0.0f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 0.5f, -0.5f, 0.0f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 0.5f, 0.5f, 0.0f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), vVertices );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the base map
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->baseMapTexId );
+
+ // Set the base map sampler to texture unit to 0
+ glUniform1i ( userData->baseMapLoc, 0 );
+
+ // Bind the light map
+ glActiveTexture ( GL_TEXTURE1 );
+ glBindTexture ( GL_TEXTURE_2D, userData->lightMapTexId );
+
+ // Set the light map sampler to texture unit 1
+ glUniform1i ( userData->lightMapLoc, 1 );
+
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->baseMapTexId );
+ glDeleteTextures ( 1, &userData->lightMapTexId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "MultiTexture", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_10/MultiTexture/basemap.tga b/tests/glbook/Chapter_10/MultiTexture/basemap.tga Binary files differnew file mode 100644 index 00000000..8acafae2 --- /dev/null +++ b/tests/glbook/Chapter_10/MultiTexture/basemap.tga diff --git a/tests/glbook/Chapter_10/MultiTexture/lightmap.tga b/tests/glbook/Chapter_10/MultiTexture/lightmap.tga Binary files differnew file mode 100644 index 00000000..d95b2628 --- /dev/null +++ b/tests/glbook/Chapter_10/MultiTexture/lightmap.tga diff --git a/tests/glbook/Chapter_11/Multisample/Multisample.c b/tests/glbook/Chapter_11/Multisample/Multisample.c new file mode 100644 index 00000000..fd064c70 --- /dev/null +++ b/tests/glbook/Chapter_11/Multisample/Multisample.c @@ -0,0 +1,302 @@ +//
+// 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
+//
+
+// Multisample.c
+//
+// This example shows various multi-sampling
+// operations.
+//
+#include <stdlib.h>
+#include <stdio.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 );
+}
+
+
+///
+// Handle keyboard input
+//
+void Key ( ESContext *esContext, unsigned char key, int x, int y)
+{
+ switch ( key )
+ {
+ case 'm':
+ printf( "Saw an 'm'\n" );
+ break;
+
+ case 'a':
+ printf( "Saw an 'a'\n" );
+ break;
+
+ case '1':
+ printf( "Saw a '1'\n" );
+ break;
+
+ case 033: // ASCII Escape Key
+ ShutDown( esContext );
+ exit( 0 );
+ break;
+ }
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Multi-sampling", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+ esRegisterKeyFunc( &esContext, Key );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c b/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c new file mode 100644 index 00000000..b3a0486d --- /dev/null +++ b/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c @@ -0,0 +1,273 @@ +//
+// 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, "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 );
+}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c new file mode 100644 index 00000000..378d05a7 --- /dev/null +++ b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c @@ -0,0 +1,294 @@ +//
+// 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
+//
+
+// ParticleSystem.c
+//
+// This is an example that demonstrates rendering a particle system
+// using a vertex shader and point sprites.
+//
+#include <stdlib.h>
+#include <math.h>
+#include "esUtil.h"
+
+#define NUM_PARTICLES 1000
+#define PARTICLE_SIZE 7
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint lifetimeLoc;
+ GLint startPositionLoc;
+ GLint endPositionLoc;
+
+ // Uniform location
+ GLint timeLoc;
+ GLint colorLoc;
+ GLint centerPositionLoc;
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ // Particle vertex data
+ float particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
+
+ // Current time
+ float time;
+
+} UserData;
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ int i;
+
+ GLbyte vShaderStr[] =
+ "uniform float u_time; \n"
+ "uniform vec3 u_centerPosition; \n"
+ "attribute float a_lifetime; \n"
+ "attribute vec3 a_startPosition; \n"
+ "attribute vec3 a_endPosition; \n"
+ "varying float v_lifetime; \n"
+ "void main() \n"
+ "{ \n"
+ " if ( u_time <= a_lifetime ) \n"
+ " { \n"
+ " gl_Position.xyz = a_startPosition + \n"
+ " (u_time * a_endPosition); \n"
+ " gl_Position.xyz += u_centerPosition; \n"
+ " gl_Position.w = 1.0; \n"
+ " } \n"
+ " else \n"
+ " gl_Position = vec4( -1000, -1000, 0, 0 ); \n"
+ " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n"
+ " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n"
+ " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
+ "}";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "varying float v_lifetime; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor; \n"
+ " texColor = texture2D( s_texture, gl_PointCoord ); \n"
+ " gl_FragColor = vec4( u_color ) * texColor; \n"
+ " gl_FragColor.a *= v_lifetime; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
+ userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
+ userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
+
+ // Get the uniform locations
+ userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
+ userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+
+ // Fill in particle data array
+ srand ( 0 );
+ for ( i = 0; i < NUM_PARTICLES; i++ )
+ {
+ float *particleData = &userData->particleData[i * PARTICLE_SIZE];
+
+ // Lifetime of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 10000.0f );
+
+ // End position of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+
+ // Start position of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+
+ }
+
+ // Initialize time to cause reset on first update
+ userData->time = 1.0f;
+
+ userData->textureId = LoadTexture ( "smoke.tga" );
+ if ( userData->textureId <= 0 )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+///
+// Update time-based variables
+//
+void Update ( ESContext *esContext, float deltaTime )
+{
+ UserData *userData = esContext->userData;
+
+ userData->time += deltaTime;
+
+ if ( userData->time >= 1.0f )
+ {
+ float centerPos[3];
+ float color[4];
+
+ userData->time = 0.0f;
+
+ // Pick a new start location and color
+ centerPos[0] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+ centerPos[1] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+ centerPos[2] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+
+ glUniform3fv ( userData->centerPositionLoc, 1, ¢erPos[0] );
+
+ // Random color
+ color[0] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[1] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[2] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[3] = 0.5;
+
+ glUniform4fv ( userData->colorLoc, 1, &color[0] );
+ }
+
+ // Load uniform time variable
+ glUniform1f ( userData->timeLoc, userData->time );
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex attributes
+ glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ userData->particleData );
+
+ glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ &userData->particleData[1] );
+
+ glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ &userData->particleData[4] );
+
+
+ glEnableVertexAttribArray ( userData->lifetimeLoc );
+ glEnableVertexAttribArray ( userData->endPositionLoc );
+ glEnableVertexAttribArray ( userData->startPositionLoc );
+ // Blend particles
+ glEnable ( GL_BLEND );
+ glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+ glEnable ( GL_TEXTURE_2D );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "ParticleSystem", 640, 480, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+ esRegisterUpdateFunc ( &esContext, Update );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/smoke.tga b/tests/glbook/Chapter_13/ParticleSystem/smoke.tga Binary files differnew file mode 100644 index 00000000..06a0705c --- /dev/null +++ b/tests/glbook/Chapter_13/ParticleSystem/smoke.tga diff --git a/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c b/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c new file mode 100644 index 00000000..af49c13c --- /dev/null +++ b/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c @@ -0,0 +1,306 @@ +//
+// 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
+//
+
+// Hello_Triangle_KD.c
+//
+// This is a simple example that draws a single triangle with
+// a minimal vertex/fragment shader using OpenKODE.
+//
+#include <KD/kd.h>
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // EGL handles
+ EGLDisplay eglDisplay;
+ EGLContext eglContext;
+ EGLSurface eglSurface;
+
+} UserData;
+
+///
+// Create a shader object, load the shader source, and
+// compile the shader.
+//
+GLuint LoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ // Create the shader object
+ shader = glCreateShader ( type );
+
+ if ( shader == 0 )
+ return 0;
+
+ // Load the shader source
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+
+ // Compile the shader
+ glCompileShader ( shader );
+
+ // Check the compile status
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = kdMalloc (sizeof(char) * infoLen );
+
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ kdLogMessage ( infoLog );
+
+ kdFree ( infoLog );
+ }
+
+ glDeleteShader ( shader );
+ return 0;
+ }
+
+ return shader;
+
+}
+
+///
+// Initialize the shader and program object
+//
+int Init ( UserData *userData )
+{
+ GLbyte vShaderStr[] =
+ "attribute vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vPosition; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float;\n"\
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
+ "} \n";
+
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint programObject;
+ GLint linked;
+
+ // Load the vertex/fragment shaders
+ vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
+ fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
+
+ // Create the program object
+ programObject = glCreateProgram ( );
+
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+
+ // Bind vPosition to attribute 0
+ glBindAttribLocation ( programObject, 0, "vPosition" );
+
+ // Link the program
+ glLinkProgram ( programObject );
+
+ // Check the link status
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = kdMalloc (sizeof(char) * infoLen );
+
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ kdLogMessage ( infoLog );
+
+ kdFree ( infoLog );
+ }
+
+ glDeleteProgram ( programObject );
+ return FALSE;
+ }
+
+ // Store the program object
+ userData->programObject = programObject;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( UserData *userData )
+{
+ GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f };
+
+ // Set the viewport
+ glViewport ( 0, 0, 320, 240 );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex data
+ glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
+ glEnableVertexAttribArray ( 0 );
+
+ glDrawArrays ( GL_TRIANGLES, 0, 3 );
+
+ eglSwapBuffers ( userData->eglDisplay, userData->eglSurface );
+}
+
+
+///
+// InitEGLContext()
+//
+// Initialize an EGL rendering context and all associated elements
+//
+EGLBoolean InitEGLContext ( UserData *userData,
+ KDWindow *window,
+ EGLConfig config )
+{
+ EGLContext context;
+ EGLSurface surface;
+ EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
+
+ // Get native window handle
+ EGLNativeWindowType hWnd; + if(kdRealizeWindow(window, &hWnd) != 0)
+ {
+ return EGL_FALSE;
+ }
+ surface = eglCreateWindowSurface(userData->eglDisplay, config, hWnd, NULL);
+ if ( surface == EGL_NO_SURFACE )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a GL context
+ context = eglCreateContext(userData->eglDisplay, config, EGL_NO_CONTEXT, contextAttribs );
+ if ( context == EGL_NO_CONTEXT )
+ {
+ return EGL_FALSE;
+ }
+
+ // Make the context current
+ if ( !eglMakeCurrent(userData->eglDisplay, surface, surface, context) )
+ {
+ return EGL_FALSE;
+ }
+
+ userData->eglContext = context;
+ userData->eglSurface = surface;
+
+ return EGL_TRUE;
+}
+
+///
+// kdMain()
+//
+// Main function for OpenKODE application
+//
+KDint kdMain ( KDint argc, const KDchar *const *argv )
+{
+ EGLint attribList[] =
+ {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, EGL_DONT_CARE,
+ EGL_STENCIL_SIZE, EGL_DONT_CARE,
+ EGL_NONE
+ };
+ EGLint majorVersion,
+ minorVersion;
+ UserData userData;
+ EGLint numConfigs;
+ EGLConfig config;
+ KDWindow *window = KD_NULL;
+
+ userData.eglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
+
+ // Initialize EGL
+ if ( !eglInitialize(userData.eglDisplay, &majorVersion, &minorVersion) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Get configs
+ if ( !eglGetConfigs(userData.eglDisplay, NULL, 0, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Choose config
+ if ( !eglChooseConfig(userData.eglDisplay, attribList, &config, 1, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+
+ // Use OpenKODE to create a Window
+ window = kdCreateWindow ( userData.eglDisplay, config, KD_NULL );
+ if( !window )
+ kdExit ( 0 );
+
+ if ( !InitEGLContext ( &userData, window, config ) )
+ kdExit ( 0 );
+
+ if ( !Init ( &userData ) )
+ kdExit ( 0 );
+
+ // Main Loop
+ while ( 1 )
+ {
+ // Wait for an event
+ const KDEvent *evt = kdWaitEvent ( 0 );
+ if ( evt )
+ {
+ // Exit app
+ if ( evt->type == KD_EVENT_WINDOW_CLOSE)
+ break;
+ }
+
+ // Draw frame
+ Draw ( &userData );
+ }
+
+ // EGL clean up
+ eglMakeCurrent ( 0, 0, 0, 0 );
+ eglDestroySurface ( userData.eglDisplay, userData.eglSurface );
+ eglDestroyContext ( userData.eglDisplay, userData.eglContext );
+
+ // Destroy the window
+ kdDestroyWindow(window);
+
+ return 0;
+}
diff --git a/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c new file mode 100644 index 00000000..fd4c506a --- /dev/null +++ b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c @@ -0,0 +1,193 @@ +// +// 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 +// + +// Hello_Triangle.c +// +// This is a simple example that draws a single triangle with +// a minimal vertex/fragment shader. The purpose of this +// example is to demonstrate the basic concepts of +// OpenGL ES 2.0 rendering. +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + +} UserData; + +/// +// Create a shader object, load the shader source, and +// compile the shader. +// +GLuint LoadShader ( GLenum type, const char *shaderSrc ) +{ + GLuint shader; + GLint compiled; + + // Create the shader object + shader = glCreateShader ( type ); + + if ( shader == 0 ) + return 0; + + // Load the shader source + glShaderSource ( shader, 1, &shaderSrc, NULL ); + + // Compile the shader + glCompileShader ( shader ); + + // Check the compile status + glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); + + if ( !compiled ) + { + GLint infoLen = 0; + + glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); + + if ( infoLen > 1 ) + { + char* infoLog = malloc (sizeof(char) * infoLen ); + + glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); + esLogMessage ( "Error compiling shader:\n%s\n", infoLog ); + + free ( infoLog ); + } + + glDeleteShader ( shader ); + return 0; + } + + return shader; + +} + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 vPosition; \n" + "void main() \n" + "{ \n" + " gl_Position = vPosition; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float;\n"\ + "void main() \n" + "{ \n" + " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n" + "} \n"; + + GLuint vertexShader; + GLuint fragmentShader; + GLuint programObject; + GLint linked; + + // Load the vertex/fragment shaders + vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr ); + fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr ); + + // Create the program object + programObject = glCreateProgram ( ); + + if ( programObject == 0 ) + return 0; + + glAttachShader ( programObject, vertexShader ); + glAttachShader ( programObject, fragmentShader ); + + // Bind vPosition to attribute 0 + glBindAttribLocation ( programObject, 0, "vPosition" ); + + // Link the program + glLinkProgram ( programObject ); + + // Check the link status + glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); + + if ( !linked ) + { + GLint infoLen = 0; + + glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); + + if ( infoLen > 1 ) + { + char* infoLog = malloc (sizeof(char) * infoLen ); + + glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); + esLogMessage ( "Error linking program:\n%s\n", infoLog ); + + free ( infoLog ); + } + + glDeleteProgram ( programObject ); + return GL_FALSE; + } + + // Store the program object + userData->programObject = programObject; + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f }; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex data + glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); + glEnableVertexAttribArray ( 0 ); + + glDrawArrays ( GL_TRIANGLES, 0, 3 ); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); +} diff --git a/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c new file mode 100644 index 00000000..6036bf0c --- /dev/null +++ b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c @@ -0,0 +1,196 @@ +// +// 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 +// + +// Simple_VertexShader.c +// +// This is a simple example that draws a rotating cube in perspective +// using a vertex shader to transform the object +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + + // Uniform locations + GLint mvpLoc; + + // Vertex daata + GLfloat *vertices; + GLuint *indices; + int numIndices; + + // Rotation angle + GLfloat angle; + + // MVP matrix + ESMatrix mvpMatrix; +} UserData; + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "uniform mat4 u_mvpMatrix; \n" + "attribute vec4 a_position; \n" + "void main() \n" + "{ \n" + " gl_Position = u_mvpMatrix * a_position; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "void main() \n" + "{ \n" + " gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); \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 uniform locations + userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" ); + + // Generate the vertex data + userData->numIndices = esGenCube( 1.0, &userData->vertices, + NULL, NULL, &userData->indices ); + + // Starting rotation angle for the cube + userData->angle = 45.0f; + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + + +/// +// Update MVP matrix based on time +// +void Update ( ESContext *esContext, float deltaTime ) +{ + UserData *userData = (UserData*) esContext->userData; + ESMatrix perspective; + ESMatrix modelview; + float aspect; + + // Compute a rotation angle based on time to rotate the cube + userData->angle += ( deltaTime * 40.0f ); + if( userData->angle >= 360.0f ) + userData->angle -= 360.0f; + + // Compute the window aspect ratio + aspect = (GLfloat) esContext->width / (GLfloat) esContext->height; + + // Generate a perspective matrix with a 60 degree FOV + esMatrixLoadIdentity( &perspective ); + esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f ); + + // Generate a model view matrix to rotate/translate the cube + esMatrixLoadIdentity( &modelview ); + + // Translate away from the viewer + esTranslate( &modelview, 0.0, 0.0, -2.0 ); + + // Rotate the cube + esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 ); + + // Compute the final MVP by multiplying the + // modevleiw and perspective matrices together + esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective ); +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 3 * sizeof(GLfloat), userData->vertices ); + + glEnableVertexAttribArray ( userData->positionLoc ); + + + // Load the MVP matrix + glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] ); + + // Draw the cube + glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_INT, userData->indices ); +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + if ( userData->vertices != NULL ) + { + free ( userData->vertices ); + } + + if ( userData->indices != NULL ) + { + free ( userData->indices ); + } + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free(userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + esRegisterUpdateFunc ( &esContext, Update ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} + diff --git a/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c b/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c new file mode 100644 index 00000000..38ab38a5 --- /dev/null +++ b/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c @@ -0,0 +1,348 @@ +// +// 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 +// + +// MipMap2D.c +// +// This is a simple example that demonstrates generating a mipmap chain +// and rendering with it +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Offset location + GLint offsetLoc; + + // Texture handle + GLuint textureId; + +} UserData; + + +/// +// From an RGB8 source image, generate the next level mipmap +// +GLboolean GenMipMap2D( GLubyte *src, GLubyte **dst, int srcWidth, int srcHeight, int *dstWidth, int *dstHeight ) +{ + int x, + y; + int texelSize = 3; + + *dstWidth = srcWidth / 2; + if ( *dstWidth <= 0 ) + *dstWidth = 1; + + *dstHeight = srcHeight / 2; + if ( *dstHeight <= 0 ) + *dstHeight = 1; + + *dst = malloc ( sizeof(GLubyte) * texelSize * (*dstWidth) * (*dstHeight) ); + if ( *dst == NULL ) + return GL_FALSE; + + for ( y = 0; y < *dstHeight; y++ ) + { + for( x = 0; x < *dstWidth; x++ ) + { + int srcIndex[4]; + float r = 0.0f, + g = 0.0f, + b = 0.0f; + int sample; + + // Compute the offsets for 2x2 grid of pixels in previous + // image to perform box filter + srcIndex[0] = + (((y * 2) * srcWidth) + (x * 2)) * texelSize; + srcIndex[1] = + (((y * 2) * srcWidth) + (x * 2 + 1)) * texelSize; + srcIndex[2] = + ((((y * 2) + 1) * srcWidth) + (x * 2)) * texelSize; + srcIndex[3] = + ((((y * 2) + 1) * srcWidth) + (x * 2 + 1)) * texelSize; + + // Sum all pixels + for ( sample = 0; sample < 4; sample++ ) + { + r += src[srcIndex[sample]]; + g += src[srcIndex[sample] + 1]; + b += src[srcIndex[sample] + 2]; + } + + // Average results + r /= 4.0; + g /= 4.0; + b /= 4.0; + + // Store resulting pixels + (*dst)[ ( y * (*dstWidth) + x ) * texelSize ] = (GLubyte)( r ); + (*dst)[ ( y * (*dstWidth) + x ) * texelSize + 1] = (GLubyte)( g ); + (*dst)[ ( y * (*dstWidth) + x ) * texelSize + 2] = (GLubyte)( b ); + } + } + + return GL_TRUE; +} + +/// +// Generate an RGB8 checkerboard image +// +GLubyte* GenCheckImage( int width, int height, int checkSize ) +{ + int x, + y; + GLubyte *pixels = malloc( width * height * 3 ); + + if ( pixels == NULL ) + return NULL; + + for ( y = 0; y < height; y++ ) + for ( x = 0; x < width; x++ ) + { + GLubyte rColor = 0; + GLubyte bColor = 0; + + if ( ( x / checkSize ) % 2 == 0 ) + { + rColor = 255 * ( ( y / checkSize ) % 2 ); + bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + else + { + bColor = 255 * ( ( y / checkSize ) % 2 ); + rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + + pixels[(y * height + x) * 3] = rColor; + pixels[(y * height + x) * 3 + 1] = 0; + pixels[(y * height + x) * 3 + 2] = bColor; + } + + return pixels; +} + +/// +// Create a mipmapped 2D texture image +// +GLuint CreateMipMappedTexture2D( ) +{ + // Texture object handle + GLuint textureId; + int width = 256, + height = 256; + int level; + GLubyte *pixels; + GLubyte *prevImage; + GLubyte *newImage; + + pixels = GenCheckImage( width, height, 8 ); + if ( pixels == NULL ) + return 0; + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load mipmap level 0 + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, + 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + level = 1; + prevImage = &pixels[0]; + + while ( width > 1 && height > 1 ) + { + int newWidth, + newHeight; + + // Generate the next mipmap level + GenMipMap2D( prevImage, &newImage, width, height, + &newWidth, &newHeight ); + + // Load the mipmap level + glTexImage2D( GL_TEXTURE_2D, level, GL_RGB, + newWidth, newHeight, 0, GL_RGB, + GL_UNSIGNED_BYTE, newImage ); + + // Free the previous image + free ( prevImage ); + + // Set the previous image for the next iteration + prevImage = newImage; + level++; + + // Half the width and height + width = newWidth; + height = newHeight; + } + + free ( newImage ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + return textureId; + +} + + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "uniform float u_offset; \n" + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " gl_Position.x += u_offset;\n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\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" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Get the offset location + userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" ); + + // Load the texture + userData->textureId = CreateMipMappedTexture2D (); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, 1.5f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -0.5f, -0.5f, 0.0f, 0.75f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 0.5f, -0.5f, 0.0f, 0.75f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 0.5f, 0.5f, 0.0f, 1.5f, // Position 3 + 1.0f, 0.0f // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), vVertices ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + // Draw quad with nearest sampling + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glUniform1f ( userData->offsetLoc, -0.6f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + + // Draw quad with trilinear filtering + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + glUniform1f ( userData->offsetLoc, 0.6f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free(esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "MipMap 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} diff --git a/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c new file mode 100644 index 00000000..cc465c9a --- /dev/null +++ b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c @@ -0,0 +1,199 @@ +// +// 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 +// + +// Simple_Texture2D.c +// +// This is a simple example that draws a quad with a 2D +// texture image. The purpose of this example is to demonstrate +// the basics of 2D texturing +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Texture handle + GLuint textureId; + +} UserData; + +/// +// Create a simple 2x2 texture image with four different colors +// +GLuint CreateSimpleTexture2D( ) +{ + // Texture object handle + GLuint textureId; + + // 2x2 Image, 3 bytes per pixel (R, G, B) + GLubyte pixels[4 * 3] = + { + 255, 0, 0, // Red + 0, 255, 0, // Green + 0, 0, 255, // Blue + 255, 255, 0 // Yellow + }; + + // Use tightly packed data + glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load the texture + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + return textureId; + +} + + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\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" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Load the texture + userData->textureId = CreateSimpleTexture2D (); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -0.5f, -0.5f, 0.0f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 0.5f, -0.5f, 0.0f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 0.5f, 0.5f, 0.0f, // Position 3 + 1.0f, 0.0f // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 5 * sizeof(GLfloat), vVertices ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free(esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} diff --git a/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c new file mode 100644 index 00000000..b981d943 --- /dev/null +++ b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c @@ -0,0 +1,227 @@ +// +// 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 +// + +// Simple_TextureCubemap.c +// +// This is a simple example that draws a sphere with a cubemap image applied. +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint normalLoc; + + // Sampler location + GLint samplerLoc; + + // Texture handle + GLuint textureId; + + // Vertex data + int numIndices; + GLfloat *vertices; + GLfloat *normals; + GLuint *indices; + +} UserData; + +/// +// Create a simple cubemap with a 1x1 face with a different +// color for each face +GLuint CreateSimpleTextureCubemap( ) +{ + GLuint textureId; + // Six 1x1 RGB faces + GLubyte cubePixels[6][3] = + { + // Face 0 - Red + 255, 0, 0, + // Face 1 - Green, + 0, 255, 0, + // Face 3 - Blue + 0, 0, 255, + // Face 4 - Yellow + 255, 255, 0, + // Face 5 - Purple + 255, 0, 255, + // Face 6 - White + 255, 255, 255 + }; + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_CUBE_MAP, textureId ); + + // Load the cube face - Positive X + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[0] ); + + // Load the cube face - Negative X + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[1] ); + + // Load the cube face - Positive Y + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[2] ); + + // Load the cube face - Negative Y + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[3] ); + + // Load the cube face - Positive Z + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[4] ); + + // Load the cube face - Negative Z + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[5] ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + return textureId; + +} + +#include <stdio.h> +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + //esContext->userData = malloc(sizeof(UserData)); + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 a_position; \n" + "attribute vec3 a_normal; \n" + "varying vec3 v_normal; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_normal = a_normal; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec3 v_normal; \n" + "uniform samplerCube s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = textureCube( s_texture, v_normal );\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" ); + userData->normalLoc = glGetAttribLocation ( userData->programObject, "a_normal" ); + + // Get the sampler locations + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Load the texture + userData->textureId = CreateSimpleTextureCubemap (); + + // Generate the vertex data + userData->numIndices = esGenSphere ( 20, 0.75f, &userData->vertices, &userData->normals, + NULL, &userData->indices ); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + glCullFace ( GL_BACK ); + glEnable ( GL_CULL_FACE ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 0, userData->vertices ); + // Load the normal + glVertexAttribPointer ( userData->normalLoc, 3, GL_FLOAT, + GL_FALSE, 0, userData->normals ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->normalLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_CUBE_MAP, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + glDrawElements ( GL_TRIANGLES, userData->numIndices, + GL_UNSIGNED_INT, userData->indices ); +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free ( userData->vertices ); + free ( userData->normals ); + + //free ( esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture Cubemap", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} diff --git a/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c b/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c new file mode 100644 index 00000000..fe22282f --- /dev/null +++ b/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c @@ -0,0 +1,257 @@ +// +// 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 +// + +// TextureWrap.c +// +// This is an example that demonstrates the three texture +// wrap modes available on 2D textures +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Offset location + GLint offsetLoc; + + // Texture handle + GLuint textureId; + +} UserData; + +/// +// Generate an RGB8 checkerboard image +// +GLubyte* GenCheckImage( int width, int height, int checkSize ) +{ + int x, + y; + GLubyte *pixels = malloc( width * height * 3 ); + + if ( pixels == NULL ) + return NULL; + + for ( y = 0; y < height; y++ ) + for ( x = 0; x < width; x++ ) + { + GLubyte rColor = 0; + GLubyte bColor = 0; + + if ( ( x / checkSize ) % 2 == 0 ) + { + rColor = 255 * ( ( y / checkSize ) % 2 ); + bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + else + { + bColor = 255 * ( ( y / checkSize ) % 2 ); + rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + + pixels[(y * height + x) * 3] = rColor; + pixels[(y * height + x) * 3 + 1] = 0; + pixels[(y * height + x) * 3 + 2] = bColor; + } + + return pixels; +} + +/// +// Create a mipmapped 2D texture image +// +GLuint CreateTexture2D( ) +{ + // Texture object handle + GLuint textureId; + int width = 256, + height = 256; + GLubyte *pixels; + + pixels = GenCheckImage( width, height, 64 ); + if ( pixels == NULL ) + return 0; + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load mipmap level 0 + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, + 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + return textureId; + +} + + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "uniform float u_offset; \n" + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " gl_Position.x += u_offset;\n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\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" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Get the offset location + userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" ); + + // Load the texture + userData->textureId = CreateTexture2D (); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { -0.3f, 0.3f, 0.0f, 1.0f, // Position 0 + -1.0f, -1.0f, // TexCoord 0 + -0.3f, -0.3f, 0.0f, 1.0f, // Position 1 + -1.0f, 2.0f, // TexCoord 1 + 0.3f, -0.3f, 0.0f, 1.0f, // Position 2 + 2.0f, 2.0f, // TexCoord 2 + 0.3f, 0.3f, 0.0f, 1.0f, // Position 3 + 2.0f, -1.0f // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), vVertices ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + // Draw quad with repeat wrap mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glUniform1f ( userData->offsetLoc, -0.7f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + + // Draw quad with clamp to edge wrap mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glUniform1f ( userData->offsetLoc, 0.0f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + + // Draw quad with mirrored repeat + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); + glUniform1f ( userData->offsetLoc, 0.7f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free ( esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "MipMap 2D", 640, 480, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} + diff --git a/tests/glbook/Common/esShader.c b/tests/glbook/Common/esShader.c new file mode 100644 index 00000000..4ea2cbcb --- /dev/null +++ b/tests/glbook/Common/esShader.c @@ -0,0 +1,155 @@ +//
+// 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
+//
+
+// ESShader.c
+//
+// Utility functions for loading shaders and creating program objects.
+//
+
+///
+// Includes
+//
+#include "esUtil.h"
+#include <stdlib.h>
+
+//////////////////////////////////////////////////////////////////
+//
+// Private Functions
+//
+//
+
+
+
+//////////////////////////////////////////////////////////////////
+//
+// Public Functions
+//
+//
+
+//
+///
+/// \brief Load a shader, check for compile errors, print error messages to output log
+/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
+/// \param shaderSrc Shader source string
+/// \return A new shader object on success, 0 on failure
+//
+GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ // Create the shader object
+ shader = glCreateShader ( type );
+
+ if ( shader == 0 )
+ return 0;
+
+ // Load the shader source
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+
+ // Compile the shader
+ glCompileShader ( shader );
+
+ // Check the compile status
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteShader ( shader );
+ return 0;
+ }
+
+ return shader;
+
+}
+
+
+//
+///
+/// \brief Load a vertex and fragment shader, create a program object, link program.
+// Errors output to log.
+/// \param vertShaderSrc Vertex shader source code
+/// \param fragShaderSrc Fragment shader source code
+/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
+//
+GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc )
+{
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint programObject;
+ GLint linked;
+
+ // Load the vertex/fragment shaders
+ vertexShader = esLoadShader ( GL_VERTEX_SHADER, vertShaderSrc );
+ if ( vertexShader == 0 )
+ return 0;
+
+ fragmentShader = esLoadShader ( GL_FRAGMENT_SHADER, fragShaderSrc );
+ if ( fragmentShader == 0 )
+ {
+ glDeleteShader( vertexShader );
+ return 0;
+ }
+
+ // Create the program object
+ programObject = glCreateProgram ( );
+
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+
+ // Link the program
+ glLinkProgram ( programObject );
+
+ // Check the link status
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ esLogMessage ( "Error linking program:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteProgram ( programObject );
+ return 0;
+ }
+
+ // Free up no longer needed shader resources
+ glDeleteShader ( vertexShader );
+ glDeleteShader ( fragmentShader );
+
+ return programObject;
+}
\ No newline at end of file diff --git a/tests/glbook/Common/esShapes.c b/tests/glbook/Common/esShapes.c new file mode 100644 index 00000000..0fa65057 --- /dev/null +++ b/tests/glbook/Common/esShapes.c @@ -0,0 +1,280 @@ +// +// 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 +// + +// ESShapes.c +// +// Utility functions for generating shapes +// + +/// +// Includes +// +#include "esUtil.h" +#include <stdlib.h> +#include <math.h> +#include <string.h> + +/// +// Defines +// +#define ES_PI (3.14159265f) + +////////////////////////////////////////////////////////////////// +// +// Private Functions +// +// + + + +////////////////////////////////////////////////////////////////// +// +// Public Functions +// +// + +// +/// \brief Generates geometry for a sphere. Allocates memory for the vertex data and stores +/// the results in the arrays. Generate index list for a TRIANGLE_STRIP +/// \param numSlices The number of slices in the sphere +/// \param vertices If not NULL, will contain array of float3 positions +/// \param normals If not NULL, will contain array of float3 normals +/// \param texCoords If not NULL, will contain array of float2 texCoords +/// \param indices If not NULL, will contain the array of indices for the triangle strip +/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array +/// if it is not NULL ) as a GL_TRIANGLE_STRIP +// +int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals, + GLfloat **texCoords, GLuint **indices ) +{ + int i; + int j; + int numParallels = numSlices / 2; + int numVertices = ( numParallels + 1 ) * ( numSlices + 1 ); + int numIndices = numParallels * numSlices * 6; + float angleStep = (2.0f * ES_PI) / ((float) numSlices); + + // Allocate memory for buffers + if ( vertices != NULL ) + *vertices = malloc ( sizeof(GLfloat) * 3 * numVertices ); + + if ( normals != NULL ) + *normals = malloc ( sizeof(GLfloat) * 3 * numVertices ); + + if ( texCoords != NULL ) + *texCoords = malloc ( sizeof(GLfloat) * 2 * numVertices ); + + if ( indices != NULL ) + *indices = malloc ( sizeof(GLuint) * numIndices ); + + for ( i = 0; i < numParallels + 1; i++ ) + { + for ( j = 0; j < numSlices + 1; j++ ) + { + int vertex = ( i * (numSlices + 1) + j ) * 3; + + if ( vertices ) + { + (*vertices)[vertex + 0] = radius * sinf ( angleStep * (float)i ) * + sinf ( angleStep * (float)j ); + (*vertices)[vertex + 1] = radius * cosf ( angleStep * (float)i ); + (*vertices)[vertex + 2] = radius * sinf ( angleStep * (float)i ) * + cosf ( angleStep * (float)j ); + } + + if ( normals ) + { + (*normals)[vertex + 0] = (*vertices)[vertex + 0] / radius; + (*normals)[vertex + 1] = (*vertices)[vertex + 1] / radius; + (*normals)[vertex + 2] = (*vertices)[vertex + 2] / radius; + } + + if ( texCoords ) + { + int texIndex = ( i * (numSlices + 1) + j ) * 2; + (*texCoords)[texIndex + 0] = (float) j / (float) numSlices; + (*texCoords)[texIndex + 1] = ( 1.0f - (float) i ) / (float) (numParallels - 1 ); + } + } + } + + // Generate the indices + if ( indices != NULL ) + { + GLuint *indexBuf = (*indices); + for ( i = 0; i < numParallels ; i++ ) + { + for ( j = 0; j < numSlices; j++ ) + { + *indexBuf++ = i * ( numSlices + 1 ) + j; + *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + j; + *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 ); + + *indexBuf++ = i * ( numSlices + 1 ) + j; + *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 ); + *indexBuf++ = i * ( numSlices + 1 ) + ( j + 1 ); + } + } + } + + return numIndices; +} + +// +/// \brief Generates geometry for a cube. Allocates memory for the vertex data and stores +/// the results in the arrays. Generate index list for a TRIANGLES +/// \param scale The size of the cube, use 1.0 for a unit cube. +/// \param vertices If not NULL, will contain array of float3 positions +/// \param normals If not NULL, will contain array of float3 normals +/// \param texCoords If not NULL, will contain array of float2 texCoords +/// \param indices If not NULL, will contain the array of indices for the triangle strip +/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array +/// if it is not NULL ) as a GL_TRIANGLE_STRIP +// +int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals, + GLfloat **texCoords, GLuint **indices ) +{ + int i; + int numVertices = 24; + int numIndices = 36; + + GLfloat cubeVerts[] = + { + -0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, -0.5f, + -0.5f, -0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + -0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, -0.5f, + }; + + GLfloat cubeNormals[] = + { + 0.0f, -1.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + }; + + GLfloat cubeTex[] = + { + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + }; + + // Allocate memory for buffers + if ( vertices != NULL ) + { + *vertices = malloc ( sizeof(GLfloat) * 3 * numVertices ); + memcpy( *vertices, cubeVerts, sizeof( cubeVerts ) ); + for ( i = 0; i < numVertices * 3; i++ ) + { + (*vertices)[i] *= scale; + } + } + + if ( normals != NULL ) + { + *normals = malloc ( sizeof(GLfloat) * 3 * numVertices ); + memcpy( *normals, cubeNormals, sizeof( cubeNormals ) ); + } + + if ( texCoords != NULL ) + { + *texCoords = malloc ( sizeof(GLfloat) * 2 * numVertices ); + memcpy( *texCoords, cubeTex, sizeof( cubeTex ) ) ; + } + + + // Generate the indices + if ( indices != NULL ) + { + GLuint cubeIndices[] = + { + 0, 2, 1, + 0, 3, 2, + 4, 5, 6, + 4, 6, 7, + 8, 9, 10, + 8, 10, 11, + 12, 15, 14, + 12, 14, 13, + 16, 17, 18, + 16, 18, 19, + 20, 23, 22, + 20, 22, 21 + }; + + *indices = malloc ( sizeof(GLuint) * numIndices ); + memcpy( *indices, cubeIndices, sizeof( cubeIndices ) ); + } + + return numIndices; +} diff --git a/tests/glbook/Common/esTransform.c b/tests/glbook/Common/esTransform.c new file mode 100644 index 00000000..5182218c --- /dev/null +++ b/tests/glbook/Common/esTransform.c @@ -0,0 +1,213 @@ +//
+// 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
+//
+
+// ESUtil.c
+//
+// A utility library for OpenGL ES. This library provides a
+// basic common framework for the example applications in the
+// OpenGL ES 2.0 Programming Guide.
+//
+
+///
+// Includes
+//
+#include "esUtil.h"
+#include <math.h>
+#include <string.h>
+
+#define PI 3.1415926535897932384626433832795f
+
+void ESUTIL_API
+esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz)
+{
+ result->m[0][0] *= sx;
+ result->m[0][1] *= sx;
+ result->m[0][2] *= sx;
+ result->m[0][3] *= sx;
+
+ result->m[1][0] *= sy;
+ result->m[1][1] *= sy;
+ result->m[1][2] *= sy;
+ result->m[1][3] *= sy;
+
+ result->m[2][0] *= sz;
+ result->m[2][1] *= sz;
+ result->m[2][2] *= sz;
+ result->m[2][3] *= sz;
+}
+
+void ESUTIL_API
+esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz)
+{
+ result->m[3][0] += (result->m[0][0] * tx + result->m[1][0] * ty + result->m[2][0] * tz);
+ result->m[3][1] += (result->m[0][1] * tx + result->m[1][1] * ty + result->m[2][1] * tz);
+ result->m[3][2] += (result->m[0][2] * tx + result->m[1][2] * ty + result->m[2][2] * tz);
+ result->m[3][3] += (result->m[0][3] * tx + result->m[1][3] * ty + result->m[2][3] * tz);
+}
+
+void ESUTIL_API
+esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat sinAngle, cosAngle;
+ GLfloat mag = sqrtf(x * x + y * y + z * z);
+
+ sinAngle = sinf ( angle * PI / 180.0f );
+ cosAngle = cosf ( angle * PI / 180.0f );
+ if ( mag > 0.0f )
+ {
+ GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
+ GLfloat oneMinusCos;
+ ESMatrix rotMat;
+
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+ xx = x * x;
+ yy = y * y;
+ zz = z * z;
+ xy = x * y;
+ yz = y * z;
+ zx = z * x;
+ xs = x * sinAngle;
+ ys = y * sinAngle;
+ zs = z * sinAngle;
+ oneMinusCos = 1.0f - cosAngle;
+
+ rotMat.m[0][0] = (oneMinusCos * xx) + cosAngle;
+ rotMat.m[0][1] = (oneMinusCos * xy) - zs;
+ rotMat.m[0][2] = (oneMinusCos * zx) + ys;
+ rotMat.m[0][3] = 0.0F;
+
+ rotMat.m[1][0] = (oneMinusCos * xy) + zs;
+ rotMat.m[1][1] = (oneMinusCos * yy) + cosAngle;
+ rotMat.m[1][2] = (oneMinusCos * yz) - xs;
+ rotMat.m[1][3] = 0.0F;
+
+ rotMat.m[2][0] = (oneMinusCos * zx) - ys;
+ rotMat.m[2][1] = (oneMinusCos * yz) + xs;
+ rotMat.m[2][2] = (oneMinusCos * zz) + cosAngle;
+ rotMat.m[2][3] = 0.0F;
+
+ rotMat.m[3][0] = 0.0F;
+ rotMat.m[3][1] = 0.0F;
+ rotMat.m[3][2] = 0.0F;
+ rotMat.m[3][3] = 1.0F;
+
+ esMatrixMultiply( result, &rotMat, result );
+ }
+}
+
+void ESUTIL_API
+esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)
+{
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ float deltaZ = farZ - nearZ;
+ ESMatrix frust;
+
+ if ( (nearZ <= 0.0f) || (farZ <= 0.0f) ||
+ (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f) )
+ return;
+
+ frust.m[0][0] = 2.0f * nearZ / deltaX;
+ frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
+
+ frust.m[1][1] = 2.0f * nearZ / deltaY;
+ frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
+
+ frust.m[2][0] = (right + left) / deltaX;
+ frust.m[2][1] = (top + bottom) / deltaY;
+ frust.m[2][2] = -(nearZ + farZ) / deltaZ;
+ frust.m[2][3] = -1.0f;
+
+ frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
+ frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
+
+ esMatrixMultiply(result, &frust, result);
+}
+
+
+void ESUTIL_API
+esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ)
+{
+ GLfloat frustumW, frustumH;
+
+ frustumH = tanf( fovy / 360.0f * PI ) * nearZ;
+ frustumW = frustumH * aspect;
+
+ esFrustum( result, -frustumW, frustumW, -frustumH, frustumH, nearZ, farZ );
+}
+
+void ESUTIL_API
+esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)
+{
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ float deltaZ = farZ - nearZ;
+ ESMatrix ortho;
+
+ if ( (deltaX == 0.0f) || (deltaY == 0.0f) || (deltaZ == 0.0f) )
+ return;
+
+ esMatrixLoadIdentity(&ortho);
+ ortho.m[0][0] = 2.0f / deltaX;
+ ortho.m[3][0] = -(right + left) / deltaX;
+ ortho.m[1][1] = 2.0f / deltaY;
+ ortho.m[3][1] = -(top + bottom) / deltaY;
+ ortho.m[2][2] = -2.0f / deltaZ;
+ ortho.m[3][2] = -(nearZ + farZ) / deltaZ;
+
+ esMatrixMultiply(result, &ortho, result);
+}
+
+
+void ESUTIL_API
+esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB)
+{
+ ESMatrix tmp;
+ int i;
+
+ for (i=0; i<4; i++)
+ {
+ tmp.m[i][0] = (srcA->m[i][0] * srcB->m[0][0]) +
+ (srcA->m[i][1] * srcB->m[1][0]) +
+ (srcA->m[i][2] * srcB->m[2][0]) +
+ (srcA->m[i][3] * srcB->m[3][0]) ;
+
+ tmp.m[i][1] = (srcA->m[i][0] * srcB->m[0][1]) +
+ (srcA->m[i][1] * srcB->m[1][1]) +
+ (srcA->m[i][2] * srcB->m[2][1]) +
+ (srcA->m[i][3] * srcB->m[3][1]) ;
+
+ tmp.m[i][2] = (srcA->m[i][0] * srcB->m[0][2]) +
+ (srcA->m[i][1] * srcB->m[1][2]) +
+ (srcA->m[i][2] * srcB->m[2][2]) +
+ (srcA->m[i][3] * srcB->m[3][2]) ;
+
+ tmp.m[i][3] = (srcA->m[i][0] * srcB->m[0][3]) +
+ (srcA->m[i][1] * srcB->m[1][3]) +
+ (srcA->m[i][2] * srcB->m[2][3]) +
+ (srcA->m[i][3] * srcB->m[3][3]) ;
+ }
+ memcpy(result, &tmp, sizeof(ESMatrix));
+}
+
+
+void ESUTIL_API
+esMatrixLoadIdentity(ESMatrix *result)
+{
+ memset(result, 0x0, sizeof(ESMatrix));
+ result->m[0][0] = 1.0f;
+ result->m[1][1] = 1.0f;
+ result->m[2][2] = 1.0f;
+ result->m[3][3] = 1.0f;
+}
+
diff --git a/tests/glbook/Common/esUtil.c b/tests/glbook/Common/esUtil.c new file mode 100644 index 00000000..fa080648 --- /dev/null +++ b/tests/glbook/Common/esUtil.c @@ -0,0 +1,420 @@ +//
+// 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
+//
+
+// ESUtil.c
+//
+// A utility library for OpenGL ES. This library provides a
+// basic common framework for the example applications in the
+// OpenGL ES 2.0 Programming Guide.
+//
+
+///
+// Includes
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+#include "esUtil.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+// X11 related local variables
+static Display *x_display = NULL;
+
+///
+// CreateEGLContext()
+//
+// Creates an EGL rendering context and all associated elements
+//
+EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
+ EGLContext* eglContext, EGLSurface* eglSurface,
+ EGLint attribList[])
+{
+ EGLint numConfigs;
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EGLDisplay display;
+ EGLContext context;
+ EGLSurface surface;
+ EGLConfig config;
+ EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
+
+ // Get Display
+ display = eglGetDisplay((EGLNativeDisplayType)x_display);
+ if ( display == EGL_NO_DISPLAY )
+ {
+ return EGL_FALSE;
+ }
+
+ // Initialize EGL
+ if ( !eglInitialize(display, &majorVersion, &minorVersion) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Get configs
+ if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Choose config
+ if ( !eglChooseConfig(display, attribList, &config, 1, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a surface
+ surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL);
+ if ( surface == EGL_NO_SURFACE )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a GL context
+ context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );
+ if ( context == EGL_NO_CONTEXT )
+ {
+ return EGL_FALSE;
+ }
+
+ // Make the context current
+ if ( !eglMakeCurrent(display, surface, surface, context) )
+ {
+ return EGL_FALSE;
+ }
+
+ *eglDisplay = display;
+ *eglSurface = surface;
+ *eglContext = context;
+ return EGL_TRUE;
+}
+
+
+///
+// WinCreate()
+//
+// This function initialized the native X11 display and window for EGL
+//
+EGLBoolean WinCreate(ESContext *esContext, const char *title)
+{
+ Window root;
+ XSetWindowAttributes swa;
+ XSetWindowAttributes xattr;
+ Atom wm_state;
+ XWMHints hints;
+ XEvent xev;
+ EGLConfig ecfg;
+ EGLint num_config;
+ Window win;
+
+ /*
+ * X11 native display initialization
+ */
+
+ x_display = XOpenDisplay(NULL);
+ if ( x_display == NULL )
+ {
+ return EGL_FALSE;
+ }
+
+ root = DefaultRootWindow(x_display);
+
+ swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
+ win = XCreateWindow(
+ x_display, root,
+ 0, 0, esContext->width, esContext->height, 0,
+ CopyFromParent, InputOutput,
+ CopyFromParent, CWEventMask,
+ &swa );
+
+ xattr.override_redirect = FALSE;
+ XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr );
+
+ hints.input = TRUE;
+ hints.flags = InputHint;
+ XSetWMHints(x_display, win, &hints);
+
+ // make the window visible on the screen
+ XMapWindow (x_display, win);
+ XStoreName (x_display, win, title);
+
+ // get identifiers for the provided atom name strings
+ wm_state = XInternAtom (x_display, "_NET_WM_STATE", FALSE);
+
+ memset ( &xev, 0, sizeof(xev) );
+ xev.type = ClientMessage;
+ xev.xclient.window = win;
+ xev.xclient.message_type = wm_state;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 1;
+ xev.xclient.data.l[1] = FALSE;
+ XSendEvent (
+ x_display,
+ DefaultRootWindow ( x_display ),
+ FALSE,
+ SubstructureNotifyMask,
+ &xev );
+
+ esContext->hWnd = (EGLNativeWindowType) win;
+ return EGL_TRUE;
+}
+
+
+///
+// userInterrupt()
+//
+// Reads from X11 event loop and interrupt program if there is a keypress, or
+// window close action.
+//
+GLboolean userInterrupt(ESContext *esContext)
+{
+ XEvent xev;
+ KeySym key;
+ GLboolean userinterrupt = GL_FALSE;
+ char text;
+
+ // Pump all messages from X server. Keypresses are directed to keyfunc (if defined)
+ while ( XPending ( x_display ) )
+ {
+ XNextEvent( x_display, &xev );
+ if ( xev.type == KeyPress )
+ {
+ if (XLookupString(&xev.xkey,&text,1,&key,0)==1)
+ {
+ if (esContext->keyFunc != NULL)
+ esContext->keyFunc(esContext, text, 0, 0);
+ }
+ }
+ if ( xev.type == DestroyNotify )
+ userinterrupt = GL_TRUE;
+ }
+ return userinterrupt;
+}
+
+
+//////////////////////////////////////////////////////////////////
+//
+// Public Functions
+//
+//
+
+///
+// esInitContext()
+//
+// Initialize ES utility context. This must be called before calling any other
+// functions.
+//
+void ESUTIL_API esInitContext ( ESContext *esContext )
+{
+ if ( esContext != NULL )
+ {
+ memset( esContext, 0, sizeof( ESContext) );
+ }
+}
+
+
+///
+// esCreateWindow()
+//
+// title - name for title bar of window
+// width - width of window to create
+// height - height of window to create
+// flags - bitwise or of window creation flags
+// ES_WINDOW_ALPHA - specifies that the framebuffer should have alpha
+// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
+// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
+// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
+//
+GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char* title, GLint width, GLint height, GLuint flags )
+{
+ EGLint attribList[] =
+ {
+ EGL_RED_SIZE, 5,
+ EGL_GREEN_SIZE, 6,
+ EGL_BLUE_SIZE, 5,
+ EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,
+ EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
+ EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
+ EGL_NONE
+ };
+
+ if ( esContext == NULL )
+ {
+ return GL_FALSE;
+ }
+
+ esContext->width = width;
+ esContext->height = height;
+
+ if ( !WinCreate ( esContext, title) )
+ {
+ return GL_FALSE;
+ }
+
+
+ if ( !CreateEGLContext ( esContext->hWnd,
+ &esContext->eglDisplay,
+ &esContext->eglContext,
+ &esContext->eglSurface,
+ attribList) )
+ {
+ return GL_FALSE;
+ }
+
+
+ return GL_TRUE;
+}
+
+
+///
+// esMainLoop()
+//
+// Start the main loop for the OpenGL ES application
+//
+
+void ESUTIL_API esMainLoop ( ESContext *esContext )
+{
+ struct timeval t1, t2;
+ struct timezone tz;
+ float deltatime;
+ float totaltime = 0.0f;
+ unsigned int frames = 0;
+
+ gettimeofday ( &t1 , &tz );
+
+ // Just one iteration! while(userInterrupt(esContext) == GL_FALSE)
+ {
+ gettimeofday(&t2, &tz);
+ deltatime = (float)(t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6);
+ t1 = t2;
+
+ if (esContext->updateFunc != NULL)
+ esContext->updateFunc(esContext, deltatime);
+ if (esContext->drawFunc != NULL)
+ esContext->drawFunc(esContext);
+
+ eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
+
+ totaltime += deltatime;
+ frames++;
+ if (totaltime > 2.0f)
+ {
+ printf("%4d frames rendered in %1.4f seconds -> FPS=%3.4f\n", frames, totaltime, frames/totaltime);
+ totaltime -= 2.0f;
+ frames = 0;
+ }
+ }
+}
+
+
+///
+// esRegisterDrawFunc()
+//
+void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) (ESContext* ) )
+{
+ esContext->drawFunc = drawFunc;
+}
+
+
+///
+// esRegisterUpdateFunc()
+//
+void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) )
+{
+ esContext->updateFunc = updateFunc;
+}
+
+
+///
+// esRegisterKeyFunc()
+//
+void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,
+ void (ESCALLBACK *keyFunc) (ESContext*, unsigned char, int, int ) )
+{
+ esContext->keyFunc = keyFunc;
+}
+
+
+///
+// esLogMessage()
+//
+// Log an error message to the debug output for the platform
+//
+void ESUTIL_API esLogMessage ( const char *formatStr, ... )
+{
+ va_list params;
+ char buf[BUFSIZ];
+
+ va_start ( params, formatStr );
+ vsprintf ( buf, formatStr, params );
+
+ printf ( "%s", buf );
+
+ va_end ( params );
+}
+
+
+///
+// esLoadTGA()
+//
+// Loads a 24-bit TGA image from a file. This is probably the simplest TGA loader ever.
+// Does not support loading of compressed TGAs nor TGAa with alpha channel. But for the
+// sake of the examples, this is sufficient.
+//
+
+char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height )
+{
+ char *buffer = NULL;
+ FILE *f;
+ unsigned char tgaheader[12];
+ unsigned char attributes[6];
+ unsigned int imagesize;
+
+ f = fopen(fileName, "rb");
+ if(f == NULL) return NULL;
+
+ if(fread(&tgaheader, sizeof(tgaheader), 1, f) == 0)
+ {
+ fclose(f);
+ return NULL;
+ }
+
+ if(fread(attributes, sizeof(attributes), 1, f) == 0)
+ {
+ fclose(f);
+ return 0;
+ }
+
+ *width = attributes[1] * 256 + attributes[0];
+ *height = attributes[3] * 256 + attributes[2];
+ imagesize = attributes[4] / 8 * *width * *height;
+ buffer = malloc(imagesize);
+ if (buffer == NULL)
+ {
+ fclose(f);
+ return 0;
+ }
+
+ if(fread(buffer, 1, imagesize, f) != imagesize)
+ {
+ free(buffer);
+ return NULL;
+ }
+ fclose(f);
+ return buffer;
+}
diff --git a/tests/glbook/Common/esUtil.h b/tests/glbook/Common/esUtil.h new file mode 100644 index 00000000..b675e367 --- /dev/null +++ b/tests/glbook/Common/esUtil.h @@ -0,0 +1,281 @@ +//
+// 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
+//
+
+//
+/// \file ESUtil.h
+/// \brief A utility library for OpenGL ES. This library provides a
+/// basic common framework for the example applications in the
+/// OpenGL ES 2.0 Programming Guide.
+//
+#ifndef ESUTIL_H
+#define ESUTIL_H
+
+///
+// Includes
+//
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+#ifdef __cplusplus
+
+extern "C" {
+#endif
+
+
+///
+// Macros
+//
+#define ESUTIL_API
+#define ESCALLBACK
+
+
+/// esCreateWindow flag - RGB color buffer
+#define ES_WINDOW_RGB 0
+/// esCreateWindow flag - ALPHA color buffer
+#define ES_WINDOW_ALPHA 1
+/// esCreateWindow flag - depth buffer
+#define ES_WINDOW_DEPTH 2
+/// esCreateWindow flag - stencil buffer
+#define ES_WINDOW_STENCIL 4
+/// esCreateWindow flat - multi-sample buffer
+#define ES_WINDOW_MULTISAMPLE 8
+
+
+///
+// Types
+//
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+typedef struct
+{
+ GLfloat m[4][4];
+} ESMatrix;
+
+typedef struct _escontext
+{
+ /// Put your user data here...
+ void* userData;
+
+ /// Window width
+ GLint width;
+
+ /// Window height
+ GLint height;
+
+ /// Window handle
+ EGLNativeWindowType hWnd;
+
+ /// EGL display
+ EGLDisplay eglDisplay;
+
+ /// EGL context
+ EGLContext eglContext;
+
+ /// EGL surface
+ EGLSurface eglSurface;
+
+ /// Callbacks
+ void (ESCALLBACK *drawFunc) ( struct _escontext * );
+ void (ESCALLBACK *keyFunc) ( struct _escontext *, unsigned char, int, int );
+ void (ESCALLBACK *updateFunc) ( struct _escontext *, float deltaTime );
+} ESContext;
+
+
+///
+// Public Functions
+//
+
+//
+///
+/// \brief Initialize ES framework context. This must be called before calling any other functions.
+/// \param esContext Application context
+//
+void ESUTIL_API esInitContext ( ESContext *esContext );
+
+//
+/// \brief Create a window with the specified parameters
+/// \param esContext Application context
+/// \param title Name for title bar of window
+/// \param width Width in pixels of window to create
+/// \param height Height in pixels of window to create
+/// \param flags Bitfield for the window creation flags
+/// ES_WINDOW_RGB - specifies that the color buffer should have R,G,B channels
+/// ES_WINDOW_ALPHA - specifies that the color buffer should have alpha
+/// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
+/// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
+/// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
+/// \return GL_TRUE if window creation is succesful, GL_FALSE otherwise
+GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char *title, GLint width, GLint height, GLuint flags );
+
+//
+/// \brief Start the main loop for the OpenGL ES application
+/// \param esContext Application context
+//
+void ESUTIL_API esMainLoop ( ESContext *esContext );
+
+//
+/// \brief Register a draw callback function to be used to render each frame
+/// \param esContext Application context
+/// \param drawFunc Draw callback function that will be used to render the scene
+//
+void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) ( ESContext* ) );
+
+//
+/// \brief Register an update callback function to be used to update on each time step
+/// \param esContext Application context
+/// \param updateFunc Update callback function that will be used to render the scene
+//
+void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) );
+
+//
+/// \brief Register an keyboard input processing callback function
+/// \param esContext Application context
+/// \param keyFunc Key callback function for application processing of keyboard input
+//
+void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,
+ void (ESCALLBACK *drawFunc) ( ESContext*, unsigned char, int, int ) );
+//
+/// \brief Log a message to the debug output for the platform
+/// \param formatStr Format string for error log.
+//
+void ESUTIL_API esLogMessage ( const char *formatStr, ... );
+
+//
+///
+/// \brief Load a shader, check for compile errors, print error messages to output log
+/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
+/// \param shaderSrc Shader source string
+/// \return A new shader object on success, 0 on failure
+//
+GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc );
+
+//
+///
+/// \brief Load a vertex and fragment shader, create a program object, link program.
+/// Errors output to log.
+/// \param vertShaderSrc Vertex shader source code
+/// \param fragShaderSrc Fragment shader source code
+/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
+//
+GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc );
+
+
+//
+/// \brief Generates geometry for a sphere. Allocates memory for the vertex data and stores
+/// the results in the arrays. Generate index list for a TRIANGLE_STRIP
+/// \param numSlices The number of slices in the sphere
+/// \param vertices If not NULL, will contain array of float3 positions
+/// \param normals If not NULL, will contain array of float3 normals
+/// \param texCoords If not NULL, will contain array of float2 texCoords
+/// \param indices If not NULL, will contain the array of indices for the triangle strip
+/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
+/// if it is not NULL ) as a GL_TRIANGLE_STRIP
+//
+int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals,
+ GLfloat **texCoords, GLuint **indices );
+
+//
+/// \brief Generates geometry for a cube. Allocates memory for the vertex data and stores
+/// the results in the arrays. Generate index list for a TRIANGLES
+/// \param scale The size of the cube, use 1.0 for a unit cube.
+/// \param vertices If not NULL, will contain array of float3 positions
+/// \param normals If not NULL, will contain array of float3 normals
+/// \param texCoords If not NULL, will contain array of float2 texCoords
+/// \param indices If not NULL, will contain the array of indices for the triangle strip
+/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
+/// if it is not NULL ) as a GL_TRIANGLES
+//
+int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals,
+ GLfloat **texCoords, GLuint **indices );
+
+//
+/// \brief Loads a 24-bit TGA image from a file
+/// \param fileName Name of the file on disk
+/// \param width Width of loaded image in pixels
+/// \param height Height of loaded image in pixels
+/// \return Pointer to loaded image. NULL on failure.
+//
+char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height );
+
+
+//
+/// \brief multiply matrix specified by result with a scaling matrix and return new matrix in result
+/// \param result Specifies the input matrix. Scaled matrix is returned in result.
+/// \param sx, sy, sz Scale factors along the x, y and z axes respectively
+//
+void ESUTIL_API esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz);
+
+//
+/// \brief multiply matrix specified by result with a translation matrix and return new matrix in result
+/// \param result Specifies the input matrix. Translated matrix is returned in result.
+/// \param tx, ty, tz Scale factors along the x, y and z axes respectively
+//
+void ESUTIL_API esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz);
+
+//
+/// \brief multiply matrix specified by result with a rotation matrix and return new matrix in result
+/// \param result Specifies the input matrix. Rotated matrix is returned in result.
+/// \param angle Specifies the angle of rotation, in degrees.
+/// \param x, y, z Specify the x, y and z coordinates of a vector, respectively
+//
+void ESUTIL_API esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+
+//
+// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param left, right Coordinates for the left and right vertical clipping planes
+/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
+/// \param nearZ, farZ Distances to the near and far depth clipping planes. Both distances must be positive.
+//
+void ESUTIL_API esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
+
+//
+/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param fovy Field of view y angle in degrees
+/// \param aspect Aspect ratio of screen
+/// \param nearZ Near plane distance
+/// \param farZ Far plane distance
+//
+void ESUTIL_API esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ);
+
+//
+/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param left, right Coordinates for the left and right vertical clipping planes
+/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
+/// \param nearZ, farZ Distances to the near and far depth clipping planes. These values are negative if plane is behind the viewer
+//
+void ESUTIL_API esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
+
+//
+/// \brief perform the following operation - result matrix = srcA matrix * srcB matrix
+/// \param result Returns multiplied matrix
+/// \param srcA, srcB Input matrices to be multiplied
+//
+void ESUTIL_API esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB);
+
+//
+//// \brief return an indentity matrix
+//// \param result returns identity matrix
+//
+void ESUTIL_API esMatrixLoadIdentity(ESMatrix *result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ESUTIL_H
diff --git a/tests/glbook/Makefile b/tests/glbook/Makefile new file mode 100644 index 00000000..299b594f --- /dev/null +++ b/tests/glbook/Makefile @@ -0,0 +1,60 @@ +# Straight forward Makefile to compile all examples in a row + +INCDIR=-I./Common +LIBS=-lGLESv2 -lEGL -lm -lX11 + +COMMONSRC=./Common/esShader.c \ + ./Common/esTransform.c \ + ./Common/esShapes.c \ + ./Common/esUtil.c +COMMONHRD=esUtil.h + +CH02SRC=./Chapter_2/Hello_Triangle/Hello_Triangle.c +CH08SRC=./Chapter_8/Simple_VertexShader/Simple_VertexShader.c +CH09SRC1=./Chapter_9/Simple_Texture2D/Simple_Texture2D.c +CH09SRC2=./Chapter_9/MipMap2D/MipMap2D.c +CH09SRC3=./Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c +CH09SRC4=./Chapter_9/TextureWrap/TextureWrap.c +CH10SRC=./Chapter_10/MultiTexture/MultiTexture.c +CH11SRC=./Chapter_11/Multisample/Multisample.c +CH11SRC2=./Chapter_11/Stencil_Test/Stencil_Test.c +CH13SRC2=./Chapter_13/ParticleSystem/ParticleSystem.c + +default: all + +all: ./Chapter_2/Hello_Triangle/CH02_HelloTriangle.bc \ +# ./Chapter_8/Simple_VertexShader/CH08_SimpleVertexShader.bc \ +# ./Chapter_9/Simple_Texture2D/CH09_SimpleTexture2D.bc \ +# ./Chapter_9/MipMap2D/CH09_MipMap2D.bc \ +# ./Chapter_9/Simple_TextureCubemap/CH09_TextureCubemap.bc \ +# ./Chapter_9/TextureWrap/CH09_TextureWrap.bc \ +# ./Chapter_10/MultiTexture/CH10_MultiTexture.bc \ +# ./Chapter_11/Multisample/CH11_Multisample.bc \ +# ./Chapter_11/Stencil_Test/CH11_Stencil_Test.bc \ +# ./Chapter_13/ParticleSystem/CH13_ParticleSystem.bc + +clean: + find . -name "CH??_*" | xargs rm -f + +./Chapter_2/Hello_Triangle/CH02_HelloTriangle.bc: ${COMMONSRC} ${COMMONHDR} ${CH02SRC} + $(CC) ${COMMONSRC} ${CH02SRC} -o $@ ${INCDIR} ${LIBS} +./Chapter_8/Simple_VertexShader/CH08_SimpleVertexShader.bc: ${COMMONSRC} ${COMMONHDR} ${CH08SRC} + $(CC) ${COMMONSRC} ${CH08SRC} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_9/Simple_Texture2D/CH09_SimpleTexture2D.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC1} + $(CC) ${COMMONSRC} ${CH09SRC1} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_9/MipMap2D/CH09_MipMap2D.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC2} + $(CC) ${COMMONSRC} ${CH09SRC2} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_9/Simple_TextureCubemap/CH09_TextureCubemap.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC3} + $(CC) ${COMMONSRC} ${CH09SRC3} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_9/TextureWrap/CH09_TextureWrap.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC4} + $(CC) ${COMMONSRC} ${CH09SRC4} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_10/MultiTexture/CH10_MultiTexture.bc: ${COMMONSRC} ${COMMONHDR} ${CH10SRC} + $(CC) ${COMMONSRC} ${CH10SRC} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_11/Multisample/CH11_Multisample.bc: ${COMMONSRC} ${COMMONHDR} ${CH11SRC} + $(CC) ${COMMONSRC} ${CH11SRC} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_11/Stencil_Test/CH11_Stencil_Test.bc: ${COMMONSRC} ${COMMONHDR} ${CH11SRC2} + $(CC) ${COMMONSRC} ${CH11SRC2} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_13/Noise3D/CH13_Noise3D.bc: ${COMMONSRC} ${COMMONHDR} ${CH13SRC1} + $(CC) ${COMMONSRC} ${CH13SRC1} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_13/ParticleSystem/CH13_ParticleSystem.bc: ${COMMONSRC} ${COMMONHDR} ${CH13SRC2} + $(CC) ${COMMONSRC} ${CH13SRC2} -o ./$@ ${INCDIR} ${LIBS} diff --git a/tests/glbook/README.linux b/tests/glbook/README.linux new file mode 100644 index 00000000..7b76357b --- /dev/null +++ b/tests/glbook/README.linux @@ -0,0 +1,32 @@ +OpenGL ES 2.0 Programming Guide - Example code for Linux/X11 environment + +Adaptation code for Linux/X11 environment for the examples of the book +OpenGL ES 2.0 Programming Guide written by Jarkko Vatjus-Anttila. All +original example code has remained unmodified. Adaptation changes are +in esUtil.c|h files, which encapsulates all X11 specific internals from +the application layer. + +Prerequisites for building the source is a valid GCC toolchain (4.5.2 +4.6.1 are tested) and properly setup X11 & GLESv2 & EGL environment. +Mesa project offers such setup, and version 7.11 has been tested with +software rendering. Also native GLESv2 renderer has been tested using +NVidia Tegra2 setup. More details about the tested environments are +below: + +The code has been tested with three configurations +- ATI Radeon HD 3200 graphics with Mesa 7.11-0ubuntu3, Ubuntu 11.10 +- NVidia Quadro FX 2800M/PCI/SSE2 with Mesa 7.11-0ubuntu3, Ubuntu 11.10 +- NVidia Tegra 2, native EGL/GLESv2 drivers, Ubuntu 10.10 + +Native GLESv2 on Tegra2 renders all the test cases correctly. However, +Mesa 7.11 has problems with the Chapter 13 particle test, which at least +with the mentioned test setups create only a black screen. + +Compiling the examples should be as easy as running "make" in the root +linux directory. + +31st Oct 2011 - Jarkko Vatjus-Anttila <jvatjusanttila@gmail.com> + +Website: http://code.google.com/p/opengles-book-samples/ +License: MIT + |