TAMSVIZ
Visualization and annotation tool for ROS
renderer.cpp
1 // TAMSVIZ
2 // (c) 2020 Philipp Ruppel
3 
4 #include "renderer.h"
5 
6 #include "../core/log.h"
7 #include "mesh.h"
8 #include "renderlist.h"
9 #include "rendertarget.h"
10 #include "shader.h"
11 #include "texture.h"
12 #include "uniformbuffer.h"
13 
14 Renderer::Renderer()
15  : camera_uniform_buffer((size_t)UniformBindingPoint::camera),
16  material_buffer((size_t)UniformBindingPoint::material),
17  light_buffer((size_t)UniformBindingPoint::lights) {
18 
19  {
20  MeshData mesh_data;
21 
22  mesh_data.indices.emplace_back(0);
23  mesh_data.indices.emplace_back(2);
24  mesh_data.indices.emplace_back(1);
25  mesh_data.indices.emplace_back(0);
26  mesh_data.indices.emplace_back(3);
27  mesh_data.indices.emplace_back(2);
28 
29  mesh_data.positions.emplace_back(-1, -1, 0);
30  mesh_data.positions.emplace_back(-1, 1, 0);
31  mesh_data.positions.emplace_back(1, 1, 0);
32  mesh_data.positions.emplace_back(1, -1, 0);
33 
34  mesh_data.texcoords.emplace_back(0, 0);
35  mesh_data.texcoords.emplace_back(0, 1);
36  mesh_data.texcoords.emplace_back(1, 1);
37  mesh_data.texcoords.emplace_back(1, 0);
38 
39  screen_quad = std::make_shared<Mesh>(mesh_data);
40  }
41 
42  default_shader = std::make_shared<Shader>(
43  "package://" ROS_PACKAGE_NAME "/shaders/default.vert",
44  "package://" ROS_PACKAGE_NAME "/shaders/default.frag");
45 
46  blend_shader = std::make_shared<Shader>(
47  "package://" ROS_PACKAGE_NAME "/shaders/quad.vert",
48  "package://" ROS_PACKAGE_NAME "/shaders/blend.frag");
49 }
50 
51 void Renderer::render(const RenderList &render_list,
52  const std::vector<RenderCommand> &commands,
53  bool picking) {
54 
55  int previous_double_sided = -1;
56 
57  for (auto &command : commands) {
58 
59  auto &material = render_list._materials[command.material_index];
60 
61  int double_sided = (command.options.double_sided ? 1 : 0);
62  if (double_sided != previous_double_sided) {
63  if (double_sided) {
64  V_GL(glDisable(GL_CULL_FACE));
65  } else {
66  V_GL(glEnable(GL_CULL_FACE));
67  }
68  previous_double_sided = double_sided;
69  }
70 
71  if (command.material_index < 0 ||
72  command.material_index >= render_list._materials.size()) {
73  throw std::runtime_error("material index out of range");
74  }
75 
76  material_buffer.update(material);
77  material_buffer.bind();
78 
79  V_GL(glActiveTexture(GL_TEXTURE0 + (int)Samplers::color));
80  V_GL(glBindTexture(GL_TEXTURE_2D, material.color_texture));
81 
82  V_GL(glActiveTexture(GL_TEXTURE0 + (int)Samplers::normal));
83  V_GL(glBindTexture(GL_TEXTURE_2D, material.normal_texture));
84 
85  V_GL(glBindVertexArray(command.vertex_array_object));
86 
87  if (command.options.primitive_type == GL_POINTS &&
88  command.options.point_size != 1) {
89  V_GL(glPointSize(std::max(1.0f, command.options.point_size)));
90  }
91 
92  // if (!command.options.colors_linear && !picking) {
93  // V_GL(glDisable(GL_FRAMEBUFFER_SRGB));
94  //}
95 
96  for (size_t instance_index = command.first_instance;
97  instance_index < command.first_instance + command.instance_count;
98  instance_index++) {
99  auto &instance = render_list._instances[instance_index];
100 
101  V_GL(glVertexAttrib4fv((GLuint)VertexAttributes::pose_x,
102  instance.pose_x.data()));
103  V_GL(glVertexAttrib4fv((GLuint)VertexAttributes::pose_y,
104  instance.pose_y.data()));
105  V_GL(glVertexAttrib4fv((GLuint)VertexAttributes::pose_z,
106  instance.pose_z.data()));
107 
108  if (command.indexed) {
109  V_GL(glDrawElements(command.options.primitive_type,
110  command.element_count, GL_UNSIGNED_INT, nullptr));
111  } else {
112  V_GL(glDrawArrays(command.options.primitive_type, 0,
113  command.element_count));
114  }
115  }
116 
117  // if (!command.options.colors_linear && !picking) {
118  // V_GL(glEnable(GL_FRAMEBUFFER_SRGB));
119  //}
120 
121  if (command.options.primitive_type == GL_POINTS &&
122  command.options.point_size != 1) {
123  V_GL(glPointSize(1));
124  }
125  }
126 }
127 
128 void Renderer::prepare(const CameraBlock &camera_block,
129  const RenderList &render_list) {
130 
131  V_GL(glEnable(GL_FRAMEBUFFER_SRGB));
132  V_GL(glEnable(GL_DEPTH_TEST));
133  V_GL(glEnable(GL_CULL_FACE));
134  V_GL(glCullFace(GL_BACK));
135  V_GL(glDisable(GL_BLEND));
136  V_GL(glDepthMask(GL_TRUE));
137 
138  glEnable(GL_MULTISAMPLE);
139 
140  camera_uniform_buffer.update(camera_block);
141  camera_uniform_buffer.bind();
142 
143  Eigen::Matrix4f view_to_world = camera_block.view_matrix.inverse();
144 
145  LightArrayBlock light_array;
146  light_array.light_count = std::min(sizeof(light_array.light_array) /
147  sizeof(light_array.light_array[0]),
148  render_list._lights.size());
149  for (size_t light_index = 0; light_index < light_array.light_count;
150  light_index++) {
151 
152  auto &light = light_array.light_array[light_index];
153 
154  light_array.light_array[light_index] = render_list._lights[light_index];
155 
156  if (light.type & uint32_t(LightType::ViewSpace)) {
157  Eigen::Vector4f p;
158  p.head(3) = light_array.light_array[light_index].position;
159  p.w() = 1.0f;
160  p = view_to_world * p;
161  p /= p.w();
162  light_array.light_array[light_index].position = p.head(3);
163 
164  light_array.light_array[light_index].pose =
165  light_array.light_array[light_index].pose * camera_block.view_matrix;
166  }
167 
168  light.type = (light.type & 0xff);
169  }
170  light_buffer.update(light_array);
171  light_buffer.bind();
172 }
173 
174 Renderer::PickResult Renderer::pick(RenderTarget &render_target,
175  const CameraBlock &camera_block,
176  const RenderList &render_list, int x,
177  int y) {
178 
179  if (x < 0 || y < 0 || x >= render_target._width ||
180  y >= render_target._height) {
181  return PickResult();
182  }
183 
184  V_GL(glDisable(GL_FRAMEBUFFER_SRGB));
185  V_GL(glEnable(GL_DEPTH_TEST));
186  V_GL(glEnable(GL_CULL_FACE));
187  V_GL(glCullFace(GL_BACK));
188  V_GL(glDisable(GL_BLEND));
189 
190  prepare(camera_block, render_list);
191 
192  default_shader->use();
193  render_target._pick_framebuffer.bind();
194 
195  V_GL(glClearColor(0, 0, 0, 0));
196  V_GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
197 
198  render(render_list, render_list._commands, true);
199 
200  PickResult ret;
201 
202  {
203  std::array<uint32_t, 4> id;
204  id[0] = 0;
205  V_GL(glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, id.data()));
206  ret.id = id[0];
207  }
208 
209  {
210  float depth = 0.0f;
211  V_GL(glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth));
212  ret.depth = depth;
213  }
214 
215  LOG_DEBUG("pick " << x << " " << y << " " << ret.id << " " << ret.depth);
216 
217  V_GL(glUseProgram(0));
218  V_GL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
219 
220  return ret;
221 }
222 
223 void Renderer::render(RenderTarget &render_target,
224  const CameraBlock &camera_block,
225  const RenderList &render_list) {
226 
227  prepare(camera_block, render_list);
228 
229  default_shader->use();
230 
231  _transparent.clear();
232  _opaque.clear();
233  for (auto &command : render_list._commands) {
234  if (command.element_count > 0) {
235  auto &material = render_list._materials[command.material_index];
236  if (command.options.transparent || material.transparent ||
237  material.color.w() < 1.0) {
238  _transparent.push_back(command);
239  } else {
240  _opaque.push_back(command);
241  }
242  }
243  }
244 
245  render_target._transparent_framebuffer_head.bind();
246  V_GL(glClearColor(0, 0, 0, 0));
247  V_GL(glClear(GL_COLOR_BUFFER_BIT));
248 
249  if (camera_block.flags & CameraBlock::SampleShadingFlag) {
250  glEnable(GL_SAMPLE_SHADING);
251  glMinSampleShading(1.0);
252  } else {
253  glDisable(GL_SAMPLE_SHADING);
254  }
255 
256  render_target._opaque_framebuffer.bind();
257  V_GL(glDepthMask(GL_TRUE));
258  V_GL(glDisable(GL_BLEND));
259  render(render_list, _opaque);
260 
261  if (_transparent.empty()) {
262 
263  std::lock_guard<std::mutex> lock(render_target._mutex);
264 
265  render_target._front_framebuffer.bind();
266  render_target._front_framebuffer.attach(render_target._front_colorbuffer,
267  GL_COLOR_ATTACHMENT0);
268 
269  V_GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
270  render_target._front_framebuffer.id()));
271  V_GL(glBindFramebuffer(GL_READ_FRAMEBUFFER,
272  render_target._opaque_framebuffer.id()));
273  V_GL(glBlitFramebuffer(0, 0, render_target._width, render_target._height, 0,
274  0, render_target._width, render_target._height,
275  GL_COLOR_BUFFER_BIT, GL_NEAREST));
276 
277  render_target._front_framebuffer.bind();
278  V_GL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
279  GL_RENDERBUFFER, 0));
280 
281  V_GL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
282 
283  V_GL(glFlush());
284  V_GL(glFinish());
285 
286  } else {
287 
288  if (camera_block.flags & CameraBlock::TransparentSampleShadingFlag) {
289  glEnable(GL_SAMPLE_SHADING);
290  glMinSampleShading(1.0);
291  } else {
292  glDisable(GL_SAMPLE_SHADING);
293  }
294 
295  render_target._transparent_framebuffer_tail.bind();
296  V_GL(glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO,
297  GL_ONE_MINUS_SRC_ALPHA));
298  V_GL(glDisable(GL_CULL_FACE));
299  V_GL(glDepthMask(GL_FALSE));
300  V_GL(glEnable(GL_BLEND));
301  V_GL(glClearColor(0, 0, 0, 1));
302  V_GL(glClear(GL_COLOR_BUFFER_BIT));
303  render(render_list, _transparent);
304 
305  render_target._transparent_framebuffer_head.bind();
306  V_GL(glDepthMask(GL_TRUE));
307  V_GL(glDisable(GL_BLEND));
308  render(render_list, _transparent);
309 
310  V_GL(glEnable(GL_CULL_FACE));
311 
312  std::lock_guard<std::mutex> lock(render_target._mutex);
313 
314  render_target._front_framebuffer.attach(render_target._front_colorbuffer,
315  GL_COLOR_ATTACHMENT0);
316  render_target._front_framebuffer.bind();
317 
318  V_GL(glDepthMask(GL_FALSE));
319 
320  glDisable(GL_SAMPLE_SHADING);
321 
322  screen_quad->bind();
323 
324  blend_shader->use();
325 
326  V_GL(glUniform1i(glGetUniformLocation(blend_shader->program(), "opaque"),
327  1));
328  V_GL(glActiveTexture(GL_TEXTURE1));
329  V_GL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,
330  render_target._opaque_texture.id()));
331 
332  V_GL(glUniform1i(
333  glGetUniformLocation(blend_shader->program(), "transparent_head"), 2));
334  V_GL(glActiveTexture(GL_TEXTURE2));
335  V_GL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,
336  render_target._transparent_texture_head.id()));
337 
338  V_GL(glUniform1i(
339  glGetUniformLocation(blend_shader->program(), "transparent_tail_color"),
340  3));
341  V_GL(glActiveTexture(GL_TEXTURE3));
342  V_GL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,
343  render_target._transparent_texture_tail_color.id()));
344 
345  V_GL(glUniform1i(
346  glGetUniformLocation(blend_shader->program(), "transparent_tail_alpha"),
347  4));
348  V_GL(glActiveTexture(GL_TEXTURE4));
349  V_GL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,
350  render_target._transparent_texture_tail_alpha.id()));
351 
352  V_GL(glUniform1i(glGetUniformLocation(blend_shader->program(), "samples"),
353  render_target._samples));
354 
355  V_GL(glDrawElements(GL_TRIANGLES, screen_quad->data().indices.size(),
356  GL_UNSIGNED_INT, nullptr));
357 
358  V_GL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
359 
360  V_GL(glActiveTexture(GL_TEXTURE1));
361  V_GL(glBindTexture(GL_TEXTURE_2D, 0));
362 
363  V_GL(glActiveTexture(GL_TEXTURE2));
364  V_GL(glBindTexture(GL_TEXTURE_2D, 0));
365 
366  V_GL(glActiveTexture(GL_TEXTURE3));
367  V_GL(glBindTexture(GL_TEXTURE_2D, 0));
368 
369  V_GL(glActiveTexture(GL_TEXTURE4));
370  V_GL(glBindTexture(GL_TEXTURE_2D, 0));
371 
372  V_GL(glFlush());
373  V_GL(glFinish());
374  }
375 
376  glDisable(GL_SAMPLE_SHADING);
377 
378  V_GL(glDepthMask(GL_TRUE));
379  V_GL(glDisable(GL_BLEND));
380 
381  V_GL(glBindVertexArray(0));
382  V_GL(glUseProgram(0));
383 }
Definition: mesh.h:11