VTK  9.4.20241218
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
17namespace RTW
18{
19VTK_ABI_NAMESPACE_BEGIN
20 class Material : public Object
21 {
22 friend class Geometry;
23
24 public:
25 Material(const std::string& type) : Object(RTW_MATERIAL), type(type)
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 {
173 case VisRTX::ParameterType::NONE:
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:
428 std::string type;
429 VisRTX::Material* material = nullptr;
430 };
431VTK_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
size_t GetNumElements() const
Definition Data.h:119
RTWDataType GetElementDataType() const
Definition Data.h:139
void * GetData() const
Definition Data.h:149
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
#define vtkLogF(verbosity_name,...)
Add to log given the verbosity level.
Definition vtkLogger.h:499