OLD | NEW |
1 // | 1 // |
2 // Book: OpenGL(R) ES 2.0 Programming Guide | 2 // Book: OpenGL(R) ES 2.0 Programming Guide |
3 // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner | 3 // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner |
4 // ISBN-10: 0321502795 | 4 // ISBN-10: 0321502795 |
5 // ISBN-13: 9780321502797 | 5 // ISBN-13: 9780321502797 |
6 // Publisher: Addison-Wesley Professional | 6 // Publisher: Addison-Wesley Professional |
7 // URLs: http://safari.informit.com/9780321563835 | 7 // URLs: http://safari.informit.com/9780321563835 |
8 // http://www.opengles-book.com | 8 // http://www.opengles-book.com |
9 // | 9 // |
10 | 10 |
11 // Hello_Triangle.c | 11 // Hello_Triangle.c |
12 // | 12 // |
13 // This is a simple example that draws a single triangle with | 13 // This is a simple example that draws a single triangle with |
14 // a minimal vertex/fragment shader. The purpose of this | 14 // a minimal vertex/fragment shader. The purpose of this |
15 // example is to demonstrate the basic concepts of | 15 // example is to demonstrate the basic concepts of |
16 // OpenGL ES 2.0 rendering. | 16 // OpenGL ES 2.0 rendering. |
| 17 #include <stdlib.h> |
| 18 #include "esUtil.h" |
17 | 19 |
18 #include "Hello_Triangle.h" | 20 typedef struct |
| 21 { |
| 22 // Handle to a program object |
| 23 GLuint programObject; |
19 | 24 |
20 #include <stdlib.h> | 25 } UserData; |
| 26 |
| 27 /// |
| 28 // Create a shader object, load the shader source, and |
| 29 // compile the shader. |
| 30 // |
| 31 GLuint LoadShader ( GLenum type, const char *shaderSrc ) |
| 32 { |
| 33 GLuint shader; |
| 34 GLint compiled; |
| 35 |
| 36 // Create the shader object |
| 37 shader = glCreateShader ( type ); |
| 38 |
| 39 if ( shader == 0 ) |
| 40 » return 0; |
| 41 |
| 42 // Load the shader source |
| 43 glShaderSource ( shader, 1, &shaderSrc, NULL ); |
| 44 |
| 45 // Compile the shader |
| 46 glCompileShader ( shader ); |
| 47 |
| 48 // Check the compile status |
| 49 glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); |
| 50 |
| 51 if ( !compiled ) |
| 52 { |
| 53 GLint infoLen = 0; |
| 54 |
| 55 glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); |
| 56 |
| 57 if ( infoLen > 1 ) |
| 58 { |
| 59 char* infoLog = malloc (sizeof(char) * infoLen ); |
| 60 |
| 61 glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); |
| 62 esLogMessage ( "Error compiling shader:\n%s\n", infoLog ); |
| 63 |
| 64 free ( infoLog ); |
| 65 } |
| 66 |
| 67 glDeleteShader ( shader ); |
| 68 return 0; |
| 69 } |
| 70 |
| 71 return shader; |
| 72 |
| 73 } |
21 | 74 |
22 /// | 75 /// |
23 // Initialize the shader and program object | 76 // Initialize the shader and program object |
24 // | 77 // |
25 int htInit ( ESContext *esContext ) | 78 int Init ( ESContext *esContext ) |
26 { | 79 { |
27 HTUserData *userData = esContext->userData; | 80 UserData *userData = esContext->userData; |
28 | |
29 GLbyte vShaderStr[] = | 81 GLbyte vShaderStr[] = |
30 "attribute vec4 vPosition; \n" | 82 "attribute vec4 vPosition; \n" |
31 "void main() \n" | 83 "void main() \n" |
32 "{ \n" | 84 "{ \n" |
33 " gl_Position = vPosition; \n" | 85 " gl_Position = vPosition; \n" |
34 "} \n"; | 86 "} \n"; |
35 | 87 |
36 // TODO(alokp): Shaders containing "precision" do not compile. | |
37 GLbyte fShaderStr[] = | 88 GLbyte fShaderStr[] = |
| 89 "precision mediump float;\n"\ |
38 "void main() \n" | 90 "void main() \n" |
39 "{ \n" | 91 "{ \n" |
40 " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n" | 92 " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n" |
41 "} \n"; | 93 "} \n"; |
42 | 94 |
43 // TODO(alokp): Client-side vertex arrays do not work. | 95 GLuint vertexShader; |
44 GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, | 96 GLuint fragmentShader; |
45 -0.5f, -0.5f, 0.0f, | 97 GLuint programObject; |
46 0.5f, -0.5f, 0.0f }; | 98 GLint linked; |
47 | 99 |
48 userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); | 100 // Load the vertex/fragment shaders |
49 if ( userData->programObject == 0 ) return FALSE; | 101 vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr ); |
| 102 fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr ); |
| 103 |
| 104 // Create the program object |
| 105 programObject = glCreateProgram ( ); |
| 106 |
| 107 if ( programObject == 0 ) |
| 108 return 0; |
| 109 |
| 110 glAttachShader ( programObject, vertexShader ); |
| 111 glAttachShader ( programObject, fragmentShader ); |
50 | 112 |
51 // Bind vPosition to attribute 0 | 113 // Bind vPosition to attribute 0 |
52 glBindAttribLocation ( userData->programObject, 0, "vPosition" ); | 114 glBindAttribLocation ( programObject, 0, "vPosition" ); |
53 | 115 |
54 glGenBuffers ( 1, &userData->vbo ); | 116 // Link the program |
55 glBindBuffer ( GL_ARRAY_BUFFER, userData->vbo ); | 117 glLinkProgram ( programObject ); |
56 glBufferData ( GL_ARRAY_BUFFER, sizeof(vVertices), NULL, GL_STATIC_DRAW ); | 118 |
57 glBufferSubData ( GL_ARRAY_BUFFER, 0, sizeof(vVertices), vVertices ); | 119 // Check the link status |
| 120 glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); |
| 121 |
| 122 if ( !linked ) |
| 123 { |
| 124 GLint infoLen = 0; |
| 125 |
| 126 glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); |
| 127 |
| 128 if ( infoLen > 1 ) |
| 129 { |
| 130 char* infoLog = malloc (sizeof(char) * infoLen ); |
| 131 |
| 132 glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); |
| 133 esLogMessage ( "Error linking program:\n%s\n", infoLog ); |
| 134 |
| 135 free ( infoLog ); |
| 136 } |
| 137 |
| 138 glDeleteProgram ( programObject ); |
| 139 return FALSE; |
| 140 } |
| 141 |
| 142 // Store the program object |
| 143 userData->programObject = programObject; |
58 | 144 |
59 glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); | 145 glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); |
60 return TRUE; | 146 return TRUE; |
61 } | 147 } |
62 | 148 |
63 /// | 149 /// |
64 // Draw a triangle using the shader pair created in Init() | 150 // Draw a triangle using the shader pair created in Init() |
65 // | 151 // |
66 void htDraw ( ESContext *esContext ) | 152 void Draw ( ESContext *esContext ) |
67 { | 153 { |
68 HTUserData *userData = esContext->userData; | 154 UserData *userData = esContext->userData; |
69 | 155 GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, |
| 156 -0.5f, -0.5f, 0.0f, |
| 157 0.5f, -0.5f, 0.0f }; |
| 158 |
70 // Set the viewport | 159 // Set the viewport |
71 glViewport ( 0, 0, esContext->width, esContext->height ); | 160 glViewport ( 0, 0, esContext->width, esContext->height ); |
72 | 161 |
73 // Clear the color buffer | 162 // Clear the color buffer |
74 glClear ( GL_COLOR_BUFFER_BIT ); | 163 glClear ( GL_COLOR_BUFFER_BIT ); |
75 | 164 |
76 // Use the program object | 165 // Use the program object |
77 glUseProgram ( userData->programObject ); | 166 glUseProgram ( userData->programObject ); |
78 | 167 |
79 // Load the vertex data | 168 // Load the vertex data |
80 glBindBuffer ( GL_ARRAY_BUFFER, userData->vbo ); | 169 glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); |
81 glEnableVertexAttribArray ( 0 ); | 170 glEnableVertexAttribArray ( 0 ); |
82 glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 ); | |
83 | 171 |
84 glDrawArrays ( GL_TRIANGLES, 0, 3 ); | 172 glDrawArrays ( GL_TRIANGLES, 0, 3 ); |
85 | 173 |
86 // Nothing is drawn or application crashes without glFlush. | 174 eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface ); |
87 // TODO(alokp): glFlush should not be necessary with SwapBuffers(). | |
88 glFlush(); | |
89 } | 175 } |
90 | 176 |
91 /// | 177 |
92 // Cleanup | 178 int main ( int argc, char *argv[] ) |
93 // | |
94 void htShutDown ( ESContext *esContext ) | |
95 { | 179 { |
96 HTUserData *userData = esContext->userData; | 180 ESContext esContext; |
| 181 UserData userData; |
97 | 182 |
98 // Delete program object | 183 esInitContext ( &esContext ); |
99 if ( userData->programObject != 0 ) | 184 esContext.userData = &userData; |
100 { | 185 |
101 glDeleteProgram ( userData->programObject ); | 186 esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB ); |
102 userData->programObject = 0; | 187 |
103 } | 188 if ( !Init ( &esContext ) ) |
104 if ( userData->vbo != 0 ) | 189 return 0; |
105 { | 190 |
106 glDeleteBuffers ( 1, &userData->vbo ); | 191 esRegisterDrawFunc ( &esContext, Draw ); |
107 userData->vbo = 0; | 192 |
108 } | 193 esMainLoop ( &esContext ); |
109 } | 194 } |
OLD | NEW |