Home | History | Annotate | Download | only in MultiTexture
      1 //
      2 // Book:      OpenGL(R) ES 2.0 Programming Guide
      3 // Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
      4 // ISBN-10:   0321502795
      5 // ISBN-13:   9780321502797
      6 // Publisher: Addison-Wesley Professional
      7 // URLs:      http://safari.informit.com/9780321563835
      8 //            http://www.opengles-book.com
      9 //
     10 
     11 // MultiTexture.c
     12 //
     13 //    This is an example that draws a quad with a basemap and
     14 //    lightmap to demonstrate multitexturing.
     15 //
     16 #include <stdlib.h>
     17 #include "esUtil.h"
     18 
     19 typedef struct
     20 {
     21    // Handle to a program object
     22    GLuint programObject;
     23 
     24    // Attribute locations
     25    GLint  positionLoc;
     26    GLint  texCoordLoc;
     27 
     28    // Sampler locations
     29    GLint baseMapLoc;
     30    GLint lightMapLoc;
     31 
     32    // Texture handle
     33    GLuint baseMapTexId;
     34    GLuint lightMapTexId;
     35 
     36 } UserData;
     37 
     38 
     39 ///
     40 // Load texture from disk
     41 //
     42 GLuint LoadTexture ( char *fileName )
     43 {
     44    int width,
     45        height;
     46    char *buffer = esLoadTGA ( fileName, &width, &height );
     47    GLuint texId;
     48 
     49    if ( buffer == NULL )
     50    {
     51       esLogMessage ( "Error loading (%s) image.\n", fileName );
     52       return 0;
     53    }
     54 
     55    glGenTextures ( 1, &texId );
     56    glBindTexture ( GL_TEXTURE_2D, texId );
     57 
     58    glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
     59    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
     60    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
     61    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
     62    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
     63 
     64    free ( buffer );
     65 
     66    return texId;
     67 }
     68 
     69 
     70 
     71 ///
     72 // Initialize the shader and program object
     73 //
     74 int Init ( ESContext *esContext )
     75 {
     76    UserData *userData = esContext->userData;
     77    GLbyte vShaderStr[] =
     78       "attribute vec4 a_position;   \n"
     79       "attribute vec2 a_texCoord;   \n"
     80       "varying vec2 v_texCoord;     \n"
     81       "void main()                  \n"
     82       "{                            \n"
     83       "   gl_Position = a_position; \n"
     84       "   v_texCoord = a_texCoord;  \n"
     85       "}                            \n";
     86 
     87    GLbyte fShaderStr[] =
     88       "precision mediump float;                            \n"
     89       "varying vec2 v_texCoord;                            \n"
     90       "uniform sampler2D s_baseMap;                        \n"
     91       "uniform sampler2D s_lightMap;                       \n"
     92       "void main()                                         \n"
     93       "{                                                   \n"
     94       "  vec4 baseColor;                                   \n"
     95       "  vec4 lightColor;                                  \n"
     96       "                                                    \n"
     97       "  baseColor = texture2D( s_baseMap, v_texCoord );   \n"
     98       "  lightColor = texture2D( s_lightMap, v_texCoord ); \n"
     99       "  gl_FragColor = baseColor * (lightColor + 0.25);   \n"
    100       "}                                                   \n";
    101 
    102    // Load the shaders and get a linked program object
    103    userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
    104 
    105    // Get the attribute locations
    106    userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
    107    userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
    108 
    109    // Get the sampler location
    110    userData->baseMapLoc = glGetUniformLocation ( userData->programObject, "s_baseMap" );
    111    userData->lightMapLoc = glGetUniformLocation ( userData->programObject, "s_lightMap" );
    112 
    113    // Load the textures
    114    userData->baseMapTexId = LoadTexture ( "basemap.tga" );
    115    userData->lightMapTexId = LoadTexture ( "lightmap.tga" );
    116 
    117    if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
    118       return FALSE;
    119 
    120    glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
    121    return TRUE;
    122 }
    123 
    124 ///
    125 // Draw a triangle using the shader pair created in Init()
    126 //
    127 void Draw ( ESContext *esContext )
    128 {
    129    UserData *userData = esContext->userData;
    130    GLfloat vVertices[] = { -0.5f,  0.5f, 0.0f,  // Position 0
    131                             0.0f,  0.0f,        // TexCoord 0
    132                            -0.5f, -0.5f, 0.0f,  // Position 1
    133                             0.0f,  1.0f,        // TexCoord 1
    134                             0.5f, -0.5f, 0.0f,  // Position 2
    135                             1.0f,  1.0f,        // TexCoord 2
    136                             0.5f,  0.5f, 0.0f,  // Position 3
    137                             1.0f,  0.0f         // TexCoord 3
    138                          };
    139    GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
    140 
    141    // Set the viewport
    142    glViewport ( 0, 0, esContext->width, esContext->height );
    143 
    144    // Clear the color buffer
    145    glClear ( GL_COLOR_BUFFER_BIT );
    146 
    147    // Use the program object
    148    glUseProgram ( userData->programObject );
    149 
    150    // Load the vertex position
    151    glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
    152                            GL_FALSE, 5 * sizeof(GLfloat), vVertices );
    153    // Load the texture coordinate
    154    glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
    155                            GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
    156 
    157    glEnableVertexAttribArray ( userData->positionLoc );
    158    glEnableVertexAttribArray ( userData->texCoordLoc );
    159 
    160    // Bind the base map
    161    glActiveTexture ( GL_TEXTURE0 );
    162    glBindTexture ( GL_TEXTURE_2D, userData->baseMapTexId );
    163 
    164    // Set the base map sampler to texture unit to 0
    165    glUniform1i ( userData->baseMapLoc, 0 );
    166 
    167    // Bind the light map
    168    glActiveTexture ( GL_TEXTURE1 );
    169    glBindTexture ( GL_TEXTURE_2D, userData->lightMapTexId );
    170 
    171    // Set the light map sampler to texture unit 1
    172    glUniform1i ( userData->lightMapLoc, 1 );
    173 
    174    glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
    175 
    176    eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
    177 }
    178 
    179 ///
    180 // Cleanup
    181 //
    182 void ShutDown ( ESContext *esContext )
    183 {
    184    UserData *userData = esContext->userData;
    185 
    186    // Delete texture object
    187    glDeleteTextures ( 1, &userData->baseMapTexId );
    188    glDeleteTextures ( 1, &userData->lightMapTexId );
    189 
    190    // Delete program object
    191    glDeleteProgram ( userData->programObject );
    192 }
    193 
    194 
    195 int main ( int argc, char *argv[] )
    196 {
    197    ESContext esContext;
    198    UserData  userData;
    199 
    200    esInitContext ( &esContext );
    201    esContext.userData = &userData;
    202 
    203    esCreateWindow ( &esContext, TEXT("MultiTexture"), 320, 240, ES_WINDOW_RGB );
    204 
    205    if ( !Init ( &esContext ) )
    206       return 0;
    207 
    208    esRegisterDrawFunc ( &esContext, Draw );
    209 
    210    esMainLoop ( &esContext );
    211 
    212    ShutDown ( &esContext );
    213 }
    214