BabylonExporter.GLTFExporter.Material.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. using BabylonExport.Entities;
  2. using GLTFExport.Entities;
  3. using System;
  4. using System.Drawing;
  5. using System.IO;
  6. namespace Max2Babylon
  7. {
  8. partial class BabylonExporter
  9. {
  10. private void ExportMaterial(BabylonMaterial babylonMaterial, GLTF gltf)
  11. {
  12. var name = babylonMaterial.name;
  13. var id = babylonMaterial.id;
  14. RaiseMessage("GLTFExporter.Material | Export material named: " + name, 1);
  15. if (babylonMaterial.GetType() == typeof(BabylonStandardMaterial))
  16. {
  17. var babylonStandardMaterial = babylonMaterial as BabylonStandardMaterial;
  18. // --- prints ---
  19. RaiseMessage("GLTFExporter.Material | babylonMaterial data", 2);
  20. RaiseMessage("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
  21. RaiseMessage("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3);
  22. RaiseMessage("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
  23. RaiseMessage("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);
  24. // Ambient
  25. for (int i = 0; i < babylonStandardMaterial.ambient.Length; i++)
  26. {
  27. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.ambient[" + i + "]=" + babylonStandardMaterial.ambient[i], 3);
  28. }
  29. // Diffuse
  30. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.diffuse.Length=" + babylonStandardMaterial.diffuse.Length, 3);
  31. for (int i = 0; i < babylonStandardMaterial.diffuse.Length; i++)
  32. {
  33. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.diffuse[" + i + "]=" + babylonStandardMaterial.diffuse[i], 3);
  34. }
  35. if (babylonStandardMaterial.diffuseTexture == null)
  36. {
  37. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture=null", 3);
  38. }
  39. // Normal / bump
  40. if (babylonStandardMaterial.bumpTexture == null)
  41. {
  42. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.bumpTexture=null", 3);
  43. }
  44. // Specular
  45. for (int i = 0; i < babylonStandardMaterial.specular.Length; i++)
  46. {
  47. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.specular[" + i + "]=" + babylonStandardMaterial.specular[i], 3);
  48. }
  49. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.specularPower=" + babylonStandardMaterial.specularPower, 3);
  50. // Occlusion
  51. if (babylonStandardMaterial.ambientTexture == null)
  52. {
  53. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.ambientTexture=null", 3);
  54. }
  55. // Emissive
  56. for (int i = 0; i < babylonStandardMaterial.emissive.Length; i++)
  57. {
  58. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.emissive[" + i + "]=" + babylonStandardMaterial.emissive[i], 3);
  59. }
  60. if (babylonStandardMaterial.emissiveTexture == null)
  61. {
  62. RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture=null", 3);
  63. }
  64. // --------------------------------
  65. // --------- gltfMaterial ---------
  66. // --------------------------------
  67. RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
  68. var gltfMaterial = new GLTFMaterial
  69. {
  70. name = name
  71. };
  72. gltfMaterial.id = babylonMaterial.id;
  73. gltfMaterial.index = gltf.MaterialsList.Count;
  74. gltf.MaterialsList.Add(gltfMaterial);
  75. // Alpha
  76. string alphaMode;
  77. float? alphaCutoff;
  78. getAlphaMode(babylonStandardMaterial, out alphaMode, out alphaCutoff);
  79. gltfMaterial.alphaMode = alphaMode;
  80. gltfMaterial.alphaCutoff = alphaCutoff;
  81. // DoubleSided
  82. gltfMaterial.doubleSided = !babylonMaterial.backFaceCulling;
  83. // Normal
  84. gltfMaterial.normalTexture = ExportTexture(babylonStandardMaterial.bumpTexture, gltf);
  85. // Occulison
  86. gltfMaterial.occlusionTexture = ExportTexture(babylonStandardMaterial.ambientTexture, gltf);
  87. // Emissive
  88. gltfMaterial.emissiveFactor = babylonStandardMaterial.emissive;
  89. gltfMaterial.emissiveTexture = ExportTexture(babylonStandardMaterial.emissiveTexture, gltf);
  90. // --------------------------------
  91. // --- gltfPbrMetallicRoughness ---
  92. // --------------------------------
  93. RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
  94. var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
  95. gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;
  96. // --- Global ---
  97. SpecularGlossiness _specularGlossiness = new SpecularGlossiness
  98. {
  99. diffuse = new BabylonColor3(babylonStandardMaterial.diffuse),
  100. opacity = babylonMaterial.alpha,
  101. specular = new BabylonColor3(babylonStandardMaterial.specular),
  102. glossiness = babylonStandardMaterial.specularPower / 256
  103. };
  104. MetallicRoughness _metallicRoughness = ConvertToMetallicRoughness(_specularGlossiness, true);
  105. // Base color
  106. gltfPbrMetallicRoughness.baseColorFactor = new float[4]
  107. {
  108. _metallicRoughness.baseColor.r,
  109. _metallicRoughness.baseColor.g,
  110. _metallicRoughness.baseColor.b,
  111. _metallicRoughness.opacity
  112. };
  113. // Metallic roughness
  114. gltfPbrMetallicRoughness.metallicFactor = _metallicRoughness.metallic;
  115. gltfPbrMetallicRoughness.roughnessFactor = _metallicRoughness.roughness;
  116. // --- Textures ---
  117. if (babylonStandardMaterial.diffuseTexture != null)
  118. {
  119. Func<string, Bitmap> loadTextureFromOutput = delegate (string textureName)
  120. {
  121. return LoadTexture(Path.Combine(gltf.OutputFolder, textureName));
  122. };
  123. Bitmap diffuseBitmap = loadTextureFromOutput(babylonStandardMaterial.diffuseTexture.name);
  124. if (diffuseBitmap != null)
  125. {
  126. Bitmap specularBitmap = null;
  127. if (babylonStandardMaterial.specularTexture != null)
  128. {
  129. specularBitmap = loadTextureFromOutput(babylonStandardMaterial.specularTexture.name);
  130. }
  131. Bitmap opacityBitmap = null;
  132. if (babylonStandardMaterial.diffuseTexture.hasAlpha == false && babylonStandardMaterial.opacityTexture != null)
  133. {
  134. opacityBitmap = loadTextureFromOutput(babylonStandardMaterial.opacityTexture.name);
  135. }
  136. // Retreive dimensions
  137. int width = 0;
  138. int height = 0;
  139. var haveSameDimensions = _getMinimalBitmapDimensions(out width, out height, diffuseBitmap, specularBitmap, opacityBitmap);
  140. if (!haveSameDimensions)
  141. {
  142. RaiseWarning("Diffuse, specular and opacity maps should have same dimensions", 2);
  143. }
  144. // Create base color and metallic+roughness maps
  145. Bitmap baseColorBitmap = new Bitmap(width, height);
  146. Bitmap metallicRoughnessBitmap = new Bitmap(width, height);
  147. var hasAlpha = false;
  148. for (int x = 0; x < width; x++)
  149. {
  150. for (int y = 0; y < height; y++)
  151. {
  152. var diffuse = diffuseBitmap.GetPixel(x, y);
  153. SpecularGlossiness specularGlossinessTexture = new SpecularGlossiness
  154. {
  155. diffuse = new BabylonColor3(diffuse),
  156. opacity = babylonStandardMaterial.diffuseTexture.hasAlpha? diffuse.A / 255.0f :
  157. opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB ? opacityBitmap.GetPixel(x, y).R / 255.0f :
  158. opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB == false ? opacityBitmap.GetPixel(x, y).A / 255.0f :
  159. 1,
  160. specular = specularBitmap != null ? new BabylonColor3(specularBitmap.GetPixel(x, y)) :
  161. new BabylonColor3(),
  162. glossiness = babylonStandardMaterial.useGlossinessFromSpecularMapAlpha && specularBitmap != null ? specularBitmap.GetPixel(x, y).A / 255.0f :
  163. 0
  164. };
  165. var displayPrints = x == width / 2 && y == height / 2;
  166. MetallicRoughness metallicRoughnessTexture = ConvertToMetallicRoughness(specularGlossinessTexture, displayPrints);
  167. Color colorBase = Color.FromArgb(
  168. (int)(metallicRoughnessTexture.opacity * 255),
  169. (int)(metallicRoughnessTexture.baseColor.r * 255),
  170. (int)(metallicRoughnessTexture.baseColor.g * 255),
  171. (int)(metallicRoughnessTexture.baseColor.b * 255)
  172. );
  173. baseColorBitmap.SetPixel(x, y, colorBase);
  174. if (metallicRoughnessTexture.opacity != 1)
  175. {
  176. hasAlpha = true;
  177. }
  178. // The metalness values are sampled from the B channel.
  179. // The roughness values are sampled from the G channel.
  180. // These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations.
  181. Color colorMetallicRoughness = Color.FromArgb(
  182. 0,
  183. (int)(metallicRoughnessTexture.roughness * 255),
  184. (int)(metallicRoughnessTexture.metallic * 255)
  185. );
  186. metallicRoughnessBitmap.SetPixel(x, y, colorMetallicRoughness);
  187. }
  188. }
  189. // Export maps and textures
  190. var baseColorFileName = babylonMaterial.name + "_baseColor" + (hasAlpha ? ".png" : ".jpg");
  191. gltfPbrMetallicRoughness.baseColorTexture = ExportBitmapTexture(babylonStandardMaterial.diffuseTexture, baseColorBitmap, baseColorFileName, gltf);
  192. if (specularBitmap != null)
  193. {
  194. gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportBitmapTexture(babylonStandardMaterial.diffuseTexture, metallicRoughnessBitmap, babylonMaterial.name + "_metallicRoughness" + ".jpg", gltf);
  195. }
  196. }
  197. }
  198. }
  199. else if (babylonMaterial.GetType() == typeof(BabylonPBRMetallicRoughnessMaterial))
  200. {
  201. var babylonPBRMetallicRoughnessMaterial = babylonMaterial as BabylonPBRMetallicRoughnessMaterial;
  202. // --- prints ---
  203. RaiseMessage("GLTFExporter.Material | babylonMaterial data", 2);
  204. RaiseMessage("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
  205. RaiseMessage("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3);
  206. RaiseMessage("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
  207. RaiseMessage("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);
  208. // Global
  209. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights=" + babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights, 3);
  210. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.disableLighting=" + babylonPBRMetallicRoughnessMaterial.disableLighting, 3);
  211. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.alphaCutOff=" + babylonPBRMetallicRoughnessMaterial.alphaCutOff, 3);
  212. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.transparencyMode=" + babylonPBRMetallicRoughnessMaterial.transparencyMode, 3);
  213. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.doubleSided=" + babylonPBRMetallicRoughnessMaterial.doubleSided, 3);
  214. // Base color
  215. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor.Length=" + babylonPBRMetallicRoughnessMaterial.baseColor.Length, 3);
  216. for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.baseColor.Length; i++)
  217. {
  218. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.baseColor[i], 3);
  219. }
  220. if (babylonPBRMetallicRoughnessMaterial.baseTexture == null)
  221. {
  222. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseTexture=null", 3);
  223. }
  224. // Metallic+roughness
  225. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallic=" + babylonPBRMetallicRoughnessMaterial.metallic, 3);
  226. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.roughness=" + babylonPBRMetallicRoughnessMaterial.roughness, 3);
  227. if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture == null)
  228. {
  229. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture=null", 3);
  230. }
  231. // Environment
  232. if (babylonPBRMetallicRoughnessMaterial.environmentTexture == null)
  233. {
  234. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.environmentTexture=null", 3);
  235. }
  236. // Normal / bump
  237. if (babylonPBRMetallicRoughnessMaterial.normalTexture == null)
  238. {
  239. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.normalTexture=null", 3);
  240. }
  241. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapX=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapX, 3);
  242. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapY=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapY, 3);
  243. // Emissive
  244. for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.emissiveColor.Length; i++)
  245. {
  246. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.emissiveColor[i], 3);
  247. }
  248. if (babylonPBRMetallicRoughnessMaterial.emissiveTexture == null)
  249. {
  250. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveTexture=null", 3);
  251. }
  252. // Ambient occlusion
  253. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionStrength=" + babylonPBRMetallicRoughnessMaterial.occlusionStrength, 3);
  254. if (babylonPBRMetallicRoughnessMaterial.occlusionTexture == null)
  255. {
  256. RaiseMessage("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionTexture=null", 3);
  257. }
  258. // --------------------------------
  259. // --------- gltfMaterial ---------
  260. // --------------------------------
  261. RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
  262. var gltfMaterial = new GLTFMaterial
  263. {
  264. name = name
  265. };
  266. gltfMaterial.id = babylonMaterial.id;
  267. gltfMaterial.index = gltf.MaterialsList.Count;
  268. gltf.MaterialsList.Add(gltfMaterial);
  269. // Alpha
  270. string alphaMode;
  271. float? alphaCutoff;
  272. getAlphaMode(babylonPBRMetallicRoughnessMaterial, out alphaMode, out alphaCutoff);
  273. gltfMaterial.alphaMode = alphaMode;
  274. gltfMaterial.alphaCutoff = alphaCutoff;
  275. // DoubleSided
  276. gltfMaterial.doubleSided = babylonPBRMetallicRoughnessMaterial.doubleSided;
  277. // Normal
  278. gltfMaterial.normalTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.normalTexture, gltf);
  279. // Occulison
  280. gltfMaterial.occlusionTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.occlusionTexture, gltf);
  281. // Emissive
  282. gltfMaterial.emissiveFactor = babylonPBRMetallicRoughnessMaterial.emissiveColor;
  283. gltfMaterial.emissiveTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.emissiveTexture, gltf);
  284. // --------------------------------
  285. // --- gltfPbrMetallicRoughness ---
  286. // --------------------------------
  287. RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
  288. var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
  289. gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;
  290. // --- Global ---
  291. // Base color
  292. gltfPbrMetallicRoughness.baseColorFactor = new float[4]
  293. {
  294. babylonPBRMetallicRoughnessMaterial.baseColor[0],
  295. babylonPBRMetallicRoughnessMaterial.baseColor[1],
  296. babylonPBRMetallicRoughnessMaterial.baseColor[2],
  297. 1.0f // TODO - alpha
  298. };
  299. gltfPbrMetallicRoughness.baseColorTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.baseTexture, gltf);
  300. // Metallic roughness
  301. gltfPbrMetallicRoughness.metallicFactor = babylonPBRMetallicRoughnessMaterial.metallic;
  302. gltfPbrMetallicRoughness.roughnessFactor = babylonPBRMetallicRoughnessMaterial.roughness;
  303. gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture, gltf);
  304. }
  305. else
  306. {
  307. RaiseWarning("GLTFExporter.Material | Unsupported material type: " + babylonMaterial.GetType(), 2);
  308. }
  309. }
  310. private void getAlphaMode(BabylonStandardMaterial babylonMaterial, out string alphaMode, out float? alphaCutoff)
  311. {
  312. if ((babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.hasAlpha) ||
  313. babylonMaterial.opacityTexture != null)
  314. {
  315. // TODO - Babylon standard material is assumed to useAlphaFromDiffuseTexture. If not, the alpha mode is a mask.
  316. alphaMode = GLTFMaterial.AlphaMode.BLEND.ToString();
  317. }
  318. else
  319. {
  320. // glTF alpha mode default value is "OPAQUE"
  321. alphaMode = null; // GLTFMaterial.AlphaMode.OPAQUE.ToString();
  322. }
  323. alphaCutoff = null;
  324. }
  325. private void getAlphaMode(BabylonPBRMetallicRoughnessMaterial babylonMaterial, out string alphaMode, out float? alphaCutoff)
  326. {
  327. if (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)
  328. {
  329. // TODO - Babylon standard material is assumed to useAlphaFromDiffuseTexture. If not, the alpha mode is a mask.
  330. alphaMode = GLTFMaterial.AlphaMode.BLEND.ToString();
  331. }
  332. else
  333. {
  334. // glTF alpha mode default value is "OPAQUE"
  335. alphaMode = null; // GLTFMaterial.AlphaMode.OPAQUE.ToString();
  336. }
  337. alphaCutoff = null;
  338. }
  339. BabylonColor3 dielectricSpecular = new BabylonColor3(0.04f, 0.04f, 0.04f);
  340. const float epsilon = 1e-6f;
  341. private MetallicRoughness ConvertToMetallicRoughness(SpecularGlossiness specularGlossiness, bool displayPrints = false)
  342. {
  343. var diffuse = specularGlossiness.diffuse;
  344. var opacity = specularGlossiness.opacity;
  345. var specular = specularGlossiness.specular;
  346. var glossiness = specularGlossiness.glossiness;
  347. var oneMinusSpecularStrength = 1 - specular.getMaxComponent();
  348. var metallic = solveMetallic(diffuse.getPerceivedBrightness(), specular.getPerceivedBrightness(), oneMinusSpecularStrength);
  349. var diffuseScaleFactor = oneMinusSpecularStrength / (1 - dielectricSpecular.r) / Math.Max(1 - metallic, epsilon);
  350. var baseColorFromDiffuse = diffuse.scale(diffuseScaleFactor);
  351. var baseColorFromSpecular = specular.subtract(dielectricSpecular.scale(1 - metallic)).scale(1 / Math.Max(metallic, epsilon));
  352. var baseColor = BabylonColor3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic).clamp();
  353. //var baseColor = baseColorFromDiffuse.clamp();
  354. if (displayPrints)
  355. {
  356. RaiseMessage("-----------------------", 3);
  357. RaiseMessage("diffuse=" + diffuse, 3);
  358. RaiseMessage("opacity=" + opacity, 3);
  359. RaiseMessage("specular=" + specular, 3);
  360. RaiseMessage("glossiness=" + glossiness, 3);
  361. RaiseMessage("oneMinusSpecularStrength=" + oneMinusSpecularStrength, 3);
  362. RaiseMessage("metallic=" + metallic, 3);
  363. RaiseMessage("diffuseScaleFactor=" + diffuseScaleFactor, 3);
  364. RaiseMessage("baseColorFromDiffuse=" + baseColorFromDiffuse, 3);
  365. RaiseMessage("baseColorFromSpecular=" + baseColorFromSpecular, 3);
  366. RaiseMessage("metallic * metallic=" + metallic * metallic, 3);
  367. RaiseMessage("baseColor=" + baseColor, 3);
  368. RaiseMessage("-----------------------", 3);
  369. }
  370. return new MetallicRoughness
  371. {
  372. baseColor = baseColor,
  373. opacity = opacity,
  374. metallic = metallic,
  375. roughness = 1 - glossiness
  376. };
  377. }
  378. private float solveMetallic(float diffuse, float specular, float oneMinusSpecularStrength)
  379. {
  380. if (specular < dielectricSpecular.r)
  381. {
  382. return 0;
  383. }
  384. var a = dielectricSpecular.r;
  385. var b = diffuse * oneMinusSpecularStrength / (1 - dielectricSpecular.r) + specular - 2 * dielectricSpecular.r;
  386. var c = dielectricSpecular.r - specular;
  387. var D = b * b - 4 * a * c;
  388. return ClampScalar((float)(-b + Math.Sqrt(D)) / (2 * a), 0, 1);
  389. }
  390. /**
  391. * Returns the value itself if it's between min and max.
  392. * Returns min if the value is lower than min.
  393. * Returns max if the value is greater than max.
  394. */
  395. private static float ClampScalar(float value, float min = 0, float max = 1)
  396. {
  397. return Math.Min(max, Math.Max(min, value));
  398. }
  399. private class SpecularGlossiness
  400. {
  401. public BabylonColor3 diffuse;
  402. public float opacity;
  403. public BabylonColor3 specular;
  404. public float glossiness;
  405. }
  406. private class MetallicRoughness
  407. {
  408. public BabylonColor3 baseColor;
  409. public float opacity;
  410. public float metallic;
  411. public float roughness;
  412. }
  413. }
  414. }