OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Native.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2014-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 
32 #include <jni.h>
33 #include <android/log.h>
34 
35 #include <GLES3/gl3.h>
36 #include "Common.h"
37 #include "CubeModel.h"
38 #include "Mathematics.h"
39 #include "Matrix.h"
40 #include "PlaneModel.h"
41 #include "ShadowMapping.h"
42 #include "Shader.h"
43 #include "Texture.h"
44 #include "Timer.h"
45 #include <cstring>
46 
47 using namespace MaliSDK;
48 
49 /* Structure holding all data needed to initialize mesh-related buffer objects. */
51 {
52  float* coordinates; /* Array holding the geometry's coordinates. */
53  float* normals; /* Array holding the geometry's normal vectors. */
54  float* position; /* Array holding position of the geometry in 3D space. */
55  int numberOfElementsInCoordinatesArray; /* Number of elements written to coordinates array. */
56  int numberOfElementsInNormalsArray; /* Number of elements written to an array holding geometry's normal vectors. */
57  int numberOfElementsInPositionArray; /* Number of elements written to position array. */
58  int numberOfPoints; /* Number of point that are making the geometry. */
59  float scalingFactor; /* Factor used for scaling geometry. */
61 
62 /* Structure holding window's data. */
64 {
65  int height; /* Height of window. */
66  int width; /* Width of window. */
67 } window;
68 
69 /* Structure holding properties of a light source. */
71 {
74 } light;
75 
76 /* Structure holding the data describing shadow-map texture. */
78 {
79  GLuint framebufferObjectName; /* Name of a framebuffer object used for rendering depth texture. */
80  GLsizei height; /* Height of the shadow map texture. */
81  GLuint textureName; /* Name of a shadow map texture (holds depth values for cubes-plane model from the light's point of view). */
82  GLsizei width; /* Width of the shadow map texture. */
83 } shadowMap;
84 
85 /* Structure holding the data used for configuring the program object that is responsible for drawing cubes and plane and calculating the shadow map. */
87 {
88  GLuint programId; /* Program name. Program does the following tasks:
89  * - moving vertices of a geometry into eye-space,
90  * - shading the rasterized primitive considering directional and spot lights and the shadow map for the spot light.
91  */
92  GLuint colorOfGeometryLocation; /* Shader uniform location that is used to hold color of a geometry. Use different color for cubes and plane. */
93  GLuint isCameraPointOfViewLocation; /* Shader uniform location that is used to hold a boolean value indicating whether the point of view of
94  * the camera (if true) or the light (if false) should be used for rendering the scene.
95  * The camera's point of view is used for the final pass, the light's point of view is used for calculating the shadow map.
96  */
97  GLint lightDirectionLocation; /* Shader uniform location that is used to hold direction of light (from cubes-plane model). */
98  GLint lightPositionLocation; /* Shader uniform location that is used to hold position of light source (from cubes-plane model). */
99  GLuint lightViewMatrixLocation; /* Shader uniform location that refers to view matrix used for rendering the scene from light point of view. */
100  GLuint normalsAttributeLocation; /* Shader attribute location that is used to hold normal vectors of the cubes or the plane. */
101  GLuint positionAttributeLocation; /* Shader attribute location that is used to hold coordinates of the cubes or the plane to be drawn. */
102  GLint shadowMapLocation; /* Shader uniform location that is used to hold the shadow map texture unit id. */
103  GLuint shouldRenderPlaneLocation; /* Shader uniform location that is used to hold boolean value indicating whether the plane (if true) or the cubes
104  * (if false) are being drawn (different data is used for cubes and plane).
105  */
107 
108 /* Structure holding data used for configuring the program object that is responsible for drawing representation of a spot light (yellow cube). */
110 {
112  * Program name. Program does the following tasks:
113  * - moving vertices of geometry into eye-space,
114  * - setting color of the cube.
115  */
116  GLint positionLocation; /* Shader uniform location that is used to hold position of the light cube. */
118 
119 /* Instance of a timer. Used for setting position and direction of light source. */
121 
122 /* Buffer object names. */
123 GLuint cubeCoordinatesBufferObjectId = 0; /* Name of buffer object which holds coordinates of the triangles making up the scene cubes. */
124 GLuint cubeNormalsBufferObjectId = 0; /* Name of buffer object which holds the scene cubes normal vectors. */
125 GLuint lightRepresentationCoordinatesBufferObjectId = 0; /* Name of buffer object which holds coordinates of the light cube. */
126 GLuint planeCoordinatesBufferObjectId = 0; /* Name of buffer object which holds coordinates of the plane. */
127 GLuint planeNormalsBufferObjectId = 0; /* Name of buffer object which holds plane's normal vectors. */
128 GLuint uniformBlockDataBufferObjectId = 0; /* Name of buffer object which holds positions of the scene cubes. */
129 
130 /* Vertex array objects. */
131 GLuint cubesVertexArrayObjectId = 0; /* Name of vertex array object used when rendering the scene cubes. */
132 GLuint lightRepresentationCoordinatesVertexArrayObjectId = 0; /* Name of vertex array object used when rendering the light cube. */
133 GLuint planeVertexArrayObjectId = 0; /* Name of vertex array object used when rendering the scene cubes. */
134 
135 /* View and Projection configuration. */
136 /* We use different projection matrices for both passes. */
139 
140 const Vec3f cameraPosition = {0.0f, 0.0f, 30.0f}; /* Array holding position of camera. */
141 Vec3f lookAtPoint = {0.0f, 0.0f, 0.0f}; /* Coordinates of a point the camera should look at (from light point of view). */
142 Matrix viewMatrixForShadowMapPass; /* Matrix used for translating geometry relative to light position. This is used for shadow map rendering pass. */
143 
144 /* Arrays holding RGBA values of the scene cubes and the plane. */
145 const float cubesColor[] = {0.8f, 0.1f, 0.2f, 0.6f};
146 const float planeColor[] = {0.2f, 0.4f, 0.8f, 0.6f};
147 
152 {
153  /* Each scene cube is placed on the same altitude described by this value. */
154  const float cubesYPosition = -3.0f;
155 
156  /* Set up cube properties. */
157  cube.coordinates = NULL;
159  cube.normals = NULL;
161  cube.numberOfElementsInPositionArray = 2 * 4; /* There are 2 cubes and 4 coordinates describing position (x, y, z, w). */
162  cube.scalingFactor = 2.0f;
163 
164  /* Allocate memory for array holding position of cubes. */
165  cube.position = (float*) malloc (cube.numberOfElementsInPositionArray * sizeof(float));
166 
167  ASSERT(cube.position != NULL, "Could not allocate memory for cube position array.");
168 
169  /* Array holding position of cubes. Y coordinate value is the same for both cubes - they are lying on the same surface. */
170  /* First cube. */
171  cube.position[0] = -3.0f; /* x */
172  cube.position[1] = cubesYPosition; /* y */
173  cube.position[2] = 5.0f; /* z */
174  cube.position[3] = 1.0f; /* w */
175  /* Second cube. */
176  cube.position[4] = 5.0f; /* x */
177  cube.position[5] = cubesYPosition; /* y */
178  cube.position[6] = 3.0f; /* z */
179  cube.position[7] = 1.0f; /* w */
180 
181  /* Set up plane properties. */
182  plane.coordinates = NULL;
183  plane.normals = NULL;
186  plane.numberOfElementsInPositionArray = 3; /* There are 3 coordinates describing position (x, y, z). */
187  plane.scalingFactor = 15.0; /* plane.scalingFactor * 2 indicates size of square's side. */
188  plane.position = (float*) malloc (plane.numberOfElementsInPositionArray * sizeof(float));
189 
190  ASSERT(plane.position != NULL, "Could not allocate memory for plane position array.");
191 
192  /* Array holding position of plane. Y coordinate value is calculated so that cubes are sitting on the plane. */
193  plane.position[0] = 0.0f;
194  plane.position[1] = cubesYPosition - cube.scalingFactor;
195  plane.position[2] = 0.0f;
196 
197  /* Set up light representation properties. */
200  lightRepresentation.scalingFactor = 0.3f; /* lightRepresentation.scalingFactor * 2 indicates size of cube's side. */
201 
202  /* Set up shadow map properties. */
204  /* [Declare shadow map texture resolution] */
206  shadowMap.width = window.width * 2;
207  /* [Declare shadow map texture resolution] */
209 
210  /* We use different projection matrices for both passes. */
212  float(window.width) / float(window.height),
213  1.0f,
214  50.0f);
215  /* [Calculate projection matrix from spot light point of view] */
217  1.0f,
218  1.0f,
219  50.0f);
220  /* [Calculate projection matrix from spot light point of view] */
221 }
222 
227 {
228  GLuint bufferObjectIds[6] = {0};
229  GLuint vertexArrayObjectsNames[3] = {0};
230 
231  /* [Generate objects for rendering the geometry] */
232  /* Generate buffer objects. */
233  GL_CHECK(glGenBuffers(6, bufferObjectIds));
234 
235  /* Store buffer object names in global variables.
236  * The variables have more friendly names, so that using them is easier. */
237  cubeCoordinatesBufferObjectId = bufferObjectIds[0];
239  cubeNormalsBufferObjectId = bufferObjectIds[2];
240  planeCoordinatesBufferObjectId = bufferObjectIds[3];
241  planeNormalsBufferObjectId = bufferObjectIds[4];
242  uniformBlockDataBufferObjectId = bufferObjectIds[5];
243 
244  /* Generate vertex array objects. */
245  GL_CHECK(glGenVertexArrays(3, vertexArrayObjectsNames));
246 
247  /* Store vertex array object names in global variables.
248  * The variables have more friendly names, so that using them is easier. */
249  cubesVertexArrayObjectId = vertexArrayObjectsNames[0];
250  lightRepresentationCoordinatesVertexArrayObjectId = vertexArrayObjectsNames[1];
251  planeVertexArrayObjectId = vertexArrayObjectsNames[2];
252  /* [Generate objects for rendering the geometry] */
253 
254  /* Generate and configure shadow map texture to hold depth values. */
255  /* [Generate depth texture object] */
256  GL_CHECK(glGenTextures (1,
258  GL_CHECK(glBindTexture (GL_TEXTURE_2D,
260  /* [Generate depth texture object] */
261  /* [Prepare depth texture storage] */
262  GL_CHECK(glTexStorage2D(GL_TEXTURE_2D,
263  1,
264  GL_DEPTH_COMPONENT24,
266  shadowMap.height));
267  /* [Prepare depth texture storage] */
268  /* [Set depth texture object parameters] */
269  GL_CHECK(glTexParameteri(GL_TEXTURE_2D,
270  GL_TEXTURE_MIN_FILTER,
271  GL_NEAREST));
272  GL_CHECK(glTexParameteri(GL_TEXTURE_2D,
273  GL_TEXTURE_MAG_FILTER,
274  GL_NEAREST));
275  GL_CHECK(glTexParameteri(GL_TEXTURE_2D,
276  GL_TEXTURE_WRAP_S,
277  GL_CLAMP_TO_EDGE));
278  GL_CHECK(glTexParameteri(GL_TEXTURE_2D,
279  GL_TEXTURE_WRAP_T,
280  GL_CLAMP_TO_EDGE));
281  GL_CHECK(glTexParameteri(GL_TEXTURE_2D,
282  GL_TEXTURE_COMPARE_FUNC,
283  GL_LEQUAL));
284  GL_CHECK(glTexParameteri(GL_TEXTURE_2D,
285  GL_TEXTURE_COMPARE_MODE,
286  GL_COMPARE_REF_TO_TEXTURE));
287  /* [Set depth texture object parameters] */
288 
289  /* Attach texture to depth attachment point of a framebuffer object. */
290  /* [Generate and bind framebuffer object] */
291  GL_CHECK(glGenFramebuffers (1,
293  GL_CHECK(glBindFramebuffer (GL_FRAMEBUFFER,
295  /* [Generate and bind framebuffer object] */
296  /* [Bind depth texture to framebuffer] */
297  GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER,
298  GL_DEPTH_ATTACHMENT,
299  GL_TEXTURE_2D,
301  0));
302  /* [Bind depth texture to framebuffer] */
303 }
304 
309 {
310  /* Delete buffers. */
311  GL_CHECK(glDeleteBuffers(1, &cubeCoordinatesBufferObjectId));
312  GL_CHECK(glDeleteBuffers(1, &cubeNormalsBufferObjectId));
314  GL_CHECK(glDeleteBuffers(1, &planeCoordinatesBufferObjectId));
315  GL_CHECK(glDeleteBuffers(1, &planeNormalsBufferObjectId));
316  GL_CHECK(glDeleteBuffers(1, &uniformBlockDataBufferObjectId));
317 
318  /* Delete framebuffer object. */
319  GL_CHECK(glDeleteFramebuffers(1, &shadowMap.framebufferObjectName));
320 
321  /* Delete texture. */
322  GL_CHECK(glDeleteTextures(1, &shadowMap.textureName));
323 
324  /* Delete vertex arrays. */
325  GL_CHECK(glDeleteVertexArrays(1, &cubesVertexArrayObjectId));
327  GL_CHECK(glDeleteVertexArrays(1, &planeVertexArrayObjectId));
328 }
329 
334 {
335  /* If triangular representation of a cube was created successfully, make sure memory is deallocated. */
336  if (cube.coordinates != NULL)
337  {
338  free (cube.coordinates);
339 
340  cube.coordinates = NULL;
341  }
342 
343  /* If representation of a cube's normal was created successfully, make sure memory is deallocated. */
344  if (cube.normals != NULL)
345  {
346  free (cube.normals);
347 
348  cube.normals = NULL;
349  }
350 
351  /* If triangular representation of a cube simulating a light source was created successfully, make sure memory is deallocated. */
352  if (lightRepresentation.coordinates != NULL)
353  {
355 
357  }
358 
359  /* If triangular representation of a plane was created successfully, make sure memory is deallocated. */
360  if (plane.coordinates != NULL)
361  {
362  free (plane.coordinates);
363 
364  plane.coordinates = NULL;
365  }
366 
367  /* If representation of a plane's normal was created successfully, make sure memory is deallocated. */
368  if (plane.normals != NULL)
369  {
370  free (plane.normals);
371 
372  plane.normals = NULL;
373  }
374 
375  /* If position of plane was created successfully, make sure memory is deallocated. */
376  if (plane.position != NULL)
377  {
378  free (plane.position);
379 
380  plane.position = NULL;
381  }
382 
383  /* If position of cube was created successfully, make sure memory is deallocated. */
384  if (cube.position != NULL)
385  {
386  free (cube.position);
387 
388  cube.position = NULL;
389  }
390 }
391 
398 {
399  Vec3f upVector = {0.0f, 1.0f, 0.0f};
400 
401  /*
402  * Position of light is very close to the scene. From this point of view, we are not able to see the whole model.
403  * We have to see whole model to calculate depth values in a final pass. To do that, we have to move camera away from the model.
404  */
405  Vec3f cameraTranslation = {0.0f, 0.0f, -20.0f};
406 
407  /* Get lookAt matrix from the light's point of view, directed at the center of a plane. Store result in viewMatrixForShadowMapPass. */
409  lookAtPoint,
410  upVector);
412  cameraTranslation.y,
413  cameraTranslation.z) *
415 }
416 
417 /* [Generate geometry data] */
424 {
425  /* Get triangular representation of the scene cube. Store the data in the cubeCoordinates array. */
428  &cube.numberOfPoints,
429  cube.scalingFactor);
430  /* Calculate normal vectors for the scene cube created above. */
433  /* Get triangular representation of a square to draw plane in XZ space. Store the data in the planeCoordinates array. */
436  &plane.numberOfPoints,
437  plane.scalingFactor);
438  /* Calculate normal vectors for the plane. Store the data in the planeNormals array. */
441  /* Get triangular representation of the light cube. Store the data in the lightRepresentationCoordinates array. */
444  &lightRepresentation.numberOfPoints,
445  lightRepresentation.scalingFactor);
446 
447  ASSERT(cube.coordinates != NULL, "Could not retrieve cube coordinates.");
448  ASSERT(cube.normals != NULL, "Could not retrieve cube normals.");
449  ASSERT(lightRepresentation.coordinates != NULL, "Could not retrieve cube coordinates.");
450  ASSERT(plane.coordinates != NULL, "Could not retrieve plane coordinates.");
451  ASSERT(plane.normals != NULL, "Could not retrieve plane normals.");
452 }
453 /* [Generate geometry data] */
454 
460 {
461  /* Create all needed GL objects. */
462  createObjects();
463 
464  /* Create all data needed to draw scene. */
466 
467  /* [Fill buffer objects with data] */
468  /* Buffer holding coordinates of triangles which make up the scene cubes. */
469  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
471  GL_CHECK(glBufferData(GL_ARRAY_BUFFER,
474  GL_STATIC_DRAW));
475 
476  /* Buffer holding coordinates of normal vectors for each vertex of the scene cubes. */
477  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
479  GL_CHECK(glBufferData(GL_ARRAY_BUFFER,
480  cube.numberOfElementsInNormalsArray * sizeof(float),
481  cube.normals,
482  GL_STATIC_DRAW));
483 
484  /* Buffer holding coordinates of triangles which make up the plane. */
485  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
487  GL_CHECK(glBufferData(GL_ARRAY_BUFFER,
490  GL_STATIC_DRAW));
491 
492  /* Buffer holding coordinates of the plane's normal vectors. */
493  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
495  GL_CHECK(glBufferData(GL_ARRAY_BUFFER,
496  plane.numberOfElementsInNormalsArray * sizeof(float),
497  plane.normals,
498  GL_STATIC_DRAW));
499 
500  /* Buffer holding coordinates of the light cube. */
501  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
503  GL_CHECK(glBufferData(GL_ARRAY_BUFFER,
506  GL_STATIC_DRAW));
507  /* [Fill buffer objects with data] */
508 
509  /* Buffer holding the positions coordinates of the scene cubes.
510  * Data is then used by a uniform buffer object to set the position of each cube drawn using glDrawArraysInstanced(). */
511  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
513  GL_CHECK(glBufferData(GL_ARRAY_BUFFER,
514  cube.numberOfElementsInPositionArray * sizeof(float),
515  cube.position,
516  GL_STATIC_DRAW));
517 }
518 
525 void setUpAndUseProgramObject(GLint programId, const char* fragmentShaderFileName, const char* vertexShaderFileName)
526 {
527  /* Initialize vertex and shader. */
530 
531  Shader::processShader(&vertexShaderId, vertexShaderFileName, GL_VERTEX_SHADER);
532  Shader::processShader(&fragmentShaderId, fragmentShaderFileName, GL_FRAGMENT_SHADER);
533 
534  /* Attach the vertex and fragment shaders to the rendering program. */
535  GL_CHECK(glAttachShader(programId, vertexShaderId));
536  GL_CHECK(glAttachShader(programId, fragmentShaderId));
537 
538  /* Link and use the rendering program object. */
539  GL_CHECK(glLinkProgram(programId));
540  GL_CHECK(glUseProgram (programId));
541 }
542 
547 {
548  /* Create program object. */
549  cubesAndPlaneProgram.programId = GL_CHECK(glCreateProgram());
550 
551  /* Call function to prepare program object to be used. */
555 
556  /* Get uniform and attribute locations from current program.
557  * Values for those uniforms and attributes will be set later. */
558  /* [Get attribute locations] */
559  cubesAndPlaneProgram.positionAttributeLocation = GL_CHECK(glGetAttribLocation (cubesAndPlaneProgram.programId, "attributePosition")); /* Attribute that is fed with the vertices of triangles that make up geometry (cube or plane). */
560  cubesAndPlaneProgram.normalsAttributeLocation = GL_CHECK(glGetAttribLocation (cubesAndPlaneProgram.programId, "attributeNormals")); /* Attribute that is fed with the normal vectors for geometry (cube or plane). */
561  /* [Get attribute locations] */
562  cubesAndPlaneProgram.isCameraPointOfViewLocation = GL_CHECK(glGetUniformLocation (cubesAndPlaneProgram.programId, "isCameraPointOfView")); /* Uniform holding boolean value that is used for setting camera or light point of view.
563  * If true: the camera's point of view is used for drawing scene with light and shadows.
564  * If false: the light's point of view-used for drawing scene to calculate depth values (create shadow map).
565  * Vertex shader is used for both calculating depth values to create shadow map and for drawing the scene.
566  */
567  /* [Get uniform location: shouldRenderPlane] */
568  cubesAndPlaneProgram.shouldRenderPlaneLocation = GL_CHECK(glGetUniformLocation (cubesAndPlaneProgram.programId, "shouldRenderPlane")); /* Uniform holding a boolean value indicating which geometry is being drawn: cube or plane. */
569  /* [Get uniform location: shouldRenderPlane] */
570  cubesAndPlaneProgram.lightViewMatrixLocation = GL_CHECK(glGetUniformLocation (cubesAndPlaneProgram.programId, "lightViewMatrix")); /* Uniform holding the calculated view matrix used to render the scene from the light's point of view. */
571  cubesAndPlaneProgram.colorOfGeometryLocation = GL_CHECK(glGetUniformLocation (cubesAndPlaneProgram.programId, "colorOfGeometry")); /* Uniform holding the color of a geometry. */
572  cubesAndPlaneProgram.lightDirectionLocation = GL_CHECK(glGetUniformLocation(cubesAndPlaneProgram.programId, "lightDirection"));
573  cubesAndPlaneProgram.lightPositionLocation = GL_CHECK(glGetUniformLocation(cubesAndPlaneProgram.programId, "lightPosition"));
574  /* [Get depth texture uniform location] */
575  cubesAndPlaneProgram.shadowMapLocation = GL_CHECK(glGetUniformLocation(cubesAndPlaneProgram.programId, "shadowMap"));
576  /* [Get depth texture uniform location] */
577 
578  /* Get uniform locations and uniform block index (index of "cubesDataUniformBlock" uniform block) for the current program.
579  * Values for those uniforms will be set now (only once, because they are constant).
580  */
581  GLuint uniformBlockIndex = GL_CHECK(glGetUniformBlockIndex(cubesAndPlaneProgram.programId, "cubesDataUniformBlock")); /* Uniform block that holds the position the scene cubes. */
582  GLuint planePositionLocation = GL_CHECK(glGetUniformLocation (cubesAndPlaneProgram.programId, "planePosition")); /* Uniform holding the position of plane. */
583  GLuint cameraPositionLocation = GL_CHECK(glGetUniformLocation (cubesAndPlaneProgram.programId, "cameraPosition")); /* Uniform holding the position of camera (which is used to render the scene from the camera's point of view). */
584  GLuint cameraProjectionMatrixLocation = GL_CHECK(glGetUniformLocation (cubesAndPlaneProgram.programId, "cameraProjectionMatrix")); /* Uniform holding the projection matrix (which is used to render the scene from the camera's point of view). */
585  GLuint lightProjectionMatrixLocation = GL_CHECK(glGetUniformLocation (cubesAndPlaneProgram.programId, "lightProjectionMatrix")); /* Uniform holding the projection matrix (which is used to render the scene from the light's point of view). */
586 
587  /* Check if uniform and attribute locations were found in the shaders. */
588  ASSERT(cubesAndPlaneProgram.positionAttributeLocation != -1, "Could not retrieve attribute location: positionAttributeLocation.");
589  ASSERT(cubesAndPlaneProgram.normalsAttributeLocation != -1, "Could not retrieve attribute location: normalsAttributeLocation.");
590  ASSERT(cubesAndPlaneProgram.isCameraPointOfViewLocation != -1, "Could not retrieve uniform location: isCameraPointOfViewLocation.");
591  ASSERT(cubesAndPlaneProgram.shouldRenderPlaneLocation != -1, "Could not retrieve uniform location: shouldRenderPlaneLocation.")
592  ASSERT(cubesAndPlaneProgram.lightViewMatrixLocation != -1, "Could not retrieve uniform location: lightViewMatrixLocation.");
593  ASSERT(cubesAndPlaneProgram.colorOfGeometryLocation != -1, "Could not retrieve uniform location: colorOfGeometryLocation.");
594  ASSERT(cubesAndPlaneProgram.lightDirectionLocation != -1, "Could not retrieve uniform location: lightDirectionLocation");
595  ASSERT(cubesAndPlaneProgram.lightPositionLocation != -1, "Could not retrieve uniform location: lightPositionLocation");
596  ASSERT(cubesAndPlaneProgram.shadowMapLocation != -1, "Could not retrieve uniform location: shadowMapLocation");
597  ASSERT(uniformBlockIndex != GL_INVALID_INDEX, "Could not retrieve uniform block index: uniformBlockIndex");
598  ASSERT(planePositionLocation != -1, "Could not retrieve uniform location: planePositionLocation");
599  ASSERT(cameraPositionLocation != -1, "Could not retrieve uniform location: cameraPositionLocation");
600  ASSERT(cameraProjectionMatrixLocation != -1, "Could not retrieve uniform location: cameraProjectionMatrixLocation");
601  ASSERT(lightProjectionMatrixLocation != -1, "Could not retrieve uniform location: lightProjectionMatrixLocation");
602 
603  /*
604  * Set the binding point for the uniform block. The uniform block holds the position of the scene cubes.
605  * The binding point is then used by glBindBufferBase() to bind buffer object (for GL_UNIFORM_BUFFER).
606  */
607  GL_CHECK(glUniformBlockBinding(cubesAndPlaneProgram.programId,
608  uniformBlockIndex,
609  0));
610  GL_CHECK(glUniform3fv (planePositionLocation,
611  1,
612  plane.position));
613  GL_CHECK(glUniform3fv (cameraPositionLocation,
614  1,
615  (float*)&cameraPosition));
616  GL_CHECK(glUniformMatrix4fv (cameraProjectionMatrixLocation,
617  1,
618  GL_FALSE,
620  GL_CHECK(glUniformMatrix4fv (lightProjectionMatrixLocation,
621  1,
622  GL_FALSE,
624 }
625 
630 {
631  /* Create program object. */
632  lightRepresentationProgram.programId = GL_CHECK(glCreateProgram());
633 
634  /* Call function to prepare the program object to be used. */
638 
639  /* Get the uniform locations for the current program.
640  * Values for those uniforms will be set later. */
641  lightRepresentationProgram.positionLocation = GL_CHECK(glGetUniformLocation(lightRepresentationProgram.programId, "cubePosition")); /* Uniform holding position of a cube (used to calculate translation matrix). */
642 
643  /* Get uniform and attribute locations for current program.
644  * Values for those uniforms and attribute will be set now (only once, because their are constant). */
645  GLuint positionLocation = GL_CHECK(glGetAttribLocation (lightRepresentationProgram.programId, "attributePosition")); /* Attribute holding coordinates of the triangles that make up the light cube. */
646  GLuint projectionMatrixLocation = GL_CHECK(glGetUniformLocation(lightRepresentationProgram.programId, "projectionMatrix")); /* Uniform holding projection matrix (cube is drawn only from camera point of view,
647  * not present in shadow map calculation). Camera is static, so the value for this
648  * uniform can be set just once. */
649  GLuint cameraPositionLocation = GL_CHECK(glGetUniformLocation(lightRepresentationProgram.programId, "cameraPosition")); /* Uniform holding the position of camera. */
650 
651  /* Check if the uniform and attribute locations were found in the shaders. Set their values. */
652  ASSERT(positionLocation != -1, "Could not retrieve attribute location: positionLocation");
653  ASSERT(projectionMatrixLocation != -1, "Could not retrieve uniform location: projectionMatrixLocation");
654  ASSERT(cameraPositionLocation != -1, "Could not retrieve uniform location: cameraPositionLocation");
655  ASSERT(lightRepresentationProgram.positionLocation != -1, "Could not retrieve uniform location: lightRepresentationPositionLocation");
656 
657  GL_CHECK(glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, cameraProjectionMatrix.getAsArray()));
658  GL_CHECK(glUniform3fv (cameraPositionLocation, 1, (float*)&cameraPosition));
659 
661  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER,
663  GL_CHECK(glEnableVertexAttribArray(positionLocation));
664  GL_CHECK(glVertexAttribPointer (positionLocation,
665  3,
666  GL_FLOAT,
667  GL_FALSE,
668  0,
669  0));
670 }
671 
677 void draw(bool hasShadowMapBeenCalculated)
678 {
679  /* Clear the depth and color buffers. */
680  GL_CHECK(glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT));
681 
682  /* Let's focus on drawing the model. */
683  GL_CHECK(glUseProgram(cubesAndPlaneProgram.programId));
684 
685  /* Values are the same for both passes (creating shadow map and drawing the scene) - can be set just once. */
686  if (!hasShadowMapBeenCalculated)
687  {
688  /* Set light and shadow values for uniforms. */
689  /* [Set uniform values for light position and direction] */
692  /* [Set uniform values for light position and direction] */
693  /* [Set texture object for depth texture sampler] */
695  /* [Set texture object for depth texture sampler] */
696  }
697 
698  /* Set uniform value indicating point of view: camera or light. */
699  GL_CHECK(glUniform1i(cubesAndPlaneProgram.isCameraPointOfViewLocation, hasShadowMapBeenCalculated));
700 
701  /* If the light's point of view, set calculated view matrix. (View is static from camera point of view - no need to change that value). */
702  if (!hasShadowMapBeenCalculated)
703  {
705  1,
706  GL_FALSE,
708  }
709 
710  /*Draw cubes. */
711  /*Set uniform value indicating which geometry to draw: cubes or plane. Set to draw cubes. */
712  /*[Set boolean value to false if cubes are being rendered] */
714  false));
715  /*[Set boolean value to false if cubes are being rendered] */
716  /* Set uniform value indicating the color of geometry (set the color for cubes). */
718  cubesColor[0],
719  cubesColor[1],
720  cubesColor[2],
721  cubesColor[3]));
722 
723  /* [Bind VAA for cube] */
724  GL_CHECK(glBindVertexArray(cubesVertexArrayObjectId));
725  /* [Bind VAA for cube] */
726 
727  /* Draw two cubes. */
728  /* [Draw cubes] */
729  GL_CHECK(glDrawArraysInstanced(GL_TRIANGLES, 0, cube.numberOfPoints, 2));
730  /* [Draw cubes] */
731 
732  /* Draw plane. */
733  /* Set uniform value indicating which shape to draw: cubes or plane. Now set to draw plane. */
734  /* [Set boolean value to true if plane is being rendered] */
736  true));
737  /* [Set boolean value to true if plane is being rendered] */
738  /* Set uniform value indicating color of the geometry (set color for plane). */
740  planeColor[0],
741  planeColor[1],
742  planeColor[2],
743  planeColor[3]));
744 
745  /* [Bind VAA for plane] */
746  GL_CHECK(glBindVertexArray(planeVertexArrayObjectId));
747  /* [Bind VAA for plane] */
748 
749  /* Draw plane. */
750  /* [Draw a plane] */
751  GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, plane.numberOfPoints));
752  /* [Draw a plane] */
753 
754  if (hasShadowMapBeenCalculated)
755  {
756  /* Let's focus on drawing the light cube. */
758 
759  /* Set the values for the uniforms (values used for translation and rotation of a cube). */
761 
763 
764  /* Draw cube. */
765  GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, lightRepresentation.numberOfPoints));
766  }
767 }
768 
773 {
774  /* Bind framebuffer object.
775  * There is a texture attached to depth attachment point for this framebuffer object.
776  * By using this framebuffer object, calculated depth values are stored in the texture. */
777  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, shadowMap.framebufferObjectName));
778 
779  /* Set the view port to size of shadow map texture. */
780  /* [Set viewport for light perspective] */
781  GL_CHECK(glViewport(0, 0, shadowMap.width, shadowMap.height));
782  /* [Set viewport for light perspective] */
783 
784  /* Set back face to be culled */
785  GL_CHECK(glEnable(GL_CULL_FACE));
786 
787  /* [Enable depth test] */
788  /* Enable depth test to do comparison of depth values. */
789  GL_CHECK(glEnable(GL_DEPTH_TEST));
790  /* [Enable depth test] */
791 
792  /* [Set colour mask for shadow map rendering] */
793  /* Disable writing of each frame buffer color component. */
794  GL_CHECK(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
795  /* [Set colour mask for shadow map rendering] */
796 
797  /* Update the lookAt matrix that we use for view matrix (to look at scene from the light's point of view). */
799 
800  /* Draw the scene.
801  * Value of parameter indicates that shadow map should now be calculated.
802  * Only the plane and scene cubes should be drawn (without cube representing light source).
803  * Scene should be rendered from the light's point of view.
804  * Enable a polygon offset to ensure eliminate z-fighting in the resulting shadow map. */
805  /* [Enable shadow map drawing properties] */
806  GL_CHECK(glEnable(GL_POLYGON_OFFSET_FILL));
807  /* [Enable shadow map drawing properties] */
808  /* [Draw the scene from spot light point of view] */
809  draw(false);
810  /* [Draw the scene from spot light point of view] */
811  GL_CHECK(glDisable(GL_POLYGON_OFFSET_FILL));
812 }
813 
817 void drawScene()
818 {
819  /* Use the default framebuffer object. */
820  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
821 
822  /* Set the view port to the size of the window. */
823  GL_CHECK(glViewport(0, 0, window.width, window.height));
824 
825  /* Disable culling. */
826  GL_CHECK(glDisable(GL_CULL_FACE));
827 
828  /* Enable writing of each frame buffer color component. */
829  GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
830 
831  /* Draw the scene.
832  * Value of parameter indicates that shadow map has been already calculated and the normal scene should now be drawn.
833  * All elements should be drawn (scene cubes, plane, and the light cube).
834  * Scene should be rendered from the camera's point of view. */
835  draw(true);
836 }
837 
842 {
843  /* Time used to set light direction and position. */
844  const float time = timer.getTime();
845 
846  /* Set position of the light. The light is moving on a circular curve (radius of a circle is now equal to 5).*/
847  const float radius = 5.0f;
848 
849  /* [Update spot light position and direction] */
850  light.position.x = radius * sinf(time / 2.0f);
851  light.position.y = 2.0f;
852  light.position.z = radius * cosf(time / 2.0f);
853 
854  /* Direction of light. */
858 
859  /* Normalize the light direction vector. */
861  /* [Update spot light position and direction] */
862 
863  /* Clear the contents of back buffer. */
864  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
865 
866  /* Fill the shadow map texture with the calculated depth values. */
867  createShadowMap();
868 
869  /* Draw the scene consisting of all objects, light and shadow. Use created shadow map to display shadows. */
870  drawScene();
871 }
872 
873 void setupGraphics(int width, int height)
874 {
875  /* Set up window properties. */
876  /* [Declare window resolution] */
877  window.height = height;
878  window.width = width;
879  /* [Declare window resolution] */
880 
882  initializeData();
883 
884  /* Set up the program for rendering the scene. */
887 
888  /* [Set shadow map drawing properties] */
889  /* Set the Polygon offset, used when rendering the into the shadow map to eliminate z-fighting in the shadows. */
890  GL_CHECK(glPolygonOffset(1.0, 0.0));
891  GL_CHECK(glCullFace(GL_BACK));
892  /* [Set shadow map drawing properties] */
893 
894  /* [Bind depth texture to specific binding point] */
895  /* Set active texture. Shadow map texture will be passed to shader. */
896  GL_CHECK(glActiveTexture(GL_TEXTURE0));
897  GL_CHECK(glBindTexture (GL_TEXTURE_2D, shadowMap.textureName));
898  /* [Bind depth texture to specific binding point] */
899 
900  /* [Set up Vertex Attrib Arrays] */
901  GL_CHECK(glBindVertexArray(cubesVertexArrayObjectId));
902  /* Set values for cubes' normal vectors. */
903  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER, cubeNormalsBufferObjectId));
904  GL_CHECK(glEnableVertexAttribArray(cubesAndPlaneProgram.normalsAttributeLocation));
905  GL_CHECK(glVertexAttribPointer (cubesAndPlaneProgram.normalsAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, 0));
906  /* Set values for the cubes' coordinates. */
907  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER, cubeCoordinatesBufferObjectId));
908  GL_CHECK(glEnableVertexAttribArray(cubesAndPlaneProgram.positionAttributeLocation));
909  GL_CHECK(glVertexAttribPointer (cubesAndPlaneProgram.positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, 0));
910 
911  GL_CHECK(glBindVertexArray(planeVertexArrayObjectId));
912  /* Set values for plane's normal vectors. */
913  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER, planeNormalsBufferObjectId));
914  GL_CHECK(glEnableVertexAttribArray(cubesAndPlaneProgram.normalsAttributeLocation));
915  GL_CHECK(glVertexAttribPointer (cubesAndPlaneProgram.normalsAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, 0));
916  /* Set values for plane's coordinates. */
917  GL_CHECK(glBindBuffer (GL_ARRAY_BUFFER, planeCoordinatesBufferObjectId));
918  GL_CHECK(glEnableVertexAttribArray(cubesAndPlaneProgram.positionAttributeLocation));
919  GL_CHECK(glVertexAttribPointer (cubesAndPlaneProgram.positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, 0));
920  /* [Set up Vertex Attrib Arrays] */
921 
922  /* Bind buffer with uniform data. Used to set the locations of the cubes. */
923  GL_CHECK(glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBlockDataBufferObjectId));
924 
925  /* Start counting time. */
926  timer.reset();
927 }
928 
929 void uninit()
930 {
931  /* Delete all created GL objects. */
932  deleteObjects();
933  /* Deallocate memory. */
935 }
936 extern "C"
937 {
938  JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_shadowMapping_NativeLibrary_init (JNIEnv * env, jobject obj, jint width, jint height);
939  JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_shadowMapping_NativeLibrary_step (JNIEnv * env, jobject obj);
940  JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_shadowMapping_NativeLibrary_uninit(JNIEnv * env, jobject obj);
941 };
942 
944  JNIEnv * env, jobject obj, jint width, jint height)
945 {
946  setupGraphics(width, height);
947 }
948 
950  JNIEnv * env, jobject obj)
951 {
952  uninit();
953 }
954 
955 
957  JNIEnv * env, jobject obj)
958 {
959  renderFrame();
960 }
void setupGraphics(int width, int height)
Definition: Native.cpp:1256
struct LightProperties light
struct LightRepresentationProgramProperties lightRepresentationProgram
GLuint lightRepresentationCoordinatesVertexArrayObjectId
Definition: Native.cpp:132
static void getTriangleRepresentation(int *numberOfCoordinates, float **coordinates)
Get coordinates of points which make up a plane. The plane is located in XZ space.
Definition: PlaneModel.cpp:117
void deleteObjects()
Deletes all created GL objects.
Definition: Native.cpp:308
#define SPOT_LIGHT_CUBE_VERTEX_SHADER_FILE_NAME
Definition: ShadowMapping.h:33
GLuint planeVertexArrayObjectId
Definition: Native.cpp:159
const Vec3f upVector
Definition: Native.cpp:573
GLint cameraPositionLocation
Definition: Native.cpp:93
#define GL_CHECK(x)
Definition: Native.cpp:64
int numberOfElementsInCoordinatesArray
Definition: Native.cpp:55
struct CubesAndPlaneProgramProperties cubesAndPlaneProgram
float * position
Definition: Native.cpp:54
float getTime()
Returns the time passed since object creation or since reset() was last called.
Definition: Timer.cpp:109
#define SPOT_LIGHT_CUBE_FRAGMENT_SHADER_FILE_NAME
Definition: ShadowMapping.h:31
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_shadowMapping_NativeLibrary_uninit(JNIEnv *env, jobject obj)
Definition: Native.cpp:949
GLuint lightRepresentationCoordinatesBufferObjectId
Definition: Native.cpp:125
Vec3f direction
Definition: Native.cpp:73
GLint positionLocation
Definition: Native.cpp:99
void setupLightRepresentationProgram()
Create a program that will be used to rasterize the geometry of light cube.
Definition: Native.cpp:629
GLuint vertexShaderId
Definition: Native.cpp:57
struct WindowProperties window
GLuint uniformBlockDataBufferObjectId
Definition: Native.cpp:99
GLuint programId
Definition: Native.cpp:137
Functions for manipulating matrices.
Definition: Matrix.h:31
float scalingFactor
Definition: Native.cpp:59
static void getNormals(int *numberOfCoordinates, float **normals)
Create normals for a cube which was created with getTriangleRepresentation() function.
Definition: CubeModel.cpp:356
void draw()
Definition: Native.cpp:267
void setupCubesAndPlaneProgram()
Create a program that will be used to convert vertices into eye-space and then rasterize cubes and pl...
Definition: Native.cpp:546
static Matrix createTranslation(float x, float y, float z)
Create and return a translation matrix.
Definition: Matrix.cpp:414
Provides a platform independent high resolution timer.
Definition: Timer.h:37
static Matrix matrixLookAt(Vec3f eye, Vec3f center, Vec3f up)
Create and return a look at matrix.
Definition: Matrix.cpp:431
void createDataForObjectsToBeDrawn()
Initialize data used for drawing the scene.
Definition: Native.cpp:423
static Matrix matrixPerspective(float FOV, float ratio, float zNear, float zFar)
Create and return a perspective projection matrix.
Definition: Matrix.cpp:425
GLuint planeCoordinatesBufferObjectId
Definition: Native.cpp:126
void createObjects()
Creates GL objects.
Definition: Native.cpp:226
Matrix viewMatrixForShadowMapPass
Definition: Native.cpp:142
void drawScene()
Draw the lit shadow-mapped scene from the camera's point of view.
Definition: Native.cpp:817
float * normals
Definition: Native.cpp:53
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:78
GLuint cubeCoordinatesBufferObjectId
Definition: Native.cpp:97
#define VERTEX_SHADER_FILE_NAME
Definition: Boids.h:29
A 3D floating point vector.
Definition: VectorTypes.h:83
void setUpAndUseProgramObject(GLint programId, const char *fragmentShaderFileName, const char *vertexShaderFileName)
Create, compile and attach vertex and fragment shaders to previously created program object...
Definition: Native.cpp:525
void deallocateMemory()
Definition: Native.cpp:333
const Vec3f lookAtPoint
Definition: Native.cpp:569
void reset()
Resets the timer to 0.0f.
Definition: Timer.cpp:100
GLuint uniformBlockIndex
Definition: Native.cpp:75
int numberOfElementsInNormalsArray
Definition: Native.cpp:56
void uninit()
Delete created objects and free allocated memory.
Definition: Native.cpp:1706
Vec3f cameraPosition
Definition: Native.cpp:563
struct GeometryProperties lightRepresentation
GLfloat GLfloat f
Definition: gl2ext.h:2707
int numberOfElementsInPositionArray
Definition: Native.cpp:57
static void getTriangleRepresentation(float scalingFactor, int *numberOfCoordinates, float **coordinates)
Compute coordinates of points which make up a cube.
Definition: CubeModel.cpp:29
GLuint cubeNormalsBufferObjectId
Definition: Native.cpp:124
void initializeStructureData()
Initialize structure data.
Definition: Native.cpp:151
void renderFrame(void)
Definition: Native.cpp:1536
#define FRAGMENT_SHADER_FILE_NAME
Definition: Boids.h:27
const float planeColor[]
Definition: Native.cpp:155
static void getNormals(int *numberOfCoordinates, float **normals)
Get normals for plane placed in XZ space.
Definition: PlaneModel.cpp:240
void initializeData()
Initializes data used for rendering.
Definition: Native.cpp:196
GLuint planeNormalsBufferObjectId
Definition: Native.cpp:127
Matrix lightProjectionMatrix
Definition: Native.cpp:138
float degreesToRadians(float degrees)
Convert an angle in degrees to radians.
Definition: Mathematics.h:86
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_shadowMapping_NativeLibrary_init(JNIEnv *env, jobject obj, jint width, jint height)
Definition: Native.cpp:943
Timer timer
Definition: Native.cpp:1059
GLuint bufferObjectIds[numberOfBufferObjectIds]
Definition: Native.cpp:113
const float cubesColor[]
Definition: Native.cpp:145
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_shadowMapping_NativeLibrary_step(JNIEnv *env, jobject obj)
Definition: Native.cpp:956
void calculateLookAtMatrix()
Calculates depth values written to shadow map texture.
Definition: Native.cpp:397
struct GeometryProperties cube
#define ASSERT(x, s)
Definition: common.h:45
GLuint fragmentShaderId
Definition: Native.cpp:55
GLint GLsizei width
Definition: gl2ext.h:179
GLuint cubesVertexArrayObjectId
Definition: Native.cpp:131
struct GeometryProperties plane
float * coordinates
Definition: Native.cpp:52
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
Matrix cameraProjectionMatrix
Definition: Native.cpp:564
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count
void createShadowMap()
Draw the scene from the light's point of view to calculate depth values (calculated values are held i...
Definition: Native.cpp:772
void normalize(void)
Normalize 3D floating point vector.
Definition: VectorTypes.h:91
Vec3f position
Definition: Native.cpp:72
uniform float time
Definition: spawn.cs:50
struct ShadowMapTextureProperties shadowMap