/* <copyright> This file contains proprietary software owned by Motorola Mobility, Inc.<br/> No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. </copyright> */ /** * supported uniform types */ function __UNIFORMTYPE() { this.INT = 0x3F0; this.FLOAT = 0x3E8; this.FLOAT2 = 0x3E9; this.FLOAT3 = 0x3EA; this.FLOAT4 = 0x3EB; this.MATRIX3 = 0x3EC; this.MATRIX4 = 0x3ED; this.TEXTURE2D = 0x3EE; this.TEXTURECUBE = 0x3EF; } UNIFORMTYPE = new __UNIFORMTYPE(); /** * RenderObject - contains references to all the data need to render, including vertex buffers, uniform handles, and matrices * @param shaderHandle */ function RenderObject(shaderHandle) { this.shader = shaderHandle; this.world = null; this.bindings = new ShaderData(); this.initRenderProc = null; this.renderProc = null; this.postRenderProc = null; } /** * Adds a uniform to the render object to bound during render * @param name - name of the uniform * @param value - reference to value that will get bound (will be referenced from now on, don't delete the ref) * @param type - type of uniform, use UNIFORMTYPE */ RenderObject.prototype.addUniform = function(name, value, type) { var uniform = gl.getUniformLocation(this.shader, name); if(uniform) { uniform.debugName = name; this.bindings.uniforms.push( new UniformPair(uniform, value, type)); } /* else { gl.console.log("ERROR: uniform - " + name + " not found!"); } */ }; /** * Adds a uniform to the render object to bound during render * @param name - name of the uniform * @param value - reference to value that will get bound (will be referenced from now on, don't delete the ref) * @param type - type of uniform, use UNIFORMTYPE */ RenderObject.prototype.addUniformArray = function(name, value, type, size) { var uniform = gl.getUniformLocation(this.shader, name); if (uniform) { for (var index=0; index<size; index) { uniform.debugName = name+index; this.bindings.uniforms.push( new UniformPair(uniform, value[index], type)); uniform+=value[index].length; value++; } } /* else { gl.console.log("ERROR: uniform - " + name + " not found!"); }*/ }; /** * Add texture to uniform * @param name - handle to the texture * @param unit - texture slot to use * @param type - UNIFORMTYPE.TEXTURE2D or TEXTURE2D.TEXTURECUBE */ RenderObject.prototype.addTexture = function(name, unit, type) { var uniform = gl.getUniformLocation(this.shader, name); if(uniform) { this.bindings.textures.push( new TexUniform(uniform, unit, type)); } /* else { gl.console.log("ERROR: texture uniform - " + name + " not found!"); } */ }; /** * Adds a vertex buffer to the render object * @param buffer - buffer to use * @param glBufferType - type of buffer i.e. gl.ARRAY_BUFFER * @param attribSize - if using attrib the size of an element (3 for vec3) * @param attribIndex - the index slot the attrib goes in * @param glAttribType - type of the attrib i.e. gl.FLOAT */ RenderObject.prototype.addBuffers = function(buffer, glBufferType, attribSize, attribIndex, glAttribType) { //gl.useProgram(this.shader); if( attribSize == undefined || attribIndex == undefined || glAttribType == undefined || attribSize == null || attribIndex == null || glAttribType == null ) { this.bindings.buffers.push( new BufferAttrib(buffer, glBufferType, null, null, null)); } else { this.bindings.buffers.push( new BufferAttrib(buffer, glBufferType, attribSize, attribIndex, glAttribType)); } //gl.useProgram(null); }; /** * bind the matrices, vertices and floats to shader uniforms */ RenderObject.prototype.bindUniforms = function() { for(var uniIndex = 0; uniIndex < this.bindings.uniforms.length; uniIndex++) { var bind = this.bindings.uniforms[uniIndex]; switch(bind.type) { case UNIFORMTYPE.INT: gl.uniform1i(bind.uniform, bind.value); break; case UNIFORMTYPE.FLOAT: gl.uniform1f(bind.uniform, bind.value); break; case UNIFORMTYPE.FLOAT2: gl.uniform2fv(bind.uniform, bind.value); break; case UNIFORMTYPE.FLOAT3: gl.uniform3fv(bind.uniform, bind.value); break; case UNIFORMTYPE.FLOAT4: gl.uniform4fv(bind.uniform, bind.value); break; case UNIFORMTYPE.MATRIX3: gl.uniformMatrix3fv(bind.uniform, false, bind.value); break; case UNIFORMTYPE.MATRIX4: gl.uniformMatrix4fv(bind.uniform, false, bind.value); break; default: // gl.console.log("RenderObject: trying to bind unknown texture type"); break; } } }; /** * binds the texture uniform to texture slots */ RenderObject.prototype.bindTextures = function() { for(var uniIndex = 0; uniIndex < this.bindings.textures.length; uniIndex++) { var bind = this.bindings.textures[uniIndex]; var error = 0; switch(bind.type) { case UNIFORMTYPE.TEXTURE2D: gl.activeTexture(gl.TEXTURE0 + bind.unit); gl.uniform1i(bind.uniform, bind.unit); break; case UNIFORMTYPE.TEXTURECUBE: gl.activeTexture(gl.TEXTURE0 + bind.unit); gl.uniform1i(bind.uniform, bind.unit); break; default: // gl.console.log("RenderObject: trying to bind unknown texture type"); break; } } }; /** * Binds all buffers and enables any vertexAttribs */ RenderObject.prototype.bindBuffers = function() { for (var bufIndex = 0; bufIndex < this.bindings.buffers.length; bufIndex++) { var bind = this.bindings.buffers[bufIndex]; gl.bindBuffer(bind.glBufferType, bind.buffer); if (bind.glAttribType != null) { // enable the attribute and point buffer to it gl.enableVertexAttribArray(bind.attribIndex); gl.vertexAttribPointer(bind.attribIndex, bind.attribSize, bind.glAttribType, false, 0, 0); } } }; RenderObject.prototype.unBindBuffers=function() { for(var bufIndex=0;bufIndex<this.bindings.buffers.length;bufIndex++) { var bind=this.bindings.buffers[bufIndex]; if(bind.glAttribType!=null) { // enable the attribute and point buffer to it gl.disableVertexAttribArray(bind.attribIndex); } gl.bindBuffer(bind.glBufferType, null); } }; RenderObject.prototype.initialize = function(initRenderProc) { initRenderProc(this); }; RenderObject.prototype.clear = function() { this.world = mat4.identity(); this.bindings = new ShaderData(); }; /*** * Shader data proto */ function ShaderData() { this.uniforms = []; this.textures = []; this.buffers = []; } /*** * Structure to contain reference data for binding to during render */ function UniformPair(uniform, value, type) { this.uniform = uniform; this.value = value; this.type = type; } function TexUniform(uniform, unit, type) { this.uniform = uniform; this.unit = unit; this.type = type; } function BufferAttrib(buffer, glBufferType, attribSize, attribIndex, glAttribType) { // buffer data this.buffer = buffer; this.glBufferType = glBufferType; // attribute data (can be null) this.attribSize = attribSize; this.glAttribType = glAttribType; this.attribIndex = attribIndex; } /*-------------------------------------------------------------RENDER PROC HANDLES----------------------------------------------------------------------*/ renderProcDefault = __renderProcDefault; postRenderProcDefault = __postRenderProcDefault; renderProcLines = __renderProcLines; renderProcScreenQuad = __renderProcScreenQuad; renderProcDepthMap = __renderProcDepthMap; renderProcShadowReceiver= __renderProcShadowReceiver; renderProcShadowProjection = __renderProcShadowProjection; /*----------------------------------------------------------------RENDER PROCS--------------------------------------------------------------------------*/ function __setActiveTexture(id, texture) { gl.activeTexture(id); gl.bindTexture(gl.TEXTURE_2D, texture); } function __renderProcDefault(primSet) { //gl.disable(gl.DEPTH_TEST); //gl.disable(gl.CULL_FACE); var activeCam = g_cameraManager.getActiveCamera(); gl.mvMatrix = activeCam.view; gl.mvMatrix = mat4.mul(gl.mvMatrix, primSet.parentMesh.world); gl.invMvMatrix = mat4.inverse(gl.mvMatrix); gl.normalMatrix = mat4.transpose( gl.invMvMatrix ); // update shadow light MV matrix gl.useProgram(arrayPeek(primSet.material.shader).shaderHandle); // Bind the texture gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, arrayPeek(primSet.material.tex.set1).diff ); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, arrayPeek(primSet.material.tex.set2).diff ); gl.activeTexture(gl.TEXTURE2); gl.bindTexture(gl.TEXTURE_2D, arrayPeek(primSet.material.tex.set1).spec ); gl.activeTexture(gl.TEXTURE3); gl.bindTexture(gl.TEXTURE_2D, arrayPeek(primSet.material.tex.set2).spec ); gl.activeTexture(gl.TEXTURE4); gl.bindTexture(gl.TEXTURE_2D, arrayPeek(primSet.material.tex.env) ); gl.activeTexture(gl.TEXTURE5); gl.bindTexture(gl.TEXTURE_2D, arrayPeek(primSet.material.tex.envDiff) ); // stickers __setActiveTexture(gl.TEXTURE7, g_cam.stickerTexture[0]); __setActiveTexture(gl.TEXTURE8, g_cam.stickerTexture[1]); __setActiveTexture(gl.TEXTURE9, g_cam.stickerTexture[2]); __setActiveTexture(gl.TEXTURE10, g_cam.stickerTexture[3]); __setActiveTexture(gl.TEXTURE11, g_cam.stickerTexture[4]); __setActiveTexture(gl.TEXTURE12, g_cam.stickerTexture[5]); __setActiveTexture(gl.TEXTURE13, g_cam.stickerTexture[6]); __setActiveTexture(gl.TEXTURE14, g_cam.stickerTexture[7]); // copy current cams matrix for (var i = 0; i < 8; i++) { primSet.parentMesh.stickers[i].load(g_cam.stickers[i]); primSet.parentMesh.stickersPos[i].setvec(g_cam.stickersPos[i]); } __setActiveTexture(gl.TEXTURE15, arrayPeek(primSet.material.tex.set1).norm); __setActiveTexture(gl.TEXTURE6, arrayPeek(primSet.material.tex.set2).norm); //bind buffers and attribs arrayPeek(primSet.material.renderObj).bindBuffers(); // bind shader uniforms arrayPeek(primSet.material.renderObj).bindTextures(); arrayPeek(primSet.material.renderObj).bindUniforms(); gl.drawElements(gl.TRIANGLES, primSet.size, gl.UNSIGNED_SHORT, primSet.indexInBuffer*2); } function __renderProcLines(renderObj, r, g, b, a) { gl.useProgram(renderObj.shader); renderObj.lineColor[0] = r; renderObj.lineColor[1] = g; renderObj.lineColor[2] = b; renderObj.lineColor[3] = a; //bind buffers and attribs renderObj.bindBuffers(); // bind shader uniforms renderObj.bindUniforms(); // draw the AABBs gl.drawArrays(gl.LINES, 0, renderObj.numPoints/3); gl.useProgram(null); } function __renderProcScreenQuad(quad) { gl.disable(gl.DEPTH_TEST); gl.useProgram(quad.shader); //bind buffers and attribs quad.renderObj.bindBuffers(); // bind shader uniforms quad.renderObj.bindTextures(); quad.renderObj.bindUniforms(); // render var offset = 0; // Bind the texture gl.bindTexture(gl.TEXTURE_2D, quad.texture); gl.drawArrays(gl.TRIANGLES, 0, 6); gl.useProgram(null); gl.enable(gl.DEPTH_TEST); } // post render proc function __postRenderProcDefault(primSet) { gl.useProgram(arrayPeek(primSet.material.renderObj).shader); //bind buffers and attribs //arrayPeek(primSet.material.renderObj).unBindBuffers(); gl.useProgram(null); } function __renderProcDepthMap(primSet) { gl.useProgram(g_depthMap.shader) //bind buffers arrayPeek(primSet.material.renderObj).bindBuffers(); g_depthMap.bindUniforms(); gl.enable(gl.DEPTH_TEST); gl.enable(gl.CULL_FACE); gl.enable(gl.POLYGON_OFFSET_FILL); gl.cullFace(gl.FRONT); gl.drawElements(gl.TRIANGLES, primSet.size, gl.UNSIGNED_SHORT, primSet.indexInBuffer*2); gl.cullFace(gl.BACK); gl.disable(gl.POLYGON_OFFSET_FILL); gl.disable(gl.CULL_FACE); //gl.disable(gl.DEPTH_TEST); gl.useProgram(null); } function __renderProcShadowReceiver(primSet) { // ---- initial pass, render shadow to target gl.bindFramebuffer(gl.FRAMEBUFFER, primSet.shadowTarget.frameBuffer); gl.viewport(0, 0, primSet.shadowTarget.frameBuffer.width, primSet.shadowTarget.frameBuffer.height); gl.clearDepth(g_farZ); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.useProgram(arrayPeek(primSet.material.shader).shaderHandle); // Bind the texture gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, g_depthMap.depthRT); // bind shader uniforms arrayPeek(primSet.material.renderObj).bindTextures(); //gl.disable(gl.DEPTH_TEST); //gl.enable(gl.CULL_FACE); gl.mvMatrix = mat4.mul( g_defaultView, primSet.parentMesh.world ); arrayPeek(primSet.material.renderObj).bindUniforms(); error = gl.getError(); //bind buffers and attribs arrayPeek(primSet.material.renderObj).bindBuffers(); gl.drawElements(gl.TRIANGLES, primSet.size, gl.UNSIGNED_SHORT, primSet.indexInBuffer*2); //gl.enable(gl.DEPTH_TEST); //gl.disable(gl.CULL_FACE); gl.useProgram(null); gl.bindTexture(gl.TEXTURE_2D, primSet.shadowTarget); gl.generateMipmap(gl.TEXTURE_2D); gl.bindTexture(gl.TEXTURE_2D, null); gl.bindFramebuffer(gl.FRAMEBUFFER, theSceneRTT.frameBuffer); gl.viewport(0, 0, theSceneRTT.frameBuffer.width, theSceneRTT.frameBuffer.height); //----------change buffers render blur pass to quad gl.bindFramebuffer(gl.FRAMEBUFFER, primSet.shadowTargetFinal.frameBuffer); gl.viewport(0, 0, primSet.shadowTargetFinal.frameBuffer.width, primSet.shadowTargetFinal.frameBuffer.height); gl.clearDepth(g_farZ); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); primSet.screenQuad.setTexture(primSet.shadowTarget); primSet.screenQuad.render(renderProcScreenQuad); gl.bindTexture(gl.TEXTURE_2D, primSet.shadowTargetFinal); gl.generateMipmap(gl.TEXTURE_2D); gl.bindTexture(gl.TEXTURE_2D, null); gl.bindFramebuffer(gl.FRAMEBUFFER, theSceneRTT.frameBuffer); gl.viewport(0, 0, theSceneRTT.frameBuffer.width, theSceneRTT.frameBuffer.height); //----------change buffers render blur pass to quad again gl.bindFramebuffer(gl.FRAMEBUFFER, primSet.shadowTarget.frameBuffer); gl.viewport(0, 0, primSet.shadowTarget.frameBuffer.width, primSet.shadowTarget.frameBuffer.height); gl.clearDepth(g_farZ); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); primSet.screenQuad.setTexture(primSet.shadowTargetFinal); primSet.screenQuad.render(renderProcScreenQuad); gl.bindTexture(gl.TEXTURE_2D, primSet.shadowTarget); gl.generateMipmap(gl.TEXTURE_2D); gl.bindTexture(gl.TEXTURE_2D, null); gl.bindFramebuffer(gl.FRAMEBUFFER, theSceneRTT.frameBuffer); gl.viewport(0, 0, theSceneRTT.frameBuffer.width, theSceneRTT.frameBuffer.height); } function __renderProcShadowProjection(primSet) { gl.useProgram(arrayPeek(primSet.material.shader).shaderHandle); // Bind the texture var error = gl.getError(); gl.activeTexture(gl.TEXTURE0); error=gl.getError(gl.bindTexture(gl.TEXTURE_2D, g_depthMap.shadowTarget)); gl.bindTexture(gl.TEXTURE_2D, g_meshMan.getModelByName("backdropReceiver").mesh.shadowToProject); // bind shader uniforms arrayPeek(primSet.material.renderObj).bindTextures(); gl.mvMatrix = mat4.mul( g_defaultView, primSet.parentMesh.world ); arrayPeek(primSet.material.renderObj).bindUniforms(); //bind buffers and attribs arrayPeek(primSet.material.renderObj).bindBuffers(); gl.drawElements(gl.TRIANGLES, primSet.size, gl.UNSIGNED_SHORT, primSet.indexInBuffer*2); gl.useProgram(null); }