/**
* 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;