GLVis  v4.2
Accurate and flexible finite element visualization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
renderer_core.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-443271.
4 //
5 // This file is part of the GLVis visualization tool and library. For more
6 // information and source code availability see https://glvis.org.
7 //
8 // GLVis is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #include "attr_traits.hpp"
13 #include "renderer_core.hpp"
14 #include "../aux_vis.hpp"
15 
16 #include <regex>
17 #include <type_traits>
18 #include <unordered_set>
19 
20 // weird but loads them inline
21 
22 const std::string BLINN_PHONG_FS =
23 #include "shaders/lighting.glsl"
24  ;
25 const std::string DEFAULT_VS =
26 #include "shaders/default.vert"
27  ;
28 const std::string DEFAULT_FS =
30 #include "shaders/default.frag"
31  ;
32 const std::string PRINTING_VS =
34 #include "shaders/printing.vert"
35  ;
36 const std::string PRINTING_FS =
37 #include "shaders/printing.frag"
38  ;
39 
40 namespace gl3
41 {
42 
43 const std::vector<std::string> CoreGLDevice::unif_list =
44 {
45  "useClipPlane",
46  "clipPlane",
47  "containsText",
48  "modelViewMatrix",
49  "projectionMatrix",
50  "textProjMatrix",
51  "normalMatrix",
52  "num_lights",
53  "g_ambient",
54  "material.specular",
55  "material.shininess",
56  "lights[0].position",
57  "lights[0].diffuse",
58  "lights[0].specular",
59  "lights[1].position",
60  "lights[1].diffuse",
61  "lights[1].specular",
62  "lights[2].position",
63  "lights[2].diffuse",
64  "lights[2].specular",
65  "colorTex",
66  "alphaTex"
67 };
68 
69 template<typename TVtx>
71 {
72  static_assert(AttrCoord<TVtx>::exists,
73  "Invalid vertex type, requires at least TVtx::coord to be present.");
78 }
79 
80 template<typename TVtx>
82 {
83  static_assert(AttrCoord<TVtx>::exists,
84  "Invalid vertex type, requires at least TVtx::coord to be present.");
89 }
90 
91 bool CoreGLDevice::compileShaders()
92 {
93  std::unordered_map<int, std::string> attribMap =
94  {
95  { CoreGLDevice::ATTR_VERTEX, "vertex"},
96  { CoreGLDevice::ATTR_TEXT_VERTEX, "textVertex"},
97  { CoreGLDevice::ATTR_NORMAL, "normal"},
98  { CoreGLDevice::ATTR_COLOR, "color"},
99  { CoreGLDevice::ATTR_TEXCOORD0, "texCoord0"}
100  };
101 
102  if (!default_prgm.create(DEFAULT_VS, DEFAULT_FS, attribMap, 1))
103  {
104  std::cerr << "Failed to create the default shader program." <<
105  std::endl;
106  return false;
107  }
108 
109 #ifndef __EMSCRIPTEN__
110  if (GLEW_EXT_transform_feedback || GLEW_VERSION_3_0)
111  {
112  const char * xfrm_varyings[] =
113  {
114  "gl_Position",
115  "fColor",
116  "fClipCoord",
117  };
118  glTransformFeedbackVaryings(feedback_prgm.getProgramId(), 3, xfrm_varyings,
119  GL_INTERLEAVED_ATTRIBS);
120 
121  if (!feedback_prgm.create(PRINTING_VS, PRINTING_FS, attribMap, 1))
122  {
123  std::cerr << "Failed to create the printing capture program." << std::endl;
124  return false;
125  }
126  }
127 #endif
128 
129  return true;
130 }
131 
132 void CoreGLDevice::initializeShaderState(const ShaderProgram& prog)
133 {
134  prog.bind();
135  uniforms = prog.getUniformMap();
136  for (const auto& uf : unif_list)
137  {
138  if (uniforms.find(uf) == uniforms.end())
139  {
140 #ifdef GLVIS_DEBUG
141  std::cerr << "Uniform \"" << uf
142  << "\" missing in shader, ignoring." << std::endl;
143 #endif
144  // set uniform index to -1 so glUniform ignores data
145  uniforms.emplace(uf, -1);
146  }
147  }
148 #ifdef GLVIS_DEBUG
149  unordered_set<string> expectedUnifs(unif_list.begin(), unif_list.end());
150  for (const auto& pairunif : uniforms)
151  {
152  if (expectedUnifs.find(pairunif.first) == expectedUnifs.end())
153  {
154  std::cerr << "Warning: unexpected uniform \""
155  << pairunif.first
156  << "\" found in shader." << std::endl;
157  }
158  }
159 #endif
160  glUniform1i(uniforms["colorTex"], 0);
161  glUniform1i(uniforms["alphaTex"], 1);
162  use_clip_plane = false;
163 }
164 
166 {
167  GLDevice::init();
168  if (!this->compileShaders())
169  {
170  std::cerr << "Unable to initialize CoreGLDevice." << std::endl;
171  return;
172  }
173  this->initializeShaderState(default_prgm);
174  if (GLEW_VERSION_3_0 || GLEW_ARB_vertex_array_object)
175  {
176  GLuint hnd_vao;
177  glGenVertexArrays(1, &hnd_vao);
178  global_vao = VtxArrayHandle(hnd_vao);
179  glBindVertexArray(global_vao);
180  }
181  GLuint hnd_fb_buf;
182  glGenBuffers(1, &hnd_fb_buf);
183  feedback_vbo = BufObjHandle(hnd_fb_buf);
184 }
185 
186 void CoreGLDevice::setTransformMatrices(glm::mat4 model_view,
187  glm::mat4 projection)
188 {
189  GLDevice::setTransformMatrices(model_view, projection);
190  glm::mat4 proj_text = glm::ortho<float>(0, vp_width, 0, vp_height, -5.0, 5.0);
191  glm::mat3 inv_normal = glm::inverseTranspose(glm::mat3(model_view));
192  glUniformMatrix4fv(uniforms["modelViewMatrix"], 1, GL_FALSE,
193  glm::value_ptr(model_view));
194  glUniformMatrix4fv(uniforms["projectionMatrix"], 1, GL_FALSE,
195  glm::value_ptr(projection));
196  glUniformMatrix4fv(uniforms["textProjMatrix"], 1, GL_FALSE,
197  glm::value_ptr(proj_text));
198  glUniformMatrix3fv(uniforms["normalMatrix"], 1, GL_FALSE,
199  glm::value_ptr(inv_normal));
200 }
201 
203 {
204  if (i > LIGHTS_MAX)
205  {
206  return;
207  }
208  glUniform1i(uniforms["num_lights"], i);
209 }
210 
212 {
213  glUniform4fv(uniforms["material.specular"], 1, mat.specular.data());
214  glUniform1f(uniforms["material.shininess"], mat.shininess);
215 }
216 
218 {
219  if (i > LIGHTS_MAX)
220  {
221  return;
222  }
223  std::string lt_index = "lights[" + std::to_string(i) + "]";
224  glUniform4fv(uniforms[lt_index + ".position"], 1, lt.position.data());
225  glUniform4fv(uniforms[lt_index + ".diffuse"], 1, lt.diffuse.data());
226  glUniform4fv(uniforms[lt_index + ".specular"], 1, lt.specular.data());
227 }
228 
229 void CoreGLDevice::setAmbientLight(const std::array<float, 4> &amb)
230 {
231  glUniform4fv(uniforms["g_ambient"], 1, amb.data());
232 }
233 
235 {
236  use_clip_plane = enable;
237  glUniform1i(uniforms["useClipPlane"], enable);
238 }
239 
240 void CoreGLDevice::setClipPlaneEqn(const std::array<double, 4> &eqn)
241 {
242  glm::vec4 clip_plane(eqn[0], eqn[1], eqn[2], eqn[3]);
243  clip_plane = glm::inverseTranspose(model_view_mtx) * clip_plane;
244  glUniform4fv(uniforms["clipPlane"], 1, glm::value_ptr(clip_plane));
245 }
246 
248 {
249  if (buf.getHandle() == 0)
250  {
251  if (buf.count() == 0) { return; }
252  GLuint handle;
253  glGenBuffers(1, &handle);
254  buf.setHandle(vbos.size());
255  vbos.emplace_back(VBOData{handle, 0, buf.getShape(), buf.count(), layout});
256  }
257  else
258  {
259  vbos[buf.getHandle()].count = buf.count();
260  }
261  glBindBuffer(GL_ARRAY_BUFFER, vbos[buf.getHandle()].vert_buf);
262  glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_STATIC_DRAW);
263  glBufferData(GL_ARRAY_BUFFER, buf.count() * buf.getStride(),
264  buf.getData(), GL_STATIC_DRAW);
265 }
266 
268 {
269  if (buf.getHandle() == 0)
270  {
271  if (buf.count() == 0) { return; }
272  GLuint handle[2];
273  glGenBuffers(2, &handle[0]);
274  buf.setHandle(vbos.size());
275  vbos.emplace_back(VBOData{handle[0], handle[1], buf.getShape(), buf.getIndices().size(), layout});
276  }
277  else
278  {
279  vbos[buf.getHandle()].count = buf.getIndices().size();
280  }
281  // Buffer vertex array
282  glBindBuffer(GL_ARRAY_BUFFER, vbos[buf.getHandle()].vert_buf);
283  glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_STATIC_DRAW);
284  glBufferData(GL_ARRAY_BUFFER, buf.count() * buf.getStride(),
285  buf.getData(), GL_STATIC_DRAW);
286  // Buffer element array
287  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[buf.getHandle()].elem_buf);
288  glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_STATIC_DRAW);
289  glBufferData(GL_ELEMENT_ARRAY_BUFFER, buf.getIndices().size() * sizeof(int),
290  buf.getIndices().data(), GL_STATIC_DRAW);
291 }
292 
294 {
295  std::vector<float> buf_data;
296  float tex_w = GetFont()->getAtlasWidth();
297  float tex_h = GetFont()->getAtlasHeight();
298  for (auto &e : t_buf)
299  {
300  float pen_x = e.ox, pen_y = e.oy;
301  char prev_c = '\0';
302  for (char c : e.text)
303  {
304  const GlVisFont::glyph &g = GetFont()->GetTexChar(c);
305  pen_x += GetFont()->GetKerning(prev_c, c);
306  // note: subtract 1 to account for the padding in the texture glyphs
307  float cur_x = pen_x + g.bear_x - 1;
308  float cur_y = -pen_y - g.bear_y - 1;
309  pen_x += g.adv_x;
310  pen_y += g.adv_y;
311  if (!g.w || !g.h)
312  {
313  continue;
314  }
315  float tris[] =
316  {
317  e.rx, e.ry, e.rz, cur_x, -cur_y, g.tex_x, 0, 0,
318  e.rx, e.ry, e.rz, cur_x + g.w, -cur_y, g.tex_x + g.w / tex_w, 0, 0,
319  e.rx, e.ry, e.rz, cur_x, -cur_y - g.h, g.tex_x, g.h / tex_h, 0,
320  e.rx, e.ry, e.rz, cur_x + g.w, -cur_y, g.tex_x + g.w / tex_w, 0, 0,
321  e.rx, e.ry, e.rz, cur_x, -cur_y - g.h, g.tex_x, g.h / tex_h, 0,
322  e.rx, e.ry, e.rz, cur_x + g.w, -cur_y - g.h, g.tex_x + g.w / tex_w, g.h / tex_h, 0
323  };
324  buf_data.insert(buf_data.end(), tris, tris + 8 * 6);
325  prev_c = c;
326  }
327  }
328  if (buf_data.size() == 0) { return; }
329  if (t_buf.getHandle() == 0)
330  {
331  GLuint handle;
332  glGenBuffers(1, &handle);
333  t_buf.setHandle(handle);
334  }
335  glBindBuffer(GL_ARRAY_BUFFER, t_buf.getHandle());
336  glBufferData(GL_ARRAY_BUFFER, sizeof(float) * buf_data.size(), buf_data.data(),
337  GL_STATIC_DRAW);
338 }
339 
340 template<typename T>
341 void CoreGLDevice::drawDeviceBufferImpl(GLenum shape, int count, bool indexed)
342 {
344  {
345  glVertexAttrib3f(CoreGLDevice::ATTR_NORMAL, 0.f, 0.f, 1.f);
346  }
347  if (!AttrColor<T>::exists && AttrTexcoord<T>::exists)
348  {
349  glVertexAttrib4f(CoreGLDevice::ATTR_COLOR, 1.f, 1.f, 1.f, 1.f);
350  }
351  setupVtxAttrLayout<T>();
352  if (indexed)
353  {
354  glDrawElements(shape, count, GL_UNSIGNED_INT, (void*)0);
355  }
356  else
357  {
358  glDrawArrays(shape, 0, count);
359  }
360  clearVtxAttrLayout<T>();
361 }
362 
364 {
365  if (hnd == 0) { return; }
366  if (vbos[hnd].count == 0) { return; }
367  glBindBuffer(GL_ARRAY_BUFFER, vbos[hnd].vert_buf);
368  bool indexed = false;
369  if (vbos[hnd].elem_buf != 0)
370  {
371  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[hnd].elem_buf);
372  indexed = true;
373  }
374  if (vbos[hnd].layout == Vertex::layout
375  || vbos[hnd].layout == VertexNorm::layout)
376  {
377  glVertexAttrib4fv(ATTR_COLOR, static_color.data());
378  }
379  GLenum shape = vbos[hnd].shape;
380  int count = vbos[hnd].count;
381  switch (vbos[hnd].layout)
382  {
383  case Vertex::layout:
384  drawDeviceBufferImpl<Vertex>(shape, count, indexed);
385  break;
386  case VertexColor::layout:
387  drawDeviceBufferImpl<VertexColor>(shape, count, indexed);
388  break;
389  case VertexTex::layout:
390  drawDeviceBufferImpl<VertexTex>(shape, count, indexed);
391  break;
392  case VertexNorm::layout:
393  drawDeviceBufferImpl<VertexNorm>(shape, count, indexed);
394  break;
396  drawDeviceBufferImpl<VertexNormColor>(shape, count, indexed);
397  break;
399  drawDeviceBufferImpl<VertexNormTex>(shape, count, indexed);
400  break;
401  default:
402  cerr << "WARNING: Unhandled vertex layout " << vbos[hnd].layout << endl;
403  }
404 }
406 {
407  if (t_buf.getHandle() == 0) { return; }
408  if (t_buf.count() == 0) { return; }
409  glUniform1i(uniforms["containsText"], GL_TRUE);
410  glEnableVertexAttribArray(ATTR_VERTEX);
411  glEnableVertexAttribArray(ATTR_TEXT_VERTEX);
412  glEnableVertexAttribArray(ATTR_TEXCOORD0);
413  glBindBuffer(GL_ARRAY_BUFFER, t_buf.getHandle());
414 
415  glVertexAttrib4fv(ATTR_COLOR, static_color.data());
416  glVertexAttribPointer(ATTR_VERTEX, 3, GL_FLOAT, GL_FALSE, t_buf.getStride(), 0);
417  glVertexAttribPointer(ATTR_TEXT_VERTEX, 2, GL_FLOAT, GL_FALSE,
418  t_buf.getStride(), (void*)(sizeof(float) * 3));
419  glVertexAttribPointer(ATTR_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, t_buf.getStride(),
420  (void*)(sizeof(float) * 5));
421  glDrawArrays(GL_TRIANGLES, 0, t_buf.count());
422 
423  glDisableVertexAttribArray(ATTR_TEXT_VERTEX);
424  glDisableVertexAttribArray(ATTR_TEXCOORD0);
425  glUniform1i(uniforms["containsText"], GL_FALSE);
426 }
427 
428 #ifndef __EMSCRIPTEN__
429 
431  float half_w, float half_h)
432 {
433  glm::vec3 coord = glm::make_vec3(v.pos);
434  glm::vec4 color = glm::make_vec4(v.color);
435  // clip coords -> ndc
436  coord /= v.pos[3];
437  // ndc -> device coords
438  coord.x = half_w * coord.x + half_w;
439  coord.y = half_h * coord.y + half_h;
440  return { coord, color };
441 }
442 
443 void CoreGLDevice::processTriangleXfbBuffer(CaptureBuffer& cbuf,
444  const vector<ShaderXfbVertex>& verts)
445 {
446  float half_w = vp_width * 0.5f;
447  float half_h = vp_height * 0.5f;
448  if (!use_clip_plane)
449  {
450  // all triangles into capture buf
451  for (size_t i = 0; i < verts.size(); i++)
452  {
453  cbuf.triangles.emplace_back(XFBPostTransform(verts[i], half_w, half_h));
454  }
455  return;
456  }
457  // clipping needed
458  for (size_t t_i = 0; t_i < verts.size() / 3; t_i++)
459  {
460  if (verts[t_i*3].clipCoord >= 0.f
461  && verts[t_i*3+1].clipCoord >= 0.f
462  && verts[t_i*3+2].clipCoord >= 0.f)
463  {
464  // triangle fully in the unclipped region
465  for (int vert_i = 0; vert_i < 3; vert_i++)
466  {
467  cbuf.triangles.emplace_back(
468  XFBPostTransform(verts[t_i*3 + vert_i], half_w, half_h));
469  }
470  }
471  else if (verts[3*t_i].clipCoord < 0.f
472  && verts[3*t_i+1].clipCoord < 0.f
473  && verts[3*t_i+2].clipCoord < 0.f)
474  {
475  // triangle fully in clipped region
476  continue;
477  }
478  else
479  {
480  // clip through middle of triangle
481  for (int vert_i = 0; vert_i < 3; vert_i++)
482  {
483  int i_a = 3*t_i+vert_i;
484  int i_b = 3*t_i+((vert_i+1) % 3);
485  int i_c = 3*t_i+((vert_i+2) % 3);
486  // find two points on the same side of clip plane
487  if ((verts[i_a].clipCoord < 0.f) == (verts[i_b].clipCoord < 0.f))
488  {
489  // pts a, b are on same side of clip plane, c on other side
490  // perspective-correct interpolation factors, needed for colors
491  float c_w_a = verts[i_a].clipCoord / verts[i_a].pos[3];
492  float c_w_b = verts[i_b].clipCoord / verts[i_b].pos[3];
493  float c_w_c = verts[i_c].clipCoord / verts[i_c].pos[3];
494  // compute clip pts
495  glm::vec4 pos[2], color[2];
496  // a --- n_0 --- c
497  pos[0] = (glm::make_vec4(verts[i_a].pos) * verts[i_c].clipCoord
498  - glm::make_vec4(verts[i_c].pos) * verts[i_a].clipCoord);
499  color[0] = (glm::make_vec4(verts[i_a].color) * c_w_c
500  - glm::make_vec4(verts[i_c].color) * c_w_a)
501  / (c_w_c - c_w_a);
502  // b --- n_1 --- c
503  pos[1] = (glm::make_vec4(verts[i_b].pos) * verts[i_c].clipCoord
504  - glm::make_vec4(verts[i_c].pos) * verts[i_b].clipCoord);
505  color[1] = (glm::make_vec4(verts[i_b].color) * c_w_c
506  - glm::make_vec4(verts[i_c].color) * c_w_b)
507  / (c_w_c - c_w_b);
508  for (int i = 0; i < 2; i++)
509  {
510  // perform transform to device coords
511  pos[i] /= pos[i].w;
512  pos[i].x *= half_w; pos[i].x += half_w;
513  pos[i].y *= half_h; pos[i].y += half_h;
514  }
515 
516  if (verts[i_c].clipCoord < 0.f)
517  {
518  // pts a, b are in clip plane
519  // create quadrilateral a -- n_0 -- n_1 -- b
520  cbuf.triangles.emplace_back(XFBPostTransform(verts[i_a], half_w, half_h));
521  cbuf.triangles.emplace_back(pos[0], color[0]);
522  cbuf.triangles.emplace_back(pos[1], color[1]);
523  cbuf.triangles.emplace_back(XFBPostTransform(verts[i_a], half_w, half_h));
524  cbuf.triangles.emplace_back(pos[1], color[1]);
525  cbuf.triangles.emplace_back(XFBPostTransform(verts[i_b], half_w, half_h));
526  }
527  else
528  {
529  // pt c is in clip plane
530  // add triangle c -- n_0 -- n_1
531  cbuf.triangles.emplace_back(XFBPostTransform(verts[i_c], half_w, half_h));
532  cbuf.triangles.emplace_back(pos[0], color[0]);
533  cbuf.triangles.emplace_back(pos[1], color[1]);
534  }
535  break;
536  }
537  }
538  }
539  }
540 }
541 
542 void CoreGLDevice::processLineXfbBuffer(CaptureBuffer& cbuf,
543  const vector<ShaderXfbVertex>& verts)
544 {
545  float half_w = vp_width * 0.5f;
546  float half_h = vp_height * 0.5f;
547  for (size_t i = 0; i < verts.size(); i += 2)
548  {
549  if (!use_clip_plane ||
550  (verts[i].clipCoord >= 0.f && verts[i+1].clipCoord >= 0.f))
551  {
552  cbuf.lines.emplace_back(XFBPostTransform(verts[i], half_w, half_h));
553  cbuf.lines.emplace_back(XFBPostTransform(verts[i+1], half_w, half_h));
554  }
555  else if (verts[i].clipCoord < 0.f && verts[i+1].clipCoord < 0.f)
556  {
557  // outside of clip plane;
558  continue;
559  }
560  else
561  {
562  int i_a, i_b;
563  if (verts[i].clipCoord < 0.f)
564  {
565  // vertex i lies in clipped region
566  i_a = i+1;
567  i_b = i;
568  }
569  else // verts[i+1].clipCoord < 0.f
570  {
571  // vertex i+1 lies in clipped region
572  i_a = i;
573  i_b = i+1;
574  }
575  // compute new vertex (CbVa - CaVb), where Vb lies in the clipped region
576  ShaderXfbVertex clip_vert;
577  // perspective-correct interpolation factors for color
578  float c_w_a = verts[i_a].clipCoord / verts[i_a].pos[3];
579  float c_w_b = verts[i_b].clipCoord / verts[i_b].pos[3];
580  for (int j = 0; j < 4; j++)
581  {
582  clip_vert.pos[j] = verts[i_a].pos[j] * verts[i_b].clipCoord
583  - verts[i_b].pos[j] * verts[i_a].clipCoord;
584  clip_vert.color[j] = (verts[i_a].color[j] * c_w_b
585  - verts[i_b].color[j] * c_w_a)
586  / (c_w_b - c_w_a);
587  }
588  cbuf.lines.emplace_back(XFBPostTransform(clip_vert, half_w, half_h));
589  cbuf.lines.emplace_back(XFBPostTransform(verts[i_a], half_w, half_h));
590  }
591  }
592 }
593 
594 
596  PaletteState& pal, CaptureBuffer& cbuf, int hnd)
597 {
598  if (hnd == 0) { return; }
599  if (vbos[hnd].count == 0) { return; }
600  // allocate feedback buffer
601  int buf_size = vbos[hnd].count * sizeof(ShaderXfbVertex);
602  glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
603  buf_size, nullptr, GL_STATIC_READ);
604  glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, feedback_vbo);
605  // Draw objects in feedback-only mode
606  glBeginTransformFeedback(vbos[hnd].shape);
607  drawDeviceBuffer(hnd);
608  glEndTransformFeedback();
609  // Read back feedback buffer
610  vector<ShaderXfbVertex> xfbBuf(buf_size);
611  glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf_size, xfbBuf.data());
612  if (vbos[hnd].shape == GL_TRIANGLES)
613  {
614  processTriangleXfbBuffer(cbuf, xfbBuf);
615  }
616  else if (vbos[hnd].shape == GL_LINES)
617  {
618  processLineXfbBuffer(cbuf, xfbBuf);
619  }
620  else
621  {
622  std::cerr << "Warning: GL_POINTS handling not implemented in transform "
623  << "feedback processing" << std::endl;
624  }
625 }
626 
627 #else
628 
630  CaptureBuffer& /*unused*/, int /*unused*/)
631 {
632  std::cerr << "CoreGLDevice::captureXfbBuffer: "
633  << "Not implemented for WebGL." << std::endl;
634 }
635 
636 #endif // __EMSCRIPTEN__
637 
638 }
virtual size_t count() const
Gets the number of vertices contained in the buffer.
Definition: types.hpp:588
void setClipPlaneEqn(const std::array< double, 4 > &eqn) override
int32_t bear_y
Definition: font.hpp:32
static void clear()
Definition: attr_traits.hpp:26
glm::mat4 model_view_mtx
Definition: renderer.hpp:102
void drawDeviceBuffer(int hnd) override
virtual void setTransformMatrices(glm::mat4 model_view, glm::mat4 projection)
Definition: renderer.cpp:438
int32_t bear_x
Definition: font.hpp:32
virtual size_t getStride() const
Gets the stride between vertices.
Definition: types.hpp:590
float shininess
Definition: material.hpp:21
GLuint getProgramId() const
Definition: shader.hpp:55
virtual size_t count() const =0
Gets the number of vertices contained in the buffer.
static const int layout
Definition: types.hpp:227
static const int layout
Definition: types.hpp:211
bool create(std::string vertexShader, std::string fragmentShader, std::unordered_map< int, std::string > inAttributes, int numOutputs)
Definition: shader.cpp:18
float adv_x
Definition: font.hpp:33
std::array< float, 4 > position
Definition: material.hpp:26
const std::string DEFAULT_VS
void setNumLights(int i) override
Handle< boCleanup > BufObjHandle
Definition: types.hpp:108
static const int layout
Definition: types.hpp:235
static const int layout
Definition: types.hpp:219
void setupVtxAttrLayout()
void setClipPlaneUse(bool enable) override
float GetKerning(char cprev, char c)
Definition: font.hpp:82
std::array< float, 4 > specular
Definition: material.hpp:20
void init() override
array_layout
Definition: types.hpp:170
void captureXfbBuffer(PaletteState &pal, CaptureBuffer &cbuf, int hnd) override
std::array< float, 4 > diffuse
Definition: material.hpp:27
static void setup()
Definition: attr_traits.hpp:24
FeedbackVertex XFBPostTransform(CoreGLDevice::ShaderXfbVertex v, float half_w, float half_h)
const std::string BLINN_PHONG_FS
std::array< float, 4 > static_color
Definition: renderer.hpp:105
Handle< vaoCleanup > VtxArrayHandle
Definition: types.hpp:110
static const int layout
Definition: types.hpp:244
void bufferToDevice(array_layout layout, IVertexBuffer &buf) override
void setHandle(int dev_hnd)
Definition: types.hpp:449
void clearVtxAttrLayout()
float getAtlasHeight()
Definition: font.hpp:105
int getHandle() const
Definition: types.hpp:448
void setPointLight(int i, Light lt) override
GlVisFont * GetFont()
Definition: aux_vis.cpp:1678
const int LIGHTS_MAX
Definition: renderer.hpp:30
virtual const void * getData() const =0
virtual size_t getStride() const =0
Gets the stride between vertices.
void setTransformMatrices(glm::mat4 model_view, glm::mat4 projection) override
std::array< float, 4 > specular
Definition: material.hpp:28
void setAmbientLight(const std::array< float, 4 > &amb) override
virtual const std::vector< int > & getIndices() const =0
virtual GLenum getShape() const =0
Gets the primitive type contained by the vertex buffer.
void setMaterial(Material mat) override
uint32_t h
Definition: font.hpp:31
const glyph & GetTexChar(char c) const
Definition: font.hpp:54
static const int layout
Definition: types.hpp:253
float tex_x
Definition: font.hpp:34
float adv_y
Definition: font.hpp:33
const std::string PRINTING_VS
uint32_t w
Definition: font.hpp:31
virtual void init()
Definition: renderer.cpp:397
float getAtlasWidth()
Definition: font.hpp:103
const std::string PRINTING_FS
const std::string DEFAULT_FS