From 8992d9baf542135e910bb59328a592d9e330703a Mon Sep 17 00:00:00 2001 From: hwc487 Date: Sun, 15 Apr 2012 05:16:34 -0700 Subject: Cloud Material --- assets/shaders/Basic.vert.glsl | 3 + assets/shaders/BasicTex.frag.glsl | 19 +++ assets/shaders/Cloud.frag.glsl | 4 +- js/lib/drawing/world.js | 13 ++ js/lib/geom/rectangle.js | 7 +- js/lib/math/matrix.js | 9 ++ js/lib/rdge/materials/cloud-material.js | 270 ++++++++++++++++++++++---------- js/lib/rdge/texture.js | 2 +- 8 files changed, 236 insertions(+), 91 deletions(-) create mode 100644 assets/shaders/BasicTex.frag.glsl diff --git a/assets/shaders/Basic.vert.glsl b/assets/shaders/Basic.vert.glsl index 0d5b8d63..f96f8322 100755 --- a/assets/shaders/Basic.vert.glsl +++ b/assets/shaders/Basic.vert.glsl @@ -14,6 +14,8 @@ precision highp float; attribute vec3 a_pos; attribute vec2 texcoord; +// varying +varying vec2 v_texCoord0; // matrix uniforms uniform mat4 u_mvMatrix; @@ -22,5 +24,6 @@ uniform mat4 u_worldMatrix; void main(void) { + v_texCoord0 = texcoord; gl_Position = u_projMatrix * u_mvMatrix * vec4(a_pos,1.0) ; } \ No newline at end of file diff --git a/assets/shaders/BasicTex.frag.glsl b/assets/shaders/BasicTex.frag.glsl new file mode 100644 index 00000000..a716e77d --- /dev/null +++ b/assets/shaders/BasicTex.frag.glsl @@ -0,0 +1,19 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + + +#ifdef GL_ES +precision highp float; +#endif + +uniform sampler2D u_tex0; + +varying vec2 v_texCoord0; + + +void main() { + gl_FragColor = texture2D(u_tex0, v_texCoord0); +} diff --git a/assets/shaders/Cloud.frag.glsl b/assets/shaders/Cloud.frag.glsl index b07bb627..ba1ef39e 100644 --- a/assets/shaders/Cloud.frag.glsl +++ b/assets/shaders/Cloud.frag.glsl @@ -17,7 +17,7 @@ varying vec2 v_texCoord0; void main() { - // gl_FragColor = texture2D(u_tex0, v_texCoord0) * u_surfaceAlpha; - gl_FragColor = vec4(1,0,0,1); + gl_FragColor = texture2D(u_tex0, v_texCoord0) * u_surfaceAlpha; + //gl_FragColor = texture2D(u_tex0, v_texCoord0); } \ No newline at end of file diff --git a/js/lib/drawing/world.js b/js/lib/drawing/world.js index 5eca26b8..4ca738f4 100755 --- a/js/lib/drawing/world.js +++ b/js/lib/drawing/world.js @@ -73,6 +73,7 @@ var World = function GLWorld( canvas, use3D, preserveDrawingBuffer ) { this._firstRender = true; this._worldCount = worldCounter; + console.log( "creating world " + this._worldCount ); worldCounter++; // keep a counter for generating node names @@ -514,6 +515,18 @@ World.prototype.restartRenderLoop = function() { } }; +World.prototype.stop = function() +{ + if (this._canvas && this._canvas.task) + this._canvas.task.stop(); +} + +World.prototype.start = function() +{ + if (this._canvas && this._canvas.task) + this._canvas.task.start(); +} + //append to the list of objects if obj doesn't already exist //if obj exists, then don't add to list of objects World.prototype.addIfNewObject = function (obj) { diff --git a/js/lib/geom/rectangle.js b/js/lib/geom/rectangle.js index d4dd8033..70f6b01b 100755 --- a/js/lib/geom/rectangle.js +++ b/js/lib/geom/rectangle.js @@ -1294,6 +1294,7 @@ RectangleGeometry.init = function() RectangleGeometry.addQuad = function( verts, normals, uvs ) { + var offset = this.vertices.length/3; for (var i=0; i<4; i++) { RectangleGeometry.pushVertex( verts[i][0], verts[i][1], verts[i][2]); @@ -1301,13 +1302,13 @@ RectangleGeometry.addQuad = function( verts, normals, uvs ) RectangleGeometry.pushUV( uvs[i] ); } - RectangleGeometry.pushIndices( 0, 1, 2 ); - RectangleGeometry.pushIndices( 2, 3, 0 ); + RectangleGeometry.pushIndices( 0+offset, 1+offset, 2+offset ); + RectangleGeometry.pushIndices( 2+offset, 3+offset, 0+offset ); } RectangleGeometry.buildPrimitive = function() { - var nVertices = this.vertices.length; + var nVertices = this.vertices.length/3; return ShapePrimitive.create(this.vertices, this.normals, this.uvs, this.indices, g_Engine.getContext().renderer.TRIANGLES, nVertices); } diff --git a/js/lib/math/matrix.js b/js/lib/math/matrix.js index 77a0966d..3a5a8215 100755 --- a/js/lib/math/matrix.js +++ b/js/lib/math/matrix.js @@ -67,6 +67,15 @@ Matrix.Rotation = function(angle, axis) { return mat; }; +Matrix.Scale = function( scaleVec ) { + var mat = Matrix.I(4); + mat[ 0] = scaleVec[0]; + mat[ 5] = scaleVec[1]; + mat[10] = scaleVec[2]; + + return mat; +}; + Matrix.flatten = function (mat) { var result = []; if (this.elements.length == 0) { diff --git a/js/lib/rdge/materials/cloud-material.js b/js/lib/rdge/materials/cloud-material.js index 126751c6..e2292c7a 100644 --- a/js/lib/rdge/materials/cloud-material.js +++ b/js/lib/rdge/materials/cloud-material.js @@ -8,6 +8,8 @@ var MaterialParser = require("js/lib/rdge/materials/material-parser").MaterialP var Material = require("js/lib/rdge/materials/material").Material; var GLWorld = require("js/lib/drawing/world").World; var Texture = require("js/lib/rdge/texture").Texture; +var ElementMediator = require("js/mediators/element-mediator").ElementMediator; +var TagTool = require("js/tools/TagTool").TagTool; /////////////////////////////////////////////////////////////////////// // Class GLMaterial @@ -20,7 +22,9 @@ var CloudMaterial = function CloudMaterial() { this._name = "CloudMaterial"; this._shaderName = "cloud"; - this._texMap = 'assets/images/cloud10.png'; + //this._texMap = 'assets/images/cloud10.png'; + this._texMap = 'assets/images/us_flag.png'; + //this._texMap = 'assets/images/cubelight.png'; this._diffuseColor = [0.5, 0.5, 0.5, 0.5]; // base size of cloud polygons. Random adjustments made to each quad @@ -31,7 +35,7 @@ var CloudMaterial = function CloudMaterial() { // parameter initial values this._time = 0.0; - this._surfaceAlpha = 1.0; + this._surfaceAlpha = 0.6; this._zmin = 0.1; this._zmax = 10.0; @@ -111,80 +115,54 @@ var CloudMaterial = function CloudMaterial() { // save the world if (world) this.setWorld( world ); - - // this variable declared above is inherited set to a smaller delta. - // the cloud material runs a little faster - this._dTime = 0.01; + var dstWorld = world; // create a canvas to render into - var doc = world.getCanvas().ownerDocument; + var dstCanvas = this.getWorld().getCanvas(); + var doc = this.getWorld().getCanvas().ownerDocument; var canvasID = "__canvas__"; //this._srcCanvas = doc.createElement(canvasID); this._srcCanvas = NJUtils.makeNJElement("canvas", canvasID, "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true); - var dstCanvas = this.getWorld().getCanvas(), - srcCanvas = this._srcCanvas; + srcCanvas = this._srcCanvas; srcCanvas.width = dstCanvas.width; srcCanvas.height = dstCanvas.height; - // save the current RDGE context - var saveContext = g_Engine.getContext(); - - // build a world to do the rendering - this._srcWorld = new GLWorld( this._srcCanvas, true, true ); - var srcWorld = this._srcWorld; - this._srcCanvas.__GLWorld = srcWorld; + ////////////////////////////////////////////////////////////////////////////////// + // IS THIS NECESSARY?? + //var elementModel = TagTool.makeElement(~~srcCanvas.width, ~~srcCanvas.height, + // Matrix.I(4), [0,0,0], srcCanvas); + //ElementMediator.addElement(srcCanvas, elementModel.data, true); + ////////////////////////////////////////////////////////////////////////////////// - // build the geometry - var prim = this.buildGeometry( srcWorld, srcCanvas.width, srcCanvas.height ); + // build the source. + // the source being the world/canvas/geometry of the clouds. + // the source is used to create a texture map that is then used by + // the destimation. + this.buildSource(); // set up the shader this._shader = new jshader(); - this._shader.def = cloudMaterialDef; + this._shader.def = cloudMapMaterialDef; this._shader.init(); // set up the material node - this._materialNode = createMaterialNode("cloudMaterial" + "_" + world.generateUniqueNodeID()); + this._materialNode = createMaterialNode("cloudMapMaterial" + "_" + world.generateUniqueNodeID()); this._materialNode.setShader(this._shader); - // initialize the shader uniforms + // initialize the time this._time = 0; - if (this._shader && this._shader['default']) { - var t = this._shader['default']; - if (t) - { - t.u_time.set( [this._time] ); - t.u_surfaceAlpha.set( [this._surfaceAlpha] ); - t.u_zmin.set( [this._zmin] ); - t.u_zmax.set( [this._zmax] ); - var wrap = 'REPEAT', mips = true; - var texMapName = this._propValues[this._propNames[0]]; - var tex = srcWorld.renderer.getTextureByName(texMapName, wrap, mips ); - if (tex) - srcWorld.textureToLoad( tex ); - } - } - - // add the nodes to the tree - var trNode = createTransformNode("objRootNode_" + this._srcWorld._nodeCounter++); - srcWorld._rootNode.insertAsChild( trNode ); - trNode.attachMeshNode(srcWorld.renderer.id + "_prim_" + srcWorld._nodeCounter++, prim); - trNode.attachMaterial( this._materialNode ); - - // create the texture + // create the texture to map the source cloud generation world/canvas to the destination var wrap = 'REPEAT', mips = true; - this._srcWorld._hasAnimatedMaterials = true; // hack to make the texture think this world is animated this._glTex = new Texture( world, this._srcCanvas, wrap, mips ); // set the shader values in the shader this.updateTexture(); this.update( 0 ); - - // restore the previous RDGE context - g_Engine.setContext( saveContext.id ); }; - this.updateTexture = function() { + this.updateTexture = function() + { var material = this._materialNode; if (material) { @@ -195,9 +173,7 @@ var CloudMaterial = function CloudMaterial() { var technique = material.shaderProgram['default']; var renderer = g_Engine.getContext().renderer; if (renderer && technique) { - var texMapName = this._propValues[this._propNames[0]]; var wrap = 'REPEAT', mips = true; - //var tex = this.loadTexture( texMapName, wrap, mips ); if (this._glTex) { this._glTex.render(); @@ -205,9 +181,9 @@ var CloudMaterial = function CloudMaterial() { if (tex) technique.u_tex0.set( tex ); } - } + // restore the context g_Engine.setContext( saveContext.id ); } }; @@ -226,29 +202,100 @@ var CloudMaterial = function CloudMaterial() { this.update = function( time ) { + var technique, renderer, tex; + + // update the cloud map material var material = this._materialNode; if (material) { - if (this._srcWorld) this._srcWorld.draw(); + technique = material.shaderProgram['default']; + renderer = g_Engine.getContext().renderer; + if (renderer && technique) + { + if (this._glTex) + { + this._glTex.render(); + tex = this._glTex.getTexture(); + technique.u_tex0.set( tex ); + } + } + } + } - var technique = material.shaderProgram['default']; - var renderer = g_Engine.getContext().renderer; - if (renderer && technique) { + // update the source material + material = this._srcMaterialNode; + if (material) + { + technique = material.shaderProgram['default']; + renderer = g_Engine.getContext().renderer; + if (renderer && technique) + { if (this._shader && this._shader['default']) { this._shader['default'].u_time.set( [this._time] ); } - this._time += this._dTime; - if (this._glTex) + this._time += this._dTime; + if (this._time > 200.0) this._time = 0.0; + } + }; + + this.buildSource = function() + { + // save the current RDGE context so we can reset it later + var saveContext = g_Engine.getContext(); + this.getWorld().stop(); + + // build a world to do the rendering + this._srcWorld = new GLWorld( this._srcCanvas, true, true ); + var srcWorld = this._srcWorld; + if (!this._srcCanvas) throw new Error( "No source canvas in Cloud material" ); + this._srcCanvas.__GLWorld = srcWorld; + + // build the geometry + var prim = this.buildGeometry( srcWorld, srcCanvas.width, srcCanvas.height ); + + // set up the shader + var shader = new jshader(); + shader.def = cloudMaterialDef; + shader.init(); + this._srcShader = shader; + + // set up the material node + var materialNode = createMaterialNode("cloudMaterial" + "_" + srcWorld.generateUniqueNodeID()); + materialNode.setShader(shader); + this._srcMaterialNode = materialNode; + + // add the nodes to the tree + var trNode = createTransformNode("objRootNode_" + srcWorld._nodeCounter++); + srcWorld._rootNode.insertAsChild( trNode ); + trNode.attachMeshNode(srcWorld.renderer.id + "_prim_" + srcWorld._nodeCounter++, prim); + trNode.attachMaterial( materialNode ); + + // initialize the shader uniforms + this._time = 0; + if (shader['default']) { + var t = shader['default']; + if (t) + { + t.u_time.set( [this._time] ); + t.u_surfaceAlpha.set( [this._surfaceAlpha] ); + t.u_zmin.set( [this._zmin] ); + t.u_zmax.set( [this._zmax] ); + + var wrap = 'REPEAT', mips = true; + var texMapName = this._propValues[this._propNames[0]]; + var tex = srcWorld.renderer.getTextureByName(texMapName, wrap, mips ); + if (tex) { - this._glTex.render(); - var tex = this._glTex.getTexture(); - technique.u_tex0.set( tex ); + srcWorld.textureToLoad( tex ); + t.u_tex0.set( tex ); } - - if (this._time > 200.0) this._time = 0.0; } } + + // restore the original context + g_Engine.setContext( saveContext.id ); + this.getWorld().start(); }; this.buildGeometry = function(world, canvasWidth, canvasHeight) @@ -278,38 +325,52 @@ var CloudMaterial = function CloudMaterial() { y = -z*(t-b)/(2.0*zn)*yNDC; // get the x and y fill - var xFill = -z*(r-l)/(2.0*zn)*xFillNDC, - yFill = -z*(t-b)/(2.0*zn)*yFillNDC; + var hWidth = -z*(r-l)/(2.0*zn)*xFillNDC, + hHeight = -z*(t-b)/(2.0*zn)*yFillNDC; //this.createFill([x,y], 2*xFill, 2*yFill, tlRadius, blRadius, brRadius, trRadius, fillMaterial); - var ctr = [x,y], width = 2*xFill, height = 2*yFill; - var prim = RectangleGeometry.create( ctr, width, height ); - return prim; + var ctr = [x,y], width = 2*hWidth, height = 2*hHeight; + var cloudSize = width > height ? 0.25*width : 0.25*height; + //var prim = RectangleGeometry.create( ctr, width, height ); + //return prim; - /* var verts = [], normals = [ [0,0,1], [0,0,1], [0,0,1], [0,0,1] ], uvs = [ [0,0], [1,0], [1,1], [0,1] ]; - - for ( i = 0; i < 2; i++ ) + + for ( i = 0; i < 12; i++ ) { - var x = Math.random() * 1000 - 500, - y = - Math.random() * Math.random() * 200 - 15, - z = i, - zRot = Math.random() * Math.PI, - size = this._cloudSize * Math.random() * Math.random() * 1.5 + 0.5; - var sz = 0.5*size; - - verts[0] = [x-sz, y-sz, z]; - verts[1] = [x-sz, y+sz, z]; - verts[2] = [x+sz, y+sz, z]; - verts[3] = [x+sz, y-sz, z]; - RectangleGeometry.addQuad( verts, normals, uvs ) + var x = hWidth*2*(Math.random() - 0.5), + //y = hHeight*2.0*(Math.random() * Math.random() - 0.5), + y = hHeight*2.0*(Math.random() - 0.5), + z = 0, //i, + zRot = (Math.random() - 0.5) * Math.PI, + sz = cloudSize * Math.random(); + + //x = 0.0; y = 0.0; z = 0.0; + //zRot = 0.0; + + verts[0] = [-sz, -sz, 0]; + verts[1] = [-sz, sz, 0]; + verts[2] = [ sz, sz, 0]; + verts[3] = [ sz, -sz, 0]; + + var rotMat = Matrix.RotationZ( zRot ); + //var scaleMat = Matrix.Scale( [sz,sz,sz] ); + var transMat = Matrix.Translation( [x,y,z] ); + + var mat = glmat4.multiply( transMat, rotMat, [] ); + + glmat4.multiplyVec3( mat, verts[0] ); + glmat4.multiplyVec3( mat, verts[1] ); + glmat4.multiplyVec3( mat, verts[2] ); + glmat4.multiplyVec3( mat, verts[3] ); + + RectangleGeometry.addQuad( verts, normals, uvs ); } return RectangleGeometry.buildPrimitive(); - */ }; // JSON export @@ -343,7 +404,8 @@ var CloudMaterial = function CloudMaterial() { /////////////////////////////////////////////////////////////////////////////////////// // RDGE shader -// shader spec (can also be loaded from a .JSON file, or constructed at runtime) +// the cloud material def is used for cloud generation on the +// local world created by the cloud material. var cloudMaterialDef = {'shaders': { @@ -384,7 +446,45 @@ var cloudMaterialDef = ] } }; + +// the cloud map material def is used to map the cloud image onto +// the destination geometry +var cloudMapMaterialDef = +{'shaders': + { + 'defaultVShader':"assets/shaders/Basic.vert.glsl", + 'defaultFShader':"assets/shaders/BasicTex.frag.glsl" + }, + 'techniques': + { + 'default': + [ + { + 'vshader' : 'defaultVShader', + 'fshader' : 'defaultFShader', + // attributes + 'attributes' : + { + 'vert' : { 'type' : 'vec3' }, + 'normal' : { 'type' : 'vec3' }, + 'texcoord' : { 'type' : 'vec2' } + }, + // parameters + 'params' : + { + 'u_tex0' : { 'type' : 'tex2d' }, + }, + // render states + 'states' : + { + 'depthEnable' : true, + 'offset':[1.0, 0.1] + } + } + ] + } +}; diff --git a/js/lib/rdge/texture.js b/js/lib/rdge/texture.js index b85ee076..15f786ea 100644 --- a/js/lib/rdge/texture.js +++ b/js/lib/rdge/texture.js @@ -233,7 +233,7 @@ function Texture( dstWorld, texMapName, wrap, mips ) } // copy the source canvas to the context to be used in the texture - renderCtx.drawImage(srcCanvas, 0, 0); + renderCtx.drawImage(srcCanvas, 0, 0, width, height); ///////////////// tex.image = renderCanvas; -- cgit v1.2.3