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