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_VertexShader.c 12 // 13 // This is a simple example that draws a rotating cube in perspective 14 // using a vertex shader to transform the object 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 27 // Uniform locations 28 GLint mvpLoc; 29 30 // Vertex daata 31 GLfloat *vertices; 32 GLushort *indices; 33 int numIndices; 34 35 // Rotation angle 36 GLfloat angle; 37 38 // MVP matrix 39 ESMatrix mvpMatrix; 40 } UserData; 41 42 /// 43 // Initialize the shader and program object 44 // 45 int Init ( ESContext *esContext ) 46 { 47 UserData *userData = esContext->userData; 48 GLbyte vShaderStr[] = 49 "uniform mat4 u_mvpMatrix; \n" 50 "attribute vec4 a_position; \n" 51 "void main() \n" 52 "{ \n" 53 " gl_Position = u_mvpMatrix * a_position; \n" 54 "} \n"; 55 56 GLbyte fShaderStr[] = 57 "precision mediump float; \n" 58 "void main() \n" 59 "{ \n" 60 " gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); \n" 61 "} \n"; 62 63 // Load the shaders and get a linked program object 64 userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); 65 66 // Get the attribute locations 67 userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); 68 69 // Get the uniform locations 70 userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" ); 71 72 // Generate the vertex data 73 userData->numIndices = esGenCube( 1.0, &userData->vertices, 74 NULL, NULL, &userData->indices ); 75 76 // Starting rotation angle for the cube 77 userData->angle = 45.0f; 78 79 glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 80 return TRUE; 81 } 82 83 84 /// 85 // Update MVP matrix based on time 86 // 87 void Update ( ESContext *esContext, float deltaTime ) 88 { 89 UserData *userData = (UserData*) esContext->userData; 90 ESMatrix perspective; 91 ESMatrix modelview; 92 float aspect; 93 94 // Compute a rotation angle based on time to rotate the cube 95 userData->angle += ( deltaTime * 40.0f ); 96 if( userData->angle >= 360.0f ) 97 userData->angle -= 360.0f; 98 99 // Compute the window aspect ratio 100 aspect = (GLfloat) esContext->width / (GLfloat) esContext->height; 101 102 // Generate a perspective matrix with a 60 degree FOV 103 esMatrixLoadIdentity( &perspective ); 104 esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f ); 105 106 // Generate a model view matrix to rotate/translate the cube 107 esMatrixLoadIdentity( &modelview ); 108 109 // Translate away from the viewer 110 esTranslate( &modelview, 0.0, 0.0, -2.0 ); 111 112 // Rotate the cube 113 esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 ); 114 115 // Compute the final MVP by multiplying the 116 // modevleiw and perspective matrices together 117 esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective ); 118 } 119 120 /// 121 // Draw a triangle using the shader pair created in Init() 122 // 123 void Draw ( ESContext *esContext ) 124 { 125 UserData *userData = esContext->userData; 126 127 // Set the viewport 128 glViewport ( 0, 0, esContext->width, esContext->height ); 129 130 131 // Clear the color buffer 132 glClear ( GL_COLOR_BUFFER_BIT ); 133 134 // Use the program object 135 glUseProgram ( userData->programObject ); 136 137 // Load the vertex position 138 glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 139 GL_FALSE, 3 * sizeof(GLfloat), userData->vertices ); 140 141 glEnableVertexAttribArray ( userData->positionLoc ); 142 143 144 // Load the MVP matrix 145 glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] ); 146 147 // Draw the cube 148 glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_SHORT, userData->indices ); 149 150 eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface ); 151 } 152 153 /// 154 // Cleanup 155 // 156 void ShutDown ( ESContext *esContext ) 157 { 158 UserData *userData = esContext->userData; 159 160 if ( userData->vertices != NULL ) 161 { 162 free ( userData->vertices ); 163 } 164 165 if ( userData->indices != NULL ) 166 { 167 free ( userData->indices ); 168 } 169 170 // Delete program object 171 glDeleteProgram ( userData->programObject ); 172 } 173 174 175 int main ( int argc, char *argv[] ) 176 { 177 ESContext esContext; 178 UserData userData; 179 180 esInitContext ( &esContext ); 181 esContext.userData = &userData; 182 183 esCreateWindow ( &esContext, TEXT("Simple Vertex Shader"), 320, 240, ES_WINDOW_RGB ); 184 185 if ( !Init ( &esContext ) ) 186 return 0; 187 188 esRegisterDrawFunc ( &esContext, Draw ); 189 esRegisterUpdateFunc ( &esContext, Update ); 190 191 esMainLoop ( &esContext ); 192 193 ShutDown ( &esContext ); 194 } 195