pbrSheenConfiguration.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. import { SerializationHelper, serialize, expandToProperty, serializeAsColor3, serializeAsTexture } from "../../Misc/decorators";
  2. import { UniformBuffer } from "../../Materials/uniformBuffer";
  3. import { Color3 } from '../../Maths/math.color';
  4. import { Scene } from "../../scene";
  5. import { MaterialFlags } from "../../Materials/materialFlags";
  6. import { MaterialHelper } from "../../Materials/materialHelper";
  7. import { BaseTexture } from "../../Materials/Textures/baseTexture";
  8. import { Nullable } from "../../types";
  9. import { IAnimatable } from '../../Animations/animatable.interface';
  10. import { EffectFallbacks } from '../effectFallbacks';
  11. /**
  12. * @hidden
  13. */
  14. export interface IMaterialSheenDefines {
  15. SHEEN: boolean;
  16. SHEEN_TEXTURE: boolean;
  17. SHEEN_TEXTUREDIRECTUV: number;
  18. SHEEN_LINKWITHALBEDO: boolean;
  19. SHEEN_ROUGHNESS: boolean;
  20. SHEEN_ALBEDOSCALING: boolean;
  21. /** @hidden */
  22. _areTexturesDirty: boolean;
  23. }
  24. /**
  25. * Define the code related to the Sheen parameters of the pbr material.
  26. */
  27. export class PBRSheenConfiguration {
  28. private _isEnabled = false;
  29. /**
  30. * Defines if the material uses sheen.
  31. */
  32. @serialize()
  33. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  34. public isEnabled = false;
  35. private _linkSheenWithAlbedo = false;
  36. /**
  37. * Defines if the sheen is linked to the sheen color.
  38. */
  39. @serialize()
  40. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  41. public linkSheenWithAlbedo = false;
  42. /**
  43. * Defines the sheen intensity.
  44. */
  45. @serialize()
  46. public intensity = 1;
  47. /**
  48. * Defines the sheen color.
  49. */
  50. @serializeAsColor3()
  51. public color = Color3.White();
  52. private _texture: Nullable<BaseTexture> = null;
  53. /**
  54. * Stores the sheen tint values in a texture.
  55. * rgb is tint
  56. * a is a intensity
  57. */
  58. @serializeAsTexture()
  59. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  60. public texture: Nullable<BaseTexture> = null;
  61. private _roughness: Nullable<number> = null;
  62. /**
  63. * Defines the sheen roughness.
  64. * It is not taken into account if linkSheenWithAlbedo is true.
  65. * To stay backward compatible, material roughness is used instead if sheen roughness = null
  66. */
  67. @serialize()
  68. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  69. public roughness: Nullable<number> = null;
  70. private _albedoScaling = false;
  71. /**
  72. * If true, the sheen effect is layered above the base BRDF with the albedo-scaling technique.
  73. * It allows the strength of the sheen effect to not depend on the base color of the material,
  74. * making it easier to setup and tweak the effect
  75. */
  76. @serialize()
  77. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  78. public albedoScaling = false;
  79. /** @hidden */
  80. private _internalMarkAllSubMeshesAsTexturesDirty: () => void;
  81. /** @hidden */
  82. public _markAllSubMeshesAsTexturesDirty(): void {
  83. this._internalMarkAllSubMeshesAsTexturesDirty();
  84. }
  85. /**
  86. * Instantiate a new istance of clear coat configuration.
  87. * @param markAllSubMeshesAsTexturesDirty Callback to flag the material to dirty
  88. */
  89. constructor(markAllSubMeshesAsTexturesDirty: () => void) {
  90. this._internalMarkAllSubMeshesAsTexturesDirty = markAllSubMeshesAsTexturesDirty;
  91. }
  92. /**
  93. * Specifies that the submesh is ready to be used.
  94. * @param defines the list of "defines" to update.
  95. * @param scene defines the scene the material belongs to.
  96. * @returns - boolean indicating that the submesh is ready or not.
  97. */
  98. public isReadyForSubMesh(defines: IMaterialSheenDefines, scene: Scene): boolean {
  99. if (defines._areTexturesDirty) {
  100. if (scene.texturesEnabled) {
  101. if (this._texture && MaterialFlags.SheenTextureEnabled) {
  102. if (!this._texture.isReadyOrNotBlocking()) {
  103. return false;
  104. }
  105. }
  106. }
  107. }
  108. return true;
  109. }
  110. /**
  111. * Checks to see if a texture is used in the material.
  112. * @param defines the list of "defines" to update.
  113. * @param scene defines the scene the material belongs to.
  114. */
  115. public prepareDefines(defines: IMaterialSheenDefines, scene: Scene): void {
  116. if (this._isEnabled) {
  117. defines.SHEEN = this._isEnabled;
  118. defines.SHEEN_LINKWITHALBEDO = this._linkSheenWithAlbedo;
  119. defines.SHEEN_ROUGHNESS = this._roughness !== null;
  120. defines.SHEEN_ALBEDOSCALING = this._albedoScaling;
  121. if (defines._areTexturesDirty) {
  122. if (scene.texturesEnabled) {
  123. if (this._texture && MaterialFlags.SheenTextureEnabled) {
  124. MaterialHelper.PrepareDefinesForMergedUV(this._texture, defines, "SHEEN_TEXTURE");
  125. } else {
  126. defines.SHEEN_TEXTURE = false;
  127. }
  128. }
  129. }
  130. }
  131. else {
  132. defines.SHEEN = false;
  133. defines.SHEEN_TEXTURE = false;
  134. defines.SHEEN_LINKWITHALBEDO = false;
  135. defines.SHEEN_ROUGHNESS = false;
  136. defines.SHEEN_ALBEDOSCALING = false;
  137. }
  138. }
  139. /**
  140. * Binds the material data.
  141. * @param uniformBuffer defines the Uniform buffer to fill in.
  142. * @param scene defines the scene the material belongs to.
  143. * @param isFrozen defines wether the material is frozen or not.
  144. */
  145. public bindForSubMesh(uniformBuffer: UniformBuffer, scene: Scene, isFrozen: boolean): void {
  146. if (!uniformBuffer.useUbo || !isFrozen || !uniformBuffer.isSync) {
  147. if (this._texture && MaterialFlags.SheenTextureEnabled) {
  148. uniformBuffer.updateFloat2("vSheenInfos", this._texture.coordinatesIndex, this._texture.level);
  149. MaterialHelper.BindTextureMatrix(this._texture, uniformBuffer, "sheen");
  150. }
  151. // Sheen
  152. uniformBuffer.updateFloat4("vSheenColor",
  153. this.color.r,
  154. this.color.g,
  155. this.color.b,
  156. this.intensity);
  157. if (this._roughness !== null) {
  158. uniformBuffer.updateFloat("vSheenRoughness", this._roughness);
  159. }
  160. }
  161. // Textures
  162. if (scene.texturesEnabled) {
  163. if (this._texture && MaterialFlags.SheenTextureEnabled) {
  164. uniformBuffer.setTexture("sheenSampler", this._texture);
  165. }
  166. }
  167. }
  168. /**
  169. * Checks to see if a texture is used in the material.
  170. * @param texture - Base texture to use.
  171. * @returns - Boolean specifying if a texture is used in the material.
  172. */
  173. public hasTexture(texture: BaseTexture): boolean {
  174. if (this._texture === texture) {
  175. return true;
  176. }
  177. return false;
  178. }
  179. /**
  180. * Returns an array of the actively used textures.
  181. * @param activeTextures Array of BaseTextures
  182. */
  183. public getActiveTextures(activeTextures: BaseTexture[]): void {
  184. if (this._texture) {
  185. activeTextures.push(this._texture);
  186. }
  187. }
  188. /**
  189. * Returns the animatable textures.
  190. * @param animatables Array of animatable textures.
  191. */
  192. public getAnimatables(animatables: IAnimatable[]): void {
  193. if (this._texture && this._texture.animations && this._texture.animations.length > 0) {
  194. animatables.push(this._texture);
  195. }
  196. }
  197. /**
  198. * Disposes the resources of the material.
  199. * @param forceDisposeTextures - Forces the disposal of all textures.
  200. */
  201. public dispose(forceDisposeTextures?: boolean): void {
  202. if (forceDisposeTextures) {
  203. if (this._texture) {
  204. this._texture.dispose();
  205. }
  206. }
  207. }
  208. /**
  209. * Get the current class name of the texture useful for serialization or dynamic coding.
  210. * @returns "PBRSheenConfiguration"
  211. */
  212. public getClassName(): string {
  213. return "PBRSheenConfiguration";
  214. }
  215. /**
  216. * Add fallbacks to the effect fallbacks list.
  217. * @param defines defines the Base texture to use.
  218. * @param fallbacks defines the current fallback list.
  219. * @param currentRank defines the current fallback rank.
  220. * @returns the new fallback rank.
  221. */
  222. public static AddFallbacks(defines: IMaterialSheenDefines, fallbacks: EffectFallbacks, currentRank: number): number {
  223. if (defines.SHEEN) {
  224. fallbacks.addFallback(currentRank++, "SHEEN");
  225. }
  226. return currentRank;
  227. }
  228. /**
  229. * Add the required uniforms to the current list.
  230. * @param uniforms defines the current uniform list.
  231. */
  232. public static AddUniforms(uniforms: string[]): void {
  233. uniforms.push("vSheenColor", "vSheenRoughness", "vSheenInfos", "sheenMatrix");
  234. }
  235. /**
  236. * Add the required uniforms to the current buffer.
  237. * @param uniformBuffer defines the current uniform buffer.
  238. */
  239. public static PrepareUniformBuffer(uniformBuffer: UniformBuffer): void {
  240. uniformBuffer.addUniform("vSheenColor", 4);
  241. uniformBuffer.addUniform("vSheenRoughness", 1);
  242. uniformBuffer.addUniform("vSheenInfos", 2);
  243. uniformBuffer.addUniform("sheenMatrix", 16);
  244. }
  245. /**
  246. * Add the required samplers to the current list.
  247. * @param samplers defines the current sampler list.
  248. */
  249. public static AddSamplers(samplers: string[]): void {
  250. samplers.push("sheenSampler");
  251. }
  252. /**
  253. * Makes a duplicate of the current configuration into another one.
  254. * @param sheenConfiguration define the config where to copy the info
  255. */
  256. public copyTo(sheenConfiguration: PBRSheenConfiguration): void {
  257. SerializationHelper.Clone(() => sheenConfiguration, this);
  258. }
  259. /**
  260. * Serializes this BRDF configuration.
  261. * @returns - An object with the serialized config.
  262. */
  263. public serialize(): any {
  264. return SerializationHelper.Serialize(this);
  265. }
  266. /**
  267. * Parses a anisotropy Configuration from a serialized object.
  268. * @param source - Serialized object.
  269. * @param scene Defines the scene we are parsing for
  270. * @param rootUrl Defines the rootUrl to load from
  271. */
  272. public parse(source: any, scene: Scene, rootUrl: string): void {
  273. SerializationHelper.Parse(() => this, source, scene, rootUrl);
  274. }
  275. }