customProceduralTexture.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import { Logger } from "../../../Misc/logger";
  2. import { Scene } from "../../../scene";
  3. import { Vector3, Vector2 } from "../../../Maths/math.vector";
  4. import { Color4, Color3 } from '../../../Maths/math.color';
  5. import { Texture } from "../../../Materials/Textures/texture";
  6. import { ProceduralTexture } from "./proceduralTexture";
  7. import { WebRequest } from '../../../Misc/webRequest';
  8. /**
  9. * Procedural texturing is a way to programmatically create a texture. There are 2 types of procedural textures: code-only, and code that references some classic 2D images, sometimes called 'refMaps' or 'sampler' images.
  10. * Custom Procedural textures are the easiest way to create your own procedural in your application.
  11. * @see http://doc.babylonjs.com/how_to/how_to_use_procedural_textures#creating-custom-procedural-textures
  12. */
  13. export class CustomProceduralTexture extends ProceduralTexture {
  14. private _animate: boolean = true;
  15. private _time: number = 0;
  16. private _config: any;
  17. private _texturePath: string;
  18. /**
  19. * Instantiates a new Custom Procedural Texture.
  20. * Procedural texturing is a way to programmatically create a texture. There are 2 types of procedural textures: code-only, and code that references some classic 2D images, sometimes called 'refMaps' or 'sampler' images.
  21. * Custom Procedural textures are the easiest way to create your own procedural in your application.
  22. * @see http://doc.babylonjs.com/how_to/how_to_use_procedural_textures#creating-custom-procedural-textures
  23. * @param name Define the name of the texture
  24. * @param texturePath Define the folder path containing all the cutom texture related files (config, shaders...)
  25. * @param size Define the size of the texture to create
  26. * @param scene Define the scene the texture belongs to
  27. * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
  28. * @param generateMipMaps Define if the texture should creates mip maps or not
  29. */
  30. constructor(name: string, texturePath: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
  31. super(name, size, null, scene, fallbackTexture, generateMipMaps);
  32. this._texturePath = texturePath;
  33. //Try to load json
  34. this._loadJson(texturePath);
  35. this.refreshRate = 1;
  36. }
  37. private _loadJson(jsonUrl: string): void {
  38. let noConfigFile = () => {
  39. try {
  40. this.setFragment(this._texturePath);
  41. }
  42. catch (ex) {
  43. Logger.Error("No json or ShaderStore or DOM element found for CustomProceduralTexture");
  44. }
  45. };
  46. var configFileUrl = jsonUrl + "/config.json";
  47. var xhr = new WebRequest();
  48. xhr.open("GET", configFileUrl);
  49. xhr.addEventListener("load", () => {
  50. if (xhr.status === 200 || (xhr.responseText && xhr.responseText.length > 0)) {
  51. try {
  52. this._config = JSON.parse(xhr.response);
  53. this.updateShaderUniforms();
  54. this.updateTextures();
  55. this.setFragment(this._texturePath + "/custom");
  56. this._animate = this._config.animate;
  57. this.refreshRate = this._config.refreshrate;
  58. }
  59. catch (ex) {
  60. noConfigFile();
  61. }
  62. }
  63. else {
  64. noConfigFile();
  65. }
  66. }, false);
  67. xhr.addEventListener("error", () => {
  68. noConfigFile();
  69. }, false);
  70. try {
  71. xhr.send();
  72. }
  73. catch (ex) {
  74. Logger.Error("CustomProceduralTexture: Error on XHR send request.");
  75. }
  76. }
  77. /**
  78. * Is the texture ready to be used ? (rendered at least once)
  79. * @returns true if ready, otherwise, false.
  80. */
  81. public isReady(): boolean {
  82. if (!super.isReady()) {
  83. return false;
  84. }
  85. for (var name in this._textures) {
  86. var texture = this._textures[name];
  87. if (!texture.isReady()) {
  88. return false;
  89. }
  90. }
  91. return true;
  92. }
  93. /**
  94. * Render the texture to its associated render target.
  95. * @param useCameraPostProcess Define if camera post process should be applied to the texture
  96. */
  97. public render(useCameraPostProcess?: boolean): void {
  98. let scene = this.getScene();
  99. if (this._animate && scene) {
  100. this._time += scene.getAnimationRatio() * 0.03;
  101. this.updateShaderUniforms();
  102. }
  103. super.render(useCameraPostProcess);
  104. }
  105. /**
  106. * Update the list of dependant textures samplers in the shader.
  107. */
  108. public updateTextures(): void {
  109. for (var i = 0; i < this._config.sampler2Ds.length; i++) {
  110. this.setTexture(this._config.sampler2Ds[i].sample2Dname, new Texture(this._texturePath + "/" + this._config.sampler2Ds[i].textureRelativeUrl, this.getScene()));
  111. }
  112. }
  113. /**
  114. * Update the uniform values of the procedural texture in the shader.
  115. */
  116. public updateShaderUniforms(): void {
  117. if (this._config) {
  118. for (var j = 0; j < this._config.uniforms.length; j++) {
  119. var uniform = this._config.uniforms[j];
  120. switch (uniform.type) {
  121. case "float":
  122. this.setFloat(uniform.name, uniform.value);
  123. break;
  124. case "color3":
  125. this.setColor3(uniform.name, new Color3(uniform.r, uniform.g, uniform.b));
  126. break;
  127. case "color4":
  128. this.setColor4(uniform.name, new Color4(uniform.r, uniform.g, uniform.b, uniform.a));
  129. break;
  130. case "vector2":
  131. this.setVector2(uniform.name, new Vector2(uniform.x, uniform.y));
  132. break;
  133. case "vector3":
  134. this.setVector3(uniform.name, new Vector3(uniform.x, uniform.y, uniform.z));
  135. break;
  136. }
  137. }
  138. }
  139. this.setFloat("time", this._time);
  140. }
  141. /**
  142. * Define if the texture animates or not.
  143. */
  144. public get animate(): boolean {
  145. return this._animate;
  146. }
  147. public set animate(value: boolean) {
  148. this._animate = value;
  149. }
  150. }