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