ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
FilamentView.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 // 4068: Filament has some clang-specific vectorizing pragma's that MSVC flags
11 // 4146: Filament's utils/algorithm.h utils::details::ctz() tries to negate
12 // an unsigned int.
13 // 4293: Filament's utils/algorithm.h utils::details::clz() does strange
14 // things with MSVC. Somehow sizeof(unsigned int) > 4, but its size is
15 // 32 so that x >> 32 gives a warning. (Or maybe the compiler can't
16 // determine the if statement does not run.)
17 #ifdef _MSC_VER
18 #pragma warning(push)
19 #pragma warning(disable : 4068 4146 4293)
20 #endif // _MSC_VER
21 
22 #include <filament/Camera.h>
23 #include <filament/ColorGrading.h>
24 #include <filament/Engine.h>
25 #include <filament/RenderableManager.h>
26 #include <filament/Scene.h>
27 #include <filament/View.h>
28 #include <filament/Viewport.h>
29 
30 #ifdef _MSC_VER
31 #pragma warning(pop)
32 #endif // _MSC_VER
33 
39 
40 namespace cloudViewer {
41 namespace visualization {
42 namespace rendering {
43 
44 namespace {
45 
46 #define AUTO_CLEAR_COLOR 0
47 
48 #if AUTO_CLEAR_COLOR
49 const filament::LinearColorA kDepthClearColor = {0.f, 0.f, 0.f, 0.f};
50 const filament::LinearColorA kNormalsClearColor = {0.5f, 0.5f, 0.5f, 1.f};
51 #endif
52 
53 } // namespace
54 
55 FilamentView::FilamentView(filament::Engine& engine,
56  FilamentResourceManager& resource_mgr)
57  : engine_(engine), resource_mgr_(resource_mgr) {
58  view_ = engine_.createView();
59  view_->setSampleCount(4);
60  SetAntiAliasing(true, false);
61  SetPostProcessing(true);
62  SetAmbientOcclusion(true, false);
63  view_->setVisibleLayers(kAllLayersMask, kMainLayer);
67  SetColorGrading(cp);
68 
69  camera_ = std::make_unique<FilamentCamera>(engine_);
70  view_->setCamera(camera_->GetNativeCamera());
71 
72  camera_->SetProjection(90, 4.f / 3.f, 0.01, 1000,
74 
75  discard_buffers_ = View::TargetBuffers::All;
76 }
77 
78 FilamentView::FilamentView(filament::Engine& engine,
79  FilamentScene& scene,
80  FilamentResourceManager& resource_mgr)
81  : FilamentView(engine, resource_mgr) {
82  scene_ = &scene;
83 
84  view_->setScene(scene_->GetNativeScene());
85 }
86 
88  view_->setCamera(nullptr);
89  view_->setScene(nullptr);
90 
91  camera_.reset();
92  engine_.destroy(view_);
93  engine_.destroy(color_grading_);
94 }
95 
96 View::Mode FilamentView::GetMode() const { return mode_; }
97 
99 // As color switching disabled, we don't need this code.
100 // Yet disabling this looks like a bad idea, so I leave code commented
101 #if AUTO_CLEAR_COLOR
102  switch (mode) {
103  case Mode::Color:
104  view_->setVisibleLayers(kAllLayersMask, kMainLayer);
105  view_->setClearColor(
106  {clearColor_.x(), clearColor_.y(), clearColor_.z(), 1.f});
107  break;
108  case Mode::Depth:
109  view_->setVisibleLayers(kAllLayersMask, kMainLayer);
110  view_->setClearColor(kDepthClearColor);
111  break;
112  case Mode::Normals:
113  view_->setVisibleLayers(kAllLayersMask, kMainLayer);
114  view_->setClearColor(kNormalsClearColor);
115  break;
116  case Mode::ColorMapX:
117  case Mode::ColorMapY:
118  case Mode::ColorMapZ:
119  view_->setVisibleLayers(kAllLayersMask, kMainLayer);
120  view_->setClearColor(kDepthClearColor);
121  break;
122  }
123 #endif
124 
125  mode_ = mode;
126 }
127 
129  discard_buffers_ = buffers;
130  view_->setRenderTarget(nullptr);
131 }
132 
133 void FilamentView::SetWireframe(bool enable) {
134  // Enable bloom for wireframe mode
135  if (enable) {
136  SetBloom(true, 0.5f, 8);
137  } else {
138  SetBloom(false);
139  }
140 }
141 
142 void FilamentView::SetSampleCount(int n) { view_->setSampleCount(n); }
143 
144 int FilamentView::GetSampleCount() const { return view_->getSampleCount(); }
145 
146 void FilamentView::SetViewport(std::int32_t x,
147  std::int32_t y,
148  std::uint32_t w,
149  std::uint32_t h) {
150  view_->setViewport({x, y, w, h});
151 }
152 
153 std::array<int, 4> FilamentView::GetViewport() const {
154  auto vp = view_->getViewport();
155  return {vp.left, vp.bottom, int(vp.width), int(vp.height)};
156 }
157 
159  view_->setPostProcessingEnabled(enabled);
160 }
161 
163  bool ssct_enabled /* = false */) {
164  filament::View::AmbientOcclusionOptions options;
165  options.enabled = enabled;
166  options.ssct.enabled = ssct_enabled;
167  view_->setAmbientOcclusionOptions(options);
168 }
169 
170 void FilamentView::SetBloom(bool enabled,
171  float strength /* = 0.5f */,
172  int spread /* = 6 */) {
173  filament::View::BloomOptions bloom_options;
174  bloom_options.enabled = enabled;
175  bloom_options.strength = strength;
176  bloom_options.threshold = false;
177  bloom_options.levels = spread;
178  view_->setBloomOptions(bloom_options);
179 }
180 
181 void FilamentView::SetAntiAliasing(bool enabled, bool temporal /* = false */) {
182  if (enabled) {
183  filament::View::TemporalAntiAliasingOptions options;
184  options.enabled = temporal;
185  view_->setAntiAliasing(filament::View::AntiAliasing::FXAA);
186  view_->setTemporalAntiAliasingOptions(options);
187  } else {
188  view_->setAntiAliasing(filament::View::AntiAliasing::NONE);
189  }
190 }
191 
193  if (enabled) {
194  filament::View::ShadowType stype =
195  (type == ShadowType::kPCF) ? filament::View::ShadowType::PCF
196  : filament::View::ShadowType::VSM;
197  view_->setShadowType(stype);
198  view_->setShadowingEnabled(true);
199  } else {
200  view_->setShadowingEnabled(false);
201  }
202 }
203 
204 static inline filament::math::float3 eigen_to_float3(const Eigen::Vector3f& v) {
205  return filament::math::float3(v.x(), v.y(), v.z());
206 }
207 
208 static inline filament::math::float4 eigen_to_float4(const Eigen::Vector4f& v) {
209  return filament::math::float4(v.x(), v.y(), v.z(), v.w());
210 }
211 
213  filament::ColorGrading::QualityLevel q =
214  filament::ColorGrading::QualityLevel::LOW;
215  switch (color_grading.GetQuality()) {
217  q = filament::ColorGrading::QualityLevel::MEDIUM;
218  break;
220  q = filament::ColorGrading::QualityLevel::HIGH;
221  break;
223  q = filament::ColorGrading::QualityLevel::ULTRA;
224  break;
225  default:
226  break;
227  }
228 
229  filament::ColorGrading::ToneMapping tm =
230  filament::ColorGrading::ToneMapping::LINEAR;
231  switch (color_grading.GetToneMapping()) {
233  tm = filament::ColorGrading::ToneMapping::ACES_LEGACY;
234  break;
236  tm = filament::ColorGrading::ToneMapping::ACES;
237  break;
239  tm = filament::ColorGrading::ToneMapping::FILMIC;
240  break;
242  tm = filament::ColorGrading::ToneMapping::UCHIMURA;
243  break;
245  tm = filament::ColorGrading::ToneMapping::REINHARD;
246  break;
248  tm = filament::ColorGrading::ToneMapping::DISPLAY_RANGE;
249  break;
250  default:
251  break;
252  }
253 
254  if (color_grading_) {
255  engine_.destroy(color_grading_);
256  }
257  color_grading_ =
258  filament::ColorGrading::Builder()
259  .quality(q)
260  .toneMapping(tm)
261  .whiteBalance(color_grading.GetTemperature(),
262  color_grading.GetTint())
263  .channelMixer(
264  eigen_to_float3(color_grading.GetMixerRed()),
265  eigen_to_float3(color_grading.GetMixerGreen()),
266  eigen_to_float3(color_grading.GetMixerBlue()))
267  .shadowsMidtonesHighlights(
268  eigen_to_float4(color_grading.GetShadows()),
269  eigen_to_float4(color_grading.GetMidtones()),
270  eigen_to_float4(color_grading.GetHighlights()),
271  eigen_to_float4(color_grading.GetRanges()))
272  .slopeOffsetPower(
273  eigen_to_float3(color_grading.GetSlope()),
274  eigen_to_float3(color_grading.GetOffset()),
275  eigen_to_float3(color_grading.GetPower()))
276  .contrast(color_grading.GetContrast())
277  .vibrance(color_grading.GetVibrance())
278  .saturation(color_grading.GetSaturation())
279  .curves(eigen_to_float3(color_grading.GetShadowGamma()),
280  eigen_to_float3(color_grading.GetMidpoint()),
281  eigen_to_float3(color_grading.GetHighlightScale()))
282  .build(engine_);
283  view_->setColorGrading(color_grading_);
284 }
285 
287  view_->setSampleCount(1);
288  SetPostProcessing(false);
289  SetAmbientOcclusion(false, false);
291  configured_for_picking_ = true;
292 }
293 
295  caching_enabled_ = enable;
296 
297  if (caching_enabled_) {
298  if (render_target_) {
299  resource_mgr_.Destroy(render_target_);
300  resource_mgr_.Destroy(color_buffer_);
301  resource_mgr_.Destroy(depth_buffer_);
302  render_target_ = RenderTargetHandle();
303  color_buffer_ = TextureHandle();
304  depth_buffer_ = TextureHandle();
305  }
306 
307  // Create RenderTarget
308  auto vp = view_->getViewport();
309  color_buffer_ =
310  resource_mgr_.CreateColorAttachmentTexture(vp.width, vp.height);
311  depth_buffer_ =
312  resource_mgr_.CreateDepthAttachmentTexture(vp.width, vp.height);
313  render_target_ =
314  resource_mgr_.CreateRenderTarget(color_buffer_, depth_buffer_);
315  SetRenderTarget(render_target_);
316  }
317 
318  if (!caching_enabled_) {
319  view_->setRenderTarget(nullptr);
320  }
321 }
322 
323 bool FilamentView::IsCached() const { return caching_enabled_; }
324 
325 TextureHandle FilamentView::GetColorBuffer() { return color_buffer_; }
326 
327 void FilamentView::SetRenderTarget(const RenderTargetHandle render_target) {
328  if (!render_target) {
329  view_->setRenderTarget(nullptr);
330  } else {
331  auto rt_weak = resource_mgr_.GetRenderTarget(render_target);
332  auto rt = rt_weak.lock();
333  if (!rt) {
335  "Invalid render target given to SetRenderTarget");
336  view_->setRenderTarget(nullptr);
337  } else {
338  view_->setRenderTarget(rt.get());
339  }
340  }
341 }
342 
343 Camera* FilamentView::GetCamera() const { return camera_.get(); }
344 
346  SetMode(other.mode_);
347  view_->setRenderTarget(nullptr);
348  auto vp = other.view_->getViewport();
349  SetViewport(0, 0, vp.width, vp.height);
350  camera_->CopyFrom(other.camera_.get());
351  if (other.configured_for_picking_) {
353  }
354 }
355 
357  scene_ = &scene;
358  view_->setScene(scene_->GetNativeScene());
359 }
360 
362  // auto& renderable_mgr = engine_.getRenderableManager();
363 
364  MaterialInstanceHandle material_handle;
365  std::shared_ptr<filament::MaterialInstance> selected_material;
366  if (mode_ == Mode::Depth) {
367  material_handle = FilamentResourceManager::kDepthMaterial;
368  // FIXME: Refresh parameters only then something ACTUALLY changed
369  selected_material =
370  resource_mgr_.GetMaterialInstance(material_handle).lock();
371  if (selected_material) {
372  const auto f = camera_->GetNativeCamera()->getCullingFar();
373  const auto n = camera_->GetNativeCamera()->getNear();
374 
375  FilamentMaterialModifier(selected_material, material_handle)
376  .SetParameter("cameraNear", n)
377  .SetParameter("cameraFar", f)
378  .Finish();
379  }
380  } else if (mode_ == Mode::Normals) {
382  selected_material =
383  resource_mgr_.GetMaterialInstance(material_handle).lock();
384  } else if (mode_ >= Mode::ColorMapX) {
386 
387  int coordinate_index = 0;
388  switch (mode_) {
389  case Mode::ColorMapX:
390  coordinate_index = 0;
391  break;
392  case Mode::ColorMapY:
393  coordinate_index = 1;
394  break;
395  case Mode::ColorMapZ:
396  coordinate_index = 2;
397  break;
398 
399  default:
400  break;
401  }
402 
403  selected_material =
404  resource_mgr_.GetMaterialInstance(material_handle).lock();
405  if (selected_material) {
406  FilamentMaterialModifier(selected_material, material_handle)
407  .SetParameter("coordinateIndex", coordinate_index)
408  .Finish();
409  }
410  }
411 
412  // TODO: is any of this necessary?
413  // if (scene_) {
414  // for (const auto& pair : scene_->entities_) {
415  // const auto& entity = pair.second;
416  // if (entity.info.type == EntityType::Geometry) {
417  // std::shared_ptr<filament::MaterialInstance> mat_inst;
418  // if (selected_material) {
419  // mat_inst = selected_material;
420 
421  // if (mode_ >= Mode::ColorMapX) {
422  // auto bbox = scene_->GetEntityBoundingBox(pair.first);
423  // Eigen::Vector3f bbox_min =
424  // bbox.GetMinBound().cast<float>();
425  // Eigen::Vector3f bbox_max =
426  // bbox.GetMaxBound().cast<float>();
427 
428  // FilamentMaterialModifier(selected_material,
429  // material_handle)
430  // .SetParameter("bboxMin", bbox_min)
431  // .SetParameter("bboxMax", bbox_max)
432  // .Finish();
433  // }
434  // } else {
435  // mat_inst =
436  // resource_mgr_.GetMaterialInstance(entity.material)
437  // .lock();
438  // }
439 
440  // filament::RenderableManager::Instance inst =
441  // renderable_mgr.getInstance(entity.info.self);
442  // renderable_mgr.setMaterialInstanceAt(inst, 0,
443  // mat_inst.get());
444  // }
445  // }
446  // }
447 }
448 
450 
451 } // namespace rendering
452 } // namespace visualization
453 } // namespace cloudViewer
char type
MaterialModifier & SetParameter(const char *parameter, int value) override
std::weak_ptr< filament::RenderTarget > GetRenderTarget(const RenderTargetHandle &id)
RenderTargetHandle CreateRenderTarget(TextureHandle color, TextureHandle depth)
std::weak_ptr< filament::MaterialInstance > GetMaterialInstance(const MaterialInstanceHandle &id)
void SetAmbientOcclusion(bool enabled, bool ssct_enabled=false) override
void SetColorGrading(const ColorGradingParams &color_grading) override
void SetViewport(std::int32_t x, std::int32_t y, std::uint32_t w, std::uint32_t h) override
FilamentView(filament::Engine &engine, FilamentResourceManager &resource_mgr)
void CopySettingsFrom(const FilamentView &other)
void SetAntiAliasing(bool enabled, bool temporal=false) override
std::array< int, 4 > GetViewport() const override
static constexpr std::uint8_t kAllLayersMask
Definition: FilamentView.h:35
void SetShadowing(bool enabled, ShadowType type) override
void SetDiscardBuffers(const TargetBuffers &buffers) override
void SetBloom(bool enabled, float strength=0.5f, int spread=6) override
virtual MaterialModifier & SetParameter(const char *parameter, int value)=0
#define LogWarning(...)
Definition: Logging.h:72
REHandle< EntityType::Texture > TextureHandle
REHandle< EntityType::RenderTarget > RenderTargetHandle
static filament::math::float4 eigen_to_float4(const Eigen::Vector4f &v)
static filament::math::float3 eigen_to_float3(const Eigen::Vector3f &v)
Generic file read and write utility for python interface.