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