OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FrameBufferObject.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 
30 #include <GLES2/gl2.h>
31 #include <GLES2/gl2ext.h>
32 
33 #include <string>
34 
35 #include <jni.h>
36 #include <android/log.h>
37 
38 #include "FrameBufferObject.h"
39 #include "Text.h"
40 #include "Shader.h"
41 #include "Texture.h"
42 #include "Matrix.h"
43 #include "AndroidPlatform.h"
44 
45 using std::string;
46 using namespace MaliSDK;
47 
48 /* Asset directories and filenames. */
49 string resourceDirectory = "/data/data/com.arm.malideveloper.openglessdk.framebufferobject/";
50 string vertexShaderFilename = "FrameBufferObject_cube.vert";
51 string fragmentShaderFilename = "FrameBufferObject_cube.frag";
52 
53 #define FBO_WIDTH 256
54 #define FBO_HEIGHT 256
55 
56 /* Shader variables. */
60 GLint iLocPosition = -1;
61 GLint iLocTextureMix = -1;
62 GLint iLocTexture = -1;
63 GLint iLocFillColor = -1;
64 GLint iLocTexCoord = -1;
65 GLint iLocProjection = -1;
66 GLint iLocModelview = -1;
67 
68 /* Animation variables. */
69 static float angleX = 0;
70 static float angleY = 0;
71 static float angleZ = 0;
79 
80 /* Framebuffer variables. */
82 
83 /* Application textures. */
85 
86 int windowWidth = -1;
87 int windowHeight = -1;
88 
89 /* A text object to draw text on the screen. */
91 
92 bool setupGraphics(int width, int height)
93 {
96 
97  /* Full paths to the shader files */
98  string vertexShaderPath = resourceDirectory + vertexShaderFilename;
99  string fragmentShaderPath = resourceDirectory + fragmentShaderFilename;
100 
101  /* Initialize matrices. */
103  projectionFBO = Matrix::matrixPerspective(45.0f, (FBO_WIDTH / (float)FBO_HEIGHT), 0.01f, 100.0f);
104  /* Move cube 2 further away from camera. */
105  translation = Matrix::createTranslation(0.0f, 0.0f, -2.0f);
106 
107  /* Initialize OpenGL ES. */
108  GL_CHECK(glEnable(GL_CULL_FACE));
109  GL_CHECK(glCullFace(GL_BACK));
110  GL_CHECK(glEnable(GL_DEPTH_TEST));
111  GL_CHECK(glEnable(GL_BLEND));
112  /* Should do src * (src alpha) + dest * (1-src alpha). */
113  GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
114 
115  /* Initialize the Text object and add some text. */
117  text->addString(0, 0, "Simple FrameBuffer Object (FBO) Example", 255, 255, 0, 255);
118 
119  /* Initialize FBO texture. */
120  GL_CHECK(glGenTextures(1, &iFBOTex));
121  GL_CHECK(glBindTexture(GL_TEXTURE_2D, iFBOTex));
122  /* Set filtering. */
123  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
124  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
125  GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, FBO_WIDTH, FBO_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
126 
127  /* Initialize FBOs. */
128  GL_CHECK(glGenFramebuffers(1, &iFBO));
129 
130  /* Render to framebuffer object. */
131  /* Bind our framebuffer for rendering. */
132  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, iFBO));
133 
134  /* Attach texture to the framebuffer. */
135  GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, iFBOTex, 0));
136 
137  /* Check FBO is OK. */
138  GLenum iResult = GL_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER));
139  if(iResult != GL_FRAMEBUFFER_COMPLETE)
140  {
141  LOGE("Framebuffer incomplete at %s:%i\n", __FILE__, __LINE__);
142  return false;
143  }
144 
145  /* Unbind framebuffer. */
146  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
147 
148  /* Process shaders. */
149  Shader::processShader(&vertexShaderID, vertexShaderPath.c_str(), GL_VERTEX_SHADER);
150  Shader::processShader(&fragmentShaderID, fragmentShaderPath.c_str(), GL_FRAGMENT_SHADER);
151 
152  /* Set up shaders. */
153  programID = GL_CHECK(glCreateProgram());
154  GL_CHECK(glAttachShader(programID, vertexShaderID));
155  GL_CHECK(glAttachShader(programID, fragmentShaderID));
156  GL_CHECK(glLinkProgram(programID));
157  GL_CHECK(glUseProgram(programID));
158 
159  /* Vertex positions. */
160  iLocPosition = GL_CHECK(glGetAttribLocation(programID, "a_v4Position"));
161  if(iLocPosition == -1)
162  {
163  LOGE("Attribute not found at %s:%i\n", __FILE__, __LINE__);
164  return false;
165  }
166  GL_CHECK(glEnableVertexAttribArray(iLocPosition));
167 
168  /* Texture mix. */
169  iLocTextureMix = GL_CHECK(glGetUniformLocation(programID, "u_fTex"));
170  if(iLocTextureMix == -1)
171  {
172  LOGD("Warning: Uniform not found at %s:%i\n", __FILE__, __LINE__);
173  }
174  else
175  {
176  GL_CHECK(glUniform1f(iLocTextureMix, 0.0));
177  }
178 
179  /* Texture. */
180  iLocTexture = GL_CHECK(glGetUniformLocation(programID, "u_s2dTexture"));
181  if(iLocTexture == -1)
182  {
183  LOGD("Warning: Uniform not found at %s:%i\n", __FILE__, __LINE__);
184  }
185  else
186  {
187  GL_CHECK(glUniform1i(iLocTexture, 0));
188  }
189 
190  /* Vertex colors. */
191  iLocFillColor = GL_CHECK(glGetAttribLocation(programID, "a_v4FillColor"));
192  if(iLocFillColor == -1)
193  {
194  LOGD("Warning: Attribute not found at %s:%i\n", __FILE__, __LINE__);
195  }
196  else
197  {
198  GL_CHECK(glEnableVertexAttribArray(iLocFillColor));
199  }
200 
201  /* Texture coords. */
202  iLocTexCoord = GL_CHECK(glGetAttribLocation(programID, "a_v2TexCoord"));
203  if(iLocTexCoord == -1)
204  {
205  LOGD("Warning: Attribute not found at %s:%i\n", __FILE__, __LINE__);
206  }
207  else
208  {
209  GL_CHECK(glEnableVertexAttribArray(iLocTexCoord));
210  }
211 
212  /* Projection matrix. */
213  iLocProjection = GL_CHECK(glGetUniformLocation(programID, "u_m4Projection"));
214  if(iLocProjection == -1)
215  {
216  LOGD("Warning: Uniform not found at %s:%i\n", __FILE__, __LINE__);
217  }
218  else
219  {
220  GL_CHECK(glUniformMatrix4fv(iLocProjection, 1, GL_FALSE, projection.getAsArray()));
221  }
222 
223  /* Modelview matrix. */
224  iLocModelview = GL_CHECK(glGetUniformLocation(programID, "u_m4Modelview"));
225  if(iLocModelview == -1)
226  {
227  LOGD("Warning: Uniform not found at %s:%i\n", __FILE__, __LINE__);
228  }
229  /* We pass this for each object, below. */
230 
231  return true;
232 }
233 
234 void renderFrame(void)
235 {
236  /* Both main window surface and FBO use the same shader program. */
237  GL_CHECK(glUseProgram(programID));
238 
239  /* Both drawing surfaces also share vertex data. */
240  GL_CHECK(glEnableVertexAttribArray(iLocPosition));
241  GL_CHECK(glVertexAttribPointer(iLocPosition, 3, GL_FLOAT, GL_FALSE, 0, cubeVertices));
242 
243  /* Including color data. */
244  if(iLocFillColor != -1)
245  {
246  GL_CHECK(glEnableVertexAttribArray(iLocFillColor));
247  GL_CHECK(glVertexAttribPointer(iLocFillColor, 4, GL_FLOAT, GL_FALSE, 0, cubeColors));
248  }
249 
250  /* And texture coordinate data. */
251  if(iLocTexCoord != -1)
252  {
253  GL_CHECK(glEnableVertexAttribArray(iLocTexCoord));
254  GL_CHECK(glVertexAttribPointer(iLocTexCoord, 2, GL_FLOAT, GL_FALSE, 0, cubeTextureCoordinates));
255  }
256 
257  /* Bind the FrameBuffer Object. */
258  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, iFBO));
259 
260  /* Set the viewport according to the FBO's texture. */
261  GL_CHECK(glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT));
262 
263  /* Clear screen on FBO. */
264  GL_CHECK(glClearColor(0.5f, 0.5f, 0.5f, 1.0));
265  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
266 
267  /* Create rotation matrix specific to the FBO's cube. */
271 
272  /* Rotate about origin, then translate away from camera. */
276 
277  /* Load FBO-specific projection and modelview matrices. */
278  GL_CHECK(glUniformMatrix4fv(iLocModelview, 1, GL_FALSE, modelView.getAsArray()));
279  GL_CHECK(glUniformMatrix4fv(iLocProjection, 1, GL_FALSE, projectionFBO.getAsArray()));
280 
281  /* The FBO cube doesn't get textured so zero the texture mix factor. */
282  if(iLocTextureMix != -1)
283  {
284  GL_CHECK(glUniform1f(iLocTextureMix, 0.0));
285  }
286 
287  /* Now draw the colored cube to the FrameBuffer Object. */
288  GL_CHECK(glDrawElements(GL_TRIANGLE_STRIP, sizeof(cubeIndices) / sizeof(GLubyte), GL_UNSIGNED_BYTE, cubeIndices));
289 
290  /* And unbind the FrameBuffer Object so subsequent drawing calls are to the EGL window surface. */
291  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER,0));
292 
293  /* Reset viewport to the EGL window surface's dimensions. */
294  GL_CHECK(glViewport(0, 0, windowWidth, windowHeight));
295 
296  /* Clear the screen on the EGL surface. */
297  GL_CHECK(glClearColor(0.0f, 0.0f, 1.0f, 1.0));
298  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
299 
300  /* Construct different rotation for main cube. */
301  rotationX = Matrix::createRotationX(angleX);
302  rotationY = Matrix::createRotationY(angleY);
303  rotationZ = Matrix::createRotationZ(angleZ);
304 
305  /* Rotate about origin, then translate away from camera. */
309 
310  /* Load EGL window-specific projection and modelview matrices. */
311  GL_CHECK(glUniformMatrix4fv(iLocModelview, 1, GL_FALSE, modelView.getAsArray()));
312  GL_CHECK(glUniformMatrix4fv(iLocProjection, 1, GL_FALSE, projection.getAsArray()));
313 
314  /* For the main cube, we use texturing so set the texture mix factor to 1. */
315  if(iLocTextureMix != -1)
316  {
317  GL_CHECK(glUniform1f(iLocTextureMix, 1.0));
318  }
319 
320  /* Ensure the correct texture is bound to texture unit 0. */
321  GL_CHECK(glActiveTexture(GL_TEXTURE0));
322  GL_CHECK(glBindTexture(GL_TEXTURE_2D, iFBOTex));
323 
324  /* And draw the cube. */
325  GL_CHECK(glDrawElements(GL_TRIANGLE_STRIP, sizeof(cubeIndices) / sizeof(GLubyte), GL_UNSIGNED_BYTE, cubeIndices));
326 
327  /* Draw any text. */
328  text->draw();
329 
330  /* Update cube's rotation angles for animating. */
331  angleX += 3;
332  angleY += 2;
333  angleZ += 1;
334 
335  if(angleX >= 360) angleX -= 360;
336  if(angleY >= 360) angleY -= 360;
337  if(angleZ >= 360) angleZ -= 360;
338 }
339 
340 extern "C"
341 {
343  (JNIEnv *env, jclass jcls, jint width, jint height)
344  {
345  /* Make sure that all resource files are in place. */
348 
349  setupGraphics(width, height);
350  }
351 
353  (JNIEnv *env, jclass jcls)
354  {
355  renderFrame();
356  }
357 
359  (JNIEnv *, jclass)
360  {
361  delete text;
362  }
363 }
string resourceDirectory
GLuint iFBO
Matrix rotationY
int windowHeight
Matrix rotationZ
GLint iLocTextureMix
GLfloat cubeColors[numberOfValuesInCubeColorsArray]
Definition: Native.cpp:67
Functions for drawing text in OpenGL ES.
Definition: Text.h:44
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
Matrix projectionFBO
Functions for manipulating matrices.
Definition: Matrix.h:31
void renderFrame(void)
static float angleY
static Matrix createTranslation(float x, float y, float z)
Create and return a translation matrix.
Definition: Matrix.cpp:414
string fragmentShaderFilename
static float angleZ
#define FBO_WIDTH
#define LOGD(...)
Definition: AstcTextures.h:28
Matrix modelView
Matrix projection
static Matrix matrixPerspective(float FOV, float ratio, float zNear, float zFar)
Create and return a perspective projection matrix.
Definition: Matrix.cpp:425
Matrix translation
GLint iLocTexCoord
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:78
static const float cubeVertices[]
Definition: EGLPreserve.h:42
GLuint programID
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_framebufferobject_FrameBufferObject_uninit(JNIEnv *, jclass)
static const GLubyte cubeIndices[]
Definition: EGLPreserve.h:29
GLint iLocTexture
string vertexShaderFilename
GLuint iFBOTex
static float angleX
GLfloat GLfloat f
Definition: gl2ext.h:2707
bool setupGraphics(int width, int height)
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
Text * text
#define GL_CHECK(x)
Definition: AstcTextures.h:59
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
static bool getAndroidAsset(JNIEnv *JNIEnvironment, const char destinationDirectory[], const char filename[])
Extract an asset file from the APK.
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_framebufferobject_FrameBufferObject_step(JNIEnv *env, jclass jcls)
GLuint fragmentShaderID
GLint iLocModelview
GLint iLocFillColor
#define LOGE(...)
Definition: AstcTextures.h:30
#define FBO_HEIGHT
Matrix rotationX
GLint GLsizei width
Definition: gl2ext.h:179
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
int windowWidth
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
GLint iLocProjection
static const float cubeTextureCoordinates[]
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
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_framebufferobject_FrameBufferObject_init(JNIEnv *env, jclass jcls, jint width, jint height)
GLuint vertexShaderID
GLint iLocPosition