Texture.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import { EventDispatcher } from '../core/EventDispatcher';
  2. import { UVMapping } from '../constants';
  3. import { MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearEncoding, UnsignedByteType, RGBAFormat, LinearMipMapLinearFilter, LinearFilter } from '../constants';
  4. import { _Math } from '../math/Math';
  5. import { Vector2 } from '../math/Vector2';
  6. /**
  7. * @author mrdoob / http://mrdoob.com/
  8. * @author alteredq / http://alteredqualia.com/
  9. * @author szimek / https://github.com/szimek/
  10. */
  11. var textureId = 0;
  12. function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
  13. Object.defineProperty( this, 'id', { value: textureId ++ } );
  14. this.uuid = _Math.generateUUID();
  15. this.name = '';
  16. this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
  17. this.mipmaps = [];
  18. this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
  19. this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
  20. this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
  21. this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
  22. this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
  23. this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
  24. this.format = format !== undefined ? format : RGBAFormat;
  25. this.type = type !== undefined ? type : UnsignedByteType;
  26. this.offset = new Vector2( 0, 0 );
  27. this.repeat = new Vector2( 1, 1 );
  28. this.generateMipmaps = true;
  29. this.premultiplyAlpha = false;
  30. this.flipY = true;
  31. this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
  32. // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
  33. //
  34. // Also changing the encoding after already used by a Material will not automatically make the Material
  35. // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
  36. this.encoding = encoding !== undefined ? encoding : LinearEncoding;
  37. this.version = 0;
  38. this.onUpdate = null;
  39. }
  40. Texture.DEFAULT_IMAGE = undefined;
  41. Texture.DEFAULT_MAPPING = UVMapping;
  42. Object.defineProperty( Texture.prototype, "needsUpdate", {
  43. set: function ( value ) {
  44. if ( value === true ) this.version ++;
  45. }
  46. } );
  47. Object.assign( Texture.prototype, EventDispatcher.prototype, {
  48. constructor: Texture,
  49. isTexture: true,
  50. clone: function () {
  51. return new this.constructor().copy( this );
  52. },
  53. copy: function ( source ) {
  54. this.name = source.name;
  55. this.image = source.image;
  56. this.mipmaps = source.mipmaps.slice( 0 );
  57. this.mapping = source.mapping;
  58. this.wrapS = source.wrapS;
  59. this.wrapT = source.wrapT;
  60. this.magFilter = source.magFilter;
  61. this.minFilter = source.minFilter;
  62. this.anisotropy = source.anisotropy;
  63. this.format = source.format;
  64. this.type = source.type;
  65. this.offset.copy( source.offset );
  66. this.repeat.copy( source.repeat );
  67. this.generateMipmaps = source.generateMipmaps;
  68. this.premultiplyAlpha = source.premultiplyAlpha;
  69. this.flipY = source.flipY;
  70. this.unpackAlignment = source.unpackAlignment;
  71. this.encoding = source.encoding;
  72. return this;
  73. },
  74. toJSON: function ( meta ) {
  75. if ( meta.textures[ this.uuid ] !== undefined ) {
  76. return meta.textures[ this.uuid ];
  77. }
  78. function getDataURL( image ) {
  79. var canvas;
  80. if ( image instanceof HTMLCanvasElement ) {
  81. canvas = image;
  82. } else {
  83. canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
  84. canvas.width = image.width;
  85. canvas.height = image.height;
  86. var context = canvas.getContext( '2d' );
  87. if ( image instanceof ImageData ) {
  88. context.putImageData( image, 0, 0 );
  89. } else {
  90. context.drawImage( image, 0, 0, image.width, image.height );
  91. }
  92. }
  93. if ( canvas.width > 2048 || canvas.height > 2048 ) {
  94. return canvas.toDataURL( 'image/jpeg', 0.6 );
  95. } else {
  96. return canvas.toDataURL( 'image/png' );
  97. }
  98. }
  99. var output = {
  100. metadata: {
  101. version: 4.5,
  102. type: 'Texture',
  103. generator: 'Texture.toJSON'
  104. },
  105. uuid: this.uuid,
  106. name: this.name,
  107. mapping: this.mapping,
  108. repeat: [ this.repeat.x, this.repeat.y ],
  109. offset: [ this.offset.x, this.offset.y ],
  110. wrap: [ this.wrapS, this.wrapT ],
  111. minFilter: this.minFilter,
  112. magFilter: this.magFilter,
  113. anisotropy: this.anisotropy,
  114. flipY: this.flipY
  115. };
  116. if ( this.image !== undefined ) {
  117. // TODO: Move to THREE.Image
  118. var image = this.image;
  119. if ( image.uuid === undefined ) {
  120. image.uuid = _Math.generateUUID(); // UGH
  121. }
  122. if ( meta.images[ image.uuid ] === undefined ) {
  123. meta.images[ image.uuid ] = {
  124. uuid: image.uuid,
  125. url: getDataURL( image )
  126. };
  127. }
  128. output.image = image.uuid;
  129. }
  130. meta.textures[ this.uuid ] = output;
  131. return output;
  132. },
  133. dispose: function () {
  134. this.dispatchEvent( { type: 'dispose' } );
  135. },
  136. transformUv: function ( uv ) {
  137. if ( this.mapping !== UVMapping ) return;
  138. uv.multiply( this.repeat );
  139. uv.add( this.offset );
  140. if ( uv.x < 0 || uv.x > 1 ) {
  141. switch ( this.wrapS ) {
  142. case RepeatWrapping:
  143. uv.x = uv.x - Math.floor( uv.x );
  144. break;
  145. case ClampToEdgeWrapping:
  146. uv.x = uv.x < 0 ? 0 : 1;
  147. break;
  148. case MirroredRepeatWrapping:
  149. if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
  150. uv.x = Math.ceil( uv.x ) - uv.x;
  151. } else {
  152. uv.x = uv.x - Math.floor( uv.x );
  153. }
  154. break;
  155. }
  156. }
  157. if ( uv.y < 0 || uv.y > 1 ) {
  158. switch ( this.wrapT ) {
  159. case RepeatWrapping:
  160. uv.y = uv.y - Math.floor( uv.y );
  161. break;
  162. case ClampToEdgeWrapping:
  163. uv.y = uv.y < 0 ? 0 : 1;
  164. break;
  165. case MirroredRepeatWrapping:
  166. if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
  167. uv.y = Math.ceil( uv.y ) - uv.y;
  168. } else {
  169. uv.y = uv.y - Math.floor( uv.y );
  170. }
  171. break;
  172. }
  173. }
  174. if ( this.flipY ) {
  175. uv.y = 1 - uv.y;
  176. }
  177. }
  178. } );
  179. export { Texture };
粤ICP备19079148号