OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MultisampledFBO.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2012-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
57 #include <GLES3/gl3.h>
58 
59 #ifdef __ANDROID__
60 
68 #include "inc/gl2ext.h"
69 #else
70 #include <GLES2/gl2ext.h>
71 #endif
72 
73 #include <EGL/egl.h>
74 
75 #include <cstdio>
76 #include <cstdlib>
77 #include <sstream>
78 #include <math.h>
79 
80 #include <jni.h>
81 #include <android/log.h>
82 
83 #include "MultisampledFBO.h"
84 #include "Teapot.h"
85 
86 #include "Text.h"
87 #include "AndroidPlatform.h"
88 #include "Shader.h"
89 #include "Matrix.h"
90 
91 /* OpenGL ES extension functions. */
92 PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC glFramebufferTexture2DMultisampleEXT = NULL;
93 PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC glRenderbufferStorageMultisampleEXT = NULL;
94 
95 using std::string;
96 using std::ostringstream;
97 using namespace MaliSDK;
98 
99 /* Asset directories and filenames. */
100 const string resourceDirectory = "/data/data/com.arm.malideveloper.openglessdk.multisampledfbo/";
101 const string teapotVertexShaderFilename = "MultisampledFBO_teapot.vert";
102 const string teapotFragmentShaderFilename = "MultisampledFBO_teapot.frag";
103 string quadVertexShaderFilename = "MultisampledFBO_quad.vert";
104 string quadFragmentShaderFilename = "MultisampledFBO_quad.frag";
105 
106 /* Some colors and contrasting backgrounds. */
107 typedef struct
108 {
112 } Color;
113 
114 const Color colors[] =
115 {
116  { 0.0706f, 0.5490f, 0.6706f }, /* ARM Teal*/
117  { 0.9882f, 0.9961f, 0.0157f }, /* Yellow */
118  { 0.9882f, 0.6039f, 0.0157f }, /* Amber */
119  { 0.9882f, 0.4000f, 0.0196f }, /* Orange */
120  { 0.9882f, 0.1961f, 0.0157f }, /* Dark Orange */
121  { 0.8000f, 0.0078f, 0.0157f }, /* Red */
122  { 0.6118f, 0.0078f, 0.3922f }, /* Magenta */
123 };
124 
125 const Color backgrounds[] =
126 {
127  { 0.0000f, 0.0000f, 0.0000f }, /* Black */
128  { 0.3922f, 0.0200f, 0.3922f }, /* Purple */
129  { 0.0156f, 0.0118f, 0.3922f }, /* Dark Blue */
130  { 0.0157f, 0.1961f, 0.6118f }, /* Blue */
131  { 0.0157f, 0.4000f, 0.3922f }, /* Teal */
132  { 0.2039f, 0.6039f, 0.0157f }, /* Green */
133  { 0.3922f, 0.8078f, 0.0157f }, /* Light Green */
134 };
135 
136 /* Texture format enums and strings. */
137 const GLenum textureFormats[] = { GL_RGBA4, GL_RGBA8, GL_RGBA16F, GL_RGBA32F };
138 const GLchar* const textureFormatStrings[] = { "GL_RGBA4", "GL_RGBA8", "GL_RGBA16F", "GL_RGBA32F" };
139 
140 /* Texture format supported by device. */
141 GLboolean textureFormatSupported[] = { false, false, false, false };
142 
143 /* Max levels of multisampling for individual texture formats. */
144 GLint textureFormatSamples[] = { 0, 0, 0, 0 };
145 
146 /* FBO texture sizes. */
147 GLuint textureSizes[] = { 32, 64, 128, 256, 512, 1024 };
148 
149 /* Max level of multisampling for all texture formats. */
150 GLint maxSamples = 0;
151 
152 /* Flags for whether we can use linear filtering on float/half-float textures. */
155 
157 GLint currentSamples = 0;
161 
162 /* Shader variables. */
165 
167 GLint iLocTeapotNormal = -1;
168 GLint iLocTeapotColor = -1;
172 
173 GLint iLocQuadPosition = -1;
174 GLint iLocQuadTexCoord = -1;
175 GLint iLocQuadMVPMatrix = -1;
176 
177 /* Framebuffers and textures. */
180 
183 
186 
187 /* Teapot dimensions */
188 GLfloat minX = 0.0f;
189 GLfloat minY = 0.0f;
190 GLfloat minZ = 0.0f;
191 GLfloat maxX = 0.0f;
192 GLfloat maxY = 0.0f;
193 GLfloat maxZ = 0.0f;
195 
199 
200 GLint windowWidth = -1;
201 GLint windowHeight = -1;
202 
203 /* Flag to enable animation. */
205 
206 /* Scale factor for pinch-to-zoom. */
208 
209 /* Rotation offsets for drag gestures. */
212 
213 /* Text object to draw text on the screen. */
215 
216 bool extensionAvailable(const char* extName)
217 {
218  string extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
219  return extensions.find(extName) != string::npos;
220 }
221 
223 {
224  minX = maxX = teapotPositions[0];
225  minY = maxY = teapotPositions[1];
226  minZ = maxZ = teapotPositions[2];
227  for (unsigned int i = 3; i < sizeof teapotPositions / sizeof (GLfloat); i+=3)
228  {
229  if (teapotPositions[i] > maxX) maxX = teapotPositions[i];
230  if (teapotPositions[i] < minX) minX = teapotPositions[i];
231  if (teapotPositions[i+1] > maxY) maxY = teapotPositions[i+1];
232  if (teapotPositions[i+1] < minY) minY = teapotPositions[i+1];
233  if (teapotPositions[i+2] > maxZ) maxZ = teapotPositions[i+2];
234  if (teapotPositions[i+2] < minZ) minZ = teapotPositions[i+2];
235  }
236 
237  maxXYZ = fmaxf(maxX, fmaxf(maxY, maxZ));
238 }
239 
241 {
242  /* If the new texture format doesn't support linear filtering, disable it. */
243  GLboolean invalidFilteringMode = (textureFormats[currentTextureFormat] == GL_RGBA16F && !canFilterHalfFloat)
244  || (textureFormats[currentTextureFormat] == GL_RGBA32F && !canFilterFloat);
245  if (linearFilteringEnabled && invalidFilteringMode)
246  {
247  linearFilteringEnabled = false;
248  return;
249  }
250  GL_CHECK(glBindTexture(GL_TEXTURE_2D, *texture));
251  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linearFilteringEnabled ? GL_LINEAR : GL_NEAREST));
252  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linearFilteringEnabled ? GL_LINEAR : GL_NEAREST));
253  GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
254 }
255 
256 bool setupFBO(GLuint* fbo, GLuint* colorBuffer, GLuint* depthBuffer, GLuint textureSize, GLenum internalFormat, GLuint samples)
257 {
258  LOGD("Creating a %dx%d %smultisampled FBO (%d samples).", textureSize, textureSize, samples ? "" : "non-", samples);
259 
260  /* Generate framebuffer object. */
261  GL_CHECK(glDeleteFramebuffers(1, fbo));
262  GL_CHECK(glGenFramebuffers(1, fbo));
263  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, *fbo));
264 
265  /* Generate and attach texture for color buffer. */
266  GL_CHECK(glDeleteTextures(1, colorBuffer));
267  GL_CHECK(glGenTextures(1, colorBuffer));
268  GL_CHECK(glBindTexture(GL_TEXTURE_2D, *colorBuffer));
269  GL_CHECK(glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, textureSize, textureSize));
270  GL_CHECK(glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *colorBuffer, 0, samples));
271 
272  setTextureFiltering(colorBuffer);
273  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
274  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
275 
276  GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
277 
278  /* Generate and attach depth buffer. */
279  GL_CHECK(glDeleteRenderbuffers(1, depthBuffer))
280  GL_CHECK(glGenRenderbuffers(1, depthBuffer));
281  GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, *depthBuffer));
282  GL_CHECK(glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT16, textureSize, textureSize));
283  GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *depthBuffer));
284  GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0));
285 
286  /* Ensure the framebuffer is 'complete'. */
287  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
288  {
289  LOGE("%s framebuffer is incomplete! Error code %d", (samples ? "Multisampled" : "Non-multisampled"), glGetError());
290  return false;
291  }
292 
293  return true;
294 }
295 
296 void setupText()
297 {
298  ostringstream maxSamplesStringStream;
299  ostringstream texFormatStringStream;
300  ostringstream descriptionStringStream;
301 
302  maxSamplesStringStream << "Max number of samples (all texture formats): " << maxSamples;
303  texFormatStringStream << "Using texture format: " << textureFormatStrings[currentTextureFormat]
304  << " (" << textureSizes[currentTextureSize] << "x"
305  << textureSizes[currentTextureSize] << ", "
306  << currentSamples << " samples, "
307  << (linearFilteringEnabled ? "GL_LINEAR" : "GL_NEAREST") << " filtering)";
308  descriptionStringStream << "Left: No anti-aliasing. Right: Multisampled anti-aliasing (" << currentSamples << " samples)";
309 
310  text->clear();
311 
312  text->addString(0, windowHeight - text->textureCharacterHeight, maxSamplesStringStream.str().c_str(), 255, 255, 255, 255);
313  text->addString(0, windowHeight - text->textureCharacterHeight * 2, texFormatStringStream.str().c_str(), 255, 255, 255, 255);
314  text->addString(0, windowHeight - text->textureCharacterHeight * 3, "Tap to screen to toggle animation. Long-press to cycle colors. Pinch-to-zoom, drag to rotate.", 0, 255, 255, 255);
315  text->addString(0, windowHeight - text->textureCharacterHeight * 4, "Volume up: switch multisampling level. Volume down: switch texture resolution.", 0, 255, 255, 255);
316  text->addString(0, windowHeight - text->textureCharacterHeight * 5, "Long press vol up: switch texture format. Long press vol down: toggle texture filtering", 0, 255, 255, 255);
317 
318  text->addString(0, text->textureCharacterHeight, descriptionStringStream.str().c_str(), 255, 255, 0, 255);
319  text->addString(0, 0, "Multisampled framebuffer objects.", 0, 255, 255, 255);
320 }
321 
322 bool setupGraphics(int width, int height)
323 {
324  /* Initialize OpenGL ES. */
325  LOGD("setupGraphics(%d, %d)", width, height);
326 
327  /* Check we have the extensions we need. */
328  LOGD("Available extensions:");
329  LOGD("GL_EXT_multisampled_render_to_texture = %s", extensionAvailable("GL_EXT_multisampled_render_to_texture") ? "YES" : "NO");
330  LOGD("GL_EXT_color_buffer_half_float = %s", extensionAvailable("GL_EXT_color_buffer_half_float") ? "YES" : "NO");
331  LOGD("GL_EXT_color_buffer_float = %s", extensionAvailable("GL_EXT_color_buffer_float") ? "YES" : "NO");
332 
333  canFilterHalfFloat = extensionAvailable("OES_texture_half_float_linear");
334  canFilterFloat = extensionAvailable("OES_texture_float_linear");
335  LOGD("OES_texture_half_float_linear = %s", canFilterHalfFloat ? "YES" : "NO");
336  LOGD("OES_texture_float_linear = %s", canFilterFloat ? "YES" : "NO");
337 
338  /* Query maximum number of samples for all formats. */
339  LOGD("Max samples for internal texture formats:");
340  GL_CHECK(glGetIntegerv(GL_MAX_SAMPLES, &maxSamples));
341  LOGD("All (MAX_SAMPLES) = %d", maxSamples);
342 
343  /* Query maximum number of samples for various texture formats. */
344  for (unsigned int i = 0; i < sizeof textureFormats / sizeof (GLenum); i++)
345  {
346  /* Try to get the number of samples. If there was an error (likely GL_INVALID_ENUM), then assume unsupported. */
347  glGetInternalformativ(GL_RENDERBUFFER, textureFormats[i], GL_SAMPLES, 1, &textureFormatSamples[i]);
348  textureFormatSupported[i] = !glGetError();
349  if (textureFormatSupported[i])
350  {
352  }
353  else
354  {
355  LOGD("%s = %s", textureFormatStrings[i], "Not supported");
356  }
357  }
358 
359  /* Initialize multisampling extension function pointers. */
360  glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) eglGetProcAddress("glFramebufferTexture2DMultisampleEXT");
362  {
363  LOGE("Couldn't get function pointer to glFramebufferTexture2DMultisampleEXT()!");
364  return false;
365  }
366 
367  glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) eglGetProcAddress("glRenderbufferStorageMultisampleEXT");
369  {
370  LOGE("Couldn't get function pointer to glRenderbufferStorageMultisampleEXT()!");
371  return false;
372  }
373 
374  /* Save window dimensions for calculating aspect ratios. */
375  windowWidth = width;
377 
378  /* Full paths to the shader files */
379  string teapotVertexShaderPath = resourceDirectory + teapotVertexShaderFilename;
380  string teapotFragmentShaderPath = resourceDirectory + teapotFragmentShaderFilename;
381  string quadVertexShaderPath = resourceDirectory + quadVertexShaderFilename;
382  string quadFragmentShaderPath = resourceDirectory + quadFragmentShaderFilename;
383 
384  /* Handles to shaders. */
385  GLuint teapotVertexShaderID = 0;
386  GLuint teapotFragmentShaderID = 0;
387  GLuint quadVertexShaderID = 0;
388  GLuint quadFragmentShaderID = 0;
389 
390  /* Enable the depth buffer (must remember to clear it on each redraw) */
391  GL_CHECK(glEnable(GL_DEPTH_TEST));
392 
393  /* Use less-than or equal for depth testing */
394  GL_CHECK(glDepthFunc(GL_LESS));
395 
396  /* Find the best texture format supporting the greatest number of samples. */
397  GLint bestSamples = 0;
398  GLint bestTextureFormat = 0;
399  for (unsigned int i = 0; i < sizeof textureFormats / sizeof (GLuint); i++)
400  {
401  if (textureFormatSamples[i] >= bestSamples)
402  {
403  bestSamples = textureFormatSamples[i];
404  bestTextureFormat = i;
405  }
406  }
407 
408  currentSamples = bestSamples;
409  currentTextureFormat = bestTextureFormat;
410 
411  /* Generate FBOs and render buffers for non-antialiased and multisampled rendering. */
413  if (!setupFBO(&frameBufferMSAA, &texColorBufferMSAA, &depthBufferMSAA, textureSizes[currentTextureSize], textureFormats[currentTextureFormat], currentSamples)) return false;
414 
415  /* Initialize the Text object and add some text. */
416  text = new Text(resourceDirectory.c_str(), width, height);
417 
418  /* Update screen text. */
419  setupText();
420 
421  /* Process shaders. */
422  Shader::processShader(&teapotVertexShaderID, teapotVertexShaderPath.c_str(), GL_VERTEX_SHADER);
423  Shader::processShader(&teapotFragmentShaderID, teapotFragmentShaderPath.c_str(), GL_FRAGMENT_SHADER);
424  Shader::processShader(&quadVertexShaderID, quadVertexShaderPath.c_str(), GL_VERTEX_SHADER);
425  Shader::processShader(&quadFragmentShaderID, quadFragmentShaderPath.c_str(), GL_FRAGMENT_SHADER);
426 
427  LOGD("teapotVertexShaderID = %d", teapotVertexShaderID);
428  LOGD("teapotFragmentShaderID = %d", teapotFragmentShaderID);
429  LOGD("quadVertexShaderID = %d", quadVertexShaderID);
430  LOGD("quadFragmentShaderID = %d", quadFragmentShaderID);
431 
432  /* Initialise shader programs. */
433  teapotProgramID = GL_CHECK(glCreateProgram());
434  quadProgramID = GL_CHECK(glCreateProgram());
435  if (teapotProgramID == 0 || quadProgramID == 0)
436  {
437  LOGE("Could not create program.");
438  return false;
439  }
440 
441  GL_CHECK(glAttachShader(teapotProgramID, teapotVertexShaderID));
442  GL_CHECK(glAttachShader(teapotProgramID, teapotFragmentShaderID));
443  GL_CHECK(glLinkProgram(teapotProgramID));
444 
445  GL_CHECK(glAttachShader(quadProgramID, quadVertexShaderID));
446  GL_CHECK(glAttachShader(quadProgramID, quadFragmentShaderID));
447  GL_CHECK(glLinkProgram(quadProgramID));
448 
449  /* Cleanup individual shaders as they're no longer needed. */
450  GL_CHECK(glDeleteShader(teapotVertexShaderID));
451  GL_CHECK(glDeleteShader(teapotFragmentShaderID));
452  GL_CHECK(glDeleteShader(quadVertexShaderID));
453  GL_CHECK(glDeleteShader(quadFragmentShaderID));
454 
455  /* Get handles to teapot shader variables. */
456  GL_CHECK(iLocTeapotPosition = glGetAttribLocation(teapotProgramID, "a_v3Position"));
457  GL_CHECK(iLocTeapotNormal = glGetAttribLocation(teapotProgramID, "a_v3Normal"));
458  GL_CHECK(iLocTeapotColor = glGetUniformLocation(teapotProgramID, "u_v3Color"));
459  GL_CHECK(iLocTeapotMVMatrix = glGetUniformLocation(teapotProgramID, "u_m4MV"));
460  GL_CHECK(iLocTeapotMVPMatrix = glGetUniformLocation(teapotProgramID, "u_m4MVP"));
461  GL_CHECK(iLocTeapotNormalMatrix = glGetUniformLocation(teapotProgramID, "u_m4Normal"));
462 
463  LOGD("glGetAttribLocation(\"a_v3Position\") = %d", iLocTeapotPosition);
464  LOGD("glGetAttribLocation(\"a_v3Normal\") = %d", iLocTeapotNormal);
465  LOGD("glGetAttribLocation(\"u_v3Color\") = %d", iLocTeapotColor);
466  LOGD("glGetUniformLocation(\"u_m4MV\") = %d", iLocTeapotMVMatrix);
467  LOGD("glGetUniformLocation(\"u_m4MVP\") = %d", iLocTeapotMVPMatrix);
468  LOGD("glGetUniformLocation(\"u_m4Normal\") = %d", iLocTeapotNormalMatrix);
469 
470  /* Get handles to quad shader variables. */
471  GL_CHECK(iLocQuadPosition = glGetAttribLocation(quadProgramID, "a_v3Position"));
472  GL_CHECK(iLocQuadTexCoord = glGetAttribLocation(quadProgramID, "a_v2TexCoord"));
473  GL_CHECK(iLocQuadMVPMatrix = glGetUniformLocation(quadProgramID, "u_m4MVP"));
474 
475  LOGD("glGetAttribLocation(\"a_v3Position\") = %d", iLocQuadPosition);
476  LOGD("glGetAttribLocation(\"a_v2TexCoord\") = %d", iLocQuadTexCoord);
477  LOGD("glGetUniformLocation(\"u_m4MVP\") = %d", iLocQuadMVPMatrix);
478 
479  /* Set clear screen color (dark grey). */
480  GL_CHECK(glClearColor(0.2f, 0.2f, 0.2f, 1.0f));
481  GL_CHECK(glClearDepthf(1.0f));
482 
483  /* Find min/max dimensions of teapot. */
485 
486  return true;
487 }
488 
490 {
493  Matrix mvpMatrix;
494  Matrix normalMatrix;
495 
496  /* Set clear screen color and clear the framebuffer. */
497  Color bg = backgrounds[currentColor];
498  GL_CHECK(glClearColor(bg.r, bg.g, bg.b, 1.0f));
499  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
500 
501  /* Set viewport to size of FBO texture. */
502  GL_CHECK(glViewport(0, 0, textureSizes[currentTextureSize], textureSizes[currentTextureSize]));
503 
504  /*
505  * Use max dimensions of the model to center it.
506  * We find the centre of the teapot by averaging the min and max Y coordinates,
507  * then push it down on the Y axis by this value before rotating so that the
508  * teapot spins about its centre.
509  */
510  GLfloat centerY = (maxY + minY) / 2.0f;
511 
512  /* Calculate model, view, and projection matrices. */
513  modelViewMatrix = Matrix::identityMatrix;
514  modelViewMatrix = Matrix::createTranslation(0.0f, -centerY, 0.0f) * modelViewMatrix;
515 
520  modelViewMatrix = Matrix::createTranslation(0.0f, 0.0f, -2.5f + pinchZoomScaleFactor) * modelViewMatrix;
521  modelViewMatrix = Matrix::createTranslation(0.0f, 0.0f, sinf(rotationDegree2 * M_PI/180.0f) / 2.0f) * modelViewMatrix;
522 
523  /* Change degree counters if animating. */
524  if (animate)
525  {
526  rotationDegree1 += 1.0f;
527  rotationDegree2 += 0.3f;
528  if (rotationDegree1 > 360.0f) rotationDegree1 -= 360.0f;
529  if (rotationDegree2 > 360.0f) rotationDegree2 -= 360.0f;
530  }
531 
532  /* Calculate the projection matrix. */
533  projectionMatrix = Matrix::matrixPerspective(45.0f, 1.0f, 0.1f, 1000.0f);
534  mvpMatrix = projectionMatrix * modelViewMatrix;
535 
536  /* Calculate the normal matrix. */
537  normalMatrix = Matrix::matrixInvert(&modelViewMatrix);
538  Matrix::matrixTranspose(&normalMatrix);
539 
540  /* Send matrices to the shaders. */
541  GL_CHECK(glUniformMatrix4fv(iLocTeapotMVMatrix, 1, GL_FALSE, modelViewMatrix.getAsArray()));
542  GL_CHECK(glUniformMatrix4fv(iLocTeapotMVPMatrix, 1, GL_FALSE, mvpMatrix.getAsArray()));
543  GL_CHECK(glUniformMatrix4fv(iLocTeapotNormalMatrix, 1, GL_FALSE, normalMatrix.getAsArray()));
544 
545  /* Send current color to the shaders. */
546  Color color = colors[currentColor];
547  GL_CHECK(glUniform3f(iLocTeapotColor, color.r, color.g, color.b));
548 
549  /* Set up vertex attributes. */
550  GL_CHECK(glVertexAttribPointer(iLocTeapotPosition, 3, GL_FLOAT, GL_FALSE, 0, teapotPositions));
551  GL_CHECK(glVertexAttribPointer(iLocTeapotNormal, 3, GL_FLOAT, GL_FALSE, 0, teapotNormals));
552 
553  GL_CHECK(glEnableVertexAttribArray(iLocTeapotPosition));
554  GL_CHECK(glEnableVertexAttribArray(iLocTeapotNormal));
555 
556  /* Draw the teapot geometry. */
557  GL_CHECK(glDrawElements(GL_TRIANGLES, sizeof(teapotIndices) / sizeof (GLuint), GL_UNSIGNED_INT, teapotIndices));
558 
559  GL_CHECK(glDisableVertexAttribArray(iLocTeapotPosition));
560  GL_CHECK(glDisableVertexAttribArray(iLocTeapotNormal));
561 }
562 
563 /* Code to draw one frame. */
564 void renderFrame(void)
565 {
566  /**************************************************************************/
567  /* DRAW TEAPOT */
568  /**************************************************************************/
569 
570  /* Switch to the teapot shader program. */
571  GL_CHECK(glUseProgram(teapotProgramID));
572 
573  /* Switch to non-antialiased FBO */
574  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBufferNoAA));
575  drawTeapot();
576 
577  /* Switch to multisampled FBO */
578  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBufferMSAA));
579  drawTeapot();
580 
581  /**************************************************************************/
582  /* DRAW QUADS */
583  /**************************************************************************/
584 
585  /* Switch to the quad shader program. */
586  GL_CHECK(glUseProgram(quadProgramID));
587 
588  /* Switch back to default framebuffer. */
589  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
590  GL_CHECK(glViewport (0, 0, windowWidth, windowHeight));
591 
592  /* Enable attributes for position and texture coordinates. */
593  GL_CHECK(glEnableVertexAttribArray(iLocQuadPosition));
594  GL_CHECK(glEnableVertexAttribArray(iLocQuadTexCoord));
595 
596  /* Populate attributes for position, color and texture coordinates etc. */
597  GL_CHECK(glVertexAttribPointer(iLocQuadPosition, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), quadVertices));
598  GL_CHECK(glVertexAttribPointer(iLocQuadTexCoord, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), quadVertices + 3));
599 
600  /* Calculate and pass matrix to the shader. */
602 
603  /* Pull the camera back. */
604  modelViewMatrix[14] -= 1.0f;
605 
606  float aspectRatio = windowWidth / (float) windowHeight;
607  Matrix projectionMatrix = Matrix::matrixPerspective(45.0f, aspectRatio, 0.1f, 1000.0f);
608  Matrix mvpMatrix = projectionMatrix * modelViewMatrix;
609 
610  GL_CHECK(glUniformMatrix4fv(iLocQuadMVPMatrix, 1, GL_FALSE, mvpMatrix.getAsArray()));
611 
612  /* Clear the screen and draw the elements. */
613  GL_CHECK(glClearColor(0.2f, 0.2f, 0.2f, 1.0f));
614  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
615 
616  /* Enable texture. */
617  GL_CHECK(glActiveTexture(GL_TEXTURE0));
618 
619  /* Select NoAA color buffer to use as a texture and draw left quad. */
620  GL_CHECK(glBindTexture(GL_TEXTURE_2D, texColorBufferNoAA));
621  GL_CHECK(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, vertexIndices));
622 
623  /* Select MSAA color buffer to use as a texture and draw right quad. */
624  GL_CHECK(glBindTexture(GL_TEXTURE_2D, texColorBufferMSAA));
625  GL_CHECK(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, vertexIndices + 6));
626 
627  /* Draw fonts - blending is required for text). */
628  GL_CHECK(glEnable(GL_BLEND));
629  GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
630  text->draw();
631  GL_CHECK(glDisable(GL_BLEND));
632 }
633 
634 extern "C"
635 {
637  (JNIEnv *env, jclass jcls, jint width, jint height)
638  {
639  /* Make sure that all resource files are in place. */
644 
645  setupGraphics(width, height);
646  }
647 
649  (JNIEnv *env, jclass jcls)
650  {
651  renderFrame();
652  }
653 
655  (JNIEnv *env, jclass jcls)
656  {
657  /* Toggle teapot animation. */
658  animate = !animate;
659  }
660 
662  (JNIEnv *env, jclass jcls)
663  {
664  /* Switch colors */
665  currentColor++;
666  currentColor = currentColor % (sizeof colors / sizeof (Color));
667  }
668 
670  (JNIEnv *env, jclass jcls)
671  {
672  /* Switch to next level of multisampling. */
674  currentSamples = 0;
675  else if (currentSamples == 0)
676  currentSamples = 2;
677  else
678  currentSamples *= 2;
679 
681  setupFBO(&frameBufferMSAA, &texColorBufferMSAA, &depthBufferMSAA, textureSizes[currentTextureSize], textureFormats[currentTextureFormat], currentSamples);
682  setupText();
683  }
684 
686  (JNIEnv *env, jclass jcls)
687  {
688  /* Switch to next supported texture format. */
689  do
690  {
693  }
695 
696  /* If the new texture format doesn't support the current sampling level, use its max. */
698 
699  /* The new texture format may not support filtering, so reset it. */
703  setupFBO(&frameBufferMSAA, &texColorBufferMSAA, &depthBufferMSAA, textureSizes[currentTextureSize], textureFormats[currentTextureFormat], currentSamples);
704  setupText();
705  }
706 
708  (JNIEnv *env, jclass jcls)
709  {
710  /* Switch to next texture size. */
713 
715  setupFBO(&frameBufferMSAA, &texColorBufferMSAA, &depthBufferMSAA, textureSizes[currentTextureSize], textureFormats[currentTextureFormat], currentSamples);
716  setupText();
717  }
718 
720  (JNIEnv *env, jclass jcls)
721  {
722  /* Toggle texture filtering. */
726  setupText();
727  }
728 
730  (JNIEnv *env, jclass jcls, jfloat scaleFactor)
731  {
732  /* Update scale factor. */
733  pinchZoomScaleFactor = scaleFactor;
734  LOGD("Scale factor now %.2f", pinchZoomScaleFactor);
735  }
736 
738  (JNIEnv *env, jclass jcls, jfloat rotationX, jfloat rotationY)
739  {
740  animate = false;
741 
742  /* Update drag rotation. */
743  dragRotateX += rotationX / 2.0f;
744  dragRotateY += rotationY / 2.0f;
745  }
746 
748  (JNIEnv *, jclass)
749  {
750  delete text;
751 
752  /* Clean up FBOs. */
753  GL_CHECK(glDeleteFramebuffers(1, &frameBufferNoAA));
754  GL_CHECK(glDeleteFramebuffers(1, &frameBufferMSAA));
755  }
756 }
void setupText()
GLint iLocTeapotPosition
GLint iLocTeapotNormal
GLuint frameBufferNoAA
Matrix rotationY
GLfloat minX
GLuint texColorBufferMSAA
static const float quadVertices[]
Definition: IntegerLogic.h:96
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_switchSamples(JNIEnv *env, jclass jcls)
GLfloat r
GLfloat rotationDegree2
float projectionMatrix[16]
Definition: Native.cpp:156
const Color colors[]
GLfloat rotationDegree1
Functions for drawing text in OpenGL ES.
Definition: Text.h:44
GLint iLocQuadMVPMatrix
PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC glFramebufferTexture2DMultisampleEXT
GLint iLocQuadPosition
GLint currentSamples
static Matrix identityMatrix
The identity matrix.
Definition: Matrix.h:90
const GLenum textureFormats[]
float modelViewMatrix[16]
Definition: Native.cpp:157
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
Text * text
GLint windowWidth
const float teapotNormals[]
Definition: Teapot.h:7344
float min(float x, float y)
Definition: noise.cpp:34
GLuint depthBufferMSAA
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_switchTextureSize(JNIEnv *env, jclass jcls)
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_step(JNIEnv *env, jclass jcls)
GLfloat g
const string teapotVertexShaderFilename
Functions for manipulating matrices.
Definition: Matrix.h:31
GLfloat minY
GLboolean canFilterFloat
GLuint counter
Definition: gl2ext.h:776
GLint iLocTeapotMVMatrix
static Matrix matrixInvert(Matrix *matrix)
Get the inverse of a matrix.
Definition: Matrix.cpp:155
void renderFrame(void)
const GLubyte vertexIndices[]
GLint maxSamples
static Matrix createTranslation(float x, float y, float z)
Create and return a translation matrix.
Definition: Matrix.cpp:414
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_toggleTextureFiltering(JNIEnv *env, jclass jcls)
void clear(void)
Removes the current string from the class.
Definition: Text.cpp:142
const GLchar *const textureFormatStrings[]
#define LOGD(...)
Definition: AstcTextures.h:28
GLint textureFormatSamples[]
GLint iLocTeapotMVPMatrix
GLuint texColorBufferNoAA
static Matrix matrixPerspective(float FOV, float ratio, float zNear, float zFar)
Create and return a perspective projection matrix.
Definition: Matrix.cpp:425
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_toggleAnim(JNIEnv *env, jclass jcls)
GLint iLocTeapotNormalMatrix
GLuint textureSizes[]
GLuint quadProgramID
GLuint teapotProgramID
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:78
static const int textureCharacterHeight
The height (in pixels) of the characters in the text texture.
Definition: Text.h:89
GLfloat minY
Definition: gl2ext.h:434
GLuint currentTextureFormat
void findTeapotDimensions()
GLfloat pinchZoomScaleFactor
GLsizei samples
Definition: gl2ext.h:707
typedef GLboolean(GL_APIENTRYP PFNGLISENABLEDIOESPROC)(GLenum target
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_setDragRotation(JNIEnv *env, jclass jcls, jfloat rotationX, jfloat rotationY)
GLfloat GLfloat GLfloat GLfloat maxX
Definition: gl2ext.h:434
GLfloat GLfloat f
Definition: gl2ext.h:2707
void addString(int xPosition, int yPosition, const char *string, int red, int green, int blue, int alpha)
Add a std::string to be drawn to the screen.
Definition: Text.cpp:157
GLboolean textureFormatSupported[]
#define M_PI
The value of pi.
Definition: Mathematics.h:37
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_switchColor(JNIEnv *env, jclass jcls)
GLfloat dragRotateY
#define GL_CHECK(x)
Definition: AstcTextures.h:59
GLuint depthBufferNoAA
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_setScaleFactor(JNIEnv *env, jclass jcls, jfloat scaleFactor)
const string resourceDirectory
static Matrix createRotationY(float angle)
Create and return a rotation matrix around the y-axis matrix.
Definition: Matrix.cpp:511
static Matrix createRotationZ(float angle)
Create and return a rotation matrix around the z-axis matrix.
Definition: Matrix.cpp:523
GLenum GLuint texture
Definition: gl2ext.h:385
static bool getAndroidAsset(JNIEnv *JNIEnvironment, const char destinationDirectory[], const char filename[])
Extract an asset file from the APK.
GLfloat GLfloat GLfloat GLfloat GLfloat maxY
Definition: gl2ext.h:434
GLfloat dragRotateX
static void matrixTranspose(Matrix *matrix)
Transpose a matrix in-place.
Definition: Matrix.cpp:374
GLboolean canFilterHalfFloat
void drawTeapot()
bool setupFBO(GLuint *fbo, GLuint *colorBuffer, GLuint *depthBuffer, GLuint textureSize, GLenum internalFormat, GLuint samples)
string quadFragmentShaderFilename
GLuint frameBufferMSAA
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC glRenderbufferStorageMultisampleEXT
GLboolean animate
GLint windowHeight
const float teapotPositions[]
Definition: Teapot.h:24
GLint iLocQuadTexCoord
string quadVertexShaderFilename
GLfloat b
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_uninit(JNIEnv *, jclass)
GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat maxZ
Definition: gl2ext.h:434
GLboolean linearFilteringEnabled
#define LOGE(...)
Definition: AstcTextures.h:30
void setTextureFiltering(GLuint *texture)
GLuint currentColor
precision highp float
Definition: hiz_cull.cs:37
Matrix rotationX
GLint GLsizei width
Definition: gl2ext.h:179
typedef GLfloat(GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC)(GLuint path
const unsigned int teapotIndices[]
Definition: Teapot.h:14664
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
const string teapotFragmentShaderFilename
GLfloat maxXYZ
bool setupGraphics(int width, int height)
GLfloat GLfloat minZ
Definition: gl2ext.h:434
static void processShader(GLuint *shader, const char *filename, GLint shaderType)
Create shader, load in source, compile, and dump debug as necessary.
Definition: Shader.cpp:29
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_init(JNIEnv *env, jclass jcls, jint width, jint height)
void draw(void)
Draw the text to the screen.
Definition: Text.cpp:265
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count
static Matrix createRotationX(float angle)
Create and return a rotation matrix around the x-axis matrix.
Definition: Matrix.cpp:499
const Color backgrounds[]
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_multisampledfbo_MultisampledFBO_switchTextureFormat(JNIEnv *env, jclass jcls)
GLint iLocTeapotColor
GLuint currentTextureSize
bool extensionAvailable(const char *extName)