416 lines
9.4 KiB
JavaScript
416 lines
9.4 KiB
JavaScript
/**
|
|
* Base class for all textures like compressed texture, texture2d, texturecube
|
|
* TODO mapping
|
|
*/
|
|
import Base from './core/Base';
|
|
import glenum from './core/glenum';
|
|
import Cache from './core/Cache';
|
|
|
|
/**
|
|
* @constructor
|
|
* @alias clay.Texture
|
|
* @extends clay.core.Base
|
|
*/
|
|
var Texture = Base.extend( /** @lends clay.Texture# */ {
|
|
/**
|
|
* Texture width, readonly when the texture source is image
|
|
* @type {number}
|
|
*/
|
|
width: 512,
|
|
/**
|
|
* Texture height, readonly when the texture source is image
|
|
* @type {number}
|
|
*/
|
|
height: 512,
|
|
/**
|
|
* Texel data type.
|
|
* Possible values:
|
|
* + {@link clay.Texture.UNSIGNED_BYTE}
|
|
* + {@link clay.Texture.HALF_FLOAT}
|
|
* + {@link clay.Texture.FLOAT}
|
|
* + {@link clay.Texture.UNSIGNED_INT_24_8_WEBGL}
|
|
* + {@link clay.Texture.UNSIGNED_INT}
|
|
* @type {number}
|
|
*/
|
|
type: glenum.UNSIGNED_BYTE,
|
|
/**
|
|
* Format of texel data
|
|
* Possible values:
|
|
* + {@link clay.Texture.RGBA}
|
|
* + {@link clay.Texture.DEPTH_COMPONENT}
|
|
* + {@link clay.Texture.DEPTH_STENCIL}
|
|
* @type {number}
|
|
*/
|
|
format: glenum.RGBA,
|
|
/**
|
|
* Texture wrap. Default to be REPEAT.
|
|
* Possible values:
|
|
* + {@link clay.Texture.CLAMP_TO_EDGE}
|
|
* + {@link clay.Texture.REPEAT}
|
|
* + {@link clay.Texture.MIRRORED_REPEAT}
|
|
* @type {number}
|
|
*/
|
|
wrapS: glenum.REPEAT,
|
|
/**
|
|
* Texture wrap. Default to be REPEAT.
|
|
* Possible values:
|
|
* + {@link clay.Texture.CLAMP_TO_EDGE}
|
|
* + {@link clay.Texture.REPEAT}
|
|
* + {@link clay.Texture.MIRRORED_REPEAT}
|
|
* @type {number}
|
|
*/
|
|
wrapT: glenum.REPEAT,
|
|
/**
|
|
* Possible values:
|
|
* + {@link clay.Texture.NEAREST}
|
|
* + {@link clay.Texture.LINEAR}
|
|
* + {@link clay.Texture.NEAREST_MIPMAP_NEAREST}
|
|
* + {@link clay.Texture.LINEAR_MIPMAP_NEAREST}
|
|
* + {@link clay.Texture.NEAREST_MIPMAP_LINEAR}
|
|
* + {@link clay.Texture.LINEAR_MIPMAP_LINEAR}
|
|
* @type {number}
|
|
*/
|
|
minFilter: glenum.LINEAR_MIPMAP_LINEAR,
|
|
/**
|
|
* Possible values:
|
|
* + {@link clay.Texture.NEAREST}
|
|
* + {@link clay.Texture.LINEAR}
|
|
* @type {number}
|
|
*/
|
|
magFilter: glenum.LINEAR,
|
|
/**
|
|
* If enable mimap.
|
|
* @type {boolean}
|
|
*/
|
|
useMipmap: true,
|
|
|
|
/**
|
|
* Anisotropic filtering, enabled if value is larger than 1
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_filter_anisotropic
|
|
* @type {number}
|
|
*/
|
|
anisotropic: 1,
|
|
// pixelStorei parameters, not available when texture is used as render target
|
|
// http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml
|
|
/**
|
|
* If flip in y axis for given image source
|
|
* @type {boolean}
|
|
* @default true
|
|
*/
|
|
flipY: true,
|
|
|
|
/**
|
|
* A flag to indicate if texture source is sRGB
|
|
*/
|
|
sRGB: true,
|
|
/**
|
|
* @type {number}
|
|
* @default 4
|
|
*/
|
|
unpackAlignment: 4,
|
|
/**
|
|
* @type {boolean}
|
|
* @default false
|
|
*/
|
|
premultiplyAlpha: false,
|
|
|
|
/**
|
|
* Dynamic option for texture like video
|
|
* @type {boolean}
|
|
*/
|
|
dynamic: false,
|
|
|
|
NPOT: false,
|
|
|
|
// PENDING
|
|
// Init it here to avoid deoptimization when it's assigned in application dynamically
|
|
__used: 0
|
|
|
|
}, function () {
|
|
this._cache = new Cache();
|
|
},
|
|
/** @lends clay.Texture.prototype */
|
|
{
|
|
|
|
getWebGLTexture: function (renderer) {
|
|
var _gl = renderer.gl;
|
|
var cache = this._cache;
|
|
cache.use(renderer.__uid__);
|
|
|
|
if (cache.miss('webgl_texture')) {
|
|
// In a new gl context, create new texture and set dirty true
|
|
cache.put('webgl_texture', _gl.createTexture());
|
|
}
|
|
if (this.dynamic) {
|
|
this.update(renderer);
|
|
}
|
|
else if (cache.isDirty()) {
|
|
this.update(renderer);
|
|
cache.fresh();
|
|
}
|
|
|
|
return cache.get('webgl_texture');
|
|
},
|
|
|
|
bind: function () {},
|
|
unbind: function () {},
|
|
|
|
/**
|
|
* Mark texture is dirty and update in the next frame
|
|
*/
|
|
dirty: function () {
|
|
if (this._cache) {
|
|
this._cache.dirtyAll();
|
|
}
|
|
},
|
|
|
|
update: function (renderer) {},
|
|
|
|
// Update the common parameters of texture
|
|
updateCommon: function (renderer) {
|
|
var _gl = renderer.gl;
|
|
_gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, this.flipY);
|
|
_gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha);
|
|
_gl.pixelStorei(_gl.UNPACK_ALIGNMENT, this.unpackAlignment);
|
|
|
|
// Use of none-power of two texture
|
|
// http://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences
|
|
if (this.format === glenum.DEPTH_COMPONENT) {
|
|
this.useMipmap = false;
|
|
}
|
|
|
|
var sRGBExt = renderer.getGLExtension('EXT_sRGB');
|
|
// Fallback
|
|
if (this.format === Texture.SRGB && !sRGBExt) {
|
|
this.format = Texture.RGB;
|
|
}
|
|
if (this.format === Texture.SRGB_ALPHA && !sRGBExt) {
|
|
this.format = Texture.RGBA;
|
|
}
|
|
|
|
this.NPOT = !this.isPowerOfTwo();
|
|
},
|
|
|
|
getAvailableWrapS: function () {
|
|
if (this.NPOT) {
|
|
return glenum.CLAMP_TO_EDGE;
|
|
}
|
|
return this.wrapS;
|
|
},
|
|
getAvailableWrapT: function () {
|
|
if (this.NPOT) {
|
|
return glenum.CLAMP_TO_EDGE;
|
|
}
|
|
return this.wrapT;
|
|
},
|
|
getAvailableMinFilter: function () {
|
|
var minFilter = this.minFilter;
|
|
if (this.NPOT || !this.useMipmap) {
|
|
if (minFilter === glenum.NEAREST_MIPMAP_NEAREST ||
|
|
minFilter === glenum.NEAREST_MIPMAP_LINEAR
|
|
) {
|
|
return glenum.NEAREST;
|
|
}
|
|
else if (minFilter === glenum.LINEAR_MIPMAP_LINEAR ||
|
|
minFilter === glenum.LINEAR_MIPMAP_NEAREST
|
|
) {
|
|
return glenum.LINEAR;
|
|
}
|
|
else {
|
|
return minFilter;
|
|
}
|
|
}
|
|
else {
|
|
return minFilter;
|
|
}
|
|
},
|
|
getAvailableMagFilter: function () {
|
|
return this.magFilter;
|
|
},
|
|
|
|
nextHighestPowerOfTwo: function (x) {
|
|
--x;
|
|
for (var i = 1; i < 32; i <<= 1) {
|
|
x = x | x >> i;
|
|
}
|
|
return x + 1;
|
|
},
|
|
/**
|
|
* @param {clay.Renderer} renderer
|
|
*/
|
|
dispose: function (renderer) {
|
|
|
|
var cache = this._cache;
|
|
|
|
cache.use(renderer.__uid__);
|
|
|
|
var webglTexture = cache.get('webgl_texture');
|
|
if (webglTexture){
|
|
renderer.gl.deleteTexture(webglTexture);
|
|
}
|
|
cache.deleteContext(renderer.__uid__);
|
|
|
|
},
|
|
/**
|
|
* Test if image of texture is valid and loaded.
|
|
* @return {boolean}
|
|
*/
|
|
isRenderable: function () {},
|
|
|
|
/**
|
|
* Test if texture size is power of two
|
|
* @return {boolean}
|
|
*/
|
|
isPowerOfTwo: function () {}
|
|
});
|
|
|
|
Object.defineProperty(Texture.prototype, 'width', {
|
|
get: function () {
|
|
return this._width;
|
|
},
|
|
set: function (value) {
|
|
this._width = value;
|
|
}
|
|
});
|
|
Object.defineProperty(Texture.prototype, 'height', {
|
|
get: function () {
|
|
return this._height;
|
|
},
|
|
set: function (value) {
|
|
this._height = value;
|
|
}
|
|
});
|
|
|
|
/* DataType */
|
|
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.BYTE = glenum.BYTE;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.UNSIGNED_BYTE = glenum.UNSIGNED_BYTE;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.SHORT = glenum.SHORT;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.UNSIGNED_SHORT = glenum.UNSIGNED_SHORT;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.INT = glenum.INT;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.UNSIGNED_INT = glenum.UNSIGNED_INT;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.FLOAT = glenum.FLOAT;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.HALF_FLOAT = 0x8D61;
|
|
|
|
/**
|
|
* UNSIGNED_INT_24_8_WEBGL for WEBGL_depth_texture extension
|
|
* @type {number}
|
|
*/
|
|
Texture.UNSIGNED_INT_24_8_WEBGL = 34042;
|
|
|
|
/* PixelFormat */
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.DEPTH_COMPONENT = glenum.DEPTH_COMPONENT;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.DEPTH_STENCIL = glenum.DEPTH_STENCIL;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.ALPHA = glenum.ALPHA;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.RGB = glenum.RGB;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.RGBA = glenum.RGBA;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.LUMINANCE = glenum.LUMINANCE;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.LUMINANCE_ALPHA = glenum.LUMINANCE_ALPHA;
|
|
|
|
/**
|
|
* @see https://www.khronos.org/registry/webgl/extensions/EXT_sRGB/
|
|
* @type {number}
|
|
*/
|
|
Texture.SRGB = 0x8C40;
|
|
/**
|
|
* @see https://www.khronos.org/registry/webgl/extensions/EXT_sRGB/
|
|
* @type {number}
|
|
*/
|
|
Texture.SRGB_ALPHA = 0x8C42;
|
|
|
|
/* Compressed Texture */
|
|
Texture.COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
|
|
Texture.COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
|
|
Texture.COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
|
|
Texture.COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
|
|
|
|
/* TextureMagFilter */
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.NEAREST = glenum.NEAREST;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.LINEAR = glenum.LINEAR;
|
|
|
|
/* TextureMinFilter */
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.NEAREST_MIPMAP_NEAREST = glenum.NEAREST_MIPMAP_NEAREST;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.LINEAR_MIPMAP_NEAREST = glenum.LINEAR_MIPMAP_NEAREST;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.NEAREST_MIPMAP_LINEAR = glenum.NEAREST_MIPMAP_LINEAR;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.LINEAR_MIPMAP_LINEAR = glenum.LINEAR_MIPMAP_LINEAR;
|
|
|
|
/* TextureWrapMode */
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.REPEAT = glenum.REPEAT;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.CLAMP_TO_EDGE = glenum.CLAMP_TO_EDGE;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
Texture.MIRRORED_REPEAT = glenum.MIRRORED_REPEAT;
|
|
|
|
|
|
export default Texture;
|