/**
* Creates buffer and sets up shaders for an object3D
* @param {Object} gl
* @param {Ayce.Object3D} object3D
* @param {Ayce.LightContainer} lightContainer
* @class
* @constructor
*/
Ayce.BufferMulti = function (gl, object3D, lightContainer) {
if (!object3D instanceof Ayce.Object3D) throw "Can't create buffers for " + object3D;
var modelViewMatrix = new Ayce.Matrix4();
modelViewMatrix.transposeUniform = false;
//VR
var leftMatrix = new Ayce.Matrix4();
var rightMatrix = new Ayce.Matrix4();
var leftNormalMatrix = new Ayce.Matrix3();
var rightNormalMatrix = new Ayce.Matrix3();
var leftPerspektive = null;
var rightPerspektive = null;
var VALUES_PER_POSITION = 3;
var VALUES_PER_NORMAL = 3;
var VALUES_PER_TEXTURE_COORD = 2;
var VALUES_PER_TEXTURE_INDEX = 1;
var VALUES_PER_COLOR = 4;
var useLighting = Boolean(object3D.normals) && lightContainer.lightsCount > 0;
var useNormals = Boolean(object3D.normals) && (useLighting || object3D.shader);
var textureCount = Array.isArray(object3D.imageSrc) ? object3D.imageSrc.length : 1;
var useWireframe = object3D.isWireframe;
this.transparent = object3D.transparent;
var isParticleSystem = Boolean(object3D.geometries && object3D.velocities && object3D.rotationAngles && object3D.lifetimes && object3D.gravities && object3D.gravityExps);
//Shader Attributes
//[attributeName, valueLength, array]
var attributes = [];
attributes.push(["aVertexPosition", VALUES_PER_POSITION, object3D.vertices]);
if(object3D.textureCoords && object3D.imageSrc) attributes.push(["aTextureCoord", VALUES_PER_TEXTURE_COORD, object3D.textureCoords]);
if(object3D.textureCoords && object3D.imageSrc && object3D.textureIndices && textureCount > 1) attributes.push(["aTextureIndex", VALUES_PER_TEXTURE_INDEX, object3D.textureIndices]);
if(object3D.colors)attributes.push(["aVertexColor", VALUES_PER_COLOR, object3D.colors]);
if(useNormals)attributes.push(["aVertexNormal", VALUES_PER_NORMAL, object3D.normals]);
if(object3D.shaderAttributes)Array.prototype.push.apply(attributes, object3D.shaderAttributes);
//Shader Uniforms
var pMatrixUniform = {
transposeUniform: false,
data: []
};
var timeObject = {
time: 0,
startTime: Date.now()
};
var uniformValues = {
useTexture: Boolean(object3D.textureCoords && object3D.imageSrc),
useLighting: useLighting,
useMultiTex: Boolean(object3D.textureIndices),
normalMatrix: new Ayce.Matrix3(),
useSpecularMap: Boolean(object3D.specularMap),
useNormalMap: Boolean(object3D.normalMap)
};
var uniforms = [];
//[uniformName, uniformType, valueObject, uniformArguments]
uniforms.push(["uPMatrix", "uniformMatrix4fv", pMatrixUniform, ["transposeUniform", "data"]]);
uniforms.push(["uMVMatrix", "uniformMatrix4fv", modelViewMatrix, ["transposeUniform", "data"]]);
if(useNormals){
uniformValues.normalMatrix.transposeUniform = false;
uniforms.push(["uNMatrix", "uniformMatrix3fv", uniformValues.normalMatrix, ["transposeUniform", "data"]]);
}
if(useLighting){
uniforms.push(["uAmbientColor", "uniform3f", lightContainer.ambientLight, ["red", "green", "blue"]]);
uniforms.push(["uLightIndex", "uniform1f", lightContainer, ["lightsCount"]]);
uniforms.push(["uPointLightingLocations", "uniform3fv", lightContainer, ["locationsArray"]]);
uniforms.push(["uPointLightingColors", "uniform3fv", lightContainer, ["colorsArray"]]);
uniforms.push(["uSpecularColors", "uniform3fv", lightContainer, ["specColorsArray"]]);
uniforms.push(["uShininess", "uniform1f", object3D, ["shininess"]]);
}
if(isParticleSystem){
uniforms.push(["uTime", "uniform1f", timeObject, ["time"]]);
}
if(object3D.shaderUniforms)Array.prototype.push.apply(uniforms, object3D.shaderUniforms);
//Load Shader
var shaderVert = null;
var shaderFrag = null;
var shaderID = "";
if(object3D.shader){
// console.log("Loading Shader File: " + object3D.shader);
shaderVert = Ayce.XMLLoader.getSourceSynch(object3D.shader + ".vert");
shaderFrag = Ayce.XMLLoader.getSourceSynch(object3D.shader + ".frag");
shaderID = "A"+object3D.shader;
if(object3D.logVertexShader) console.log(shaderVert);
if(object3D.logFragmentShader) console.log(shaderFrag);
}else{
var shaderGenerator = new Ayce.ShaderGenerator();
if(useLighting){
shaderGenerator.useVertexLighting = Boolean(object3D.normals && !object3D.useFragmentLighting);
shaderGenerator.lightsCount = lightContainer.lightsCount;
shaderGenerator.useFragmentLighting = Boolean(object3D.normals && object3D.useFragmentLighting);
shaderGenerator.useSpecularLighting = object3D.useSpecularLighting;
}
shaderGenerator.useNormals = useNormals;
shaderGenerator.useColor = Boolean(object3D.colors);
shaderGenerator.texturesCount = Array.isArray(object3D.imageSrc) ? object3D.imageSrc.length : 1;
shaderGenerator.useTexture = Boolean(object3D.imageSrc && object3D.textureCoords);
shaderGenerator.useSpecularMap = Boolean(object3D.specularMap && object3D.useSpecularLighting);
shaderGenerator.useNormalMap = Boolean(object3D.normalMap);
shaderGenerator.isParticleSystem = isParticleSystem;
shaderGenerator.init();
shaderVert = shaderGenerator.vertexShader;
shaderFrag = shaderGenerator.fragmentShader;
shaderID = "B"+shaderGenerator.useNormals+shaderGenerator.lightsCount+shaderGenerator.texturesCount+
shaderGenerator.useVertexLighting+shaderGenerator.useFragmentLighting+
shaderGenerator.useTexture+shaderGenerator.useColor+shaderGenerator.useSpecularMap+
shaderGenerator.useNormalMap+shaderGenerator.isParticleSystem;
if(object3D.logVertexShader) console.log(shaderVert.replace(/;/g, ";\n").replace(/{/g, "{\n").replace(/}/g, "}\n"));
if(object3D.logFragmentShader) console.log(shaderFrag.replace(/;/g, ";\n").replace(/{/g, "{\n").replace(/}/g, "}\n"));
}
var shader = null;
if(gl.shaders[shaderID]){
shader = gl.shaders[shaderID];
}
else{
shader = new Ayce.Shader(gl, shaderVert, shaderFrag);
gl.shaders[shaderID] = shader;
}
//Create Buffer
var drawMode = useWireframe ? gl.LINES : undefined;
var buffer = new Ayce.Buffer(gl, object3D, shader, attributes, uniforms, drawMode);
if(object3D.twoFaceTransparency) {
var indices = object3D.indices;
indices = indices.slice().reverse().concat(indices);
buffer.indices = new Uint16Array(indices);
}
else{
buffer.indices = new Uint16Array(object3D.indices);
}
buffer.useTexture = Boolean(object3D.textureCoords && object3D.imageSrc);
buffer.useSpecularMap = Boolean(object3D.textureCoords && object3D.specularMap);
buffer.useNormalMap = Boolean(object3D.textureCoords && object3D.normalMap);
buffer.useTransparency = object3D.transparent;
buffer.texturesO3D = (Array.isArray(object3D.imageSrc)) ? object3D.imageSrc : [object3D.imageSrc];
buffer.isSkybox = Boolean(object3D.isSkybox);
buffer.init();
/*********************************************
*
* Render function
*
*********************************************/
var copyMatrix = new Ayce.Matrix4();
/**
* Updates perspective Matrix
* @param {Ayce.Camera} camera
*/
this.update = function (camera) {
//Create ModelViewMatrix
Ayce.Matrix4.prototype.copyToMatrix(object3D.modelMatrix, modelViewMatrix);
modelViewMatrix.apply(camera.getViewMatrix());
Ayce.Matrix4.prototype.copyToMatrix(modelViewMatrix, copyMatrix);
copyMatrix.invert();
copyMatrix.transpose();
copyMatrix.getMatrix3(uniformValues.normalMatrix);
pMatrixUniform.data = camera.getPerspectiveMatrix().data;
timeObject = Date.now()-timeObject.startTime;
buffer.update();
};
/**
* Renders buffer
*/
this.render = function(){
if(!object3D.visible)return;
buffer.render();
};
/**
* Updates VR perspective Matrices
* @param {Ayce.Camera} camera
*/
this.updateVR = function(camera){
//Create ModelViewMatrix Left eye
Ayce.Matrix4.prototype.copyToMatrix(object3D.modelMatrix, leftMatrix);
leftMatrix.apply(camera.getViewMatrix("left"));
Ayce.Matrix4.prototype.copyToMatrix(leftMatrix, copyMatrix);
copyMatrix.invert();
copyMatrix.transpose();
copyMatrix.getMatrix3(leftNormalMatrix);
//Create ModelViewMatrix Right eye
Ayce.Matrix4.prototype.copyToMatrix(object3D.modelMatrix, rightMatrix);
rightMatrix.apply(camera.getViewMatrix("right"));
Ayce.Matrix4.prototype.copyToMatrix(rightMatrix, copyMatrix);
copyMatrix.invert();
copyMatrix.transpose();
copyMatrix.getMatrix3(rightNormalMatrix);
//Set Perspektive Matrix
leftPerspektive = camera.getPerspectiveMatrix("left");
rightPerspektive = camera.getPerspectiveMatrix("right");
//Update Buffer
buffer.update();
};
/**
* Renders VR buffers
* @param {String} eye
*/
this.renderVR = function(eye){
if(!object3D.visible)return;
if(eye === "left"){
modelViewMatrix.data = leftMatrix.data;
uniformValues.normalMatrix.data = leftNormalMatrix.data;
pMatrixUniform.data = leftPerspektive.data;
lightContainer.locationsArray = lightContainer.locationsArrayLeftEye;
}
else if(eye === "right"){
modelViewMatrix.data = rightMatrix.data;
uniformValues.normalMatrix.data = rightNormalMatrix.data;
pMatrixUniform.data = rightPerspektive.data;
lightContainer.locationsArray = lightContainer.locationsArrayRightEye;
}
buffer.render();
};
this.dispose = function(){
buffer.dispose();
};
};
Ayce.BufferMulti.prototype = {
};