Texture.js 6.2 KB
Newer Older
M
Mr.doob 已提交
1
/**
M
Mr.doob 已提交
2
 * @author mrdoob / http://mrdoob.com/
3
 * @author alteredq / http://alteredqualia.com/
4
 * @author szimek / https://github.com/szimek/
M
Mr.doob 已提交
5 6
 */

B
bentok 已提交
7 8 9 10 11 12
import { EventDispatcher } from '../core/EventDispatcher.js';
import { UVMapping } from '../constants.js';
import { MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearEncoding, UnsignedByteType, RGBAFormat, LinearMipMapLinearFilter, LinearFilter } from '../constants.js';
import { _Math } from '../math/Math.js';
import { Vector2 } from '../math/Vector2.js';
import { Matrix3 } from '../math/Matrix3.js';
R
Rich Harris 已提交
13

14 15
var textureId = 0;

M
Mr.doob 已提交
16
function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
M
Mr.doob 已提交
17

18
	Object.defineProperty( this, 'id', { value: textureId ++ } );
M
Mr.doob 已提交
19

R
Rich Harris 已提交
20
	this.uuid = _Math.generateUUID();
M
Mr.doob 已提交
21

22 23
	this.name = '';

R
Rich Harris 已提交
24
	this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
25
	this.mipmaps = [];
26

R
Rich Harris 已提交
27
	this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
28

R
Rich Harris 已提交
29 30
	this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
	this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
M
Mr.doob 已提交
31

R
Rich Harris 已提交
32 33
	this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
	this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
34

35 36
	this.anisotropy = anisotropy !== undefined ? anisotropy : 1;

R
Rich Harris 已提交
37 38
	this.format = format !== undefined ? format : RGBAFormat;
	this.type = type !== undefined ? type : UnsignedByteType;
39

R
Rich Harris 已提交
40 41
	this.offset = new Vector2( 0, 0 );
	this.repeat = new Vector2( 1, 1 );
T
Tentone 已提交
42
	this.center = new Vector2( 0, 0 );
43
	this.rotation = 0;
W
WestLangley 已提交
44 45 46

	this.matrixAutoUpdate = true;
	this.matrix = new Matrix3();
47

48
	this.generateMipmaps = true;
49
	this.premultiplyAlpha = false;
50
	this.flipY = true;
51
	this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
52 53 54 55 56

	// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
	//
	// Also changing the encoding after already used by a Material will not automatically make the Material
	// update.  You need to explicitly call Material.needsUpdate to trigger it to recompile.
57
	this.encoding = encoding !== undefined ? encoding : LinearEncoding;
58

59
	this.version = 0;
60
	this.onUpdate = null;
61

M
Mr.doob 已提交
62
}
M
Mr.doob 已提交
63

R
Rich Harris 已提交
64 65
Texture.DEFAULT_IMAGE = undefined;
Texture.DEFAULT_MAPPING = UVMapping;
66

T
Tristan VALCKE 已提交
67
Object.defineProperty( Texture.prototype, "needsUpdate", {
M
Mr.doob 已提交
68

M
Mr.doob 已提交
69 70 71 72
	set: function ( value ) {

		if ( value === true ) this.version ++;

T
Style  
Tristan VALCKE 已提交
73
	}
74

M
Mr.doob 已提交
75
} );
76

T
Tristan VALCKE 已提交
77
Object.assign( Texture.prototype, EventDispatcher.prototype, {
M
Mr.doob 已提交
78

T
Tristan VALCKE 已提交
79
	constructor: Texture,
M
Mr.doob 已提交
80

T
Tristan VALCKE 已提交
81
	isTexture: true,
M
Mr.doob 已提交
82

83
	clone: function () {
84

85
		return new this.constructor().copy( this );
86

87 88
	},

D
dubejf 已提交
89
	copy: function ( source ) {
90

91
		this.name = source.name;
92

93
		this.image = source.image;
94
		this.mipmaps = source.mipmaps.slice( 0 );
M
Mr.doob 已提交
95 96 97 98 99 100 101 102 103 104 105

		this.mapping = source.mapping;

		this.wrapS = source.wrapS;
		this.wrapT = source.wrapT;

		this.magFilter = source.magFilter;
		this.minFilter = source.minFilter;

		this.anisotropy = source.anisotropy;

M
Mr.doob 已提交
106
		this.format = source.format;
107
		this.type = source.type;
108

109 110
		this.offset.copy( source.offset );
		this.repeat.copy( source.repeat );
111
		this.rotation = source.rotation;
W
WestLangley 已提交
112 113 114

		this.matrixAutoUpdate = source.matrixAutoUpdate;
		this.matrix.copy( source.matrix );
M
Mr.doob 已提交
115

116 117 118 119
		this.generateMipmaps = source.generateMipmaps;
		this.premultiplyAlpha = source.premultiplyAlpha;
		this.flipY = source.flipY;
		this.unpackAlignment = source.unpackAlignment;
120
		this.encoding = source.encoding;
M
Mr.doob 已提交
121

122
		return this;
123

124 125
	},

126 127 128 129 130 131 132
	toJSON: function ( meta ) {

		if ( meta.textures[ this.uuid ] !== undefined ) {

			return meta.textures[ this.uuid ];

		}
E
elephantatwork 已提交
133

M
Mr.doob 已提交
134 135 136 137
		function getDataURL( image ) {

			var canvas;

138
			if ( image instanceof HTMLCanvasElement ) {
M
Mr.doob 已提交
139 140 141 142 143

				canvas = image;

			} else {

E
Eli Grey 已提交
144
				canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
M
Mr.doob 已提交
145 146 147
				canvas.width = image.width;
				canvas.height = image.height;

148 149 150 151 152 153 154 155 156 157 158
				var context = canvas.getContext( '2d' );

				if ( image instanceof ImageData ) {

					context.putImageData( image, 0, 0 );

				} else {

					context.drawImage( image, 0, 0, image.width, image.height );

				}
M
Mr.doob 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

			}

			if ( canvas.width > 2048 || canvas.height > 2048 ) {

				return canvas.toDataURL( 'image/jpeg', 0.6 );

			} else {

				return canvas.toDataURL( 'image/png' );

			}

		}

E
elephantatwork 已提交
174 175
		var output = {
			metadata: {
176
				version: 4.5,
E
elephantatwork 已提交
177
				type: 'Texture',
178
				generator: 'Texture.toJSON'
E
elephantatwork 已提交
179
			},
180

181
			uuid: this.uuid,
182 183 184 185 186 187
			name: this.name,

			mapping: this.mapping,

			repeat: [ this.repeat.x, this.repeat.y ],
			offset: [ this.offset.x, this.offset.y ],
188
			rotation: this.rotation,
W
WestLangley 已提交
189

190 191 192 193
			wrap: [ this.wrapS, this.wrapT ],

			minFilter: this.minFilter,
			magFilter: this.magFilter,
M
Mr.doob 已提交
194 195 196
			anisotropy: this.anisotropy,

			flipY: this.flipY
E
elephantatwork 已提交
197 198
		};

199
		if ( this.image !== undefined ) {
E
elephantatwork 已提交
200

201
			// TODO: Move to THREE.Image
E
elephantatwork 已提交
202

203
			var image = this.image;
E
elephantatwork 已提交
204

205
			if ( image.uuid === undefined ) {
E
elephantatwork 已提交
206

R
Rich Harris 已提交
207
				image.uuid = _Math.generateUUID(); // UGH
E
elephantatwork 已提交
208

209
			}
E
elephantatwork 已提交
210

211 212 213 214 215 216
			if ( meta.images[ image.uuid ] === undefined ) {

				meta.images[ image.uuid ] = {
					uuid: image.uuid,
					url: getDataURL( image )
				};
217 218 219 220

			}

			output.image = image.uuid;
E
elephantatwork 已提交
221 222 223

		}

224 225
		meta.textures[ this.uuid ] = output;

E
elephantatwork 已提交
226
		return output;
227

E
elephantatwork 已提交
228 229
	},

230
	dispose: function () {
231

232
		this.dispatchEvent( { type: 'dispose' } );
233

234 235 236 237
	},

	transformUv: function ( uv ) {

238
		if ( this.mapping !== UVMapping ) return;
239

240
		uv.applyMatrix3( this.matrix );
241 242

		if ( uv.x < 0 || uv.x > 1 ) {
R
rfm1201 已提交
243

244
			switch ( this.wrapS ) {
R
rfm1201 已提交
245

R
Rich Harris 已提交
246
				case RepeatWrapping:
R
rfm1201 已提交
247

248 249
					uv.x = uv.x - Math.floor( uv.x );
					break;
R
rfm1201 已提交
250

R
Rich Harris 已提交
251
				case ClampToEdgeWrapping:
R
rfm1201 已提交
252

253 254
					uv.x = uv.x < 0 ? 0 : 1;
					break;
R
rfm1201 已提交
255

R
Rich Harris 已提交
256
				case MirroredRepeatWrapping:
R
rfm1201 已提交
257 258 259

					if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {

260
						uv.x = Math.ceil( uv.x ) - uv.x;
R
rfm1201 已提交
261

262
					} else {
R
rfm1201 已提交
263

264
						uv.x = uv.x - Math.floor( uv.x );
R
rfm1201 已提交
265

266
					}
R
rfm1201 已提交
267 268
					break;

269
			}
R
rfm1201 已提交
270

271 272 273
		}

		if ( uv.y < 0 || uv.y > 1 ) {
R
rfm1201 已提交
274

275
			switch ( this.wrapT ) {
R
rfm1201 已提交
276

R
Rich Harris 已提交
277
				case RepeatWrapping:
R
rfm1201 已提交
278

279 280
					uv.y = uv.y - Math.floor( uv.y );
					break;
R
rfm1201 已提交
281

R
Rich Harris 已提交
282
				case ClampToEdgeWrapping:
R
rfm1201 已提交
283

284 285
					uv.y = uv.y < 0 ? 0 : 1;
					break;
R
rfm1201 已提交
286

R
Rich Harris 已提交
287
				case MirroredRepeatWrapping:
R
rfm1201 已提交
288

289
					if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
R
rfm1201 已提交
290

291
						uv.y = Math.ceil( uv.y ) - uv.y;
R
rfm1201 已提交
292

293
					} else {
R
rfm1201 已提交
294

295
						uv.y = uv.y - Math.floor( uv.y );
R
rfm1201 已提交
296

297 298
					}
					break;
R
rfm1201 已提交
299

300
			}
R
rfm1201 已提交
301

302 303 304
		}

		if ( this.flipY ) {
R
rfm1201 已提交
305

306
			uv.y = 1 - uv.y;
R
rfm1201 已提交
307

308
		}
R
rfm1201 已提交
309

310
	}
M
Mr.doob 已提交
311

312
} );
313

R
Rich Harris 已提交
314

315
export { Texture };