threex
Version:
Game Extensions for three.js http://www.threejsgames.com/extensions/
174 lines (153 loc) • 5.62 kB
JavaScript
var THREEx = THREEx || {}
//////////////////////////////////////////////////////////////////////////////////
// //
//////////////////////////////////////////////////////////////////////////////////
THREEx.TextureUtils = {};
/**
* set the alpha channel of a texture based on its luminance.
* very usefull to generate alpha channel from image which doesnt have one (like .jpg files)
*
* @param {THREE.texture} texture the texture to modify
* @param {function} computeAlpha function(p, i) which returns the alpha
* @param {number} power the value by which the luminance will be powered
*/
THREEx.TextureUtils.generateAlpha = function(texture, computeAlpha){
// sanity check
console.assert( texture instanceof THREE.Texture );
// create a canvas
var image = texture.image;
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
// draw the image in it
ctx.drawImage(image, 0, 0);
// create an alpha channel based on color luminance
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var p = imgData.data;
for(var i = 0, y = 0; y < canvas.height; y++){
for(var x = 0; x < canvas.width; x++, i += 4){
// compute alpha pixel value
var alpha = computeAlpha(p, i);
// set the alpha in the imageData
p[i+3] = alpha;
}
}
// put the generated image in the canvas
ctx.putImageData(imgData, 0, 0);
// update the texture object itself
texture.image = canvas;
texture.needsUpdate = true;
}
/**
* set the alpha channel of a texture based on its luminance.
* very usefull to generate alpha channel from image which doesnt have one (like .jpg files)
* TODO Find a better name. shorter one
*
* @param {THREE.texture} texture the texture to modify
* @param {number} multiplier the value by which the luminance will be multiplied
* @param {number} power the value by which the luminance will be powered
*/
THREEx.TextureUtils.generateAlphaFromLuminance = function(texture, multiplier, power){
// handle parameters polymorphism
multiplier = multiplier !== undefined ? multiplier : 1;
power = power !== undefined ? power : 1;
// forward to THREEx.TextureUtils.setAlphaFromLuminance
THREEx.TextureUtils.generateAlpha(texture, function(p, i){
// compute luminance
var luminance = (0.2126*p[i+0]) + (0.7152*p[i+1]) + (0.0722*p[i+2]);
// increase contrast of the luminance based on 'power'
// TODO experiment with normal tween funciton
var alpha = Math.pow(luminance/255, power)*255;
// set the luminance after mutiplying it
alpha *= multiplier;
return alpha;
});
}
//////////////////////////////////////////////////////////////////////////////////
// //
//////////////////////////////////////////////////////////////////////////////////
/**
* Load multiple images
*
* @param {array.<string>} urls the urls to load
* @param {function(Array.<Image>, Array.<string>)} onLoad the function
* called when all the images are loaded
*/
THREEx.TextureUtils.loadImages = function(urls, onLoad){
// handle parameter polymorphism
if( typeof(urls) === 'string' ) urls = [urls];
// init images
var images = new Array(urls.length);
// load all the images and convert them
var flow = Flow();
urls.forEach(function(url, idx){
flow.par(function(next){
var image = new Image;
// TODO what if the images isnt properly loaded
image.onload = function(){
images[idx] = image;
next();
};
image.src = url;
});
});
// build the function which is run once all is loaded
flow.seq(function(){
//console.log("all flow completed")
// notify the caller
onLoad(images, urls);
});
return;
/**
* Flow control - from https://github.com/jeromeetienne/gowiththeflow.js
*/
function Flow(){
var self, stack = [], timerId = setTimeout(function(){ timerId = null; self._next(); }, 0);
return self = {
destroy : function(){ timerId && clearTimeout(timerId); },
par : function(callback, isSeq){
if(isSeq || !(stack[stack.length-1] instanceof Array)) stack.push([]);
stack[stack.length-1].push(callback);
return self;
},seq : function(callback){ return self.par(callback, true); },
_next : function(err, result){
var errors = [], results = [], callbacks = stack.shift() || [], nbReturn = callbacks.length, isSeq = nbReturn == 1;
callbacks && callbacks.forEach(function(fct, index){
fct(function(error, result){
errors[index] = error;
results[index] = result;
if(--nbReturn == 0) self._next(isSeq?errors[0]:errors, isSeq?results[0]:results)
}, err, result)
})
}
}
};
};
/**
* Build a canvas spritesheet based on opts
*/
THREEx.TextureUtils.buildTiledSpriteSheet = function(opts){
var images = opts.images || console.assert(false);
var spriteW = opts.spriteW || console.assert(false);
var spriteH = opts.spriteH || console.assert(false);
var nSpriteX = opts.nSpriteX || 1;
var nSpriteY = opts.nSpriteY || (images.length / nSpriteX);
var canvasW = opts.canvasW || (spriteW * nSpriteX);
var canvasH = opts.canvasH || (spriteH * nSpriteY);
// create the canvas
var canvas = document.createElement('canvas');
canvas.width = canvasW;
canvas.height = canvasH;
var ctx = canvas.getContext('2d');
// draw each images in the canvas
images.forEach(function(image, idx){
var destX = spriteW * (idx % nSpriteX);
var destY = spriteH * Math.floor(idx / nSpriteX);
ctx.drawImage(image,
0, 0, image.width, image.height,
destX, destY, spriteW, spriteH);
});
// return the resulting canvas
return canvas;
}