KHR_texture_transform.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { ImageMimeType } from "babylonjs-gltf2interface";
  2. import { Nullable } from "babylonjs/types";
  3. import { Tools } from "babylonjs/Misc/tools";
  4. import { Texture } from "babylonjs/Materials/Textures/texture";
  5. import { ProceduralTexture } from "babylonjs/Materials/Textures/Procedurals/proceduralTexture";
  6. import { Scene } from "babylonjs/scene";
  7. import { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
  8. import { _Exporter } from "../glTFExporter";
  9. const NAME = "KHR_texture_transform";
  10. import "../shaders/textureTransform.fragment";
  11. /**
  12. * Interface for handling KHR texture transform
  13. * @hidden
  14. */
  15. interface IKHRTextureTransform {
  16. offset?: number[];
  17. rotation?: number;
  18. scale?: number[];
  19. texCoord?: number;
  20. }
  21. /**
  22. * @hidden
  23. */
  24. export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
  25. /** Name of this extension */
  26. public readonly name = NAME;
  27. /** Defines whether this extension is enabled */
  28. public enabled = true;
  29. /** Defines whether this extension is required */
  30. public required = false;
  31. /** Reference to the glTF exporter */
  32. private _exporter: _Exporter;
  33. constructor(exporter: _Exporter) {
  34. this._exporter = exporter;
  35. }
  36. public dispose() {
  37. delete this._exporter;
  38. }
  39. public preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>> {
  40. return new Promise((resolve, reject) => {
  41. const scene = babylonTexture.getScene();
  42. if (!scene) {
  43. reject(`${context}: "scene" is not defined for Babylon texture ${babylonTexture.name}!`);
  44. return;
  45. }
  46. // TODO: this doesn't take into account rotation center values
  47. const texture_transform_extension: IKHRTextureTransform = {};
  48. if (babylonTexture.uOffset !== 0 || babylonTexture.vOffset !== 0) {
  49. texture_transform_extension.offset = [babylonTexture.uOffset, babylonTexture.vOffset];
  50. }
  51. if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {
  52. texture_transform_extension.scale = [babylonTexture.uScale, babylonTexture.vScale];
  53. }
  54. if (babylonTexture.wAng !== 0) {
  55. texture_transform_extension.rotation = babylonTexture.wAng;
  56. }
  57. if (!Object.keys(texture_transform_extension).length) {
  58. resolve(babylonTexture);
  59. return;
  60. }
  61. return this._textureTransformTextureAsync(babylonTexture, scene);
  62. });
  63. }
  64. /**
  65. * Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
  66. * @param babylonTexture
  67. * @param offset
  68. * @param rotation
  69. * @param scale
  70. * @param scene
  71. */
  72. private _textureTransformTextureAsync(babylonTexture: Texture, scene: Scene): Promise<Texture> {
  73. return new Promise((resolve) => {
  74. const proceduralTexture = new ProceduralTexture(`${babylonTexture.name}`, babylonTexture.getSize(), "textureTransform", scene);
  75. if (!proceduralTexture) {
  76. Tools.Log(`Cannot create procedural texture for ${babylonTexture.name}!`);
  77. resolve(babylonTexture);
  78. }
  79. proceduralTexture.setTexture("textureSampler", babylonTexture);
  80. proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());
  81. // isReady trigger creation of effect if it doesnt exist yet
  82. if (proceduralTexture.isReady()) {
  83. proceduralTexture.render();
  84. resolve(proceduralTexture);
  85. } else {
  86. proceduralTexture.getEffect().executeWhenCompiled(() => {
  87. proceduralTexture.render();
  88. resolve(proceduralTexture);
  89. });
  90. }
  91. });
  92. }
  93. }
  94. _Exporter.RegisterExtension(NAME, (exporter) => new KHR_texture_transform(exporter));