mirror of
https://github.com/gpujs/gpu.js.git
synced 2026-01-18 16:04:10 +00:00
252 lines
6.8 KiB
JavaScript
252 lines
6.8 KiB
JavaScript
/**
|
|
* Utilities
|
|
* @class
|
|
* @constructor
|
|
*/
|
|
WebCLGLUtils = function() {
|
|
|
|
};
|
|
|
|
/** @private */
|
|
WebCLGLUtils.prototype.isPowerOfTwo = function(x) {
|
|
return (x & (x - 1)) == 0;
|
|
};
|
|
/** @private */
|
|
WebCLGLUtils.prototype.nextHighestPowerOfTwo = function(x) {
|
|
--x;
|
|
for (var i = 1; i < 32; i <<= 1) {
|
|
x = x | x >> i;
|
|
}
|
|
return x + 1;
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
WebCLGLUtils.prototype.loadQuad = function(node, length, height) {
|
|
var l=(length==undefined)?0.5:length;
|
|
var h=(height==undefined)?0.5:height;
|
|
this.vertexArray = [-l, -h, 0.0,
|
|
l, -h, 0.0,
|
|
l, h, 0.0,
|
|
-l, h, 0.0];
|
|
|
|
this.textureArray = [0.0, 0.0, 0.0,
|
|
1.0, 0.0, 0.0,
|
|
1.0, 1.0, 0.0,
|
|
0.0, 1.0, 0.0];
|
|
|
|
this.indexArray = [0, 1, 2, 0, 2, 3];
|
|
|
|
var meshObject = new Object;
|
|
meshObject.vertexArray = this.vertexArray;
|
|
meshObject.vertexItemSize = this.vertexItemSize;
|
|
meshObject.vertexNumItems = this.vertexNumItems;
|
|
|
|
meshObject.textureArray = this.textureArray;
|
|
meshObject.textureItemSize = this.textureItemSize;
|
|
meshObject.textureNumItems = this.textureNumItems;
|
|
|
|
meshObject.indexArray = this.indexArray;
|
|
meshObject.indexItemSize = this.indexItemSize;
|
|
meshObject.indexNumItems = this.indexNumItems;
|
|
|
|
return meshObject;
|
|
};
|
|
/** @private **/
|
|
WebCLGLUtils.prototype.getWebGLContextFromCanvas = function(canvas, ctxOpt) {
|
|
var gl;
|
|
try {
|
|
if(ctxOpt == undefined) gl = canvas.getContext("webgl");
|
|
else gl = canvas.getContext("webgl", ctxOpt);
|
|
} catch(e) {
|
|
gl = null;
|
|
}
|
|
if(gl == null) {
|
|
try {
|
|
if(ctxOpt == undefined) gl = canvas.getContext("experimental-webgl");
|
|
else gl = canvas.getContext("experimental-webgl", ctxOpt);
|
|
} catch(e) {
|
|
gl = null;
|
|
}
|
|
}
|
|
if(gl == null) gl = false;
|
|
return gl;
|
|
};
|
|
/**
|
|
* @private
|
|
*/
|
|
WebCLGLUtils.prototype.createShader = function(gl, name, sourceVertex, sourceFragment, shaderProgram) {
|
|
var _sv = false, _sf = false;
|
|
|
|
var makeDebug = (function(infoLog, shader) {
|
|
console.log(infoLog);
|
|
|
|
var arrErrors = [];
|
|
var errors = infoLog.split("\n");
|
|
for(var n = 0, f = errors.length; n < f; n++) {
|
|
if(errors[n].match(/^ERROR/gim) != null) {
|
|
var expl = errors[n].split(':');
|
|
var line = parseInt(expl[2]);
|
|
arrErrors.push([line,errors[n]]);
|
|
}
|
|
}
|
|
var sour = gl.getShaderSource(shader).split("\n");
|
|
sour.unshift("");
|
|
for(var n = 0, f = sour.length; n < f; n++) {
|
|
var lineWithError = false;
|
|
var errorStr = '';
|
|
for(var e = 0, fe = arrErrors.length; e < fe; e++) {
|
|
if(n == arrErrors[e][0]) {
|
|
lineWithError = true;
|
|
errorStr = arrErrors[e][1];
|
|
break;
|
|
}
|
|
}
|
|
if(lineWithError == false) {
|
|
console.log("%c"+n+' %c'+sour[n], "color:black", "color:blue");
|
|
} else {
|
|
console.log('%c►►%c'+n+' %c'+sour[n]+'\n%c'+errorStr, "color:red", "color:black", "color:blue", "color:red");
|
|
}
|
|
}
|
|
}).bind(this);
|
|
|
|
|
|
var shaderVertex = gl.createShader(gl.VERTEX_SHADER);
|
|
gl.shaderSource(shaderVertex, sourceVertex);
|
|
gl.compileShader(shaderVertex);
|
|
if (!gl.getShaderParameter(shaderVertex, gl.COMPILE_STATUS)) {
|
|
alert(name+' ERROR (vertex program). See console.');
|
|
|
|
var infoLog = gl.getShaderInfoLog(shaderVertex);
|
|
console.log("%c"+name+' ERROR (vertex program)', "color:red");
|
|
|
|
if(infoLog != undefined)
|
|
makeDebug(infoLog, shaderVertex);
|
|
} else {
|
|
gl.attachShader(shaderProgram, shaderVertex);
|
|
_sv = true;
|
|
}
|
|
|
|
var shaderFragment = gl.createShader(gl.FRAGMENT_SHADER);
|
|
gl.shaderSource(shaderFragment, sourceFragment);
|
|
gl.compileShader(shaderFragment);
|
|
if (!gl.getShaderParameter(shaderFragment, gl.COMPILE_STATUS)) {
|
|
alert(name+' ERROR (fragment program). See console.');
|
|
|
|
var infoLog = gl.getShaderInfoLog(shaderFragment);
|
|
console.log("%c"+name+' ERROR (fragment program)', "color:red");
|
|
|
|
if(infoLog != undefined)
|
|
makeDebug(infoLog, shaderFragment);
|
|
} else {
|
|
gl.attachShader(shaderProgram, shaderFragment);
|
|
_sf = true;
|
|
}
|
|
|
|
if(_sv == true && _sf == true) {
|
|
gl.linkProgram(shaderProgram);
|
|
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
|
|
alert('Error in shader '+name);
|
|
console.log('Error shader program '+name+':\n ');
|
|
if(gl.getProgramInfoLog(shaderProgram) != undefined) {
|
|
console.log(gl.getProgramInfoLog(shaderProgram));
|
|
}
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Get Uint8Array from HTMLImageElement
|
|
* @returns {Uint8Array}
|
|
* @param {HTMLImageElement} imageElement
|
|
*/
|
|
WebCLGLUtils.prototype.getUint8ArrayFromHTMLImageElement = function(imageElement) {
|
|
var e = document.createElement('canvas');
|
|
e.width = imageElement.width;
|
|
e.height = imageElement.height;
|
|
var ctx2D_tex = e.getContext("2d");
|
|
ctx2D_tex.drawImage(imageElement, 0, 0);
|
|
var arrayTex = ctx2D_tex.getImageData(0, 0, imageElement.width, imageElement.height);
|
|
|
|
return arrayTex.data;
|
|
};
|
|
/**
|
|
* Dot product vector4float
|
|
* @private
|
|
*/
|
|
WebCLGLUtils.prototype.dot4 = function(vector4A,vector4B) {
|
|
return vector4A[0]*vector4B[0] + vector4A[1]*vector4B[1] + vector4A[2]*vector4B[2] + vector4A[3]*vector4B[3];
|
|
};
|
|
/**
|
|
* Compute the fractional part of the argument. fract(pi)=0.14159265...
|
|
* @private
|
|
*/
|
|
WebCLGLUtils.prototype.fract = function(number) {
|
|
return number - Math.floor(number);
|
|
};
|
|
/**
|
|
* Pack 1float (0.0-1.0) to 4float rgba (0.0-1.0, 0.0-1.0, 0.0-1.0, 0.0-1.0)
|
|
* @private
|
|
*/
|
|
WebCLGLUtils.prototype.pack = function(v) {
|
|
var bias = [1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0];
|
|
|
|
var r = v;
|
|
var g = this.fract(r * 255.0);
|
|
var b = this.fract(g * 255.0);
|
|
var a = this.fract(b * 255.0);
|
|
var colour = [r, g, b, a];
|
|
|
|
var dd = [colour[1]*bias[0],colour[2]*bias[1],colour[3]*bias[2],colour[3]*bias[3]];
|
|
|
|
return [colour[0]-dd[0],colour[1]-dd[1],colour[2]-dd[2],colour[3]-dd[3] ];
|
|
};
|
|
/**
|
|
* Unpack 4float rgba (0.0-1.0, 0.0-1.0, 0.0-1.0, 0.0-1.0) to 1float (0.0-1.0)
|
|
* @private
|
|
*/
|
|
WebCLGLUtils.prototype.unpack = function(colour) {
|
|
var bitShifts = [1.0, 1.0/255.0, 1.0/(255.0*255.0), 1.0/(255.0*255.0*255.0)];
|
|
return this.dot4(colour, bitShifts);
|
|
};
|
|
/**
|
|
* Get pack GLSL function string
|
|
* @returns {String}
|
|
*/
|
|
WebCLGLUtils.prototype.packGLSLFunctionString = function() {
|
|
return 'vec4 pack (float depth) {\n'+
|
|
'const vec4 bias = vec4(1.0 / 255.0,\n'+
|
|
'1.0 / 255.0,\n'+
|
|
'1.0 / 255.0,\n'+
|
|
'0.0);\n'+
|
|
|
|
'float r = depth;\n'+
|
|
'float g = fract(r * 255.0);\n'+
|
|
'float b = fract(g * 255.0);\n'+
|
|
'float a = fract(b * 255.0);\n'+
|
|
'vec4 colour = vec4(r, g, b, a);\n'+
|
|
|
|
'return colour - (colour.yzww * bias);\n'+
|
|
'}\n';
|
|
};
|
|
/**
|
|
* Get unpack GLSL function string
|
|
* @returns {String}
|
|
*/
|
|
WebCLGLUtils.prototype.unpackGLSLFunctionString = function() {
|
|
return 'float unpack (vec4 colour) {\n'+
|
|
'const vec4 bitShifts = vec4(1.0,\n'+
|
|
'1.0 / 255.0,\n'+
|
|
'1.0 / (255.0 * 255.0),\n'+
|
|
'1.0 / (255.0 * 255.0 * 255.0));\n'+
|
|
'return dot(colour, bitShifts);\n'+
|
|
'}\n';
|
|
};
|