Texture.js 5.5 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
Ben Houston (Clara.io) 已提交
7
THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
M
Mr.doob 已提交
8

M
Mr.doob 已提交
9 10
	Object.defineProperty( this, 'id', { value: THREE.TextureIdCount ++ } );

11
	this.uuid = THREE.Math.generateUUID();
M
Mr.doob 已提交
12

13
	this.name = '';
14
	this.sourceFile = '';
15

16
	this.image = image !== undefined ? image : THREE.Texture.DEFAULT_IMAGE;
17
	this.mipmaps = [];
18

19
	this.mapping = mapping !== undefined ? mapping : THREE.Texture.DEFAULT_MAPPING;
20

21 22
	this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping;
	this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping;
M
Mr.doob 已提交
23

24 25
	this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter;
	this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter;
26

27 28
	this.anisotropy = anisotropy !== undefined ? anisotropy : 1;

29 30 31
	this.format = format !== undefined ? format : THREE.RGBAFormat;
	this.type = type !== undefined ? type : THREE.UnsignedByteType;

32
	this.offset = new THREE.Vector2( 0, 0 );
33 34
	this.repeat = new THREE.Vector2( 1, 1 );

35
	this.generateMipmaps = true;
36
	this.premultiplyAlpha = false;
37
	this.flipY = true;
38
	this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
39 40 41 42 43 44


	// 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.
B
Ben Houston (Clara.io) 已提交
45
	this.encoding = encoding !== undefined ? encoding :  THREE.LinearEncoding;
46

47
	this.version = 0;
48
	this.onUpdate = null;
49

M
Mr.doob 已提交
50 51
};

M
Mr.doob 已提交
52
THREE.Texture.DEFAULT_IMAGE = undefined;
53
THREE.Texture.DEFAULT_MAPPING = THREE.UVMapping;
54

M
Mr.doob 已提交
55 56
THREE.Texture.prototype = {

57 58
	constructor: THREE.Texture,

59
	set needsUpdate( value ) {
M
Mr.doob 已提交
60

M
Mr.doob 已提交
61
		if ( value === true ) this.version ++;
M
Mr.doob 已提交
62 63 64

	},

65
	clone: function () {
66

67
		return new this.constructor().copy( this );
68

69 70
	},

D
dubejf 已提交
71
	copy: function ( source ) {
72

73
		this.image = source.image;
74
		this.mipmaps = source.mipmaps.slice( 0 );
M
Mr.doob 已提交
75 76 77 78 79 80 81 82 83 84 85

		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 已提交
86
		this.format = source.format;
87
		this.type = source.type;
88

89 90
		this.offset.copy( source.offset );
		this.repeat.copy( source.repeat );
M
Mr.doob 已提交
91

92 93 94 95
		this.generateMipmaps = source.generateMipmaps;
		this.premultiplyAlpha = source.premultiplyAlpha;
		this.flipY = source.flipY;
		this.unpackAlignment = source.unpackAlignment;
96
		this.encoding = source.encoding;
M
Mr.doob 已提交
97

98
		return this;
99

100 101
	},

102 103 104 105 106 107 108
	toJSON: function ( meta ) {

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

			return meta.textures[ this.uuid ];

		}
E
elephantatwork 已提交
109

M
Mr.doob 已提交
110 111 112 113 114 115 116 117 118 119
		function getDataURL( image ) {

			var canvas;

			if ( image.toDataURL !== undefined ) {

				canvas = image;

			} else {

E
Eli Grey 已提交
120
				canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
M
Mr.doob 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
				canvas.width = image.width;
				canvas.height = image.height;

				canvas.getContext( '2d' ).drawImage( image, 0, 0, image.width, image.height );

			}

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

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

			} else {

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

			}

		}

E
elephantatwork 已提交
140 141
		var output = {
			metadata: {
142
				version: 4.4,
E
elephantatwork 已提交
143
				type: 'Texture',
144
				generator: 'Texture.toJSON'
E
elephantatwork 已提交
145
			},
146

147
			uuid: this.uuid,
148 149 150 151 152 153 154 155 156 157
			name: this.name,

			mapping: this.mapping,

			repeat: [ this.repeat.x, this.repeat.y ],
			offset: [ this.offset.x, this.offset.y ],
			wrap: [ this.wrapS, this.wrapT ],

			minFilter: this.minFilter,
			magFilter: this.magFilter,
M
Mr.doob 已提交
158 159 160
			anisotropy: this.anisotropy,

			flipY: this.flipY
E
elephantatwork 已提交
161 162
		};

163
		if ( this.image !== undefined ) {
E
elephantatwork 已提交
164

165
			// TODO: Move to THREE.Image
E
elephantatwork 已提交
166

167
			var image = this.image;
E
elephantatwork 已提交
168

169
			if ( image.uuid === undefined ) {
E
elephantatwork 已提交
170

171
				image.uuid = THREE.Math.generateUUID(); // UGH
E
elephantatwork 已提交
172

173
			}
E
elephantatwork 已提交
174

175 176 177 178 179 180
			if ( meta.images[ image.uuid ] === undefined ) {

				meta.images[ image.uuid ] = {
					uuid: image.uuid,
					url: getDataURL( image )
				};
181 182 183 184

			}

			output.image = image.uuid;
E
elephantatwork 已提交
185 186 187

		}

188 189
		meta.textures[ this.uuid ] = output;

E
elephantatwork 已提交
190
		return output;
191

E
elephantatwork 已提交
192 193
	},

194
	dispose: function () {
195

196
		this.dispatchEvent( { type: 'dispose' } );
197

198 199 200 201
	},

	transformUv: function ( uv ) {

R
rfm1201 已提交
202
		if ( this.mapping !== THREE.UVMapping )  return;
203 204 205 206 207

		uv.multiply( this.repeat );
		uv.add( this.offset );

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

209
			switch ( this.wrapS ) {
R
rfm1201 已提交
210

211
				case THREE.RepeatWrapping:
R
rfm1201 已提交
212

213 214
					uv.x = uv.x - Math.floor( uv.x );
					break;
R
rfm1201 已提交
215

216
				case THREE.ClampToEdgeWrapping:
R
rfm1201 已提交
217

218 219
					uv.x = uv.x < 0 ? 0 : 1;
					break;
R
rfm1201 已提交
220

221
				case THREE.MirroredRepeatWrapping:
R
rfm1201 已提交
222 223 224

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

225
						uv.x = Math.ceil( uv.x ) - uv.x;
R
rfm1201 已提交
226

227
					} else {
R
rfm1201 已提交
228

229
						uv.x = uv.x - Math.floor( uv.x );
R
rfm1201 已提交
230

231
					}
R
rfm1201 已提交
232 233
					break;

234
			}
R
rfm1201 已提交
235

236 237 238
		}

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

240
			switch ( this.wrapT ) {
R
rfm1201 已提交
241

242
				case THREE.RepeatWrapping:
R
rfm1201 已提交
243

244 245
					uv.y = uv.y - Math.floor( uv.y );
					break;
R
rfm1201 已提交
246

247
				case THREE.ClampToEdgeWrapping:
R
rfm1201 已提交
248

249 250
					uv.y = uv.y < 0 ? 0 : 1;
					break;
R
rfm1201 已提交
251

252
				case THREE.MirroredRepeatWrapping:
R
rfm1201 已提交
253

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

256
						uv.y = Math.ceil( uv.y ) - uv.y;
R
rfm1201 已提交
257

258
					} else {
R
rfm1201 已提交
259

260
						uv.y = uv.y - Math.floor( uv.y );
R
rfm1201 已提交
261

262 263
					}
					break;
R
rfm1201 已提交
264

265
			}
R
rfm1201 已提交
266

267 268 269
		}

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

271
			uv.y = 1 - uv.y;
R
rfm1201 已提交
272

273
		}
R
rfm1201 已提交
274

275
	}
M
Mr.doob 已提交
276 277

};
278

279
Object.assign( THREE.Texture.prototype, THREE.EventDispatcher.prototype );
M
Mr.doob 已提交
280

281
THREE.TextureIdCount = 0;