OpenGL ES中MRT应用

Demo涵盖了OpenGL ES 3.0 的一系列新特性:

1、VAO和VBO

2、帧缓冲对象

3、MRT

效果:

代码:

  1 //yf's version
  2 #define STB_IMAGE_IMPLEMENTATION
  3 #include <stdlib.h>
  4 #include "esUtil.h"
  5 #include "stb_image.h"
  6 
  7 typedef struct
  8 {
  9     // Handle to a program object
 10     GLuint programObject;
 11     GLuint programObjectQuad;
 12 
 13     GLuint cubeVAO, cubeVBO;
 14     GLuint floorVAO, floorVBO;
 15     GLuint quadVAO, quadVBO;
 16     GLuint framebuffer;
 17 
 18     ESMatrix mvMatrix;
 19     ESMatrix mvpMatrix;
 20 
 21     GLuint mvLoc;
 22     GLuint mvpLoc;
 23 
 24     GLuint cubeTexture;
 25     GLuint floorTexture;
 26 
 27     // Rotation angle
 28     GLfloat angle;
 29 
 30     GLuint texIDfloor;
 31     GLuint texIDcube;
 32 
 33     GLuint texColorbuffer;
 34     GLuint texColorArray[4];
 35 
 36     GLuint textureWidth;
 37     GLuint textureHeight;
 38 } UserData;
 39 
 40 GLfloat cubeVertices[] = {
 41     // Positions          // Texture Coords
 42     -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
 43     0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
 44     0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
 45     0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
 46     -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
 47     -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
 48 
 49     -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
 50     0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
 51     0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
 52     0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
 53     -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
 54     -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
 55 
 56     -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
 57     -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
 58     -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
 59     -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
 60     -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
 61     -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
 62 
 63     0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
 64     0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
 65     0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
 66     0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
 67     0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
 68     0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
 69 
 70     -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
 71     0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
 72     0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
 73     0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
 74     -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
 75     -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
 76 
 77     -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
 78     0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
 79     0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
 80     0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
 81     -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
 82     -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
 83 };
 84 GLfloat floorVertices[] = {
 85     // Positions          // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat)
 86     5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
 87     -5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
 88     -5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
 89 
 90     5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
 91     -5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
 92     5.0f, -0.5f, -5.0f, 2.0f, 2.0f
 93 };
 94 //渲染到这个四边形
 95 GLfloat quadVertices[] = {   // Vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
 96     // Positions   // TexCoords
 97     -1.0f, 1.0f, 0.0f, 1.0f,
 98     -1.0f, -1.0f, 0.0f, 0.0f,
 99     1.0f, -1.0f, 1.0f, 0.0f,
100 
101     -1.0f, 1.0f, 0.0f, 1.0f,
102     1.0f, -1.0f, 1.0f, 0.0f,
103     1.0f, 1.0f, 1.0f, 1.0f
104 };
105 
106 GLuint screenWidth = 600;
107 GLuint screenHeight = 400;
108 
109 GLuint LoadTextureFile(const char* filename)
110 {
111     GLuint texID;
112     glGenTextures(1, &texID);
113     glBindTexture(GL_TEXTURE_2D, texID);
114     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
115     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
116     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
117     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
118     int width, height, nrChannels;
119     unsigned char *data = stbi_load(filename, &width, &height, &nrChannels, 0);
120     if (data)
121     {
122         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
123         glGenerateMipmap(GL_TEXTURE_2D);
124     }
125     else
126         printf("Failed to load texture
");
127     stbi_image_free(data);
128     return texID;
129 }
130 
131 char vShaderStr[] =
132 "#version 300 es                                         
"
133 "layout(location = 0) in vec4 a_position;                 
"
134 "layout(location = 1) in vec2 a_texCoord;                 
"
135 "uniform mat4 u_mvpMatrix;                                 
"
136 "out vec2 v_texCoord;                                     
"
137 "void main()                                             
"
138 "{                                                         
"
139 "    gl_Position = u_mvpMatrix * a_position;             
"
140 "     v_texCoord=a_texCoord;                                 
"
141 "}                                                         
";
142 
143 char fShaderStr[] =
144 "#version 300 es                                         
"
145 "precision mediump float;                                 
"
146 "in vec2 v_texCoord;                                     
"
147 "uniform sampler2D screenTexture;                         
"
148 "out vec4 outColor;                                         
"
149 "void main()                                             
"
150 "{                                                         
"
151 "    outColor = texture(screenTexture,v_texCoord);         
"
152 "}                                                         
";
153 
154 //填充quad面片的VS
155 char vScreenShaderStr[] =
156 "#version 300 es                                                    
"
157 "layout(location = 0) in vec2 a_position;                            
"
158 "layout(location = 1) in vec2 texCoord;                                
"
159 "out vec2 v_texCoord;                                                
"
160 "void main()                                                        
"
161 "{                                                                    
"
162 "   gl_Position = vec4(a_position.x,a_position.y,0.0,1.0);          
"
163 "   v_texCoord=texCoord;                                            
"
164 "}                                                                    
";
165 
166 ////正常:outColor=texture(Texture,v_texCoord);
167 char fScreenShaderStr[] =                                                //正常Shader
168 "#version 300 es                                                    
"
169 "precision mediump float;                                            
"
170 "out vec4 outColor;                                                    
"
171 "in vec2 v_texCoord;                                                
"
172 "uniform sampler2D Texture;                                            
"
173 "void main()                                                        
"
174 "{                                                                    
"
175 //"    outColor=texture(Texture,v_texCoord);                            
"//正常色
176 "    outColor=vec4(vec3(1.0-texture(Texture,v_texCoord)),1.0);        
"//反色
177 "}                                                                    
";
178 
179 char fScreenShaderStrKernel[] =//核效果着色器
180 "#version 300 es                                                    
"
181 "precision mediump float;                                            
"
182 "const float offset=1.0/300.0;                                        
"
183 "layout(location = 0) out vec4 outColor0;                            
"
184 "layout(location = 1) out vec4 outColor1;                            
"
185 "layout(location = 2) out vec4 outColor2;                            
"
186 "layout(location = 3) out vec4 outColor3;                            
"
187 "in vec2 v_texCoord;                                                
"
188 "uniform sampler2D Texture;                                            
"
189 "void main()                                                        
"
190 "{                                                                    
"
191 "    vec2 offsets[9] = vec2[](                                                                
"
192 "    vec2(-offset, offset),                                                                     
"
193 "    vec2(0.0f, offset),                                                                     
"
194 "    vec2(offset, offset),                                                                     
"
195 "    vec2(-offset, 0.0f),                                                                       
"
196 "    vec2(0.0f, 0.0f),                                                                       
"
197 "    vec2(offset, 0.0f),                                                                       
"
198 "    vec2(-offset, -offset),                                                                 
"
199 "    vec2(0.0f, -offset),                                                                    
"
200 "    vec2(offset, -offset)                                                                     
"
201 "    );                                                                                        
"
202 
203 "    float kernel[9] = float[](                                                                
"//模糊核0
204 "        1.0/16.0, 2.0/16.0, 1.0/16.0,                                                        
"
205 "        2.0/16.0, 4.0/16.0, 2.0/16.0,                                                        
"
206 "        1.0/16.0, 2.0/16.0, 1.0/16.0                                                        
"
207 "    );                                                                                        
"
208 "    vec3 sampleTex[9];                                                                        
"
209 "    for (int i = 0; i < 9; i++)                                                                
"
210 "    {                                                                                        
"
211 "        sampleTex[i] = vec3(texture(Texture, v_texCoord.st + offsets[i]));                    
"
212 "    }                                                                                        
"
213 "    vec3 col = vec3(0.0);                                                                    
"
214 "    for (int i = 0; i < 9; i++)                                                                
"
215 "        col += sampleTex[i] * kernel[i];                                                    
"
216 "    outColor0 = vec4(col, 1.0);                                                                
"
217 
218 "    kernel = float[](                                                                        
"//锐化核1
219 "        -1, -1, -1,                                                                            
"
220 "        -1, 9, -1,                                                                            
"
221 "        -1, -1, -1                                                                            
"
222 "        );                                                                                    
"
223 "    for (int i = 0; i < 9; i++)                                                                
"
224 "    {                                                                                        
"
225 "        sampleTex[i] = vec3(texture(Texture, v_texCoord.st + offsets[i]));                    
"
226 "    }                                                                                        
"
227 "    col = vec3(0.0);                                                                        
"
228 "    for (int i = 0; i < 9; i++)                                                                
"
229 "        col += sampleTex[i] * kernel[i];                                                    
"
230 "    outColor1 = vec4(col, 1.0);                                                                
"
231 "    outColor2 = texture(Texture,v_texCoord);                                                
"//正常色2
232 "    outColor3 = vec4(vec3(1.0-texture(Texture,v_texCoord)),1.0);                            
"//反色3
233 "}                                                                                            
";
234 
235 int Init(ESContext *esContext)
236 {
237     UserData *userData = esContext->userData;
238     userData->textureWidth = 600;
239     userData->textureHeight = 400;
240     // Load the shaders and get a linked program object
241     userData->programObject = esLoadProgram(vShaderStr, fShaderStr);//载入文件、附件、编译、判错、删除Shader
242     userData->programObjectQuad = esLoadProgram(vScreenShaderStr, fScreenShaderStrKernel);
243 
244     userData->angle = 0.0f;
245     userData->mvLoc = glGetUniformLocation(userData->programObject, "u_mvMatrix");
246     userData->mvpLoc = glGetUniformLocation(userData->programObject, "u_mvpMatrix");
247     //cube
248     glGenVertexArrays(1, &userData->cubeVAO);//初始化cube的vao
249     glGenBuffers(1, &userData->cubeVBO);//初始化装载cube属性的vbo
250     glBindVertexArray(userData->cubeVAO);//以下操作对cubeVAO负责
251     glBindBuffer(GL_ARRAY_BUFFER, userData->cubeVBO);//以下操作对cubeVBO负责
252     glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);//复制数据到当前vbo 
253     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLvoid*)0);//设置顶点位置
254     glEnableVertexAttribArray(0);
255     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLvoid*)(sizeof(GLfloat) * 3));
256     glEnableVertexAttribArray(1);
257     userData->texIDcube = LoadTextureFile("container.jpg");
258     glBindVertexArray(0);//完成cubeVAO的设置
259     //floor
260     glGenVertexArrays(1, &userData->floorVAO);//初始化地板vao
261     glGenBuffers(1, &userData->floorVBO);
262     glBindVertexArray(userData->floorVAO);
263     glBindBuffer(GL_ARRAY_BUFFER, userData->floorVBO);
264     glBufferData(GL_ARRAY_BUFFER, sizeof(floorVertices), floorVertices, GL_STATIC_DRAW);
265     glEnableVertexAttribArray(0);
266     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLvoid*)0);
267     glEnableVertexAttribArray(1);
268     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLvoid*)(sizeof(GLfloat) * 3));
269     userData->texIDfloor = LoadTextureFile("brick_DIFF.bmp");
270     glBindVertexArray(0);//完成floorVAO的设置
271     //quad
272     glGenVertexArrays(1, &userData->quadVAO);
273     glGenBuffers(1, &userData->quadVBO);
274     glBindVertexArray(userData->quadVAO);
275     glBindBuffer(GL_ARRAY_BUFFER, userData->quadVBO);
276     glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
277     glEnableVertexAttribArray(0);
278     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid*)0);
279     glEnableVertexAttribArray(1);
280     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid*)(sizeof(GLfloat) * 2));
281     glBindVertexArray(0);
282 
283     //GLuint defaultFramebuffer = 0;
284     const GLenum attachments[4] = {
285         GL_COLOR_ATTACHMENT0,
286         GL_COLOR_ATTACHMENT1,
287         GL_COLOR_ATTACHMENT2,
288         GL_COLOR_ATTACHMENT3
289     };
290     //glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFramebuffer);
291 
292     //设置FBO
293     glGenFramebuffers(1, &userData->framebuffer);//初始化帧缓冲framebuffer
294     glBindFramebuffer(GL_FRAMEBUFFER, userData->framebuffer);//以下代码对framebuffer负责,包括纹理附件设置和rbo附件设置
295         glGenTextures(4, &userData->texColorArray);
296         for (int i = 0; i < 4; i++){
297             //userData->texColorArray[i] = generateAttachmentTexture(GL_FALSE, GL_FALSE);//纹理附件
298             glBindTexture(GL_TEXTURE_2D, userData->texColorArray[i]);
299             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
300                 userData->textureWidth, userData->textureHeight,
301                 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);//设置宽高但不赋予纹理文件的数据
302             // Set the filtering mode
303             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
304             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
305             glBindTexture(GL_TEXTURE_2D, 0);
306             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, userData->texColorArray[i], 0);//完成FBO的纹理附件挂载
307         }
308         glDrawBuffers(4, attachments);
309         if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER))
310             return FALSE;
311 
312         //设置渲染缓冲对象附件
313         GLuint rbo;
314         glGenRenderbuffers(1, &rbo);//初始化rbo附件
315         glBindRenderbuffer(GL_RENDERBUFFER, rbo);//以下操作对rbo负责
316         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screenWidth, screenHeight);
317         glBindRenderbuffer(GL_RENDERBUFFER, 0);//完成对rbo的设置
318         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);//完成FBO的rbo附件挂载
319 
320         if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
321             printf("ERROR::FRAMEBUFFER:: Framebuffer is not complete!");
322 
323     glBindFramebuffer(GL_FRAMEBUFFER, 0);//完成纹理附件和rbo附件的设置,解绑fbo
324 
325     glClearColor(1.0f, 1.0f, 1.0f, 0.0f);//初始刷新一下
326     glEnable(GL_DEPTH_TEST);
327     return TRUE;
328 }
329 
330 void Update(ESContext *esContext, float deltaTime)
331 {
332     UserData *userData = esContext->userData;
333 
334     userData->angle += (deltaTime * 50.0f);//转动
335     if (userData->angle >= 360.0f)
336         userData->angle -= 360.0f;
337 
338     esMatrixLoadIdentity(&userData->mvMatrix);
339     esTranslate(&userData->mvMatrix, 0.0f, 0.0f, -3.0f);
340     esRotate(&userData->mvMatrix, userData->angle, 0.0f, 1.0f, 0.0f);
341 
342     ESMatrix perspective;
343     esMatrixLoadIdentity(&perspective);//单位化一个矩阵作为透视投影矩阵
344     float aspect = (GLfloat)esContext->width / ((GLfloat)esContext->height);
345     esPerspective(&perspective, 60.f, aspect, 0.2f, 20.f);
346 
347     esMatrixMultiply(&userData->mvpMatrix, &userData->mvMatrix, &perspective);
348 }
349 
350 void DrawQuad(ESContext *esContext)
351 {
352     UserData *userData = esContext->userData;
353     glBindFramebuffer(GL_FRAMEBUFFER, userData->framebuffer);
354         glViewport(0, 0, esContext->width, esContext->height);
355         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
356         glEnable(GL_DEPTH_TEST);
357         glUseProgram(userData->programObject);//启用programObject
358         glUniformMatrix4fv(userData->mvpLoc, 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix);//mvpMatrix在Update里更新
359 
360         glBindVertexArray(userData->cubeVAO);
361         glBindTexture(GL_TEXTURE_2D, userData->texIDcube);
362         glDrawArrays(GL_TRIANGLES, 0, 36);
363         glBindVertexArray(0);
364 
365         glBindVertexArray(userData->floorVAO);
366         glBindTexture(GL_TEXTURE_2D, userData->texIDfloor);
367         glDrawArrays(GL_TRIANGLES, 0, 6);
368         glBindVertexArray(0);
369     glBindFramebuffer(GL_FRAMEBUFFER, 0);
370     
371     // Bind to default framebuffer again and draw the quad plane with attched screen texture.
372     glBindFramebuffer(GL_FRAMEBUFFER, userData->framebuffer);//闪烁是因为重复渲染了三维图像和QUAD
373         glUseProgram(userData->programObjectQuad);//启用programObjectQuad
374         glBindVertexArray(userData->quadVAO);
375         glBindTexture(GL_TEXTURE_2D, userData->texColorArray[0]);//texColorArray在Init里绑定到了fbo的纹理Attachment
376         glDrawArrays(GL_TRIANGLES, 0, 6);
377         glBindVertexArray(0);
378     glBindFramebuffer(GL_FRAMEBUFFER, 0);
379     //ID号为0表示缺省帧缓存,即默认的window提供的帧缓存。因此,在glBindFramebuffer()中将ID号设置为0可以解绑定当前FBO。
380 }
381 
382 void BlitTextures(ESContext *esContext)//区位块传送
383 {
384     UserData *userData = esContext->userData;
385 
386     // set the fbo for reading
387     glBindFramebuffer(GL_READ_FRAMEBUFFER, userData->framebuffer);
388     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
389     // Copy the output red buffer to lower left quadrant
390     glReadBuffer(GL_COLOR_ATTACHMENT0);
391     glBlitFramebuffer(0, 0, userData->textureWidth, userData->textureHeight,
392         0, 0, esContext->width / 2, esContext->height / 2,
393         GL_COLOR_BUFFER_BIT, GL_LINEAR);
394     //(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 
395     // GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
396 
397     // Copy the output green buffer to lower right quadrant
398     glReadBuffer(GL_COLOR_ATTACHMENT1);
399     glBlitFramebuffer(0, 0, userData->textureWidth, userData->textureHeight,
400         esContext->width / 2, 0, esContext->width, esContext->height / 2,
401         GL_COLOR_BUFFER_BIT, GL_LINEAR);
402 
403     // Copy the output blue buffer to upper left quadrant
404     glReadBuffer(GL_COLOR_ATTACHMENT2);
405     glBlitFramebuffer(0, 0, userData->textureWidth, userData->textureHeight,
406         0, esContext->height / 2, esContext->width / 2, esContext->height,
407         GL_COLOR_BUFFER_BIT, GL_LINEAR);
408 
409     // Copy the output gray buffer to upper right quadrant
410     glReadBuffer(GL_COLOR_ATTACHMENT3);
411     glBlitFramebuffer(0, 0, userData->textureWidth, userData->textureHeight,
412         esContext->width / 2, esContext->height / 2, esContext->width, esContext->height,
413         GL_COLOR_BUFFER_BIT, GL_LINEAR);
414 }
415 
416 void Draw(ESContext *esContext)
417 {
418     DrawQuad(esContext);
419     BlitTextures(esContext);
420 }
421 
422 void ShutDown(ESContext *esContext)
423 {
424     UserData *userData = esContext->userData;
425 
426     glDeleteVertexArrays(1, &userData->cubeVAO);
427     glDeleteBuffers(1, &userData->cubeVBO);
428     glDeleteVertexArrays(1, &userData->floorVAO);
429     glDeleteBuffers(1, &userData->floorVBO);
430     glDeleteVertexArrays(1, &userData->quadVAO);
431     glDeleteBuffers(1, &userData->quadVBO);
432 
433     glDeleteBuffers(4, userData->texColorArray);
434     glDeleteFramebuffers(1, &userData->framebuffer);
435 
436     glDeleteProgram(userData->programObject);
437     glDeleteProgram(userData->programObjectQuad);
438 }
439 
440 int esMain(ESContext *esContext)
441 {
442     esContext->userData = malloc(sizeof(UserData));
443 
444     esCreateWindow(esContext, "正常,反色,模糊,锐化", screenWidth, screenHeight, ES_WINDOW_RGB | ES_WINDOW_ALPHA | ES_WINDOW_DEPTH);
445 
446     if (!Init(esContext))
447     {
448         return GL_FALSE;
449     }
450     esRegisterShutdownFunc(esContext, ShutDown);
451     esRegisterUpdateFunc(esContext, Update);
452     esRegisterDrawFunc(esContext, Draw);
453 
454     return GL_TRUE;
455 }
原文地址:https://www.cnblogs.com/zeppelin5/p/10019381.html