OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mesh.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2015-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 "common.hpp"
22 #include "vector_math.h"
23 #include "mesh.hpp"
24 #include <limits.h>
25 
26 #include <vector>
27 #include <stdexcept>
28 #include <algorithm>
29 
30 using namespace std;
31 
32 constexpr float TessellatedMesh::patch_size;
33 constexpr float TessellatedMesh::lod0_distance;
34 constexpr unsigned TessellatedMesh::blocks_x;
35 constexpr unsigned TessellatedMesh::blocks_z;
36 
37 constexpr unsigned MorphedGeoMipMapMesh::patch_size;
38 constexpr unsigned MorphedGeoMipMapMesh::max_instances;
39 constexpr unsigned MorphedGeoMipMapMesh::lods;
41 constexpr unsigned MorphedGeoMipMapMesh::blocks_x;
42 constexpr unsigned MorphedGeoMipMapMesh::blocks_z;
43 
44 bool BoundingSphere::test_frustum(const vec4 *frustum) const
45 {
46  for (unsigned i = 0; i < 6; i++)
47  if (vec_dot(center, frustum[i]) < -radius)
48  return false;
49  return true;
50 }
51 
52 Mesh::Mesh(const char *vs_shader, const char *fs_shader)
53 {
54  prog = common_compile_shader_from_file(vs_shader, fs_shader);
55  if (!prog)
56  {
57  throw runtime_error("Failed to compile shader.");
58  }
59 
60  GL_CHECK(glGenVertexArrays(1, &vao));
61  GL_CHECK(glGenBuffers(1, &vbo));
62  GL_CHECK(glGenBuffers(1, &ibo));
63 }
64 
65 Mesh::Mesh(const char *vs_shader, const char *tc_shader, const char *te_shader,
66  const char *geom_shader, const char *fs_shader)
67 {
68  prog = common_compile_shader_from_file(vs_shader, tc_shader, te_shader,
69  geom_shader, fs_shader);
70  if (!prog)
71  {
72  throw runtime_error("Failed to compile shader.");
73  }
74 
75  GL_CHECK(glGenVertexArrays(1, &vao));
76  GL_CHECK(glGenBuffers(1, &vbo));
77  GL_CHECK(glGenBuffers(1, &ibo));
78 }
79 
81 {
82  if (prog)
83  {
84  GL_CHECK(glDeleteProgram(prog));
85  }
86 
87  if (vao)
88  {
89  GL_CHECK(glDeleteVertexArrays(1, &vao));
90  }
91 
92  if (vbo)
93  {
94  GL_CHECK(glDeleteBuffers(1, &vbo));
95  }
96 
97  if (ibo)
98  {
99  GL_CHECK(glDeleteBuffers(1, &ibo));
100  }
101 }
102 
103 static void generate_block_indices(vector<GLushort> &ibo, int vertex_buffer_offset,
104  int width, int height, int stride)
105 {
106  const GLushort restart_index = 0xffff;
107 
108  // Stamp out triangle strips back and forth.
109  int strips = height - 1;
110 
111  // After even indices in a strip, always step to next strip.
112  // After odd indices in a strip, step back again and one to the right or left.
113  // Which direction we take depends on which strip we're generating.
114  // This creates a zig-zag pattern.
115  for (int z = 0; z < strips; z++)
116  {
117  int step_even = stride;
118  int step_odd = 1 - step_even;
119  int pos = z * stride + vertex_buffer_offset;
120 
121  for (int x = 0; x < 2 * width - 1; x++)
122  {
123  ibo.push_back(pos);
124  pos += (x & 1) ? step_odd : step_even;
125  }
126 
127  ibo.push_back(pos); // Complete strip
128 
129  if (z + 1 < strips)
130  ibo.push_back(restart_index); // Restart
131  }
132 }
133 
135 {
136  GL_CHECK(glActiveTexture(GL_TEXTURE0 + 0));
137  GL_CHECK(glBindTexture(GL_TEXTURE_2D, info.height_displacement));
138  GL_CHECK(glActiveTexture(GL_TEXTURE0 + 1));
139  GL_CHECK(glBindTexture(GL_TEXTURE_2D, info.gradient_jacobian));
140  GL_CHECK(glActiveTexture(GL_TEXTURE0 + 2));
141  GL_CHECK(glBindTexture(GL_TEXTURE_2D, info.normal));
142  GL_CHECK(glActiveTexture(GL_TEXTURE0 + 3));
143  GL_CHECK(glBindTexture(GL_TEXTURE_CUBE_MAP, info.skydome));
144 }
145 
147  : Mesh("water.vs", "water.fs")
148 {
149  init();
150 }
151 
152 static inline float lod_factor(float max_lod, float distance_mod, vec3 dist)
153 {
154  float level = log2((vec_length(dist) + 0.0001f) * distance_mod);
155  return clamp(level, 0.0f, max_lod);
156 }
157 
159 {
160  vec2 patch_size_mod = vec2(patch_size) * info.tile_extent / vec2(info.fft_size);
161 
162  vec2 scale = info.tile_extent / vec2(info.fft_size);
163  ivec2 block_off = ivec2(vec_round(vec2(info.cam_pos.x, info.cam_pos.z) / patch_size_mod));
164  block_off -= ivec2(blocks_x >> 1, blocks_z >> 1);
165  vec2 block_offset = vec2(patch_size) * vec2(block_off);
166 
167  float distance_mod = 1.0f / ((info.vp_width / 1920.0f) * lod0_distance);
168  vec3 cam_pos = info.cam_pos;
169 
170  // Compute LOD and visibility.
171  for (auto &patch : patches)
172  {
173  const vec2 half_block = scale * vec2(0.5f * patch_size);
174 
175  vec2 newpos = scale * (patch.pos + block_offset) + half_block;
176  vec3 dist = cam_pos - vec3(newpos.x, 0.0f, newpos.y);
177  patch.lod = lod_factor(lods - 1.0f, distance_mod, dist);
178 
179  BoundingSphere bs(vec3(newpos.x, 0.0f, newpos.y), vec3(10.0f + half_block.x, 20.0f, 10.0f + half_block.y));
180  patch.visible = bs.test_frustum(info.frustum);
181  }
182 
183  for (unsigned z = 0; z < blocks_z; z++)
184  {
185  for (unsigned x = 0; x < blocks_x; x++)
186  {
187  float lod = patches[z * blocks_x + x].lod;
188  lod_buffer[z * blocks_x + x] = lod;
189  }
190  }
191 
192  // Upload the LOD texture to a PBO first.
193  GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo));
194  GL_CHECK(void *ptr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, blocks_x * blocks_z, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
195  if (ptr)
196  {
197  // Quantize the LOD to a R8_UNORM value as well.
198  transform(begin(lod_buffer), end(lod_buffer), static_cast<uint8_t*>(ptr), [](float v) -> GLubyte {
199  return clamp(GLubyte(round(v * 32.0f)), GLubyte(0), GLubyte(255));
200  });
201 
202  GL_CHECK(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));
203 
204  GL_CHECK(glBindTexture(GL_TEXTURE_2D, lod_tex));
205  GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
206  blocks_x, blocks_z, GL_RED, GL_UNSIGNED_BYTE, nullptr));
207  }
208  GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
209  GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
210 
211  for (auto &lod : lod_meshes)
212  lod.full.instances = 0;
213 
214  GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, ubo));
215  GL_CHECK(PatchData *ubo_data = static_cast<PatchData*>(glMapBufferRange(GL_UNIFORM_BUFFER,
216  0, lods * blocks_x * blocks_z * sizeof(PatchData),
217  GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)));
218 
219  if (!ubo_data)
220  {
221  LOGE("Failed to map buffer!");
222  return;
223  }
224 
225  // Fill in instancing info for all patches.
226  for (unsigned z = 0; z < blocks_z; z++)
227  {
228  for (unsigned x = 0; x < blocks_x; x++)
229  {
230  if (!patches[z * blocks_x + x].visible)
231  continue;
232 
233  // Clamp-to-edge.
234  unsigned px = x ? (x - 1) : 0;
235  unsigned pz = z ? (z - 1) : 0;
236  unsigned nx = min(x + 1, blocks_x - 1);
237  unsigned nz = min(z + 1, blocks_z - 1);
238 
239  // Look at neighbors.
240  float left = lod_buffer[z * blocks_x + px];
241  float top = lod_buffer[nz * blocks_x + x];
242  float right = lod_buffer[z * blocks_x + nx];
243  float bottom = lod_buffer[pz * blocks_x + x];
244  float center = lod_buffer[z * blocks_x + x];
245 
246  // .. and pick out the lowest LOD for edges.
247  float left_lod = max(left, center);
248  float top_lod = max(top, center);
249  float right_lod = max(right, center);
250  float bottom_lod = max(bottom, center);
251  int center_lod = int(center);
252 
253  auto &lod = lod_meshes[center_lod];
254 
255  unsigned ubo_offset = center_lod * blocks_x * blocks_z;
256 
257  ubo_data[ubo_offset + lod.full.instances].Offsets = vec4(
258  patches[z * blocks_x + x].pos + block_offset, // Offset to world space.
259  patches[z * blocks_x + x].pos);
260  ubo_data[ubo_offset + lod.full.instances].LODs = vec4(left_lod, top_lod, right_lod, bottom_lod);
261  ubo_data[ubo_offset + lod.full.instances].InnerLOD = vec4(center);
262 
263  lod.full.instances++;
264  }
265  }
266 
267  GL_CHECK(glUnmapBuffer(GL_UNIFORM_BUFFER));
268 }
269 
270 void MorphedGeoMipMapMesh::LODMesh::draw(GLuint ubo, unsigned ubo_offset)
271 {
272  // Draw everything with instancing.
273  for (unsigned i = 0; i < instances; i += max_instances)
274  {
275  unsigned to_draw = min(instances - i, max_instances);
276  GL_CHECK(glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, i * sizeof(PatchData) + ubo_offset, max_instances * sizeof(PatchData)));
277  GL_CHECK(glDrawElementsInstanced(GL_TRIANGLE_STRIP, elems, GL_UNSIGNED_SHORT,
278  reinterpret_cast<const GLvoid*>(uintptr_t(offset * sizeof(GLushort))),
279  to_draw));
280  }
281 }
282 
284 {
285  GL_CHECK(glUseProgram(prog));
286  GL_CHECK(glBindVertexArray(vao));
287 
288  calculate_lods(info);
289 
290  GL_CHECK(glUniformMatrix4fv(0, 1, GL_FALSE, value_ptr(info.mvp)));
291  GL_CHECK(glUniform4fv(1, 1, value_ptr(vec4(info.tile_extent / vec2(info.fft_size),
292  info.normal_scale.x, info.normal_scale.y))));
293  GL_CHECK(glUniform2fv(3, 1, value_ptr(vec2(info.fft_size) / info.tile_extent)));
294  GL_CHECK(glUniform3fv(4, 1, value_ptr(info.cam_pos)));
295 
296  GL_CHECK(glUniform2f(5,
297  1.0f / (patch_size * blocks_x),
298  1.0f / (patch_size * blocks_z)));
299 
300  GL_CHECK(glUniform2f(6,
301  1.0f / info.fft_size.x,
302  1.0f / info.fft_size.y));
303 
304  bind_textures(info);
305  GL_CHECK(glActiveTexture(GL_TEXTURE0 + 4));
306  GL_CHECK(glBindTexture(GL_TEXTURE_2D, lod_tex));
307 
308  GL_CHECK(glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX));
309  for (unsigned i = 0; i < lods; i++)
310  lod_meshes[i].full.draw(ubo, i * blocks_x * blocks_z * sizeof(PatchData));
311  GL_CHECK(glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX));
312 
313  GL_CHECK(glBindVertexArray(0));
314  GL_CHECK(glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0));
315 }
316 
318 {
319  int size = patch_size >> lod;
320  int size_1 = size + 1;
321  int mod = 1 << lod;
322 
323  LOD lodmesh;
324 
325  lodmesh.full_vbo = vertices.size();
326  // Stamp out a simple grid with (N + 1)^2 vertices (N^2 * 2 quads).
327  for (int y = 0; y < size_1; y++)
328  for (int x = 0; x < size_1; x++)
329  vertices.emplace_back(x * mod, y * mod);
330 
331  lodmesh.full.offset = indices.size();
332  // Stamp out a tight strip representation of the mesh.
333  generate_block_indices(indices, lodmesh.full_vbo, size_1, size_1, size_1);
334  lodmesh.full.elems = indices.size() - lodmesh.full.offset;
335 
336  for (unsigned i = lodmesh.full_vbo; i < vertices.size(); i++)
337  {
338  auto &v = vertices[i];
339 
340  // When creating new vertices create them towards center of the patch
341  // to avoid popping artifacts at edges.
342  v.rounding_x = v.x < patch_size / 2;
343  v.rounding_y = v.y < patch_size / 2;
344 
345  // We don't really care about the corners since they will never snap anywhere, so it doesn't matter
346  // which vertex LOD they snap to.
347  memset(v.lod_weight, 0, sizeof(v.lod_weight));
348  if (v.x == 0)
349  v.lod_weight[0] = 1;
350  else if (v.y == patch_size)
351  v.lod_weight[1] = 1;
352  else if (v.x == patch_size)
353  v.lod_weight[2] = 1;
354  else if (v.y == 0)
355  v.lod_weight[3] = 1;
356 
357  // For inner vertices, use weights (0, 0, 0, 0) which means use center LOD.
358  }
359 
360  lod_meshes.push_back(move(lodmesh));
361 }
362 
364 {
365  for (unsigned z = 0; z < blocks_z; z++)
366  for (unsigned x = 0; x < blocks_x; x++)
367  patches.push_back({ vec2(ivec2(x, z) * ivec2(patch_size)), 0.0f, false });
368 }
369 
371 {
372  GL_CHECK(glGenTextures(1, &lod_tex));
373  GL_CHECK(glBindTexture(GL_TEXTURE_2D, lod_tex));
374  GL_CHECK(glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, blocks_x, blocks_z));
375  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
376  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
377  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
378  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
379  GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
380 
381  lod_buffer.resize(blocks_x * blocks_z);
382 }
383 
385 {
386  GL_CHECK(glDeleteTextures(1, &lod_tex));
387  GL_CHECK(glDeleteBuffers(1, &ubo));
388  GL_CHECK(glDeleteBuffers(1, &pbo));
389 }
390 
392 {
393  // Create VBOs and IBOs for every lod.
394  for (unsigned i = 0; i < lods; i++)
395  build_lod(i);
396 
397  // Initalize patch data.
398  build_patches();
399 
400  // Create LOD texture.
401  init_lod_tex();
402 
403  // Create an UBO large enough to hold PatchData for all LODs.
404  GL_CHECK(glGenBuffers(1, &ubo));
405  GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, ubo));
406  GL_CHECK(glBufferData(GL_UNIFORM_BUFFER, lods * blocks_x * blocks_z * sizeof(PatchData), nullptr, GL_STREAM_DRAW));
407  GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0));
408 
409  // Create a PBO for updating LOD texture.
410  GL_CHECK(glGenBuffers(1, &pbo));
411  GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo));
412  GL_CHECK(glBufferData(GL_PIXEL_UNPACK_BUFFER, blocks_x * blocks_z, nullptr, GL_STREAM_DRAW));
413  GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
414 
415  // Set up VAO.
416  GL_CHECK(glBindVertexArray(vao));
417 
418  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vbo));
419  GL_CHECK(glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW));
420  GL_CHECK(glEnableVertexAttribArray(0));
421  GL_CHECK(glEnableVertexAttribArray(1));
422  // We take in uvec4 in vertex shader, so use IPointer.
423  GL_CHECK(glVertexAttribIPointer(0, 4, GL_UNSIGNED_BYTE, sizeof(Vertex), 0));
424  GL_CHECK(glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), reinterpret_cast<const GLvoid*>(uintptr_t(4))));
425 
426  GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo));
427  GL_CHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), indices.data(), GL_STATIC_DRAW));
428 
429  GL_CHECK(glBindVertexArray(0));
430  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
431  GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
432 }
433 
435  : Mesh("water_tess.vs", "water_tess.tesc", "water_tess.tese", nullptr, "water.fs")
436 {
437  init_vao();
438 }
439 
441 {
442  GL_CHECK(glBindVertexArray(vao));
443 
444  vector<ubvec2> verts(blocks_x * blocks_z);
445 
446  // Place patches on a large grid.
447  for (unsigned z = 0; z < blocks_z; z++)
448  {
449  for (unsigned x = 0; x < blocks_x; x++)
450  {
451  verts[z * blocks_x + x].x = x;
452  verts[z * blocks_x + x].y = z;
453  }
454  }
455 
456  // Sort patches front-to-back. X/Z coordinates close to (blocks_x / 2, blocks_z / 2) are centered around camera.
457  sort(begin(verts), end(verts), [](vec2 a, vec2 b) {
458  a -= vec2(blocks_x / 2, blocks_z / 2);
459  b -= vec2(blocks_x / 2, blocks_z / 2);
460  return vec_dot(a, a) < vec_dot(b, b);
461  });
462 
464 
465  // Setup VAO.
466  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vbo));
467  GL_CHECK(glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(ubvec2), verts.data(), GL_STATIC_DRAW));
468  GL_CHECK(glEnableVertexAttribArray(0));
469  GL_CHECK(glVertexAttribIPointer(0, 2, GL_UNSIGNED_BYTE, 0, 0));
470 
471  GL_CHECK(glBindVertexArray(0));
472  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
473 }
474 
476 {
477  GL_CHECK(glUseProgram(prog));
478  GL_CHECK(glBindVertexArray(vao));
479 
480  vec2 patch_size_mod = vec2(patch_size) * info.tile_extent / vec2(info.fft_size);
481 
482  ivec2 block_off = ivec2(vec_round(vec2(info.cam_pos.x, info.cam_pos.z) / patch_size_mod));
483  block_off -= ivec2(blocks_x >> 1, blocks_z >> 1);
484 
485  GL_CHECK(glUniformMatrix4fv(0, 1, GL_FALSE, value_ptr(info.mvp)));
486  GL_CHECK(glUniform4fv(1, 1, value_ptr(vec4(info.tile_extent / vec2(info.fft_size),
487  info.normal_scale.x, info.normal_scale.y))));
488  GL_CHECK(glUniform2iv(2, 1, value_ptr(block_off)));
489  GL_CHECK(glUniform2fv(3, 1, value_ptr(vec2(info.fft_size) / info.tile_extent)));
490  GL_CHECK(glUniform3fv(4, 1, value_ptr(info.cam_pos)));
491 
492  GL_CHECK(glUniform2f(5, patch_size, patch_size));
493  GL_CHECK(glUniform2f(6, log2(float(patch_size)), patch_size));
494  GL_CHECK(glUniform1f(7, 1.0f / ((info.vp_width / 1920.0f) * lod0_distance)));
495  GL_CHECK(glUniform2f(8,
496  1.0f / info.fft_size.x, 1.0f / info.fft_size.y));
497  GL_CHECK(glUniform4fv(9, 6, value_ptr(info.frustum[0])));
498 
499  bind_textures(info);
500 
501  // Render patches with tessellation.
502  GL_CHECK(glPatchParameteriEXT(GL_PATCH_VERTICES_EXT, 1));
503  GL_CHECK(glDrawArrays(GL_PATCHES_EXT, 0, num_vertices));
504  GL_CHECK(glBindVertexArray(0));
505 }
506 
const GLfloat * v
Definition: gl2ext.h:2231
vec2 tile_extent
Definition: mesh.hpp:43
void init_lod_tex()
Definition: mesh.cpp:370
void draw(GLuint ubo, unsigned ubo_offset)
Definition: mesh.cpp:270
GLuint GLuint end
Definition: gl2ext.h:323
static vec3 cam_pos
Definition: ocean.cpp:66
static constexpr float patch_size
Definition: mesh.hpp:189
unsigned vp_width
Definition: mesh.hpp:64
GLuint height_displacement
Definition: mesh.hpp:52
GLboolean GLboolean GLboolean GLboolean a
Definition: gl2ext.h:306
void init_vao()
Definition: mesh.cpp:440
uint32_t y
Definition: vector_math.h:68
Definition: matrix.h:51
std::vector< Patch > patches
Definition: mesh.hpp:147
float vec_dot(const T &a, const T &b)
Definition: vector_math.h:289
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
GLuint vao
Definition: mesh.hpp:80
Definition: matrix.h:28
uint32_t x
Definition: vector_math.h:68
float min(float x, float y)
Definition: noise.cpp:34
std::vector< float > lod_buffer
Definition: mesh.hpp:162
GLenum GLuint GLintptr offset
Definition: gl2ext.h:629
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
static constexpr unsigned max_instances
Definition: mesh.hpp:159
precision highp int
Definition: hiz_cull.cs:38
const T::data_type * value_ptr(const T &vec)
Definition: vector_math.h:35
std::vector< Vertex > vertices
Definition: mesh.hpp:175
static constexpr unsigned blocks_x
Definition: mesh.hpp:192
GLuint ibo
Definition: mesh.hpp:82
float z
Definition: matrix.h:55
static void generate_block_indices(vector< GLushort > &ibo, int vertex_buffer_offset, int width, int height, int stride)
Definition: mesh.cpp:103
bool test_frustum(const vec4 *frustum) const
Definition: mesh.cpp:44
#define GL_PATCH_VERTICES_EXT
Definition: gl2ext.h:1631
Definition: matrix.h:75
GLuint normal
Definition: mesh.hpp:58
static constexpr float lod0_distance
Definition: mesh.hpp:190
void build_lod(unsigned lod)
Definition: mesh.cpp:317
#define GL_PATCHES_EXT
Definition: gl2ext.h:1630
void calculate_lods(const RenderInfo &info)
Definition: mesh.cpp:158
float vec_length(const T &vec)
Definition: vector_math.h:298
void bind_textures(const RenderInfo &info)
Definition: mesh.cpp:134
vec3 cam_pos
Definition: mesh.hpp:49
GLsizei GLenum const void * indices
Definition: gl2ext.h:322
void render(const RenderInfo &info) override
Definition: mesh.cpp:283
static constexpr unsigned blocks_z
Definition: mesh.hpp:156
GLfloat GLfloat f
Definition: gl2ext.h:2707
GLuint gradient_jacobian
Definition: mesh.hpp:55
static constexpr unsigned patch_size
Definition: mesh.hpp:151
float y
Definition: matrix.h:31
#define GL_CHECK(x)
Definition: AstcTextures.h:59
Matrix scale
Definition: RotoZoom.cpp:64
static constexpr float lod0_distance
Definition: mesh.hpp:154
float x
Definition: matrix.h:53
GLuint skydome
Definition: mesh.hpp:61
GLuint prog
Definition: mesh.hpp:79
static constexpr unsigned blocks_x
Definition: mesh.hpp:155
float max(float x, float y)
Definition: noise.cpp:29
static constexpr unsigned lods
Definition: mesh.hpp:153
detail::ivec2< uint8_t > ubvec2
Definition: vector_math.h:92
GLenum GLuint GLintptr GLsizeiptr size
Definition: gl2ext.h:629
vec2 normal_scale
Definition: mesh.hpp:46
GLint GLint GLint GLint GLint x
Definition: gl2ext.h:574
GLenum GLuint GLint level
Definition: gl2ext.h:385
const void GLsizei GLsizei stride
Definition: gl2ext.h:1335
GLint left
Definition: gl2ext.h:2704
GLuint vbo
Definition: mesh.hpp:81
unsigned num_vertices
Definition: mesh.hpp:187
#define GL_MAP_WRITE_BIT
Definition: gl2ext.h:1050
#define LOGE(...)
Definition: AstcTextures.h:30
static constexpr unsigned blocks_z
Definition: mesh.hpp:193
GLboolean GLboolean GLboolean b
Definition: gl2ext.h:306
GLint GLsizei width
Definition: gl2ext.h:179
float x
Definition: matrix.h:30
virtual ~Mesh()
Definition: mesh.cpp:80
std::vector< LOD > lod_meshes
Definition: mesh.hpp:146
Mesh(const char *vs_shader, const char *fs_shader)
Definition: mesh.cpp:52
T vec_round(const T &vec)
Definition: vector_math.h:319
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count
detail::ivec2< int32_t > ivec2
Definition: vector_math.h:91
vec4 frustum[6]
Definition: mesh.hpp:37
GLint y
Definition: gl2ext.h:179
uvec2 fft_size
Definition: mesh.hpp:40
GLint GLint bottom
Definition: gl2ext.h:2704
void render(const RenderInfo &info) override
Definition: mesh.cpp:475
void build_patches()
Definition: mesh.cpp:363
static float lod_factor(float max_lod, float distance_mod, vec3 dist)
Definition: mesh.cpp:152