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 // Simple_TextureCubemap.c 12 // 13 // This is a simple example that draws a sphere with a cubemap image applied. 14 // 15 #include <stdlib.h> 16 #include "esUtil.h" 17 18 typedef struct 19 { 20 // Handle to a program object 21 GLuint programObject; 22 23 // Attribute locations 24 GLint positionLoc; 25 GLint normalLoc; 26 27 // Sampler location 28 GLint samplerLoc; 29 30 // Texture handle 31 GLuint textureId; 32 33 // Vertex data 34 int numIndices; 35 GLfloat *vertices; 36 GLfloat *normals; 37 GLushort *indices; 38 39 } UserData; 40 41 /// 42 // Create a simple cubemap with a 1x1 face with a different 43 // color for each face 44 GLuint CreateSimpleTextureCubemap( ) 45 { 46 GLuint textureId; 47 // Six 1x1 RGB faces 48 GLubyte cubePixels[6][3] = 49 { 50 // Face 0 - Red 51 255, 0, 0, 52 // Face 1 - Green, 53 0, 255, 0, 54 // Face 3 - Blue 55 0, 0, 255, 56 // Face 4 - Yellow 57 255, 255, 0, 58 // Face 5 - Purple 59 255, 0, 255, 60 // Face 6 - White 61 255, 255, 255 62 }; 63 64 // Generate a texture object 65 glGenTextures ( 1, &textureId ); 66 67 // Bind the texture object 68 glBindTexture ( GL_TEXTURE_CUBE_MAP, textureId ); 69 70 // Load the cube face - Positive X 71 glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, 1, 1, 0, 72 GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[0] ); 73 74 // Load the cube face - Negative X 75 glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, 1, 1, 0, 76 GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[1] ); 77 78 // Load the cube face - Positive Y 79 glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, 1, 1, 0, 80 GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[2] ); 81 82 // Load the cube face - Negative Y 83 glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, 1, 1, 0, 84 GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[3] ); 85 86 // Load the cube face - Positive Z 87 glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, 1, 1, 0, 88 GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[4] ); 89 90 // Load the cube face - Negative Z 91 glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, 1, 1, 0, 92 GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[5] ); 93 94 // Set the filtering mode 95 glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); 96 glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); 97 98 return textureId; 99 100 } 101 102 103 /// 104 // Initialize the shader and program object 105 // 106 int Init ( ESContext *esContext ) 107 { 108 UserData *userData = esContext->userData; 109 GLbyte vShaderStr[] = 110 "attribute vec4 a_position; \n" 111 "attribute vec3 a_normal; \n" 112 "varying vec3 v_normal; \n" 113 "void main() \n" 114 "{ \n" 115 " gl_Position = a_position; \n" 116 " v_normal = a_normal; \n" 117 "} \n"; 118 119 GLbyte fShaderStr[] = 120 "precision mediump float; \n" 121 "varying vec3 v_normal; \n" 122 "uniform samplerCube s_texture; \n" 123 "void main() \n" 124 "{ \n" 125 " gl_FragColor = textureCube( s_texture, v_normal );\n" 126 "} \n"; 127 128 // Load the shaders and get a linked program object 129 userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); 130 131 // Get the attribute locations 132 userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); 133 userData->normalLoc = glGetAttribLocation ( userData->programObject, "a_normal" ); 134 135 // Get the sampler locations 136 userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); 137 138 // Load the texture 139 userData->textureId = CreateSimpleTextureCubemap (); 140 141 // Generate the vertex data 142 userData->numIndices = esGenSphere ( 20, 0.75f, &userData->vertices, &userData->normals, 143 NULL, &userData->indices ); 144 145 146 glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 147 return TRUE; 148 } 149 150 /// 151 // Draw a triangle using the shader pair created in Init() 152 // 153 void Draw ( ESContext *esContext ) 154 { 155 UserData *userData = esContext->userData; 156 157 // Set the viewport 158 glViewport ( 0, 0, esContext->width, esContext->height ); 159 160 // Clear the color buffer 161 glClear ( GL_COLOR_BUFFER_BIT ); 162 163 164 glCullFace ( GL_BACK ); 165 glEnable ( GL_CULL_FACE ); 166 167 // Use the program object 168 glUseProgram ( userData->programObject ); 169 170 // Load the vertex position 171 glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 172 GL_FALSE, 0, userData->vertices ); 173 // Load the normal 174 glVertexAttribPointer ( userData->normalLoc, 3, GL_FLOAT, 175 GL_FALSE, 0, userData->normals ); 176 177 glEnableVertexAttribArray ( userData->positionLoc ); 178 glEnableVertexAttribArray ( userData->normalLoc ); 179 180 // Bind the texture 181 glActiveTexture ( GL_TEXTURE0 ); 182 glBindTexture ( GL_TEXTURE_CUBE_MAP, userData->textureId ); 183 184 // Set the sampler texture unit to 0 185 glUniform1i ( userData->samplerLoc, 0 ); 186 187 glDrawElements ( GL_TRIANGLES, userData->numIndices, 188 GL_UNSIGNED_SHORT, userData->indices ); 189 190 eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface ); 191 } 192 193 /// 194 // Cleanup 195 // 196 void ShutDown ( ESContext *esContext ) 197 { 198 UserData *userData = esContext->userData; 199 200 // Delete texture object 201 glDeleteTextures ( 1, &userData->textureId ); 202 203 // Delete program object 204 glDeleteProgram ( userData->programObject ); 205 206 free ( userData->vertices ); 207 free ( userData->normals ); 208 } 209 210 211 int main ( int argc, char *argv[] ) 212 { 213 ESContext esContext; 214 UserData userData; 215 216 esInitContext ( &esContext ); 217 esContext.userData = &userData; 218 219 esCreateWindow ( &esContext, TEXT("Simple Texture Cubemap"), 320, 240, ES_WINDOW_RGB ); 220 221 if ( !Init ( &esContext ) ) 222 return 0; 223 224 esRegisterDrawFunc ( &esContext, Draw ); 225 226 esMainLoop ( &esContext ); 227 228 ShutDown ( &esContext ); 229 } 230