VTK  9.3.20240418
Material.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
3 #pragma once
4 
5 #include "vtkLogger.h"
6 
7 #include "../Types.h"
8 #include "OSPRayMDL.h"
9 #include "Texture.h"
10 
11 #include <VisRTX.h>
12 #include <cassert>
13 #include <set>
14 #include <sstream>
15 #include <string>
16 
17 namespace RTW
18 {
19 VTK_ABI_NAMESPACE_BEGIN
20  class Material : public Object
21  {
22  friend class Geometry;
23 
24  public:
26  {
27  VisRTX::Context* rtx = VisRTX_GetContext();
28 
29  /*
30  * Basic material
31  */
32  if (this->type == "obj" || this->type == "luminous")
33  {
34  this->material = rtx->CreateBasicMaterial();
35  }
36 
37  /*
38  * MDL material
39  */
40  else
41  {
42  //OSPRay 2.0 name backward compatibility.
43  if (this->type == "alloy")
44  this->type = "Alloy";
45  else if (this->type == "carPaint")
46  this->type = "CarPaint";
47  else if (this->type == "glass")
48  this->type = "Glass";
49  else if (this->type == "metal")
50  this->type = "Metal";
51  else if (this->type == "metallicPaint")
52  this->type = "MetallicPaint";
53  else if (this->type == "obj")
54  this->type = "OBJMaterial";
55  else if (this->type == "principled")
56  this->type = "Principled";
57  else if (this->type == "thinGlass")
58  this->type = "ThinGlass";
59 
60  const std::string materialname = "::ospray::" + this->type;
61  try
62  {
63  this->material = rtx->CreateMDLMaterial(materialname.c_str(), (char*)OSPRay_mdl, (uint32_t) sizeof(OSPRay_mdl), 0, nullptr, VisRTX::CompilationType::INSTANCE);
64  }
65  catch(const std::exception&)
66  {
67  vtkLogF(ERROR, "VisRTX Error: CreateMDLMaterial failed! Falling back to BasicMaterial.");
68  this->material = nullptr;
69  }
70  if (!this->material)
71  {
72  this->material = rtx->CreateBasicMaterial();
73  }
74  }
75  assert(this->material != nullptr);
76  }
77 
79  {
80  this->material->Release();
81  }
82 
83  void Commit() override
84  {
85  assert(this->material != nullptr);
86 
87  /*
88  * OBJMaterial (Basic material)
89  */
90  if (this->type == "obj" && this->material->GetType() == VisRTX::MaterialType::BASIC)
91  {
92  VisRTX::BasicMaterial* basicMaterial = dynamic_cast<VisRTX::BasicMaterial*>(this->material);
93  assert(basicMaterial);
94  if (!basicMaterial)
95  {
96  return;
97  }
98 
99  //this->PrintAllParameters();
100 
101  basicMaterial->SetDiffuse(this->GetVec3f({ "kd", "Kd" }, VisRTX::Vec3f(0.8f, 0.8f, 0.8f)));
102  basicMaterial->SetSpecular(this->GetVec3f({ "ks", "Ks" }, VisRTX::Vec3f(0.0f, 0.0f, 0.0f)));
103  basicMaterial->SetShininess(this->GetFloat({ "ns", "Ns" }, 10.0f));
104  basicMaterial->SetOpacity(this->GetFloat({ "d", "alpha" }, 1.0f));
105  basicMaterial->SetTransparencyFilter(this->GetVec3f({ "tf", "Tf" }, VisRTX::Vec3f(0.0f, 0.0f, 0.0f)));
106 
107  Texture* diffuseTex = this->GetObject<Texture>({ "map_Kd", "map_kd" });
108  if (diffuseTex)
109  basicMaterial->SetDiffuseTexture(diffuseTex->texture);
110 
111  Texture* specularTex = this->GetObject<Texture>({ "map_Ks", "map_ks" });
112  if (specularTex)
113  basicMaterial->SetSpecularTexture(specularTex->texture);
114 
115  Texture* shininessTex = this->GetObject<Texture>({ "map_Ns", "map_ns" });
116  if (shininessTex)
117  basicMaterial->SetShininessTexture(shininessTex->texture);
118 
119  Texture* opacityTex = this->GetObject<Texture>({ "map_d", "map_alpha" });
120  if (opacityTex)
121  basicMaterial->SetOpacityTexture(opacityTex->texture);
122 
123  Texture* bumpTex = this->GetObject<Texture>({ "map_Bump", "map_bump" });
124  if (bumpTex)
125  basicMaterial->SetBumpMapTexture(bumpTex->texture);
126  }
127 
128  /*
129  * Luminous (Basic material)
130  */
131  else if (this->type == "luminous" && this->material->GetType() == VisRTX::MaterialType::BASIC)
132  {
133  VisRTX::BasicMaterial* basicMaterial = dynamic_cast<VisRTX::BasicMaterial*>(this->material);
134  assert(basicMaterial);
135  if (!basicMaterial)
136  {
137  return;
138  }
139  basicMaterial->SetEmissive(this->GetVec3f({ "color" }, VisRTX::Vec3f(0.0f, 0.0f, 0.0f)));
140  basicMaterial->SetLuminosity(this->GetFloat({ "intensity" }, 0.0f));
141  }
142 
143  /*
144  * Others (MDL material)
145  */
146  else if (this->material->GetType() == VisRTX::MaterialType::MDL)
147  {
148  VisRTX::MDLMaterial* mdlMaterial = dynamic_cast<VisRTX::MDLMaterial*>(this->material);
149  assert(mdlMaterial);
150  if (!mdlMaterial)
151  {
152  return;
153  }
154 
155  std::set<std::string> ospparams_current = this->GetAllParameters();
156 
157 #define PRINT_MATERIAL_PARAMETERS 0
158 #if PRINT_MATERIAL_PARAMETERS
159  static std::set<std::string> mdltypes_printed;
160  if (mdltypes_printed.find(this->type) == mdltypes_printed.end())
161  {
162  std::vector<std::string> availableParams;
163  for (uint32_t i = 0; i < mdlMaterial->GetParameterCount(); ++i)
164  {
165  availableParams.push_back(mdlMaterial->GetParameterName(i));
166  }
167 
168  for (const auto &parameter : availableParams)
169  {
170  std::string parameterType;
171  switch (mdlMaterial->GetParameterType(parameter.c_str()))
172  {
174  parameterType = "none"; break;
175  case VisRTX::ParameterType::COLOR:
176  parameterType = "color"; break;
177  case VisRTX::ParameterType::DOUBLE:
178  parameterType = "double"; break;
179  case VisRTX::ParameterType::FLOAT:
180  parameterType = "float"; break;
181  case VisRTX::ParameterType::INT:
182  parameterType = "int"; break;
183  case VisRTX::ParameterType::BOOL:
184  parameterType = "bool"; break;
185  case VisRTX::ParameterType::TEXTURE:
186  parameterType = "texture"; break;
187  }
188  std::stringstream logStrBuf;
189  logStrBuf << "(mdl) " << this->type << ": " << parameterType << " " << parameter;
190  vtkLogF(INFO, "%s", logStrBuf.str().c_str());
191  }
192  mdltypes_printed.insert(this->type);
193  }
194 
195 
196  static std::set<std::string> ospparams_printed;
197 
198  for (auto param : ospparams_current)
199  {
200  std::string complete = this->type + ": " + param;
201  if (ospparams_printed.find(complete) == ospparams_printed.end())
202  {
203  vtkLogF(INFO, "(osp) %s", complete.c_str());
204  ospparams_printed.insert(complete);
205  }
206  }
207 #endif //PRINT_MATERIAL_PARAMETERS
208 
209 #define WARN_NOT_IMPLEMENTED() vtkLogF(WARNING, "Warning: type \"%s\" not implemented (Material: %s, %s)", paramType.c_str(), this->type.c_str(), paramName.c_str());
210 
211  for (const std::string &param : ospparams_current)
212  {
213  std::string paramType, paramName;
214  {
215  std::istringstream iss(param);
216  iss >> paramType;
217  iss >> paramName;
218  }
219 
220  //getters for osp materials require a vector of names
221  std::vector<std::string> names;
222  names.push_back(paramName);
223 
224  //rename parameters if needed (osp name -> mdl name)
225 
226  static const std::map<std::pair<std::string, std::string>, std::string> renameMap
227  {
228  { { "obj", "map_kd" }, "map_Kd"},
229  { { "obj", "map_bump" }, "map_Bump"},
230  { { "Glass", "etaInside" }, "eta"},
231  { { "obj", "alpha" }, "d"},
232  { { "ThinGlass", "transmission" }, "attenuationColor"}
233  };
234 
235  // explicit renames first
236  auto rename_it = renameMap.find(std::make_pair(this->type, paramName));
237  if (rename_it != renameMap.end())
238  {
239  paramName = rename_it->second;
240  }
241  else
242  {
243  //replace "...Map" with "map_..."
244  const std::string ospSuffix = "Map";
245  const std::string mdlPrefix = "map_";
246  if (paramName.length() >= ospSuffix.length()
247  && paramName.compare(paramName.length() - ospSuffix.length(),
248  ospSuffix.length(), ospSuffix) == 0)
249  {
250  std::string name =
251  paramName.substr(0, paramName.length() - ospSuffix.length());
252  paramName = mdlPrefix + name;
253  }
254  }
255 
256  //exceptions first, e.g. spectra; then handle parameters by type
257  if (paramName == std::string("ior") && paramType == std::string("object"))
258  {
259  Data* iorData = this->GetObject<Data>(names);
260  assert(iorData->GetElementDataType() == RTW_VEC3F);
261 
262  if (iorData->GetElementDataType() != RTW_VEC3F)
263  {
264  vtkLogF(ERROR, "Error: unexpected data type in ior object");
265  return;
266  }
267 
268  const unsigned n_input = iorData->GetNumElements();
269 
270  const VisRTX::Vec3f *input = (const VisRTX::Vec3f*)iorData->GetData();
271 
272  static const unsigned spectrum_size = 8;
273  static const float wavelength_begin = 430.f;
274  static const float wavelength_spacing = 35.f;
275 
276  float eta[spectrum_size], k[spectrum_size];
277 
278  //subsample ior array
279  unsigned iinput = 0u, iprev = 0u;
280  for (unsigned iwl = 0u; iwl < spectrum_size; iwl++)
281  {
282  const float currentwl = wavelength_begin + (float)iwl * wavelength_spacing;
283  for (; iinput < n_input - 1 && input[iinput].x < currentwl; ++iinput)
284  {
285  iprev = iinput;
286  }
287  if (input[iprev].x == input[iinput].x)
288  {
289  eta[iwl] = input[iprev].y;
290  k[iwl] = input[iprev].z;
291  }
292  else
293  {
294  const float t = (currentwl - input[iprev].x) / (input[iinput].x - input[iprev].x);
295  eta[iwl] = (1.f - t) * input[iprev].y + t * input[iinput].y;
296  k[iwl] = (1.f - t) * input[iprev].z + t * input[iinput].z;
297  }
298  }
299 
300  //response functions
301  static const float response_sRGB_r[spectrum_size] =
302  {
303  0.0598548,
304  -0.0234574,
305  -0.220138,
306  -0.238902,
307  0.316327,
308  0.738315,
309  0.323302,
310  0.0446981
311  };
312 
313  static const float response_sRGB_g[spectrum_size] =
314  {
315  -0.0567346,
316  -0.0160361,
317  0.223861,
318  0.531185,
319  0.337221,
320  0.0149718,
321  -0.0296053,
322  -0.00486239
323  };
324 
325  static const float response_sRGB_b[spectrum_size] =
326  {
327  0.420693,
328  0.616597,
329  0.0796766,
330  -0.0496266,
331  -0.0473149,
332  -0.0167536,
333  -0.00295686,
334  -0.000314818
335  };
336 
337  //apply response functions to convert to RGB
338  VisRTX::Vec3f eta3(0.f, 0.f, 0.f), k3(0.f, 0.f, 0.f);
339  for (unsigned iwl = 0u; iwl < spectrum_size; ++iwl)
340  {
341  VisRTX::Vec3f response(response_sRGB_r[iwl], response_sRGB_g[iwl], response_sRGB_b[iwl]);
342 
343  eta3.x += response.x * eta[iwl];
344  eta3.y += response.y * eta[iwl];
345  eta3.z += response.z * eta[iwl];
346  k3.x += response.x * k[iwl];
347  k3.y += response.y * k[iwl];
348  k3.z += response.z * k[iwl];
349  }
350 
351  mdlMaterial->SetParameterColor("eta", eta3);
352  mdlMaterial->SetParameterColor("k", k3);
353  }
354  else if (paramType == std::string("string"))
355  {
356  std::string ospParam = this->GetString(names);
358  }
359  else if (paramType == std::string("object"))
360  {
361  Texture* ospParam = this->GetObject<Texture>(names);
362  if (ospParam)
363  {
364  mdlMaterial->SetParameterTexture(paramName.c_str(), ospParam->texture);
365  }
366  else
367  {
368  vtkLogF(WARNING, "Object \"%s\" of material type \"%s\" is not a texture.", paramName.c_str(), this->type.c_str());
369  }
370  }
371  else if (paramType == std::string("int1"))
372  {
373  int ospParam = this->GetInt(names);
374 
375  if (mdlMaterial->GetParameterType(paramName.c_str()) == VisRTX::ParameterType::BOOL)
376  {
377  mdlMaterial->SetParameterBool(paramName.c_str(), ospParam > 0);
378  }
379  else
380  {
381  mdlMaterial->SetParameterInt(paramName.c_str(), ospParam);
382  }
383  }
384  else if (paramType == std::string("float1"))
385  {
386  float ospParam = this->GetFloat(names);
387 
388  if (mdlMaterial->GetParameterType(paramName.c_str()) == VisRTX::ParameterType::BOOL)
389  {
390  mdlMaterial->SetParameterBool(paramName.c_str(), ospParam > 0.0f);
391  }
392  else
393  {
394  mdlMaterial->SetParameterFloat(paramName.c_str(), ospParam);
395  }
396  }
397  else if (paramType == std::string("float2"))
398  {
399  VisRTX::Vec2f ospParam = this->GetVec2f(names);
401  }
402  else if (paramType == std::string("int3"))
403  {
404  VisRTX::Vec3i ospParam = this->GetVec3i(names);
406  }
407  else if (paramType == std::string("float3"))
408  {
409  VisRTX::Vec3f ospParam = this->GetVec3f(names);
410  mdlMaterial->SetParameterColor(paramName.c_str(), ospParam);
411  }
412  else if (paramType == std::string("float4"))
413  {
414  VisRTX::Vec4f ospParam = this->GetVec4f(names);
416  }
417  else
418  {
420  }
421  }
422 
423  mdlMaterial->Compile();
424  }
425  }
426 
427  private:
429  VisRTX::Material* material = nullptr;
430  };
431 VTK_ABI_NAMESPACE_END
432 }
#define WARN_NOT_IMPLEMENTED()
unsigned char OSPRay_mdl[]
Definition: OSPRayMDL.h:11
@ RTW_VEC3F
Definition: Types.h:186
@ RTW_MATERIAL
Definition: Types.h:148
Definition: Data.h:13
size_t GetNumElements() const
Definition: Data.h:119
void * GetData() const
Definition: Data.h:149
RTWDataType GetElementDataType() const
Definition: Data.h:139
Material(const std::string &type)
Definition: Material.h:25
void Commit() override
Definition: Material.h:83
int32_t GetInt(const std::vector< std::string > &ids, int32_t defaultValue=0, bool *found=nullptr) const
Definition: Object.h:119
const std::string GetString(const std::vector< std::string > &ids, const std::string &defaultValue="", bool *found=nullptr) const
Definition: Object.h:64
VisRTX::Vec2f GetVec2f(const std::vector< std::string > &ids, const VisRTX::Vec2f &defaultValue=VisRTX::Vec2f(), bool *found=nullptr) const
Definition: Object.h:170
std::set< std::string > GetAllParameters() const
Definition: Object.h:277
VisRTX::Vec3i GetVec3i(const std::vector< std::string > &ids, const VisRTX::Vec3i &defaultValue=VisRTX::Vec3i(), bool *found=nullptr) const
Definition: Object.h:187
float GetFloat(const std::vector< std::string > &ids, float defaultValue=0.0f, bool *found=nullptr) const
Definition: Object.h:136
VisRTX::Vec4f GetVec4f(const std::vector< std::string > &ids, const VisRTX::Vec4f &defaultValue=VisRTX::Vec4f(), bool *found=nullptr) const
Definition: Object.h:221
VisRTX::Vec3f GetVec3f(const std::vector< std::string > &ids, const VisRTX::Vec3f &defaultValue=VisRTX::Vec3f(), bool *found=nullptr) const
Definition: Object.h:204
Definition: Backend.h:8
@ Material
Definition: vtkX3D.h:38
@ type
Definition: vtkX3D.h:516
@ parameter
Definition: vtkX3D.h:443
@ name
Definition: vtkX3D.h:219
@ string
Definition: vtkX3D.h:490
#define vtkLogF(verbosity_name,...)
Add to log given the verbosity level.
Definition: vtkLogger.h:499