customProceduralTexture.ts 6.7 KB

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