pbrClearCoatConfiguration.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. import { __decorate } from "../../tslib.es6.js";
  2. import { serialize, serializeAsTexture, expandToProperty, serializeAsColor3 } from "../../Misc/decorators.js";
  3. import { Color3 } from "../../Maths/math.color.js";
  4. import { MaterialFlags } from "../materialFlags.js";
  5. import { MaterialPluginBase } from "../materialPluginBase.js";
  6. import { MaterialDefines } from "../materialDefines.js";
  7. import { BindTextureMatrix, PrepareDefinesForMergedUV } from "../materialHelper.functions.js";
  8. /**
  9. * @internal
  10. */
  11. export class MaterialClearCoatDefines extends MaterialDefines {
  12. constructor() {
  13. super(...arguments);
  14. this.CLEARCOAT = false;
  15. this.CLEARCOAT_DEFAULTIOR = false;
  16. this.CLEARCOAT_TEXTURE = false;
  17. this.CLEARCOAT_TEXTURE_ROUGHNESS = false;
  18. this.CLEARCOAT_TEXTUREDIRECTUV = 0;
  19. this.CLEARCOAT_TEXTURE_ROUGHNESSDIRECTUV = 0;
  20. this.CLEARCOAT_BUMP = false;
  21. this.CLEARCOAT_BUMPDIRECTUV = 0;
  22. this.CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE = false;
  23. this.CLEARCOAT_REMAP_F0 = false;
  24. this.CLEARCOAT_TINT = false;
  25. this.CLEARCOAT_TINT_TEXTURE = false;
  26. this.CLEARCOAT_TINT_TEXTUREDIRECTUV = 0;
  27. this.CLEARCOAT_TINT_GAMMATEXTURE = false;
  28. }
  29. }
  30. /**
  31. * Plugin that implements the clear coat component of the PBR material
  32. */
  33. export class PBRClearCoatConfiguration extends MaterialPluginBase {
  34. /** @internal */
  35. _markAllSubMeshesAsTexturesDirty() {
  36. this._enable(this._isEnabled);
  37. this._internalMarkAllSubMeshesAsTexturesDirty();
  38. }
  39. constructor(material, addToPluginList = true) {
  40. super(material, "PBRClearCoat", 100, new MaterialClearCoatDefines(), addToPluginList);
  41. this._isEnabled = false;
  42. /**
  43. * Defines if the clear coat is enabled in the material.
  44. */
  45. this.isEnabled = false;
  46. /**
  47. * Defines the clear coat layer strength (between 0 and 1) it defaults to 1.
  48. */
  49. this.intensity = 1;
  50. /**
  51. * Defines the clear coat layer roughness.
  52. */
  53. this.roughness = 0;
  54. this._indexOfRefraction = PBRClearCoatConfiguration._DefaultIndexOfRefraction;
  55. /**
  56. * Defines the index of refraction of the clear coat.
  57. * This defaults to 1.5 corresponding to a 0.04 f0 or a 4% reflectance at normal incidence
  58. * The default fits with a polyurethane material.
  59. * Changing the default value is more performance intensive.
  60. */
  61. this.indexOfRefraction = PBRClearCoatConfiguration._DefaultIndexOfRefraction;
  62. this._texture = null;
  63. /**
  64. * Stores the clear coat values in a texture (red channel is intensity and green channel is roughness)
  65. * If useRoughnessFromMainTexture is false, the green channel of texture is not used and the green channel of textureRoughness is used instead
  66. * if textureRoughness is not empty, else no texture roughness is used
  67. */
  68. this.texture = null;
  69. this._useRoughnessFromMainTexture = true;
  70. /**
  71. * Indicates that the green channel of the texture property will be used for roughness (default: true)
  72. * If false, the green channel from textureRoughness is used for roughness
  73. */
  74. this.useRoughnessFromMainTexture = true;
  75. this._textureRoughness = null;
  76. /**
  77. * Stores the clear coat roughness in a texture (green channel)
  78. * Not used if useRoughnessFromMainTexture is true
  79. */
  80. this.textureRoughness = null;
  81. this._remapF0OnInterfaceChange = true;
  82. /**
  83. * Defines if the F0 value should be remapped to account for the interface change in the material.
  84. */
  85. this.remapF0OnInterfaceChange = true;
  86. this._bumpTexture = null;
  87. /**
  88. * Define the clear coat specific bump texture.
  89. */
  90. this.bumpTexture = null;
  91. this._isTintEnabled = false;
  92. /**
  93. * Defines if the clear coat tint is enabled in the material.
  94. */
  95. this.isTintEnabled = false;
  96. /**
  97. * Defines the clear coat tint of the material.
  98. * This is only use if tint is enabled
  99. */
  100. this.tintColor = Color3.White();
  101. /**
  102. * Defines the distance at which the tint color should be found in the
  103. * clear coat media.
  104. * This is only use if tint is enabled
  105. */
  106. this.tintColorAtDistance = 1;
  107. /**
  108. * Defines the clear coat layer thickness.
  109. * This is only use if tint is enabled
  110. */
  111. this.tintThickness = 1;
  112. this._tintTexture = null;
  113. /**
  114. * Stores the clear tint values in a texture.
  115. * rgb is tint
  116. * a is a thickness factor
  117. */
  118. this.tintTexture = null;
  119. this._internalMarkAllSubMeshesAsTexturesDirty = material._dirtyCallbacks[1];
  120. }
  121. isReadyForSubMesh(defines, scene, engine) {
  122. if (!this._isEnabled) {
  123. return true;
  124. }
  125. const disableBumpMap = this._material._disableBumpMap;
  126. if (defines._areTexturesDirty) {
  127. if (scene.texturesEnabled) {
  128. if (this._texture && MaterialFlags.ClearCoatTextureEnabled) {
  129. if (!this._texture.isReadyOrNotBlocking()) {
  130. return false;
  131. }
  132. }
  133. if (this._textureRoughness && MaterialFlags.ClearCoatTextureEnabled) {
  134. if (!this._textureRoughness.isReadyOrNotBlocking()) {
  135. return false;
  136. }
  137. }
  138. if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.ClearCoatBumpTextureEnabled && !disableBumpMap) {
  139. // Bump texture cannot be not blocking.
  140. if (!this._bumpTexture.isReady()) {
  141. return false;
  142. }
  143. }
  144. if (this._isTintEnabled && this._tintTexture && MaterialFlags.ClearCoatTintTextureEnabled) {
  145. if (!this._tintTexture.isReadyOrNotBlocking()) {
  146. return false;
  147. }
  148. }
  149. }
  150. }
  151. return true;
  152. }
  153. prepareDefinesBeforeAttributes(defines, scene) {
  154. if (this._isEnabled) {
  155. defines.CLEARCOAT = true;
  156. defines.CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE = this._useRoughnessFromMainTexture;
  157. defines.CLEARCOAT_REMAP_F0 = this._remapF0OnInterfaceChange;
  158. if (defines._areTexturesDirty) {
  159. if (scene.texturesEnabled) {
  160. if (this._texture && MaterialFlags.ClearCoatTextureEnabled) {
  161. PrepareDefinesForMergedUV(this._texture, defines, "CLEARCOAT_TEXTURE");
  162. }
  163. else {
  164. defines.CLEARCOAT_TEXTURE = false;
  165. }
  166. if (this._textureRoughness && MaterialFlags.ClearCoatTextureEnabled) {
  167. PrepareDefinesForMergedUV(this._textureRoughness, defines, "CLEARCOAT_TEXTURE_ROUGHNESS");
  168. }
  169. else {
  170. defines.CLEARCOAT_TEXTURE_ROUGHNESS = false;
  171. }
  172. if (this._bumpTexture && MaterialFlags.ClearCoatBumpTextureEnabled) {
  173. PrepareDefinesForMergedUV(this._bumpTexture, defines, "CLEARCOAT_BUMP");
  174. }
  175. else {
  176. defines.CLEARCOAT_BUMP = false;
  177. }
  178. defines.CLEARCOAT_DEFAULTIOR = this._indexOfRefraction === PBRClearCoatConfiguration._DefaultIndexOfRefraction;
  179. if (this._isTintEnabled) {
  180. defines.CLEARCOAT_TINT = true;
  181. if (this._tintTexture && MaterialFlags.ClearCoatTintTextureEnabled) {
  182. PrepareDefinesForMergedUV(this._tintTexture, defines, "CLEARCOAT_TINT_TEXTURE");
  183. defines.CLEARCOAT_TINT_GAMMATEXTURE = this._tintTexture.gammaSpace;
  184. }
  185. else {
  186. defines.CLEARCOAT_TINT_TEXTURE = false;
  187. }
  188. }
  189. else {
  190. defines.CLEARCOAT_TINT = false;
  191. defines.CLEARCOAT_TINT_TEXTURE = false;
  192. }
  193. }
  194. }
  195. }
  196. else {
  197. defines.CLEARCOAT = false;
  198. defines.CLEARCOAT_TEXTURE = false;
  199. defines.CLEARCOAT_TEXTURE_ROUGHNESS = false;
  200. defines.CLEARCOAT_BUMP = false;
  201. defines.CLEARCOAT_TINT = false;
  202. defines.CLEARCOAT_TINT_TEXTURE = false;
  203. defines.CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE = false;
  204. defines.CLEARCOAT_DEFAULTIOR = false;
  205. defines.CLEARCOAT_TEXTUREDIRECTUV = 0;
  206. defines.CLEARCOAT_TEXTURE_ROUGHNESSDIRECTUV = 0;
  207. defines.CLEARCOAT_BUMPDIRECTUV = 0;
  208. defines.CLEARCOAT_REMAP_F0 = false;
  209. defines.CLEARCOAT_TINT_TEXTUREDIRECTUV = 0;
  210. defines.CLEARCOAT_TINT_GAMMATEXTURE = false;
  211. }
  212. }
  213. bindForSubMesh(uniformBuffer, scene, engine, subMesh) {
  214. if (!this._isEnabled) {
  215. return;
  216. }
  217. const defines = subMesh.materialDefines;
  218. const isFrozen = this._material.isFrozen;
  219. const disableBumpMap = this._material._disableBumpMap;
  220. const invertNormalMapX = this._material._invertNormalMapX;
  221. const invertNormalMapY = this._material._invertNormalMapY;
  222. if (!uniformBuffer.useUbo || !isFrozen || !uniformBuffer.isSync) {
  223. if ((this._texture || this._textureRoughness) && MaterialFlags.ClearCoatTextureEnabled) {
  224. uniformBuffer.updateFloat4("vClearCoatInfos", this._texture?.coordinatesIndex ?? 0, this._texture?.level ?? 0, this._textureRoughness?.coordinatesIndex ?? 0, this._textureRoughness?.level ?? 0);
  225. if (this._texture) {
  226. BindTextureMatrix(this._texture, uniformBuffer, "clearCoat");
  227. }
  228. if (this._textureRoughness && !defines.CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) {
  229. BindTextureMatrix(this._textureRoughness, uniformBuffer, "clearCoatRoughness");
  230. }
  231. }
  232. if (this._bumpTexture && engine.getCaps().standardDerivatives && MaterialFlags.ClearCoatTextureEnabled && !disableBumpMap) {
  233. uniformBuffer.updateFloat2("vClearCoatBumpInfos", this._bumpTexture.coordinatesIndex, this._bumpTexture.level);
  234. BindTextureMatrix(this._bumpTexture, uniformBuffer, "clearCoatBump");
  235. if (scene._mirroredCameraPosition) {
  236. uniformBuffer.updateFloat2("vClearCoatTangentSpaceParams", invertNormalMapX ? 1.0 : -1.0, invertNormalMapY ? 1.0 : -1.0);
  237. }
  238. else {
  239. uniformBuffer.updateFloat2("vClearCoatTangentSpaceParams", invertNormalMapX ? -1.0 : 1.0, invertNormalMapY ? -1.0 : 1.0);
  240. }
  241. }
  242. if (this._tintTexture && MaterialFlags.ClearCoatTintTextureEnabled) {
  243. uniformBuffer.updateFloat2("vClearCoatTintInfos", this._tintTexture.coordinatesIndex, this._tintTexture.level);
  244. BindTextureMatrix(this._tintTexture, uniformBuffer, "clearCoatTint");
  245. }
  246. // Clear Coat General params
  247. uniformBuffer.updateFloat2("vClearCoatParams", this.intensity, this.roughness);
  248. // Clear Coat Refraction params
  249. const a = 1 - this._indexOfRefraction;
  250. const b = 1 + this._indexOfRefraction;
  251. const f0 = Math.pow(-a / b, 2); // Schlicks approx: (ior1 - ior2) / (ior1 + ior2) where ior2 for air is close to vacuum = 1.
  252. const eta = 1 / this._indexOfRefraction;
  253. uniformBuffer.updateFloat4("vClearCoatRefractionParams", f0, eta, a, b);
  254. if (this._isTintEnabled) {
  255. uniformBuffer.updateFloat4("vClearCoatTintParams", this.tintColor.r, this.tintColor.g, this.tintColor.b, Math.max(0.00001, this.tintThickness));
  256. uniformBuffer.updateFloat("clearCoatColorAtDistance", Math.max(0.00001, this.tintColorAtDistance));
  257. }
  258. }
  259. // Textures
  260. if (scene.texturesEnabled) {
  261. if (this._texture && MaterialFlags.ClearCoatTextureEnabled) {
  262. uniformBuffer.setTexture("clearCoatSampler", this._texture);
  263. }
  264. if (this._textureRoughness && !defines.CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE && MaterialFlags.ClearCoatTextureEnabled) {
  265. uniformBuffer.setTexture("clearCoatRoughnessSampler", this._textureRoughness);
  266. }
  267. if (this._bumpTexture && engine.getCaps().standardDerivatives && MaterialFlags.ClearCoatBumpTextureEnabled && !disableBumpMap) {
  268. uniformBuffer.setTexture("clearCoatBumpSampler", this._bumpTexture);
  269. }
  270. if (this._isTintEnabled && this._tintTexture && MaterialFlags.ClearCoatTintTextureEnabled) {
  271. uniformBuffer.setTexture("clearCoatTintSampler", this._tintTexture);
  272. }
  273. }
  274. }
  275. hasTexture(texture) {
  276. if (this._texture === texture) {
  277. return true;
  278. }
  279. if (this._textureRoughness === texture) {
  280. return true;
  281. }
  282. if (this._bumpTexture === texture) {
  283. return true;
  284. }
  285. if (this._tintTexture === texture) {
  286. return true;
  287. }
  288. return false;
  289. }
  290. getActiveTextures(activeTextures) {
  291. if (this._texture) {
  292. activeTextures.push(this._texture);
  293. }
  294. if (this._textureRoughness) {
  295. activeTextures.push(this._textureRoughness);
  296. }
  297. if (this._bumpTexture) {
  298. activeTextures.push(this._bumpTexture);
  299. }
  300. if (this._tintTexture) {
  301. activeTextures.push(this._tintTexture);
  302. }
  303. }
  304. getAnimatables(animatables) {
  305. if (this._texture && this._texture.animations && this._texture.animations.length > 0) {
  306. animatables.push(this._texture);
  307. }
  308. if (this._textureRoughness && this._textureRoughness.animations && this._textureRoughness.animations.length > 0) {
  309. animatables.push(this._textureRoughness);
  310. }
  311. if (this._bumpTexture && this._bumpTexture.animations && this._bumpTexture.animations.length > 0) {
  312. animatables.push(this._bumpTexture);
  313. }
  314. if (this._tintTexture && this._tintTexture.animations && this._tintTexture.animations.length > 0) {
  315. animatables.push(this._tintTexture);
  316. }
  317. }
  318. dispose(forceDisposeTextures) {
  319. if (forceDisposeTextures) {
  320. this._texture?.dispose();
  321. this._textureRoughness?.dispose();
  322. this._bumpTexture?.dispose();
  323. this._tintTexture?.dispose();
  324. }
  325. }
  326. getClassName() {
  327. return "PBRClearCoatConfiguration";
  328. }
  329. addFallbacks(defines, fallbacks, currentRank) {
  330. if (defines.CLEARCOAT_BUMP) {
  331. fallbacks.addFallback(currentRank++, "CLEARCOAT_BUMP");
  332. }
  333. if (defines.CLEARCOAT_TINT) {
  334. fallbacks.addFallback(currentRank++, "CLEARCOAT_TINT");
  335. }
  336. if (defines.CLEARCOAT) {
  337. fallbacks.addFallback(currentRank++, "CLEARCOAT");
  338. }
  339. return currentRank;
  340. }
  341. getSamplers(samplers) {
  342. samplers.push("clearCoatSampler", "clearCoatRoughnessSampler", "clearCoatBumpSampler", "clearCoatTintSampler");
  343. }
  344. getUniforms() {
  345. return {
  346. ubo: [
  347. { name: "vClearCoatParams", size: 2, type: "vec2" },
  348. { name: "vClearCoatRefractionParams", size: 4, type: "vec4" },
  349. { name: "vClearCoatInfos", size: 4, type: "vec4" },
  350. { name: "clearCoatMatrix", size: 16, type: "mat4" },
  351. { name: "clearCoatRoughnessMatrix", size: 16, type: "mat4" },
  352. { name: "vClearCoatBumpInfos", size: 2, type: "vec2" },
  353. { name: "vClearCoatTangentSpaceParams", size: 2, type: "vec2" },
  354. { name: "clearCoatBumpMatrix", size: 16, type: "mat4" },
  355. { name: "vClearCoatTintParams", size: 4, type: "vec4" },
  356. { name: "clearCoatColorAtDistance", size: 1, type: "float" },
  357. { name: "vClearCoatTintInfos", size: 2, type: "vec2" },
  358. { name: "clearCoatTintMatrix", size: 16, type: "mat4" },
  359. ],
  360. };
  361. }
  362. }
  363. /**
  364. * This defaults to 1.5 corresponding to a 0.04 f0 or a 4% reflectance at normal incidence
  365. * The default fits with a polyurethane material.
  366. * @internal
  367. */
  368. PBRClearCoatConfiguration._DefaultIndexOfRefraction = 1.5;
  369. __decorate([
  370. serialize(),
  371. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  372. ], PBRClearCoatConfiguration.prototype, "isEnabled", void 0);
  373. __decorate([
  374. serialize()
  375. ], PBRClearCoatConfiguration.prototype, "intensity", void 0);
  376. __decorate([
  377. serialize()
  378. ], PBRClearCoatConfiguration.prototype, "roughness", void 0);
  379. __decorate([
  380. serialize(),
  381. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  382. ], PBRClearCoatConfiguration.prototype, "indexOfRefraction", void 0);
  383. __decorate([
  384. serializeAsTexture(),
  385. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  386. ], PBRClearCoatConfiguration.prototype, "texture", void 0);
  387. __decorate([
  388. serialize(),
  389. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  390. ], PBRClearCoatConfiguration.prototype, "useRoughnessFromMainTexture", void 0);
  391. __decorate([
  392. serializeAsTexture(),
  393. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  394. ], PBRClearCoatConfiguration.prototype, "textureRoughness", void 0);
  395. __decorate([
  396. serialize(),
  397. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  398. ], PBRClearCoatConfiguration.prototype, "remapF0OnInterfaceChange", void 0);
  399. __decorate([
  400. serializeAsTexture(),
  401. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  402. ], PBRClearCoatConfiguration.prototype, "bumpTexture", void 0);
  403. __decorate([
  404. serialize(),
  405. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  406. ], PBRClearCoatConfiguration.prototype, "isTintEnabled", void 0);
  407. __decorate([
  408. serializeAsColor3()
  409. ], PBRClearCoatConfiguration.prototype, "tintColor", void 0);
  410. __decorate([
  411. serialize()
  412. ], PBRClearCoatConfiguration.prototype, "tintColorAtDistance", void 0);
  413. __decorate([
  414. serialize()
  415. ], PBRClearCoatConfiguration.prototype, "tintThickness", void 0);
  416. __decorate([
  417. serializeAsTexture(),
  418. expandToProperty("_markAllSubMeshesAsTexturesDirty")
  419. ], PBRClearCoatConfiguration.prototype, "tintTexture", void 0);
  420. //# sourceMappingURL=pbrClearCoatConfiguration.js.map