Home Reference Source

cables_dev/cables/src/core/cgp/cgp_texture.js

  1. import { Logger } from "cables-shared-client";
  2. import CgTexture from "../cg/cg_texture.js";
  3.  
  4. export default class Texture extends CgTexture
  5. {
  6. constructor(_cgp, options = {})
  7. {
  8. super(options);
  9. if (!_cgp) throw new Error("no cgp");
  10. this._log = new Logger("cgp_texture");
  11. this._cgp = _cgp;
  12. // this.id = CABLES.uuid();
  13. this.gpuTexture = null;
  14. this.gpuTextureDescriptor = null;
  15.  
  16. options = options || {};
  17.  
  18. this.name = options.name || "unknown";
  19.  
  20. this.samplerDesc = {
  21. "addressModeU": options.wrap || options.addressModeU || "clamp-to-edge",
  22. "addressModeV": options.wrap || options.addressModeV || "clamp-to-edge",
  23. "magFilter": options.magFilter || options.filter || "linear",
  24. "minFilter": options.minFilter || options.filter || "linear",
  25. };
  26.  
  27.  
  28. this._cgp.on("deviceChange", () =>
  29. {
  30. // this.reInit();
  31. });
  32. }
  33.  
  34. /**
  35. * set texture data from an image/canvas object
  36. * @function initTexture
  37. * @memberof Texture
  38. * @instance
  39. * @param {Object} img image
  40. * @param {Number} filter
  41. */
  42. initTexture(img, filter)
  43. {
  44. this.width = img.width;
  45. this.height = img.height;
  46.  
  47. const textureType = "rgba8unorm";
  48.  
  49. this._cgp.pushErrorScope("inittexture", { "logger": this._log });
  50.  
  51. this.gpuTextureDescriptor = {
  52.  
  53. "size": { "width": img.width, "height": img.height },
  54. "format": textureType,
  55. "usage": GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
  56. };
  57.  
  58. this.gpuTexture = this._cgp.device.createTexture(this.gpuTextureDescriptor);
  59. this._cgp.device.queue.copyExternalImageToTexture({ "source": img }, { "texture": this.gpuTexture }, this.gpuTextureDescriptor.size);
  60.  
  61. this._cgp.popErrorScope();
  62.  
  63. return this.gpuTexture;
  64. }
  65.  
  66. dispose()
  67. {
  68. console.log("todo dispose");
  69. }
  70.  
  71. getInfo()
  72. {
  73. const tex = this;
  74. const obj = {};
  75.  
  76. obj.name = tex.name;
  77. obj.size = tex.width + " x " + tex.height;
  78.  
  79. obj.textureType = tex.textureType;
  80.  
  81. return obj;
  82. }
  83.  
  84. createView()
  85. {
  86. if (!this.gpuTexture)
  87. {
  88. console.log("no gputexture...");
  89. return null;
  90. }
  91. return this.gpuTexture.createView();
  92. }
  93.  
  94. getSampler()
  95. {
  96. // "clamp-to-edge"
  97. // "repeat"
  98. // "mirror-repeat"
  99.  
  100. return this.samplerDesc;
  101. }
  102.  
  103. /**
  104. * @function initFromData
  105. * @memberof Texture
  106. * @instance
  107. * @description create texturem from rgb data
  108. * @param {Array<Number>} data rgb color array [r,g,b,a,r,g,b,a,...]
  109. * @param {Number} w width
  110. * @param {Number} h height
  111. * @param {Number} filter
  112. * @param {Number} wrap
  113. */
  114. initFromData(data, w, h, filter, wrap)
  115. {
  116. if (!w || !h) this._log.error("texture size is 0");
  117. this.width = w;
  118. this.height = h;
  119. this.gpuTexture = this._cgp.device.createTexture(
  120. {
  121. "size": [w, h],
  122. "format": "rgba8unorm",
  123. "usage": GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
  124. });
  125.  
  126. this._cgp.device.queue.writeTexture(
  127. { "texture": this.gpuTexture },
  128. data,
  129. { "bytesPerRow": w * 4 },
  130. { "width": w, "height": h });
  131. }
  132.  
  133.  
  134. setWrap(v)
  135. {
  136. this.samplerDesc.addressModeU = this.samplerDesc.addressModeV = v;
  137. }
  138.  
  139. setFilter(v)
  140. {
  141. this.samplerDesc.minFilter = this.samplerDesc.magFilter = v;
  142. }
  143. }
  144.  
  145.  
  146. /**
  147. * @function load
  148. * @static
  149. * @memberof Texture
  150. * @description load an image from an url
  151. * @param {Context} cgp
  152. * @param {String} url
  153. * @param {Function} onFinished
  154. * @param {Object} settings
  155. * @return {Texture}
  156. */
  157. Texture.load = function (cgp, url, onFinished, settings)
  158. {
  159. fetch(url).then((response) =>
  160. {
  161. const texture = new Texture(cgp, { "name": url });
  162.  
  163. response.blob().then((blob) =>
  164. {
  165. createImageBitmap(blob).then((imgBitmap) =>
  166. {
  167. texture.initTexture(imgBitmap);
  168. if (onFinished)onFinished(texture);
  169. else console.log("Texture.load no onFinished callback");
  170. }).catch((err) =>
  171. {
  172. if (onFinished)onFinished(cgp.getErrorTexture());
  173. });
  174. });
  175. });
  176. };