var inherit = require('../inherit');
var timestamp = require('../timestamp');
var vgl = require('../vgl');
/**
* Switch to a specific texture unit.
*
* @param {vgl.renderState} renderState An object that contains the context
* used for drawing.
* @param {number} textureUnit The number of the texture unit [0-15].
* @private
*/
function activateTextureUnit(renderState, textureUnit) {
if (textureUnit >= 0 && textureUnit <= 31) {
renderState.m_context.activeTexture(vgl.GL.TEXTURE0 + textureUnit);
} else {
throw Error('[error] Texture unit ' + textureUnit + ' is not supported');
}
}
/**
* Create a new instance of class webgl_lookupTable2D.
*
* @class
* @alias geo.webgl.lookupTable2D
* @param {object} arg Options object.
* @param {number} [arg.maxWidth] Maximum width to use for the texture. If the
* number of colors set is less than this, the texture is 1D. If greater, it
* will be a rectangle of maxWidth x whatever height is necessary.
* @param {number[]} [arg.colorTable] Initial color table for the texture.
* This is of the form RGBARGBA... where each value is an integer on the
* scale [0,255].
* @extends vgl.texture
* @returns {geo.webgl.lookupTable2D}
*/
var webgl_lookupTable2D = function (arg) {
'use strict';
if (!(this instanceof webgl_lookupTable2D)) {
return new webgl_lookupTable2D(arg);
}
arg = arg || {};
vgl.texture.call(this);
var m_setupTimestamp = timestamp(),
m_maxWidth = arg.maxWidth || 4096,
m_colorTable = new Uint8Array([0, 0, 0, 0]),
m_colorTableOrig,
m_this = this;
/**
* Create lookup table, initialize parameters, and bind data to it.
*
* @param {vgl.renderState} renderState An object that contains the context
* used for drawing.
*/
this.setup = function (renderState) {
activateTextureUnit(renderState, m_this.textureUnit());
renderState.m_context.deleteTexture(m_this.m_textureHandle);
m_this.m_textureHandle = renderState.m_context.createTexture();
renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, m_this.m_textureHandle);
renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_MIN_FILTER, vgl.GL.NEAREST);
renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_MAG_FILTER, vgl.GL.NEAREST);
renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_WRAP_S, vgl.GL.CLAMP_TO_EDGE);
renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_WRAP_T, vgl.GL.CLAMP_TO_EDGE);
renderState.m_context.pixelStorei(vgl.GL.UNPACK_ALIGNMENT, 1);
renderState.m_context.pixelStorei(vgl.GL.UNPACK_FLIP_Y_WEBGL, true);
renderState.m_context.texImage2D(
vgl.GL.TEXTURE_2D, 0, vgl.GL.RGBA, m_this.width, m_this.height, 0,
vgl.GL.RGBA, vgl.GL.UNSIGNED_BYTE, m_colorTable);
renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, null);
m_setupTimestamp.modified();
};
/**
* Get/set color table.
*
* @param {number[]} [val] An array of RGBARGBA... integers on a scale
* of [0, 255]. `undefined` to get the current value.
* @returns {number[]|this}
*/
this.colorTable = function (val) {
if (val === undefined) {
return m_colorTableOrig;
}
m_colorTableOrig = val;
if (val.length < 4) {
val = [0, 0, 0, 0];
}
m_this.width = Math.min(m_maxWidth, val.length / 4);
m_this.height = Math.ceil(val.length / 4 / m_maxWidth);
if (!(val instanceof Uint8Array) || val.length !== m_this.width * m_this.height * 4) {
if (val.length < m_this.width * m_this.height * 4) {
val = val.concat(new Array(m_this.width * m_this.height * 4 - val.length).fill(0));
}
m_colorTable = new Uint8Array(val);
} else {
m_colorTable = val;
}
m_this.modified();
return m_this;
};
/**
* Get maxWidth value.
*
* @returns {number} The maxWidth of the texture used.
*/
this.maxWidth = function () {
return m_maxWidth;
};
this.colorTable(arg.colorTable || []);
return this;
};
inherit(webgl_lookupTable2D, vgl.texture);
module.exports = webgl_lookupTable2D;