customProceduralTexture.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. Logger.Log("No config file found in " + jsonUrl + " trying to use ShadersStore or DOM element");
  40. try {
  41. this.setFragment(this._texturePath);
  42. }
  43. catch (ex) {
  44. Logger.Error("No json or ShaderStore or DOM element found for CustomProceduralTexture");
  45. }
  46. };
  47. var configFileUrl = jsonUrl + "/config.json";
  48. var xhr = new WebRequest();
  49. xhr.open("GET", configFileUrl);
  50. xhr.addEventListener("load", () => {
  51. if (xhr.status === 200 || (xhr.responseText && xhr.responseText.length > 0)) {
  52. try {
  53. this._config = JSON.parse(xhr.response);
  54. this.updateShaderUniforms();
  55. this.updateTextures();
  56. this.setFragment(this._texturePath + "/custom");
  57. this._animate = this._config.animate;
  58. this.refreshRate = this._config.refreshrate;
  59. }
  60. catch (ex) {
  61. noConfigFile();
  62. }
  63. }
  64. else {
  65. noConfigFile();
  66. }
  67. }, false);
  68. xhr.addEventListener("error", () => {
  69. noConfigFile();
  70. }, false);
  71. try {
  72. xhr.send();
  73. }
  74. catch (ex) {
  75. Logger.Error("CustomProceduralTexture: Error on XHR send request.");
  76. }
  77. }
  78. /**
  79. * Is the texture ready to be used ? (rendered at least once)
  80. * @returns true if ready, otherwise, false.
  81. */
  82. public isReady(): boolean {
  83. if (!super.isReady()) {
  84. return false;
  85. }
  86. for (var name in this._textures) {
  87. var texture = this._textures[name];
  88. if (!texture.isReady()) {
  89. return false;
  90. }
  91. }
  92. return true;
  93. }
  94. /**
  95. * Render the texture to its associated render target.
  96. * @param useCameraPostProcess Define if camera post process should be applied to the texture
  97. */
  98. public render(useCameraPostProcess?: boolean): void {
  99. let scene = this.getScene();
  100. if (this._animate && scene) {
  101. this._time += scene.getAnimationRatio() * 0.03;
  102. this.updateShaderUniforms();
  103. }
  104. super.render(useCameraPostProcess);
  105. }
  106. /**
  107. * Update the list of dependant textures samplers in the shader.
  108. */
  109. public updateTextures(): void {
  110. for (var i = 0; i < this._config.sampler2Ds.length; i++) {
  111. this.setTexture(this._config.sampler2Ds[i].sample2Dname, new Texture(this._texturePath + "/" + this._config.sampler2Ds[i].textureRelativeUrl, this.getScene()));
  112. }
  113. }
  114. /**
  115. * Update the uniform values of the procedural texture in the shader.
  116. */
  117. public updateShaderUniforms(): void {
  118. if (this._config) {
  119. for (var j = 0; j < this._config.uniforms.length; j++) {
  120. var uniform = this._config.uniforms[j];
  121. switch (uniform.type) {
  122. case "float":
  123. this.setFloat(uniform.name, uniform.value);
  124. break;
  125. case "color3":
  126. this.setColor3(uniform.name, new Color3(uniform.r, uniform.g, uniform.b));
  127. break;
  128. case "color4":
  129. this.setColor4(uniform.name, new Color4(uniform.r, uniform.g, uniform.b, uniform.a));
  130. break;
  131. case "vector2":
  132. this.setVector2(uniform.name, new Vector2(uniform.x, uniform.y));
  133. break;
  134. case "vector3":
  135. this.setVector3(uniform.name, new Vector3(uniform.x, uniform.y, uniform.z));
  136. break;
  137. }
  138. }
  139. }
  140. this.setFloat("time", this._time);
  141. }
  142. /**
  143. * Define if the texture animates or not.
  144. */
  145. public get animate(): boolean {
  146. return this._animate;
  147. }
  148. public set animate(value: boolean) {
  149. this._animate = value;
  150. }
  151. }