OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
scene.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 
21 #include "scene.hpp"
22 #include "mesh.hpp"
23 #include <algorithm>
24 #include <stdlib.h>
25 
26 using namespace std;
27 
28 #define PHYSICS_GROUP_SIZE 128
29 
30 // Spread our spheres out in three dimensions.
31 #define SPHERE_INSTANCES_X 24
32 #define SPHERE_INSTANCES_Y 24
33 #define SPHERE_INSTANCES_Z 24
34 #define SPHERE_INSTANCES (SPHERE_INSTANCES_X * SPHERE_INSTANCES_Y * SPHERE_INSTANCES_Z)
35 
36 #define SPHERE_RADIUS 0.30f
37 
38 // Defines how densely spheres should be tesselated (offline) at each LOD level.
39 #define SPHERE_VERT_PER_CIRC_LOD0 24
40 #define SPHERE_VERT_PER_CIRC_LOD1 20
41 #define SPHERE_VERT_PER_CIRC_LOD2 16
42 #define SPHERE_VERT_PER_CIRC_LOD3 12
43 
44 // We use fixed uniform locations in the shaders (GLES 3.1 feature).
45 #define UNIFORM_MVP_LOCATION 0
46 #define UNIFORM_COLOR_LOCATION 1
47 #define UNIFORM_LIGHT_DIR_LOCATION 2
48 
49 static const unsigned verts_per_circ[] = {
54 };
55 
57 {
58  // Compile shaders.
59  occluder_program = common_compile_shader_from_file("scene.vs", "scene.fs");
60  sphere_program = common_compile_shader_from_file("scene_sphere.vs", "scene_sphere.fs");
61  quad_program = common_compile_shader_from_file("quad.vs", "quad.fs");
62  physics_program = common_compile_compute_shader_from_file("physics.cs");
63 
64  // Instantiate our various culling methods.
65  culling_implementations.push_back(new HiZCulling);
66  culling_implementations.push_back(new HiZCullingNoLOD);
67  culling_implementation_index = CullHiZ;
68  enable_culling = true;
69 
70  // Set up buffers, etc.
71  init_instances();
72 
73  camera_rotation_y = 0.0f;
74  camera_rotation_x = 0.0f;
75 
76  num_render_sphere_instances = SPHERE_INSTANCES;
77  physics_speed = 1.0f;
78 
79  show_redundant = false;
80 }
81 
82 // Move camera around. The view-projection matrix is recomputed elsewhere.
84 {
85  // Angles are mapped from [0, 1] => [0, 2pi] radians.
86  camera_rotation_y -= delta_x * 0.25f;
87  camera_rotation_x += delta_y * 0.15f;
88  camera_rotation_x = clamp(camera_rotation_x, -0.20f, 0.20f);
89  camera_rotation_y -= floor(camera_rotation_y);
90 }
91 
92 // Bake our instanced occluder geometry into a single vertex buffer and index buffer.
93 // Makes the implementation somewhat more generic and simple.
94 void Scene::bake_occluder_geometry(vector<vec4> &occluder_positions, vector<uint32_t> &occluder_indices,
95  const Mesh &box_mesh, const vec4 *instances, unsigned num_instances)
96 {
97  unsigned total_vertices = num_instances * box_mesh.vbo.size();
98  occluder_positions.reserve(total_vertices);
99 
100  unsigned total_indices = num_instances * box_mesh.ibo.size();
101  occluder_indices.reserve(total_indices);
102 
103  // Bake the index buffer.
104  for (unsigned i = 0; i < total_indices; i++)
105  {
106  unsigned instance = i / box_mesh.ibo.size();
107  unsigned index = i % box_mesh.ibo.size();
108 
109  unsigned baked_index = box_mesh.ibo[index] + instance * box_mesh.vbo.size();
110  occluder_indices.push_back(baked_index);
111  }
112 
113  // Bake the vertex buffer.
114  for (unsigned i = 0; i < total_vertices; i++)
115  {
116  unsigned instance = i / box_mesh.vbo.size();
117  unsigned index = i % box_mesh.vbo.size();
118 
119  vec4 pos = instances[instance] + vec4(box_mesh.vbo[index].position, 1.0f);
120  occluder_positions.push_back(pos);
121  }
122 }
123 
125 {
126  bool operator()(const vec4 &a, const vec4 &b)
127  {
128  return vec_dot(a, a) < vec_dot(b, b);
129  }
130 };
131 
132 struct SphereInstance
133 {
134  vec4 position;
135  vec4 velocity;
136 };
137 
139 {
140  // Create occluder boxes.
141  AABB aabb = { vec4(-1.0f, 0.0f, -1.0f, 0.0f), vec4(1.0f, 8.0f, 1.0f, 0.0f) };
142  Mesh box_mesh = create_box_mesh(aabb);
143  box = new GLDrawable(box_mesh);
144 
145  // Create meshes for spheres at various LOD levels.
146  for (unsigned i = 0; i < SPHERE_LODS; i++)
147  {
148  sphere[i] = new GLDrawable(create_sphere_mesh(1.0f, vec3(0, 0, 0), verts_per_circ[i]));
149  }
150 
151  // Spread occluder geometry out on a grid on the XZ plane.
152  // Skip the center, because we put our camera there.
153  vector<vec4> occluder_instances;
154  for (int z = 0; z < 13; z++)
155  {
156  for (int x = 0; x < 13; x++)
157  {
158  if (z >= 5 && z <= 7 && x >= 5 && x <= 7)
159  {
160  continue;
161  }
162  occluder_instances.push_back(vec4(3.0f) * vec4(x - 6, 0, z - 6, 0));
163  }
164  }
165  // Rough front-to-back ordering to get more ideal rendering order.
166  sort(occluder_instances.begin(), occluder_instances.end(), OccluderSorter());
167 
168  num_occluder_instances = occluder_instances.size();
169 
170  // Upload instance buffer.
171  GL_CHECK(glGenBuffers(1, &occluder_instances_buffer));
172  GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, occluder_instances_buffer));
173  GL_CHECK(glBufferData(GL_UNIFORM_BUFFER, occluder_instances.size() * sizeof(vec4), &occluder_instances[0], GL_STATIC_DRAW));
174 
175  // Place out spheres with different positions and velocities.
176  // The W component contains the sphere radius, which is random.
177  std::vector<SphereInstance> sphere_instances;
178  for (int x = 0; x < SPHERE_INSTANCES_X; x++)
179  {
180  for (int y = 0; y < SPHERE_INSTANCES_Y; y++)
181  {
182  for (int z = 0; z < SPHERE_INSTANCES_Z; z++)
183  {
184  SphereInstance instance;
185  instance.position = vec4(1.0f) * vec4(x - 11.35f, y * 0.10f + 0.5f, z - 11.45f, 0);
186  instance.position.c.w = SPHERE_RADIUS * (1.0f - 0.5f * rand() / RAND_MAX);
187  instance.velocity = vec4(vec3(4.0) * vec_normalize(vec3(x - 11.35f, 0.5f * y - 11.55f, z - 11.25f)), 0.0f);
188 
189  sphere_instances.push_back(instance);
190  }
191  }
192  }
193 
194  // Upload sphere instance buffer.
195  GL_CHECK(glGenBuffers(1, &sphere_instances_buffer));
196  GL_CHECK(glBindBuffer(GL_SHADER_STORAGE_BUFFER, sphere_instances_buffer));
197  GL_CHECK(glBufferData(GL_SHADER_STORAGE_BUFFER, sphere_instances.size() * sizeof(SphereInstance), &sphere_instances[0], GL_STATIC_DRAW));
198 
199  // Initialize storage for our post-culled instance buffer.
200  // The buffers must be at least as large as the sphere instance buffer (in case we have 100% visibility).
201  GL_CHECK(glGenBuffers(SPHERE_LODS, indirect.instance_buffer));
202  for (unsigned i = 0; i < SPHERE_LODS; i++)
203  {
204  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, indirect.instance_buffer[i]));
205  GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sphere_instances.size() * sizeof(vec4), NULL, GL_DYNAMIC_COPY));
206  }
207 
208  // Setup occluder geometry for each implementation.
209  vector<vec4> occluder_positions;
210  vector<uint32_t> occluder_indices;
211  bake_occluder_geometry(occluder_positions, occluder_indices, box_mesh, &occluder_instances[0], occluder_instances.size());
212 
213  for (unsigned i = 0; i < culling_implementations.size(); i++)
214  {
215  culling_implementations[i]->setup_occluder_geometry(occluder_positions, occluder_indices);
216  }
217 
218  // Initialize our indirect draw buffers.
219  // Use a ring buffer of them, since we might want to read back old results to monitor our culling performance without stalling the pipeline.
220  GL_CHECK(glGenBuffers(INDIRECT_BUFFERS, indirect.buffer));
221  for (unsigned i = 0; i < SPHERE_LODS; i++)
222  {
223  GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect.buffer[i]));
224  GL_CHECK(glBufferData(GL_DRAW_INDIRECT_BUFFER, SPHERE_LODS * sizeof(IndirectCommand), NULL, GL_DYNAMIC_COPY));
225  }
226  indirect.buffer_index = 0;
227 }
228 
229 #define Z_NEAR 1.0f
230 #define Z_FAR 500.0f
231 void Scene::update_camera(float rotation_y, float rotation_x, unsigned viewport_width, unsigned viewport_height)
232 {
233  // Compute view and projection matrices.
234  float radians_y = 2.0f * PI * rotation_y;
235  float radians_x = 2.0f * PI * rotation_x;
236 
237  mat4 rotation_matrix_y = mat_rotate_y(radians_y);
238  mat4 rotation_matrix_x = mat_rotate_x(radians_x);
239  vec3 camera_dir = vec3(rotation_matrix_y * rotation_matrix_x * vec4(0, 0, -1, 1));
240 
241  vec3 camera_position = vec3(0, 2, 0);
242 
243  view = mat_look_at(camera_position, camera_position + camera_dir, vec3(0, 1, 0));
244  projection = mat_perspective_fov(60.0f, float(viewport_width) / viewport_height, Z_NEAR, Z_FAR);
245  mat4 view_projection = projection * view;
246 
247  GL_CHECK(glProgramUniformMatrix4fv(occluder_program, UNIFORM_MVP_LOCATION, 1, GL_FALSE, value_ptr(view_projection)));
248  GL_CHECK(glProgramUniformMatrix4fv(sphere_program, UNIFORM_MVP_LOCATION, 1, GL_FALSE, value_ptr(view_projection)));
249 }
250 
252 {
253  if (method == CullNone)
254  {
255  enable_culling = false;
256  culling_implementation_index = 0;
257  }
258  else
259  {
260  enable_culling = true;
261  culling_implementation_index = static_cast<unsigned>(method);
262  }
263 }
264 
265 void Scene::apply_physics(float delta_time)
266 {
267  if (physics_speed <= 0.0f)
268  {
269  return;
270  }
271 
272  // Do physics on the spheres, in a compute shader.
273  GL_CHECK(glUseProgram(physics_program));
274  GL_CHECK(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, sphere_instances_buffer));
275  GL_CHECK(glProgramUniform1ui(physics_program, 0, SPHERE_INSTANCES));
276  GL_CHECK(glProgramUniform1f(physics_program, 1, physics_speed * delta_time));
277  GL_CHECK(glDispatchCompute((SPHERE_INSTANCES + PHYSICS_GROUP_SIZE - 1) / PHYSICS_GROUP_SIZE, 1, 1));
278 
279  // We don't need data here until bounding box check, so we can let rasterizer and physics run in parallel, avoiding memory barrier here.
280 }
281 
282 void Scene::update(float delta_time, unsigned width, unsigned height)
283 {
284  // Update scene rendering parameters.
285  update_camera(camera_rotation_y, camera_rotation_x, width, height);
286 
287  // Update light direction, here it's static.
288  vec3 light_dir = vec_normalize(vec3(2, 4, 1));
289  GL_CHECK(glProgramUniform3fv(occluder_program, UNIFORM_LIGHT_DIR_LOCATION, 1, value_ptr(light_dir)));
290  GL_CHECK(glProgramUniform3fv(sphere_program, UNIFORM_LIGHT_DIR_LOCATION, 1, value_ptr(light_dir)));
291 
292  // Move spheres around in a compute shader to make it more exciting.
293  apply_physics(delta_time);
294 
295  if (enable_culling)
296  {
297  CullingInterface *culler = culling_implementations[culling_implementation_index];
298  num_sphere_render_lods = culler->get_num_lods();
299 
300  // Rasterize occluders to depth map and mipmap it.
301  culler->set_view_projection(projection, view, vec2(Z_NEAR, Z_FAR));
302  culler->rasterize_occluders();
303 
304  // We need physics results after this.
305  GL_CHECK(glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT));
306 
307  IndirectCommand indirect_command[SPHERE_LODS];
308  unsigned offsets[SPHERE_LODS];
309 
310  memset(indirect_command, 0, sizeof(indirect_command));
311 
312  for (unsigned i = 0; i < SPHERE_LODS; i++)
313  {
314  indirect_command[i].count = sphere[i]->get_num_elements();
315  offsets[i] = 4 + sizeof(IndirectCommand) * i;
316  }
317 
318  // Clear out our indirect draw buffer.
319  GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect.buffer[indirect.buffer_index]));
320  GL_CHECK(glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirect_command), indirect_command, GL_STREAM_DRAW));
321 
322  // Test occluders and build indirect commands as well as per-instance buffers for every LOD.
323  culler->test_bounding_boxes(indirect.buffer[indirect.buffer_index], offsets, SPHERE_LODS,
324  indirect.instance_buffer, sphere_instances_buffer,
325  num_render_sphere_instances);
326  }
327  else
328  {
329  // If we don't do culling, we need to make sure we call the memory barrier for physics.
330  GL_CHECK(glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT));
331  num_sphere_render_lods = 1;
332  }
333 }
334 
336 {
337  if (enable_culling)
338  {
339  GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect.buffer[indirect.buffer_index]));
340 
341  for (unsigned i = 0; i < num_sphere_render_lods; i++)
342  {
343  // Use different colors for different LOD levels to easily spot them.
344  GL_CHECK(glProgramUniform3fv(sphere_program, UNIFORM_COLOR_LOCATION, 1,
345  value_ptr(color_mod * vec3(0.8f - 0.2f * i, 1.2f - 0.2f * i, 0.8f + 0.2f * i))));
346 
347  // Use different meshes for different LOD levels.
348  GL_CHECK(glBindVertexArray(sphere[i]->get_vertex_array()));
349 
350  GL_CHECK(glEnableVertexAttribArray(3));
351  GL_CHECK(glVertexAttribDivisor(3, 1));
352  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, indirect.instance_buffer[i]));
353  GL_CHECK(glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(vec4), 0));
354 
355  GL_CHECK(glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
356  reinterpret_cast<const void*>(i * sizeof(IndirectCommand))));
357  }
358  }
359  else
360  {
361  // Unconditionally draw every instance of LOD0.
362  GL_CHECK(glProgramUniform3fv(sphere_program, UNIFORM_COLOR_LOCATION, 1, value_ptr(color_mod * vec3(0.8f, 1.2f, 0.8f))));
363  GL_CHECK(glBindVertexArray(sphere[0]->get_vertex_array()));
364  GL_CHECK(glEnableVertexAttribArray(3));
365  GL_CHECK(glVertexAttribDivisor(3, 1));
366  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, sphere_instances_buffer));
367  GL_CHECK(glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 2 * sizeof(vec4), 0));
368  GL_CHECK(glDrawElementsInstanced(GL_TRIANGLES, sphere[0]->get_num_elements(),
369  GL_UNSIGNED_SHORT, NULL, num_render_sphere_instances));
370  }
371 }
372 
373 void Scene::render(unsigned width, unsigned height)
374 {
375  if (enable_culling)
376  {
377  GL_CHECK(glClearColor(0.02f, 0.02f, 0.35f, 0.05f));
378  }
379  else
380  {
381  GL_CHECK(glClearColor(0.35f, 0.02f, 0.02f, 0.05f));
382  }
383 
384  // Enable depth testing and culling.
385  GL_CHECK(glEnable(GL_DEPTH_TEST));
386  GL_CHECK(glEnable(GL_CULL_FACE));
387 
388  GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
389  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
390  GL_CHECK(glViewport(0, 0, width, height));
391 
392  // Render occluder boxes.
393  GL_CHECK(glUseProgram(occluder_program));
394  GL_CHECK(glProgramUniform3f(occluder_program, UNIFORM_COLOR_LOCATION, 1.2f, 0.6f, 0.6f));
395  GL_CHECK(glBindVertexArray(box->get_vertex_array()));
396  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, occluder_instances_buffer));
397  GL_CHECK(glEnableVertexAttribArray(3));
398  GL_CHECK(glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vec4), 0));
399  GL_CHECK(glVertexAttribDivisor(3, 1));
400  GL_CHECK(glDrawElementsInstanced(GL_TRIANGLES, box->get_num_elements(), GL_UNSIGNED_SHORT, 0, num_occluder_instances));
401 
402  GL_CHECK(glUseProgram(sphere_program));
403  if (show_redundant)
404  {
405  // Draw false-positive meshes in a dark color.
406  // False-positives will fail the depth test (pass with GL_GREATER).
407  // We don't want to update the depth buffer, so the false-positives will be rendered in a "glitchy"
408  // way due to the random ordering that occlusion culling introduces.
409  GL_CHECK(glDepthFunc(GL_GREATER));
410  GL_CHECK(glDepthMask(GL_FALSE));
411  render_spheres(vec3(0.25f));
412  GL_CHECK(glDepthMask(GL_TRUE));
413  GL_CHECK(glDepthFunc(GL_LESS));
414  }
415  render_spheres(vec3(1.0f));
416 
417  if (enable_culling)
418  {
419  render_depth_map();
420  }
421 
422  // Restore viewport (for text rendering).
423  GL_CHECK(glViewport(0, 0, width, height));
424 
425  // Jump to next indirect draw buffer (ring buffer).
426  indirect.buffer_index = (indirect.buffer_index + 1) % INDIRECT_BUFFERS;
427 }
428 
430 {
431  GL_CHECK(glDisable(GL_DEPTH_TEST));
432  GL_CHECK(glUseProgram(quad_program));
433 
434  // Debug
435  GL_CHECK(glBindVertexArray(quad.get_vertex_array()));
436 
437  unsigned offset_x = 0;
438 
439  GL_CHECK(glBindTexture(GL_TEXTURE_2D, culling_implementations[culling_implementation_index]->get_depth_texture()));
440  for (unsigned lod = 0; lod <= DEPTH_SIZE_LOG2; lod++)
441  {
442  GL_CHECK(glViewport(offset_x, 0, DEPTH_SIZE >> lod, DEPTH_SIZE >> lod));
443 
444  // Mipmapped filtering mode will ensure we draw correct miplevel.
445  GL_CHECK(glDrawElements(GL_TRIANGLES, quad.get_num_elements(), GL_UNSIGNED_SHORT, 0));
446 
447  offset_x += DEPTH_SIZE >> lod;
448  }
449 }
450 
452 {
453  delete box;
454 
455  for (unsigned i = 0; i < SPHERE_LODS; i++)
456  {
457  delete sphere[i];
458  }
459 
460  for (unsigned i = 0; i < culling_implementations.size(); i++)
461  {
462  delete culling_implementations[i];
463  }
464 
465  GL_CHECK(glDeleteBuffers(1, &occluder_instances_buffer));
466  GL_CHECK(glDeleteBuffers(1, &sphere_instances_buffer));
467  GL_CHECK(glDeleteProgram(occluder_program));
468  GL_CHECK(glDeleteProgram(quad_program));
469  GL_CHECK(glDeleteProgram(physics_program));
470  GL_CHECK(glDeleteProgram(sphere_program));
471 
472  GL_CHECK(glDeleteBuffers(INDIRECT_BUFFERS, indirect.buffer));
473  GL_CHECK(glDeleteBuffers(SPHERE_LODS, indirect.instance_buffer));
474 }
475 
#define UNIFORM_COLOR_LOCATION
Definition: scene.cpp:46
#define SPHERE_INSTANCES_X
Definition: scene.cpp:31
const void * indirect
Definition: gl2ext.h:1335
#define SPHERE_INSTANCES_Y
Definition: scene.cpp:32
static const unsigned verts_per_circ[]
Definition: scene.cpp:49
void render(unsigned width, unsigned height)
Definition: scene.cpp:373
vec4 velocity
Definition: hiz_cull.cs:66
GLboolean GLboolean GLboolean GLboolean a
Definition: gl2ext.h:306
Definition: matrix.h:51
Mesh create_box_mesh(const AABB &aabb)
Definition: mesh.cpp:206
float vec_dot(const T &a, const T &b)
Definition: vector_math.h:289
virtual unsigned get_num_lods() const
Definition: culling.hpp:62
virtual void test_bounding_boxes(GLuint counter_buffer, const unsigned *counter_offsets, unsigned num_offsets, const GLuint *culled_instance_buffer, GLuint instance_data_buffer, unsigned num_instances)=0
mat4 mat_look_at(const vec3 &eye, const vec3 &center, const vec3 &up)
Definition: vector_math.h:358
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
void bake_occluder_geometry(std::vector< vec4 > &occluder_positions, std::vector< uint32_t > &occluder_indices, const Mesh &box_mesh, const vec4 *instances, unsigned num_instances)
Definition: scene.cpp:94
#define DEPTH_SIZE_LOG2
Definition: culling.hpp:70
~Scene()
Definition: scene.cpp:451
Definition: matrix.h:28
#define SPHERE_INSTANCES_Z
Definition: scene.cpp:33
GLuint common_compile_compute_shader_from_file(const char *cs_source)
Definition: common.cpp:317
void update(float delta_time, unsigned width, unsigned height)
Definition: scene.cpp:282
#define SPHERE_VERT_PER_CIRC_LOD0
Definition: scene.cpp:39
float clamp(float x, float min, float max)
Definition: noise.cpp:24
GLuint common_compile_shader_from_file(const char *vs_source, const char *fs_source)
Definition: common.cpp:241
void render_spheres(vec3 color_mod)
Definition: scene.cpp:335
void apply_physics(float delta_time)
Definition: scene.cpp:265
const T::data_type * value_ptr(const T &vec)
Definition: vector_math.h:35
mat4 mat_rotate_y(float radians)
Definition: vector_math.h:382
GLuint ibo
Definition: mesh.hpp:82
void move_camera(float delta_x, float delta_y)
Definition: scene.cpp:83
Matrix projection
Definition: matrix.h:75
GLuint index
Definition: gl2ext.h:300
Scene()
Definition: scene.cpp:56
#define PI
Definition: matrix.h:24
#define SPHERE_VERT_PER_CIRC_LOD3
Definition: scene.cpp:42
vec4 position
Definition: hiz_cull.cs:65
void set_culling_method(CullingMethod method)
Definition: scene.cpp:251
struct vec4::@39::@42 c
#define Z_FAR
Definition: scene.cpp:230
#define SPHERE_RADIUS
Definition: scene.cpp:36
#define UNIFORM_MVP_LOCATION
Definition: scene.cpp:45
Mesh quad
Definition: app.cpp:40
static float delta_x
Definition: app.cpp:85
GLfloat GLfloat f
Definition: gl2ext.h:2707
#define DEPTH_SIZE
Definition: culling.hpp:69
#define GL_CHECK(x)
Definition: AstcTextures.h:59
#define SPHERE_VERT_PER_CIRC_LOD2
Definition: scene.cpp:41
#define UNIFORM_LIGHT_DIR_LOCATION
Definition: scene.cpp:47
Mesh sphere
Definition: app.cpp:40
GLuint count
Definition: culling.hpp:35
mat4 mat_rotate_x(float radians)
Definition: vector_math.h:371
#define INDIRECT_BUFFERS
Definition: scene.hpp:74
mat4 mat_perspective_fov(float fovy, float aspect, float zn, float zf)
Definition: vector_math.h:419
#define SPHERE_LODS
Definition: culling.hpp:29
float velocity
Definition: Native.cpp:157
static float delta_y
Definition: app.cpp:86
#define Z_NEAR
Definition: scene.cpp:229
#define SPHERE_INSTANCES
Definition: scene.cpp:34
GLint GLint GLint GLint GLint x
Definition: gl2ext.h:574
#define PHYSICS_GROUP_SIZE
Definition: scene.cpp:28
virtual void set_view_projection(const mat4 &projection, const mat4 &view, const vec2 &zNearFar)=0
#define SPHERE_VERT_PER_CIRC_LOD1
Definition: scene.cpp:40
Definition: matrix.h:104
virtual void rasterize_occluders()=0
GLuint vbo
Definition: mesh.hpp:81
T vec_normalize(const T &vec)
Definition: vector_math.h:304
CullingMethod
Definition: scene.hpp:39
Definition: mesh.hpp:39
bool operator()(const vec4 &a, const vec4 &b)
Definition: scene.cpp:126
GLboolean GLboolean GLboolean b
Definition: gl2ext.h:306
GLint GLsizei width
Definition: gl2ext.h:179
void render_depth_map()
Definition: scene.cpp:429
void init_instances()
Definition: scene.cpp:138
GLint y
Definition: gl2ext.h:179
Mesh create_sphere_mesh(float radius, vec3 center, unsigned vertices_per_circumference)
Definition: mesh.cpp:122
void update_camera(float rotation_y, float rotation_x, unsigned viewport_width, unsigned viewport_height)
Definition: scene.cpp:231