Thanks to visit codestin.com
Credit goes to glvis.github.io

GLVis  v4.2
Accurate and flexible finite element visualization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
renderer.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 "renderer.hpp"
13 
14 namespace gl3
15 {
16 
17 // Beginning in OpenGL 3.0, there were two changes in texture format support:
18 // - The older single-channel internal format GL_ALPHA was deprecated in favor
19 // of GL_RED
20 // - New sized internal formats were introduced, e.g. GL_RGBA32F defines a 4-
21 // channel texture with each channel holding a 32-bit floating point value
22 //
23 // An additional complication is introduced with OpenGL ES 3/WebGL 2 - the
24 // unsized formats like GL_RED and GL_RGBA no longer support floating-point
25 // data being passed in, so use of the sized internal formats is obligatory in
26 // WebGL 2.
28 {
29 #ifdef __EMSCRIPTEN__
30  const std::string versionString
31  = reinterpret_cast<const char*>(glGetString(GL_VERSION));
32  if (versionString.find("OpenGL ES 3.0") != std::string::npos)
33  {
34  return false;
35  }
36  else
37  {
38  return true;
39  }
40 #else
41  return !GLEW_VERSION_3_0;
42 #endif
43 }
44 
45 void MeshRenderer::setAntialiasing(bool aa_status)
46 {
47  if (msaa_enable != aa_status)
48  {
49  msaa_enable = aa_status;
50  if (msaa_enable)
51  {
52  if (!feat_use_fbo_antialias)
53  {
54  glEnable(GL_MULTISAMPLE);
55  glEnable(GL_LINE_SMOOTH);
56  device->enableBlend();
57  }
58  device->setLineWidth(line_w_aa);
59  }
60  else
61  {
62  if (!feat_use_fbo_antialias)
63  {
64  glDisable(GL_MULTISAMPLE);
65  glDisable(GL_LINE_SMOOTH);
66  device->disableBlend();
67  }
68  device->setLineWidth(line_w);
69  }
70  }
71 }
72 
74 {
75  line_w = w;
76  if (device && !msaa_enable)
77  {
78  device->setLineWidth(line_w);
79  }
80 }
81 
83 {
84  line_w_aa = w;
85  if (device && msaa_enable)
86  {
87  device->setLineWidth(line_w_aa);
88  }
89 }
90 
91 void MeshRenderer::init()
92 {
93 #ifdef __EMSCRIPTEN__
94  const std::string versionString
95  = reinterpret_cast<const char*>(glGetString(GL_VERSION));
96  bool is_webgl2 = (versionString.find("OpenGL ES 3.0") != std::string::npos);
97  feat_use_fbo_antialias = is_webgl2;
98  if (feat_use_fbo_antialias)
99  {
100  glGetIntegerv(GL_MAX_SAMPLES, &msaa_samples);
101  }
102 #else
103  // TODO: we could also support ARB_framebuffer_object
104  feat_use_fbo_antialias = GLEW_VERSION_3_0;
105  glGetIntegerv(GL_MAX_SAMPLES, &msaa_samples);
106 #endif
107 }
108 
110 {
111  // elements containing opaque objects should be rendered first
112  RenderQueue sorted_queue = queue;
113  std::stable_partition(sorted_queue.begin(), sorted_queue.end(),
114  [](RenderQueue::value_type& renderPair)
115  {
116  return !renderPair.first.contains_translucent;
117  });
118  RenderBufHandle renderBufs[2];
119  FBOHandle msaaFb;
120  if (feat_use_fbo_antialias && msaa_enable)
121  {
122  GLuint colorBuf, depthBuf;
123  glGenRenderbuffers(1, &colorBuf);
124  glGenRenderbuffers(1, &depthBuf);
125  renderBufs[0] = RenderBufHandle(colorBuf);
126  renderBufs[1] = RenderBufHandle(depthBuf);
127 
128  GLuint fbo;
129  glGenFramebuffers(1, &fbo);
130 
131  int vp[4];
132  device->getViewport(vp);
133  int width = vp[2];
134  int height = vp[3];
135  glBindRenderbuffer(GL_RENDERBUFFER, colorBuf);
136  glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa_samples,
137  GL_RGBA8, width, height);
138  glBindRenderbuffer(GL_RENDERBUFFER, depthBuf);
139  glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa_samples,
140  GL_DEPTH_COMPONENT24, width, height);
141  glBindRenderbuffer(GL_RENDERBUFFER, 0);
142 
143  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
144  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
145  GL_RENDERBUFFER, colorBuf);
146  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
147  GL_RENDERBUFFER, depthBuf);
148 
149  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
150  {
151  cerr << "Unable to create multisampled renderbuffer." << flush;
152  glDeleteFramebuffers(1, &fbo);
153  glBindFramebuffer(GL_FRAMEBUFFER, 0);
154  }
155  else
156  {
157  msaaFb = FBOHandle(fbo);
158  }
159 #ifndef __EMSCRIPTEN__
160  glEnable(GL_MULTISAMPLE);
161 #endif
162  }
163  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
164  for (auto& q_elem : sorted_queue)
165  {
166  const RenderParams& params = q_elem.first;
167  device->setTransformMatrices(params.model_view.mtx, params.projection.mtx);
168  device->setMaterial(params.mesh_material);
169  device->setNumLights(params.num_pt_lights);
170  for (int i = 0; i < params.num_pt_lights; i++)
171  {
172  device->setPointLight(i, params.lights[i]);
173  }
174  device->setAmbientLight(params.light_amb_scene);
175  device->setStaticColor(params.static_color);
176  device->setClipPlaneUse(params.use_clip_plane);
177  device->setClipPlaneEqn(params.clip_plane_eqn);
178  // aggregate buffers with common parameters
179  std::vector<int> tex_bufs, no_tex_bufs;
180  std::vector<TextBuffer*> text_bufs;
181  GlDrawable* curr_drawable = q_elem.second;
182  for (int i = 0; i < NUM_LAYOUTS; i++)
183  {
184  for (size_t j = 0; j < GlDrawable::NUM_SHAPES; j++)
185  {
186  if (curr_drawable->buffers[i][j])
187  {
189  {
190  tex_bufs.emplace_back(curr_drawable->buffers[i][j].get()->getHandle());
191  }
192  else
193  {
194  no_tex_bufs.emplace_back(curr_drawable->buffers[i][j].get()->getHandle());
195  }
196  }
197  if (curr_drawable->indexed_buffers[i][j])
198  {
200  {
201  tex_bufs.emplace_back(curr_drawable->indexed_buffers[i][j].get()->getHandle());
202  }
203  else
204  {
205  no_tex_bufs.emplace_back(
206  curr_drawable->indexed_buffers[i][j].get()->getHandle());
207  }
208  }
209  }
210  }
211  text_bufs.emplace_back(&curr_drawable->text_buffer);
212  if (params.contains_translucent)
213  {
214  device->enableBlend();
215  }
216  else
217  {
218  device->enableDepthWrite();
219  }
220  device->attachTexture(GLDevice::SAMPLER_COLOR, color_tex);
221  device->attachTexture(GLDevice::SAMPLER_ALPHA, alpha_tex);
222  for (auto buf : tex_bufs)
223  {
224  device->drawDeviceBuffer(buf);
225  }
226  device->detachTexture(GLDevice::SAMPLER_COLOR);
227  device->detachTexture(GLDevice::SAMPLER_ALPHA);
228  for (auto buf : no_tex_bufs)
229  {
230  device->drawDeviceBuffer(buf);
231  }
232  if (!params.contains_translucent)
233  {
234  device->enableBlend();
235  device->disableDepthWrite();
236  }
237  device->attachTexture(1, font_tex);
238  device->setNumLights(0);
239  for (TextBuffer* buf : text_bufs)
240  {
241  device->drawDeviceBuffer(*buf);
242  }
243  device->enableDepthWrite();
244  if (feat_use_fbo_antialias || !msaa_enable) { device->disableBlend(); }
245  }
246  if (feat_use_fbo_antialias && msaa_enable && msaaFb)
247  {
248  device->enableBlend();
249  int vp[4];
250  device->getViewport(vp);
251  int width = vp[2];
252  int height = vp[3];
253  GLuint colorBufId;
254  glGenRenderbuffers(1, &colorBufId);
255  RenderBufHandle colorBuf(colorBufId);
256 
257  GLuint fboId;
258  glGenFramebuffers(1, &fboId);
259  FBOHandle resolveFb(fboId);
260 
261  glBindRenderbuffer(GL_RENDERBUFFER, colorBuf);
262  glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
263  glBindRenderbuffer(GL_RENDERBUFFER, 0);
264 
265  glBindFramebuffer(GL_FRAMEBUFFER, resolveFb);
266  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
267  GL_RENDERBUFFER, colorBuf);
268 
269  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
270  {
271  cerr << "Unable to create resolve renderbuffer." << endl;
272  glBindFramebuffer(GL_FRAMEBUFFER, 0);
273  }
274 
275  // bind our draw framebuffer and blit the multisampled image
276  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFb);
277  glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFb);
278  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
279  glBlitFramebuffer(0, 0, width, height,
280  0, 0, width, height,
281  GL_COLOR_BUFFER_BIT,
282  GL_NEAREST);
283 #ifndef __EMSCRIPTEN__
284  glDisable(GL_MULTISAMPLE);
285 #endif
286  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
287  glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFb);
288  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
289  glBlitFramebuffer(0, 0, width, height,
290  0, 0, width, height,
291  GL_COLOR_BUFFER_BIT,
292  GL_LINEAR);
293  device->disableBlend();
294  }
295 }
296 
298 {
299  CaptureBuffer cbuf;
300  device->initXfbMode();
301  for (auto& q_elem : queue)
302  {
303  const RenderParams& params = q_elem.first;
304  device->setTransformMatrices(params.model_view.mtx, params.projection.mtx);
305  device->setMaterial(params.mesh_material);
306  device->setNumLights(params.num_pt_lights);
307  for (int i = 0; i < params.num_pt_lights; i++)
308  {
309  device->setPointLight(i, params.lights[i]);
310  }
311  device->setAmbientLight(params.light_amb_scene);
312  device->setStaticColor(params.static_color);
313  device->setClipPlaneUse(params.use_clip_plane);
314  device->setClipPlaneEqn(params.clip_plane_eqn);
315  // aggregate buffers with common parameters
316  std::vector<int> tex_bufs, no_tex_bufs;
317  std::vector<TextBuffer*> text_bufs;
318  GlDrawable* curr_drawable = q_elem.second;
319  for (int i = 0; i < NUM_LAYOUTS; i++)
320  {
321  for (size_t j = 0; j < GlDrawable::NUM_SHAPES; j++)
322  {
323  if (curr_drawable->buffers[i][j])
324  {
326  {
327  tex_bufs.emplace_back(curr_drawable->buffers[i][j].get()->getHandle());
328  }
329  else
330  {
331  no_tex_bufs.emplace_back(curr_drawable->buffers[i][j].get()->getHandle());
332  }
333  }
334  if (curr_drawable->indexed_buffers[i][j])
335  {
337  {
338  tex_bufs.emplace_back(curr_drawable->indexed_buffers[i][j].get()->getHandle());
339  }
340  else
341  {
342  no_tex_bufs.emplace_back(
343  curr_drawable->indexed_buffers[i][j].get()->getHandle());
344  }
345  }
346  }
347  }
348  text_bufs.emplace_back(&curr_drawable->text_buffer);
349 
350  device->attachTexture(GLDevice::SAMPLER_COLOR, color_tex);
351  device->attachTexture(GLDevice::SAMPLER_ALPHA, alpha_tex);
352  for (auto buf : tex_bufs)
353  {
354  device->captureXfbBuffer(*palette, cbuf, buf);
355  }
356  device->detachTexture(GLDevice::SAMPLER_COLOR);
357  device->detachTexture(GLDevice::SAMPLER_ALPHA);
358  for (auto buf : no_tex_bufs)
359  {
360  device->captureXfbBuffer(*palette, cbuf, buf);
361  }
362  if (!params.contains_translucent)
363  {
364  device->enableBlend();
365  device->disableDepthWrite();
366  }
367  device->attachTexture(1, font_tex);
368  device->setNumLights(0);
369  for (TextBuffer* buf : text_bufs)
370  {
371  device->captureXfbBuffer(cbuf, *buf);
372  }
373  }
374  device->exitXfbMode();
375  return cbuf;
376 }
377 
379 {
380  for (int i = 0; i < NUM_LAYOUTS; i++)
381  {
382  for (size_t j = 0; j < GlDrawable::NUM_SHAPES; j++)
383  {
384  if (buf->buffers[i][j])
385  {
386  device->bufferToDevice((array_layout) i, *(buf->buffers[i][j].get()));
387  }
388  if (buf->indexed_buffers[i][j])
389  {
390  device->bufferToDevice((array_layout) i, *(buf->indexed_buffers[i][j].get()));
391  }
392  }
393  }
394  device->bufferToDevice(buf->text_buffer);
395 }
396 
398 {
399  // enable depth testing
400  glDepthFunc(GL_LEQUAL);
401  glEnable(GL_DEPTH_TEST);
402  // enable polygon offset to expose mesh lines
403  glPolygonOffset(1,1);
404  glEnable(GL_POLYGON_OFFSET_FILL);
405  // use "over" blending equation
406  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
407  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
408  // generate a white default texture modulation with default texture will just
409  // pass through input color
410  GLuint default_texture;
411  glGenTextures(1, &default_texture);
412  glBindTexture(GL_TEXTURE_2D, default_texture);
413  int black_color = 0xFFFFFFFF;
414  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
415  &black_color);
416  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
417  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
418  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
419  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
420 
421  passthrough_texture = TextureHandle(default_texture);
422 }
423 
424 void GLDevice::setViewport(GLsizei w, GLsizei h)
425 {
426  vp_width = w;
427  vp_height = h;
428  glViewport(0, 0, w, h);
429 }
430 
431 void GLDevice::getViewport(GLint (&vp)[4])
432 {
433  vp[0] = vp[1] = 0;
434  vp[2] = vp_width;
435  vp[3] = vp_height;
436 }
437 
438 void GLDevice::setTransformMatrices(glm::mat4 model_view, glm::mat4 projection)
439 {
440  model_view_mtx = model_view;
441  proj_mtx = projection;
442 }
443 
445 {
446  for (const auto& entry : t_buf)
447  {
448  glm::vec3 raster = glm::project(
449  glm::vec3(entry.rx, entry.ry, entry.rz),
451  proj_mtx,
452  glm::vec4(0, 0, vp_width, vp_height));
453  capture.text.emplace_back(raster, glm::make_vec4(static_color.data()),
454  entry.text);
455  }
456 }
457 
458 }
glm::mat4 proj_mtx
Definition: renderer.hpp:103
glm::mat4 model_view_mtx
Definition: renderer.hpp:102
GlMatrix projection
Definition: renderer.hpp:41
virtual void setTransformMatrices(glm::mat4 model_view, glm::mat4 projection)
Definition: renderer.cpp:438
Handle< rboCleanup > RenderBufHandle
Definition: types.hpp:115
TextureHandle passthrough_texture
Definition: renderer.hpp:108
void render(const RenderQueue &queued)
Definition: renderer.cpp:109
void setLineWidth(float w)
Definition: renderer.cpp:73
std::array< float, 4 > light_amb_scene
Definition: renderer.hpp:47
vector< FeedbackText > text
Definition: renderer.hpp:93
std::array< Light, LIGHTS_MAX > lights
Definition: renderer.hpp:46
array_layout
Definition: types.hpp:170
CaptureBuffer capture(const RenderQueue &queued)
Definition: renderer.cpp:297
std::array< float, 4 > static_color
Definition: renderer.hpp:105
static bool useLegacyTextureFmts()
Definition: renderer.cpp:27
Handle< texCleanup > TextureHandle
Definition: types.hpp:113
glm::mat4 mtx
Definition: types.hpp:121
void buffer(GlDrawable *buf)
Definition: renderer.cpp:378
void getViewport(GLint(&vp)[4])
Definition: renderer.cpp:431
static const int SAMPLER_ALPHA
Definition: renderer.hpp:121
static const int SAMPLER_COLOR
Definition: renderer.hpp:120
virtual void captureXfbBuffer(PaletteState &pal, CaptureBuffer &capture, int hnd)=0
vector< pair< RenderParams, GlDrawable * > > RenderQueue
Definition: renderer.hpp:58
bool contains_translucent
Definition: renderer.hpp:55
void setLineWidthMS(float w)
Definition: renderer.cpp:82
std::array< float, 4 > static_color
Definition: renderer.hpp:48
void setAntialiasing(bool aa_status)
Definition: renderer.cpp:45
GlMatrix model_view
Definition: renderer.hpp:40
Material mesh_material
Definition: renderer.hpp:44
virtual void init()
Definition: renderer.cpp:397
std::array< double, 4 > clip_plane_eqn
Definition: renderer.hpp:52
void setViewport(GLsizei w, GLsizei h)
Definition: renderer.cpp:424
Handle< fboCleanup > FBOHandle
Definition: types.hpp:114