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 //
LoadTexture(char * fileName)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 //
Init(ESContext * esContext)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 //
Draw(ESContext * esContext)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 //
ShutDown(ESContext * esContext)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 
main(int argc,char * argv[])195 int main ( int argc, char *argv[] )
196 {
197    ESContext esContext;
198    UserData  userData;
199 
200    esInitContext ( &esContext );
201    esContext.userData = &userData;
202 
203    esCreateWindow ( &esContext, "MultiTexture", 320, 240, ES_WINDOW_RGB );
204 
205    if ( !Init ( &esContext ) )
206       return 0;
207 
208    esRegisterDrawFunc ( &esContext, Draw );
209 
210    esMainLoop ( &esContext );
211 
212    ShutDown ( &esContext );
213 }
214