diff options
author | luchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-22 18:23:55 +0000 |
---|---|---|
committer | luchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-22 18:23:55 +0000 |
commit | a94ede07c59c3be79641234930638be4ae40947c (patch) | |
tree | 26f1053c2d982c7edd33893f8b4719fd208bb495 /o3d | |
parent | 23781f7eda2276973b2da5e7bf34fb455af825e5 (diff) | |
download | chromium_src-a94ede07c59c3be79641234930638be4ae40947c.zip chromium_src-a94ede07c59c3be79641234930638be4ae40947c.tar.gz chromium_src-a94ede07c59c3be79641234930638be4ae40947c.tar.bz2 |
Adding WebGL version of the trends demo, including the original and new particle versions. Differences in the non-particle version:
* Switched the created energy texture from 3x32 (NPOT) to 4x32; made the energy shard width smaller.
* In the shaders, added abs before the sqrt call to normalize behavior across CG/GLSL.
Translated GLSL shader string in particles.js to be more human readable.
Review URL: http://codereview.chromium.org/2934013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53363 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/assets/clouds.jpg | bin | 0 -> 107460 bytes | |||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/assets/earth-large-with-ocean-mask.png | bin | 0 -> 2367738 bytes | |||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/assets/earth-large.jpg | bin | 0 -> 586564 bytes | |||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/assets/earth.jpg | bin | 0 -> 46696 bytes | |||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/assets/energy.png | bin | 0 -> 136 bytes | |||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/assets/moon.jpg | bin | 0 -> 67152 bytes | |||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/assets/night-large.jpg | bin | 0 -> 313629 bytes | |||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/assets/night.jpg | bin | 0 -> 86315 bytes | |||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/trends-with-particles.html | 803 | ||||
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/trends.html | 869 | ||||
-rw-r--r-- | o3d/samples/o3djs/particles.js | 675 | ||||
-rwxr-xr-x | o3d/samples/trends/trends-with-particles.html | 791 |
12 files changed, 2636 insertions, 502 deletions
diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/clouds.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/clouds.jpg Binary files differnew file mode 100644 index 0000000..8767681 --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/assets/clouds.jpg diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/earth-large-with-ocean-mask.png b/o3d/samples/o3d-webgl-samples/trends/assets/earth-large-with-ocean-mask.png Binary files differnew file mode 100644 index 0000000..850d0ff --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/assets/earth-large-with-ocean-mask.png diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/earth-large.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/earth-large.jpg Binary files differnew file mode 100644 index 0000000..ce797dc --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/assets/earth-large.jpg diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/earth.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/earth.jpg Binary files differnew file mode 100644 index 0000000..f04b09d --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/assets/earth.jpg diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/energy.png b/o3d/samples/o3d-webgl-samples/trends/assets/energy.png Binary files differnew file mode 100644 index 0000000..576ddbb --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/assets/energy.png diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/moon.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/moon.jpg Binary files differnew file mode 100644 index 0000000..f916c70 --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/assets/moon.jpg diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/night-large.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/night-large.jpg Binary files differnew file mode 100644 index 0000000..4979d6e --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/assets/night-large.jpg diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/night.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/night.jpg Binary files differnew file mode 100644 index 0000000..2bfb99e --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/assets/night.jpg diff --git a/o3d/samples/o3d-webgl-samples/trends/trends-with-particles.html b/o3d/samples/o3d-webgl-samples/trends/trends-with-particles.html new file mode 100644 index 0000000..61b9cf1 --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/trends-with-particles.html @@ -0,0 +1,803 @@ +<!-- +Copyright 2009, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<!-- +TODO: + O Set Sun to correct location for time. + O Put in moon + O Put in Google satellite + O Put in Star Shader that uses star data from a texture + O Add Halo + O Add Sun Model + O with glowing rays. +--> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<title> +Google Trends Visualizer +</title> +<style> + html, body { + border: 0; + margin: 0; + height: 100%; + height: 100%; + text-align: center; + } +</style> +</head> +<body onload="init();" onunload="uninit();"> +<script type="text/javascript" src="../../o3d-webgl/base.js"></script> +<script type="text/javascript" src="../../o3djs/base.js"></script> +<script type="text/javascript" id="o3dscript"> +o3djs.base.o3d = o3d; +o3djs.require('o3djs.webgl'); +o3djs.require('o3djs.math'); +o3djs.require('o3djs.quaternions'); +o3djs.require('o3djs.rendergraph'); +o3djs.require('o3djs.primitives'); +o3djs.require('o3djs.arcball'); +o3djs.require('o3djs.io'); +o3djs.require('o3djs.particles'); + +var g = { + EARTH_RADIUS: 25, + ENERGY_WIDTH: 0.5, + ENERGY_HEIGHT: 10 +}; + +g.camera = { + eye: [0, 0, 75], + target: [0, 0, 0] +}; + +var g_finished = false; // for selenium. +var dragging = false; + +function startDragging(e) { + g.lastRot = g.thisRot; + g.aball.click([e.x, e.y]); + dragging = true; +} + +function drag(e) { + if (dragging) { + var rotationQuat = g.aball.drag([e.x, e.y]); + var rot_mat = g.quaternions.quaternionToRotation(rotationQuat); + g.thisRot = g.math.matrix4.mul(g.lastRot, rot_mat); + + var m = g.root.localMatrix; + g.math.matrix4.setUpper3x3(m, g.thisRot); + g.root.localMatrix = m; + } +} + +function stopDragging(e) { + dragging = false; +} + +function updateViewFromCamera() { + var target = g.camera.target; + var eye = g.camera.eye; + var up = [0, 1, 0]; + g.viewInfo.drawContext.view = g.math.matrix4.lookAt(eye, target, up); + g.eyePosParam.value = eye; +} + +function scrollMe(e) { + if (e.deltaY > 0) { + g.camera.eye[0] *= 11 / 12; + g.camera.eye[1] *= 11 / 12; + g.camera.eye[2] *= 11 / 12; + + } else { + g.camera.eye[0] *= (1 + 1 / 12); + g.camera.eye[1] *= (1 + 1 / 12); + g.camera.eye[2] *= (1 + 1 / 12); + } + updateViewFromCamera(); +} + +function getURL(path) { + var base = window.location.href; + var index = base.lastIndexOf('/'); + base = base.substring(0, index + 1); + return base + path; +} + +function setClientSize() { + var newWidth = g.client.width; + var newHeight = g.client.height; + + if (newWidth != g.o3dWidth || newHeight != g.o3dHeight) { + g.o3dWidth = newWidth; + g.o3dHeight = newHeight; + + // Create a perspective projection matrix + g.viewInfo.drawContext.projection = g.math.matrix4.perspective( + g.math.degToRad(45), g.o3dWidth / g.o3dHeight, 0.1, 5000); + + // Sets a new area size for arcball. + g.aball.setAreaSize(g.o3dWidth, g.o3dHeight); + } +} + +function onRender() { + setClientSize(); +} + +// A geo is a float where the integer part is in degrees and the fractional +// part is in 60ths +function geoToRad(geo) { + var sign = geo >= 0 ? 1 : -1; + geo = Math.abs(geo); + var integerPart = Math.floor(geo); + var fractionalPart = (geo % 1) * 100; + fractionalPart = fractionalPart / 60; + return g.math.degToRad(integerPart + fractionalPart); +} + +function addEnergyShard(latitude, longitude, energy, height, color) { + // Decide how many particles we want in this shard. + g.trailParameters.numParticles = Math.floor(Math.random() * 10) + 1; + // Set the color for the shard's particles. + g.trailParameters.colorMult = color; + // Compute a base position for the shard and a velocity for the particles. + var matrix = g.math.matrix4.rotationZ(geoToRad(latitude)); + g.math.matrix4.rotateY(matrix, geoToRad(-longitude)); + g.math.matrix4.rotateZ(matrix, g.math.degToRad(90)); + g.shardStartPosition = + g.math.matrix4.transformDirection(matrix, [0, g.EARTH_RADIUS, 0]); + g.shardVelocity = g.math.matrix4.transformDirection(matrix, [0, 2.5, 0]); + // Birth the particles. NOTE: the position passed in here is overridden by + // our per particle function. + g.trail.birthParticles([0, 0, 0]); +} + +function shardPerParticleFunc(particleIndex, parameters) { + // This function sets parameters for each individual particle that is + // birthed. We'll calculate these in addEneryShard so all the + // particles genearted come out of the same position going in the + // same direction + parameters.position = g.shardStartPosition; + parameters.velocity = g.shardVelocity; + // Pick a random time for the particle to appear. + parameters.startTime = Math.random() * parameters.timeRange; +} + +/** + * Creates the client area. + */ +function init() { + o3djs.webgl.makeClients(initStep2); +} +/** + * Initializes o3d + * @param {Array} clientElements Array of o3d object elements. + */ +function initStep2(clientElements) { + var path = window.location.href; + var index = path.lastIndexOf('/'); + + g.o3dElement = clientElements[0]; + g.o3d = g.o3dElement.o3d; + g.math = o3djs.math; + g.quaternions = o3djs.quaternions; + g.client = g.o3dElement.client; + + g.pack = g.client.createPack(); + + // Create the render graph for a view. + g.viewInfo = o3djs.rendergraph.createBasicView( + g.pack, + g.client.root, + g.client.renderGraphRoot); + + // Set the background color to black. + g.viewInfo.clearBuffer.clearColor = [0, 0, 0, 0]; + + // Set states for shards. + g.viewInfo.zOrderedState.getStateParam('CullMode').value = + g.o3d.State.CULL_NONE; + g.viewInfo.zOrderedState.getStateParam('DestinationBlendFunction').value = + g.o3d.State.BLENDFUNC_ONE; + g.viewInfo.zOrderedState.getStateParam('ZWriteEnable').value = false; + + g.viewInfo.performanceDrawPass.sortMethod = g.o3d.DrawList.BY_PRIORITY; + + g.lastRot = g.math.matrix4.identity(); + g.thisRot = g.math.matrix4.identity(); + + var root = g.client.root; + + // Create a param for the sun and eye positions that we can bind + // to auto update a bunch of materials. + g.globalParams = g.pack.createObject('ParamObject'); + g.sunPosParam = g.globalParams.createParam('sunPos', 'ParamFloat3'); + g.sunPosParam.value = [1000, 200, 100]; + g.eyePosParam = g.globalParams.createParam('eyePos', 'ParamFloat3'); + + updateViewFromCamera(); + + g.aball = o3djs.arcball.create(100, 100); + setClientSize(); + + g.client.setRenderCallback(onRender); + + + // Create Materials. + var effectNames = [ + "noTexture", + "dayOnly", + "nightAndDay", + "mask", + "atmosphere" + ]; + g.materials = []; + for (var ii = 0; ii < effectNames.length; ++ii) { + var effectName = effectNames[ii]; + var effect = g.pack.createObject('Effect'); + effect.loadFromFXString(document.getElementById(effectName).value); + + // Create a Material for the effect. + var material = g.pack.createObject('Material'); + + // Apply our effect to this material. The effect tells the 3D hardware + // which shader to use. + material.effect = effect; + + // Set the material's drawList + material.drawList = g.viewInfo.performanceDrawList; + + // This will create the effects's params on the material. + effect.createUniformParameters(material); + + // Bind the sun position to a global value so we can easily change it + // globally. + var sunParam = material.getParam('sunPos'); + if (sunParam) { + sunParam.bind(g.sunPosParam); + } + + // Save off the material. + g.materials.push(material); + } + g.noTextureMaterial = g.materials[0]; + g.dayOnlyMaterial = g.materials[1]; + g.nightAndDayMaterial = g.materials[2]; + g.maskMaterial = g.materials[3]; + g.atmosphereMaterial = g.materials[4]; + + // create samplers + g.samplers = []; + for (var ii = 0; ii < 4; ++ii) { + var sampler = g.pack.createObject('Sampler'); + g.samplers[ii] = sampler; + } + + g.daySampler = g.samplers[0]; + g.nightSampler = g.samplers[1]; + g.maskSampler = g.samplers[2]; + + // set the material samplers. + g.dayOnlyMaterial.getParam('daySampler').value = g.daySampler; + g.nightAndDayMaterial.getParam('daySampler').value = g.daySampler; + g.nightAndDayMaterial.getParam('nightSampler').value = g.nightSampler; + g.maskMaterial.getParam('daySampler').value = g.daySampler; + g.maskMaterial.getParam('maskSampler').value = g.maskSampler; + g.maskMaterial.getParam('nightSampler').value = g.nightSampler; + + // Setup counters for shard animation. + g.shardCounter = g.pack.createObject('SecondCounter'); + + // Setup counters to fade in textures. + g.flatToDayCounter = g.pack.createObject('SecondCounter'); + g.flatToDayCounter.end = 1; + g.flatToDayCounter.multiplier = 0.5; + g.flatToDayCounter.countMode = g.o3d.Counter.ONCE; + g.flatToDayCounter.running = false; + g.flatToDayCounter.addCallback(1, loadNightTexture); + g.dayOnlyMaterial.getParam('time').bind( + g.flatToDayCounter.getParam('count')); + + g.dayOnlyToNightCounter = g.pack.createObject('SecondCounter'); + g.dayOnlyToNightCounter.end = 1; + g.dayOnlyToNightCounter.multiplier = 0.5; + g.dayOnlyToNightCounter.countMode = g.o3d.Counter.ONCE; + g.dayOnlyToNightCounter.running = false; + g.dayOnlyToNightCounter.addCallback(1, loadMaskTexture); + g.nightAndDayMaterial.getParam('time').bind( + g.dayOnlyToNightCounter.getParam('count')); + + g.noMaskToMaskCounter = g.pack.createObject('SecondCounter'); + g.noMaskToMaskCounter.end = 1; + g.noMaskToMaskCounter.multiplier = 0.5; + g.noMaskToMaskCounter.countMode = g.o3d.Counter.ONCE; + g.noMaskToMaskCounter.running = false; + g.maskMaterial.getParam('time').bind( + g.noMaskToMaskCounter.getParam('count')); + + // Create a sphere at the origin for the earth. + var earth = o3djs.primitives.createSphere(g.pack, + g.noTextureMaterial, + 25, + 50, + 50); + + // Get a the element so we can set its material later. + g.earthPrimitive = earth.elements[0]; + g.atmosphereState = g.pack.createObject('State'); + g.atmosphereState.getStateParam('AlphaBlendEnable').value = true; + g.atmosphereState.getStateParam('SourceBlendFunction').value = + g.o3d.State.BLENDFUNC_SOURCE_ALPHA; + g.atmosphereState.getStateParam('DestinationBlendFunction').value = + g.o3d.State.BLENDFUNC_INVERSE_SOURCE_ALPHA; + g.atmosphereState.getStateParam('ZWriteEnable').value = false; + g.atmosphereMaterial.state = g.atmosphereState; + + g.root = g.pack.createObject('Transform'); + g.root.parent = g.client.root; + g.earth = g.pack.createObject('Transform'); + g.earth.addShape(earth); + g.earth.parent = g.root; + + // Create a sphere at the origin for the atmosphere. + var atmosphere = o3djs.primitives.createSphere(g.pack, + g.atmosphereMaterial, + 26, + 50, + 50); + g.atmospherePrimitive = atmosphere.elements[0]; + g.atmospherePrimitive.priority = 1; + g.atmosphere = g.pack.createObject('Transform'); + g.atmosphere.addShape(atmosphere); + g.atmosphere.parent = g.root; + + // Set shading language. + o3djs.particles.setLanguage('glsl'); + + // Make a particle system + g.particleSystem = o3djs.particles.createParticleSystem( + g.pack, + g.viewInfo, + g.shardCounter.getParam('count'), + g.math.pseudoRandom); + + // Make a transform for the particle emitter. + var transform = g.pack.createObject('Transform'); + transform.parent = g.root; + // Make a single pixel white texture as our particle. + var texture = g.pack.createTexture2D(1, 1, g.o3d.Texture.ARGB8, 1, false); + texture.set(0, [1, 1, 1, 1]); + + // Setup some basic parameters for our particles. + g.trailParameters = { + lifeTime: 4, // each particle lasts 4 seconds + timeRange: 4, // The clock is modded by this so the *world* clock repeats + // every 4 seconds making each particle reappear + startSize: 0.1, // Size to start a particle + endSize: 0.1, // Size to end a particle + // (the particle lerps in side between start and end) + }; + + // Create a trail. Trails are just a particle system that lets us more + // easily birth individual particles. + g.trail = g.particleSystem.createTrail( + transform, // Transform for particles. + 10000, // Total number of particles in system. If 10001 + // particles are birthed, the oldest particle is + // reused. + g.trailParameters, // Our static birth parameters. + texture, // The texture to use. + shardPerParticleFunc); // A function to set parameters per particle. + g.trail.setState(o3djs.particles.ParticleStateIds.BLEND); + // This ramp makes the particles full bright for 4/5ths of their lifespan + // and they fade out during the last 1/5th. + g.trail.setColorRamp( + [1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 0]); + + + addEnergyShard(0, 0, 1, 1, [1, 1, 1, 1]); + + // Honolulu, Hawaii, 21, 18, 157, 50 + addEnergyShard(21.18, 157.50, 1, 1, [0, 1, 0, 1]); + // San Francisco, Calif. 37 47 122 26 + addEnergyShard(37.47, 122.26, 1, 1, [1, 0.5, 0.5, 1]); + + for (var ii = 0; ii < 24; ++ii) { + var longitude = Math.random() * 360; + var latitude = Math.random() * 360 - 180; + var color = [ Math.random() * 0.5 + 0.2, + Math.random() * 0.5 + 0.2, + Math.random() * 0.5 + 0.2, + 1 ]; + // Make a least 1 color component full bright. + color[Math.floor(Math.random() * 2.99)] = 1; + for (var jj = 0; jj < 24; ++jj) { + addEnergyShard(latitude + (Math.random() - 0.5) * 10, + longitude + (Math.random() - 0.5) * 10, + 1, + 1, + color); + } + } + + o3djs.event.addEventListener(g.o3dElement, 'mousedown', startDragging); + o3djs.event.addEventListener(g.o3dElement, 'mousemove', drag); + o3djs.event.addEventListener(g.o3dElement, 'mouseup', stopDragging); + o3djs.event.addEventListener(g.o3dElement, 'wheel', scrollMe); + + loadDayTexture(); +} + +function loadTexture(path, callback) { + var url = getURL(path); + o3djs.io.loadTexture(g.pack, url, function(texture, exception) { + if (exception) { + alert(exception); + } else { + callback(texture); + } + }); +} + +function loadDayTexture() { + loadTexture('assets/earth.jpg', function(texture) { + g.daySampler.texture = texture; + g.earthPrimitive.material = g.dayOnlyMaterial; + g.flatToDayCounter.running = true; + }); +} + +function loadNightTexture() { + loadTexture('assets/night.jpg', function(texture) { + g.nightSampler.texture = texture; + g.earthPrimitive.material = g.nightAndDayMaterial; + g.dayOnlyToNightCounter.running = true; + }); +} + +function loadMaskTexture() { + loadTexture('assets/earth-large-with-ocean-mask.png', function(texture) { + g.maskSampler.texture = texture; + g.earthPrimitive.material = g.maskMaterial; + g.noMaskToMaskCounter.running = true; + g_finished = true; // for selenium + }); +} + +function uninit() { + // TODO: We should clean up any counters that have callbacks here. + if (g.client) { + g.client.cleanup(); + } +} +</script> +<!--<h1> +Google Trends Visualizer. +</h1>--> +<div id="o3d" style="width:100%; height: 100%;"></div> +<div style="display:none"> +<textarea id="noTexture" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 world; +uniform mat4 view; + +uniform vec3 sunPos; + +attribute vec4 position; +attribute vec3 normal; + +varying vec4 v_pos; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +void main() { + gl_Position = worldViewProjection * position; + v_normal = (world * vec4(normal, 0)).xyz; + vec3 worldPos = (world * position).xyz; + v_sun = sunPos - worldPos; + v_view = (view[3].xyz- worldPos); + v_pos = gl_Position; +} + +// #o3d SplitMarker + +varying vec4 v_pos; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +vec4 lit(float l, float h, float m) { + return vec4(1.0, + max(l, 0.0), + (l > 0.0) ? pow(max(0.0, h), m) : 0.0, + 1.0); +} + +void main() { + vec3 norm = normalize(v_normal); + vec3 sun = normalize(v_sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1.0 - sqrt(abs(light)); + dayNight = dayNight * dayNight; + dayNight = (1.0 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0.0, 1.0); + vec3 view = normalize(v_view); + vec3 r = normalize(reflect(norm, sun)); + vec4 litR = vec4(lit(light, dot(r, view), 0.0).y); + vec3 day = vec3(0.5, 0.5, 1.0) * litR.y + vec3(1,1,1) * litR.z; + vec3 night = vec3(0.2, 0.2, 0.5); + gl_FragColor = vec4(mix(night, day, dayNight),1); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="dayOnly" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 world; +uniform mat4 view; + +uniform vec3 sunPos; + +attribute vec4 position; +attribute vec3 normal; +attribute vec2 texCoord0; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +void main() { + gl_Position = (worldViewProjection * position); + v_uv = texCoord0; + v_normal = (world * vec4(normal, 0)).xyz; + vec3 worldPos = (world * position).xyz; + v_sun = sunPos - worldPos; + v_view = (view[3].xyz - worldPos); +} + +// #o3d SplitMarker + +uniform float time; + +uniform sampler2D daySampler; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +vec4 lit(float l, float h, float m) { + return vec4(1.0, + max(l, 0.0), + (l > 0.0) ? pow(max(0.0, h), m) : 0.0, + 1.0); +} + +void main() { + vec3 norm = normalize(v_normal); + vec3 sun = normalize(v_sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1.0 - sqrt(abs(light)); + dayNight = dayNight * dayNight; + dayNight = (1.0 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0.0, 1.0); + vec3 view = normalize(v_view); + vec3 r = normalize(reflect(norm, sun)); + vec4 litR = vec4(lit(light, dot(r, view), 0.0).y); + vec3 earth = texture2D(daySampler, v_uv).xyz; + vec3 day = mix(vec3(0.5, 0.5, 1.0), earth, time); + day = day * litR.y + vec3(1,1,1) * litR.z; + vec3 night = mix(vec3(0.2, 0.2, 0.5), earth * 0.3, time); + gl_FragColor = vec4(mix(night, day, dayNight),1); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="nightAndDay" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 world; +uniform mat4 view; + +uniform vec3 sunPos; + +attribute vec4 position; +attribute vec3 normal; +attribute vec2 texCoord0; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +void main() { + gl_Position = worldViewProjection * position; + v_uv = texCoord0; + v_normal = (world * vec4(normal, 0)).xyz; + vec3 worldPos = (world * position).xyz; + v_sun = sunPos - worldPos; + v_view = (view[3].xyz - worldPos); +} + +// #o3d SplitMarker + +uniform float time; + +uniform sampler2D daySampler; +uniform sampler2D nightSampler; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +vec4 lit(float l, float h, float m) { + return vec4(1.0, + max(l, 0.0), + (l > 0.0) ? pow(max(0.0, h), m) : 0.0, + 1.0); +} + +void main() { + vec3 norm = normalize(v_normal); + vec3 sun = normalize(v_sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1.0 - sqrt(abs(light)); + dayNight = dayNight * dayNight; + dayNight = (1.0 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0.0, 1.0); + vec3 view = normalize(v_view); + vec3 r = normalize(reflect(norm, sun)); + vec4 litR = vec4(lit(light, dot(r, view), 0.0).y); + vec3 earth = texture2D(daySampler, v_uv).xyz; + vec3 day = texture2D(daySampler, v_uv).xyz; + vec3 night = mix(day * 0.3, texture2D(nightSampler, v_uv).xyz, time); + day = day * litR.y + vec3(1,1,1) * litR.z; + gl_FragColor = vec4(mix(night, day, dayNight),1); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<!-- +This shader renders the ocean different then the non-ocean using a mask +stored in the alpha channel of the maskSampler +--> +<textarea id="mask" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 world; +uniform mat4 view; + +uniform vec3 sunPos; + +attribute vec4 position; +attribute vec3 normal; +attribute vec2 texCoord0; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +void main() { + gl_Position = worldViewProjection * position; + v_uv = texCoord0; + v_normal = (world * vec4(normal, 0)).xyz; + vec3 worldPos = (world * position).xyz; + v_sun = sunPos - worldPos; + v_view = (view[3].xyz - worldPos); +} + +// #o3d SplitMarker + +uniform float time; + +uniform sampler2D daySampler; +uniform sampler2D nightSampler; +uniform sampler2D maskSampler; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +vec4 lit(float l, float h, float m) { + return vec4(1.0, + max(l, 0.0), + (l > 0.0) ? pow(max(0.0, h), m) : 0.0, + 1.0); +} + +void main() { + vec3 norm = normalize(v_normal); + vec3 sun = normalize(v_sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1.0 - sqrt(abs(light)); + dayNight = dayNight * dayNight; + dayNight = (1.0 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0.0, 1.0); + vec3 view = normalize(v_view); + vec3 r = normalize(reflect(norm, sun)); + vec4 litR = vec4(lit(light, dot(r, view), 0.0).y); + vec3 earth = texture2D(daySampler, v_uv).xyz; + vec4 mask = texture2D(maskSampler, v_uv); + vec3 day = mix(texture2D(daySampler, v_uv).xyz, + mask.xyz, time); + vec3 night = texture2D(nightSampler, v_uv).xyz; + day = day * litR.y + vec3(1,1,1) * litR.z * (1.0 - mask.w * time); + vec3 color = mix(night, day, dayNight); + gl_FragColor = vec4(color, 1); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="atmosphere" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 worldView; + +attribute vec4 position; +attribute vec3 normal; + +varying vec3 v_normal; + +void main() { + gl_Position = worldViewProjection * position; + v_normal = normalize((worldView * vec4(normal,0)).xyz); +} + +// #o3d SplitMarker + +varying vec3 v_normal; + +void main() { + float n = 1.0 - log(2.0 * normalize(v_normal).z); + gl_FragColor = vec4(0.3, 0.3, 1, n * n * n * n); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +</div> +</body> +</html> + + diff --git a/o3d/samples/o3d-webgl-samples/trends/trends.html b/o3d/samples/o3d-webgl-samples/trends/trends.html new file mode 100644 index 0000000..d5eb1a9 --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/trends/trends.html @@ -0,0 +1,869 @@ +<!-- +Copyright 2009, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<!-- +TODO: + O Set Sun to correct location for time. + O Put in moon + O Put in Google satellite + O Put in Star Shader that uses star data from a texture + O Add Halo + O Add Sun Model + O with glowing rays. +--> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<title> +Google Trends Visualizer +</title> +<style> + html, body { + border: 0; + margin: 0; + height: 100%; + height: 100%; + text-align: center; + } +</style> +</head> +<body onload="init();" onunload="uninit();"> +<script type="text/javascript" src="../../o3d-webgl/base.js"></script> +<script type="text/javascript" src="../../o3djs/base.js"></script> +<script type="text/javascript" id="o3dscript"> +o3djs.base.o3d = o3d; +o3djs.require('o3djs.webgl'); +o3djs.require('o3djs.math'); +o3djs.require('o3djs.quaternions'); +o3djs.require('o3djs.rendergraph'); +o3djs.require('o3djs.primitives'); +o3djs.require('o3djs.arcball'); +o3djs.require('o3djs.io'); + +var g = { + EARTH_RADIUS: 25, + ENERGY_WIDTH: 0.3, + ENERGY_HEIGHT: 10 +}; + +g.camera = { + eye: [0, 0, 75], + target: [0, 0, 0] +}; + +var g_finished = false; // for selenium. +var dragging = false; + +function startDragging(e) { + g.lastRot = g.thisRot; + g.aball.click([e.x, e.y]); + dragging = true; +} + +function drag(e) { + if (dragging) { + var rotationQuat = g.aball.drag([e.x, e.y]); + var rot_mat = g.quaternions.quaternionToRotation(rotationQuat); + g.thisRot = g.math.matrix4.mul(g.lastRot, rot_mat); + + var m = g.root.localMatrix; + g.math.matrix4.setUpper3x3(m, g.thisRot); + g.root.localMatrix = m; + } +} + +function stopDragging(e) { + dragging = false; +} + +function updateViewFromCamera() { + var target = g.camera.target; + var eye = g.camera.eye; + var up = [0, 1, 0]; + g.viewInfo.drawContext.view = g.math.matrix4.lookAt(eye, target, up); + g.eyePosParam.value = eye; +} + +function scrollMe(e) { + if (e.deltaY > 0) { + g.camera.eye[0] *= 11 / 12; + g.camera.eye[1] *= 11 / 12; + g.camera.eye[2] *= 11 / 12; + + } else { + g.camera.eye[0] *= (1 + 1 / 12); + g.camera.eye[1] *= (1 + 1 / 12); + g.camera.eye[2] *= (1 + 1 / 12); + } + updateViewFromCamera(); +} + +function getURL(path) { + var base = window.location.href; + var index = base.lastIndexOf('/'); + base = base.substring(0, index + 1); + return base + path; +} + +function setClientSize() { + var newWidth = g.client.width; + var newHeight = g.client.height; + + if (newWidth != g.o3dWidth || newHeight != g.o3dHeight) { + g.o3dWidth = newWidth; + g.o3dHeight = newHeight; + + // Create a perspective projection matrix + g.viewInfo.drawContext.projection = g.math.matrix4.perspective( + g.math.degToRad(45), g.o3dWidth / g.o3dHeight, 0.1, 5000); + + // Sets a new area size for arcball. + g.aball.setAreaSize(g.o3dWidth, g.o3dHeight); + } +} + +function onRender() { + setClientSize(); +} + +function createEnergyShape(pack, material, width, height) { + var vertexInfo = o3djs.primitives.createVertexInfo(); + var positionStream = vertexInfo.addStream( + 3, g.o3d.Stream.POSITION); + var normalStream = vertexInfo.addStream( + 3, g.o3d.Stream.NORMAL); + var colorStream = vertexInfo.addStream( + 4, g.o3d.Stream.COLOR); + var texCoordStream = vertexInfo.addStream( + 2, g.o3d.Stream.TEXCOORD, 0); + + var vScale = 1; + positionStream.addElement(width * -0.5, height, 0); + normalStream.addElement(0, 0, 1); + colorStream.addElement(1, 1, 1, 0); + texCoordStream.addElement(0, 0); + positionStream.addElement(width * 0.5, height, 0); + normalStream.addElement(0, 0, 1); + colorStream.addElement(1, 1, 1, 0); + texCoordStream.addElement(1, 0); + positionStream.addElement(width * -0.5, 0, 0); + normalStream.addElement(0, 0, 1); + colorStream.addElement(1, 1, 1, 1); + texCoordStream.addElement(0, vScale); + positionStream.addElement(width * 0.5, 0, 0); + normalStream.addElement(0, 0, 1); + colorStream.addElement(1, 1, 1, 1); + texCoordStream.addElement(1, vScale); + positionStream.addElement(0, height, width * -0.5); + normalStream.addElement(1, 0, 0); + colorStream.addElement(1, 1, 1, 0); + texCoordStream.addElement(0, 0); + positionStream.addElement(0, height, width * 0.5); + normalStream.addElement(1, 0, 0); + colorStream.addElement(1, 1, 1, 0); + texCoordStream.addElement(1, 0); + positionStream.addElement(0, 0, width * -0.5); + normalStream.addElement(1, 0, 0); + colorStream.addElement(1, 1, 1, 1); + texCoordStream.addElement(0, vScale); + positionStream.addElement(0, 0, width * 0.5); + normalStream.addElement(1, 0, 0); + colorStream.addElement(1, 1, 1, 1); + texCoordStream.addElement(1, vScale); + + vertexInfo.addTriangle(0, 1, 2); + vertexInfo.addTriangle(1, 2, 3); + vertexInfo.addTriangle(4, 5, 6); + vertexInfo.addTriangle(5, 6, 7); + + return vertexInfo.createShape(pack, material); +} + +// A geo is a float where the integer part is in degrees and the fractional +// part is in 60ths +function geoToRad(geo) { + var sign = geo >= 0 ? 1 : -1; + geo = Math.abs(geo); + var integerPart = Math.floor(geo); + var fractionalPart = (geo % 1) * 100; + fractionalPart = fractionalPart / 60; + return g.math.degToRad(integerPart + fractionalPart); +} + +function addEnergyShard(latitude, longitude, energy, height, color) { + var transform = g.pack.createObject('Transform'); + transform.rotateZ(geoToRad(latitude)); + transform.rotateY(geoToRad(-longitude)); + transform.rotateZ(g.math.degToRad(90)); + transform.translate(0, g.EARTH_RADIUS, 0); + transform.parent = g.root; + transform.addShape(g.energyShape); + transform.createParam('colorMult', 'ParamFloat4').value = color; + transform.createParam('offset', 'ParamFloat').value = Math.random(); + return transform; +} + +/** + * Creates the client area. + */ +function init() { + o3djs.webgl.makeClients(initStep2); +} +/** + * Initializes o3d + * @param {Array} clientElements Array of o3d object elements. + */ +function initStep2(clientElements) { + var path = window.location.href; + var index = path.lastIndexOf('/'); + + g.o3dElement = clientElements[0]; + g.o3d = g.o3dElement.o3d; + g.math = o3djs.math; + g.quaternions = o3djs.quaternions; + g.client = g.o3dElement.client; + + g.pack = g.client.createPack(); + + // Create the render graph for a view. + g.viewInfo = o3djs.rendergraph.createBasicView( + g.pack, + g.client.root, + g.client.renderGraphRoot); + + // Set the background color to black. + g.viewInfo.clearBuffer.clearColor = [0, 0, 0, 0]; + + // Set states for shards. + g.viewInfo.zOrderedState.getStateParam('CullMode').value = + g.o3d.State.CULL_NONE; + g.viewInfo.zOrderedState.getStateParam('DestinationBlendFunction').value = + g.o3d.State.BLENDFUNC_ONE; + g.viewInfo.zOrderedState.getStateParam('ZWriteEnable').value = false; + + g.viewInfo.performanceDrawPass.sortMethod = g.o3d.DrawList.BY_PRIORITY; + + g.lastRot = g.math.matrix4.identity(); + g.thisRot = g.math.matrix4.identity(); + + var root = g.client.root; + + // Create a param for the sun and eye positions that we can bind + // to auto update a bunch of materials. + g.globalParams = g.pack.createObject('ParamObject'); + g.sunPosParam = g.globalParams.createParam('sunPos', 'ParamFloat3'); + g.sunPosParam.value = [1000, 200, 100]; + g.eyePosParam = g.globalParams.createParam('eyePos', 'ParamFloat3'); + + updateViewFromCamera(); + + g.aball = o3djs.arcball.create(100, 100); + setClientSize(); + + g.client.setRenderCallback(onRender); + + + // Create Materials. + var effectNames = [ + "noTexture", + "dayOnly", + "nightAndDay", + "mask", + "energy", + "atmosphere" + ]; + g.materials = []; + for (var ii = 0; ii < effectNames.length; ++ii) { + var effectName = effectNames[ii]; + var effect = g.pack.createObject('Effect'); + effect.loadFromFXString(document.getElementById(effectName).value); + + // Create a Material for the effect. + var material = g.pack.createObject('Material'); + + // Apply our effect to this material. The effect tells the 3D hardware + // which shader to use. + material.effect = effect; + + // Set the material's drawList + material.drawList = g.viewInfo.performanceDrawList; + + // This will create the effects's params on the material. + effect.createUniformParameters(material); + + // Bind the sun position to a global value so we can easily change it + // globally. + var sunParam = material.getParam('sunPos'); + if (sunParam) { + sunParam.bind(g.sunPosParam); + } + + // Save off the material. + g.materials.push(material); + } + g.noTextureMaterial = g.materials[0]; + g.dayOnlyMaterial = g.materials[1]; + g.nightAndDayMaterial = g.materials[2]; + g.maskMaterial = g.materials[3]; + g.energyMaterial = g.materials[4]; + g.energyMaterial.drawList = g.viewInfo.zOrderedDrawList; + g.atmosphereMaterial = g.materials[5]; + + // create samplers + g.samplers = []; + for (var ii = 0; ii < 4; ++ii) { + var sampler = g.pack.createObject('Sampler'); + g.samplers[ii] = sampler; + } + + g.daySampler = g.samplers[0]; + g.nightSampler = g.samplers[1]; + g.maskSampler = g.samplers[2]; + g.energySampler = g.samplers[3]; + + // set the material samplers. + g.dayOnlyMaterial.getParam('daySampler').value = g.daySampler; + g.nightAndDayMaterial.getParam('daySampler').value = g.daySampler; + g.nightAndDayMaterial.getParam('nightSampler').value = g.nightSampler; + g.maskMaterial.getParam('daySampler').value = g.daySampler; + g.maskMaterial.getParam('maskSampler').value = g.maskSampler; + g.maskMaterial.getParam('nightSampler').value = g.nightSampler; + g.energyMaterial.getParam('energySampler').value = g.energySampler; + + // Create energy texture(s) + { + // WebGL expects power-of-two textures, so use 4x32 instead of 3x32. + var dots = [ 0, 1, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, 1, 0, 0, + 1, 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0 ]; + var texture = g.pack.createTexture2D(4, + dots.length, + g.o3d.Texture.XRGB8, + 1, + false); + var pixels = []; + for (var yy = 0; yy < dots.length; ++yy) { + for (var xx = 0; xx < 4; ++xx) { + var pixelOffset = (yy * 4 + xx) * 3; + var color = (xx == 1 || xx == 2) ? dots[yy] : 0; + for (var cc = 0; cc < 3; ++cc) { + pixels[pixelOffset + cc] = color; + } + } + } + texture.set(0, pixels); + g.energySampler.texture = texture; + } + + // Setup counters for shard animation. + g.shardCounter = g.pack.createObject('SecondCounter'); + g.shardCounter.multiplier = 0.1; + g.energyMaterial.getParam('time').bind( + g.shardCounter.getParam('count')); + + // Setup counters to fade in textures. + g.flatToDayCounter = g.pack.createObject('SecondCounter'); + g.flatToDayCounter.end = 1; + g.flatToDayCounter.multiplier = 0.5; + g.flatToDayCounter.countMode = g.o3d.Counter.ONCE; + g.flatToDayCounter.running = false; + g.flatToDayCounter.addCallback(1, loadNightTexture); + g.dayOnlyMaterial.getParam('time').bind( + g.flatToDayCounter.getParam('count')); + + g.dayOnlyToNightCounter = g.pack.createObject('SecondCounter'); + g.dayOnlyToNightCounter.end = 1; + g.dayOnlyToNightCounter.multiplier = 0.5; + g.dayOnlyToNightCounter.countMode = g.o3d.Counter.ONCE; + g.dayOnlyToNightCounter.running = false; + g.dayOnlyToNightCounter.addCallback(1, loadMaskTexture); + g.nightAndDayMaterial.getParam('time').bind( + g.dayOnlyToNightCounter.getParam('count')); + + g.noMaskToMaskCounter = g.pack.createObject('SecondCounter'); + g.noMaskToMaskCounter.end = 1; + g.noMaskToMaskCounter.multiplier = 0.5; + g.noMaskToMaskCounter.countMode = g.o3d.Counter.ONCE; + g.noMaskToMaskCounter.running = false; + g.maskMaterial.getParam('time').bind( + g.noMaskToMaskCounter.getParam('count')); + + // Create a sphere at the origin for the earth. + var earth = o3djs.primitives.createSphere(g.pack, + g.noTextureMaterial, + 25, + 50, + 50); + + // Get a the element so we can set its material later. + g.earthPrimitive = earth.elements[0]; + g.atmosphereState = g.pack.createObject('State'); + g.atmosphereState.getStateParam('AlphaBlendEnable').value = true; + g.atmosphereState.getStateParam('SourceBlendFunction').value = + g.o3d.State.BLENDFUNC_SOURCE_ALPHA; + g.atmosphereState.getStateParam('DestinationBlendFunction').value = + g.o3d.State.BLENDFUNC_INVERSE_SOURCE_ALPHA; + g.atmosphereState.getStateParam('ZWriteEnable').value = false; + g.atmosphereMaterial.state = g.atmosphereState; + + g.root = g.pack.createObject('Transform'); + g.root.parent = g.client.root; + g.earth = g.pack.createObject('Transform'); + g.earth.addShape(earth); + g.earth.parent = g.root; + + // Create a sphere at the origin for the atmosphere. + var atmosphere = o3djs.primitives.createSphere(g.pack, + g.atmosphereMaterial, + 26, + 50, + 50); + g.atmospherePrimitive = atmosphere.elements[0]; + g.atmospherePrimitive.priority = 1; + g.atmosphere = g.pack.createObject('Transform'); + g.atmosphere.addShape(atmosphere); + g.atmosphere.parent = g.root; + + g.energyShape = createEnergyShape(g.pack, + g.energyMaterial, + g.ENERGY_WIDTH, + g.ENERGY_HEIGHT); + + addEnergyShard(0, 0, 1, 1, [1, 1, 1, 1]); + + // Honolulu, Hawaii, 21, 18, 157, 50 + addEnergyShard(21.18, 157.50, 1, 1, [0, 1, 0, 1]); + // San Francisco, Calif. 37 47 122 26 + addEnergyShard(37.47, 122.26, 1, 1, [1, 0.5, 0.5, 1]); + + for (var ii = 0; ii < 24; ++ii) { + var longitude = Math.random() * 360; + var latitude = Math.random() * 360 - 180; + var color = [ Math.random() * 0.5 + 0.2, + Math.random() * 0.5 + 0.2, + Math.random() * 0.5 + 0.2, + 1 ]; + for (var jj = 0; jj < 24; ++jj) { + addEnergyShard(latitude + (Math.random() - 0.5) * 10, + longitude + (Math.random() - 0.5) * 10, + 1, + 1, + color); + } + } + + o3djs.event.addEventListener(g.o3dElement, 'mousedown', startDragging); + o3djs.event.addEventListener(g.o3dElement, 'mousemove', drag); + o3djs.event.addEventListener(g.o3dElement, 'mouseup', stopDragging); + o3djs.event.addEventListener(g.o3dElement, 'wheel', scrollMe); + + loadDayTexture(); +} + +function loadTexture(path, callback) { + var url = getURL(path); + o3djs.io.loadTexture(g.pack, url, function(texture, exception) { + if (exception) { + alert(exception); + } else { + callback(texture); + } + }); +} + +function loadDayTexture() { + loadTexture('assets/earth.jpg', function(texture) { + g.daySampler.texture = texture; + g.earthPrimitive.material = g.dayOnlyMaterial; + g.flatToDayCounter.running = true; + }); +} + +function loadNightTexture() { + loadTexture('assets/night.jpg', function(texture) { + g.nightSampler.texture = texture; + g.earthPrimitive.material = g.nightAndDayMaterial; + g.dayOnlyToNightCounter.running = true; + }); +} + +function loadMaskTexture() { + loadTexture('assets/earth-large-with-ocean-mask.png', function(texture) { + g.maskSampler.texture = texture; + g.earthPrimitive.material = g.maskMaterial; + g.noMaskToMaskCounter.running = true; + g_finished = true; // for selenium + }); +} + +function uninit() { + // TODO: We should clean up any counters that have callbacks here. + if (g.client) { + g.client.cleanup(); + } +} +</script> +<!--<h1> +Google Trends Visualizer. +</h1>--> +<div id="o3d" style="width:100%; height: 100%;"></div> +<div style="display:none"> +<textarea id="noTexture" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 world; +uniform mat4 view; + +uniform vec3 sunPos; + +attribute vec4 position; +attribute vec3 normal; + +varying vec4 v_pos; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +void main() { + gl_Position = worldViewProjection * position; + v_normal = (world * vec4(normal, 0)).xyz; + vec3 worldPos = (world * position).xyz; + v_sun = sunPos - worldPos; + v_view = (view[3].xyz- worldPos); + v_pos = gl_Position; +} + +// #o3d SplitMarker + +varying vec4 v_pos; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +vec4 lit(float l, float h, float m) { + return vec4(1.0, + max(l, 0.0), + (l > 0.0) ? pow(max(0.0, h), m) : 0.0, + 1.0); +} + +void main() { + vec3 norm = normalize(v_normal); + vec3 sun = normalize(v_sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1.0 - sqrt(abs(light)); + dayNight = dayNight * dayNight; + dayNight = (1.0 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0.0, 1.0); + vec3 view = normalize(v_view); + vec3 r = normalize(reflect(norm, sun)); + vec4 litR = vec4(lit(light, dot(r, view), 0.0).y); + vec3 day = vec3(0.5, 0.5, 1.0) * litR.y + vec3(1,1,1) * litR.z; + vec3 night = vec3(0.2, 0.2, 0.5); + gl_FragColor = vec4(mix(night, day, dayNight),1); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="dayOnly" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 world; +uniform mat4 view; + +uniform vec3 sunPos; + +attribute vec4 position; +attribute vec3 normal; +attribute vec2 texCoord0; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +void main() { + gl_Position = (worldViewProjection * position); + v_uv = texCoord0; + v_normal = (world * vec4(normal, 0)).xyz; + vec3 worldPos = (world * position).xyz; + v_sun = sunPos - worldPos; + v_view = (view[3].xyz - worldPos); +} + +// #o3d SplitMarker + +uniform float time; + +uniform sampler2D daySampler; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +vec4 lit(float l, float h, float m) { + return vec4(1.0, + max(l, 0.0), + (l > 0.0) ? pow(max(0.0, h), m) : 0.0, + 1.0); +} + +void main() { + vec3 norm = normalize(v_normal); + vec3 sun = normalize(v_sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1.0 - sqrt(abs(light)); + dayNight = dayNight * dayNight; + dayNight = (1.0 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0.0, 1.0); + vec3 view = normalize(v_view); + vec3 r = normalize(reflect(norm, sun)); + vec4 litR = vec4(lit(light, dot(r, view), 0.0).y); + vec3 earth = texture2D(daySampler, v_uv).xyz; + vec3 day = mix(vec3(0.5, 0.5, 1.0), earth, time); + day = day * litR.y + vec3(1,1,1) * litR.z; + vec3 night = mix(vec3(0.2, 0.2, 0.5), earth * 0.3, time); + gl_FragColor = vec4(mix(night, day, dayNight),1); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="nightAndDay" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 world; +uniform mat4 view; + +uniform vec3 sunPos; + +attribute vec4 position; +attribute vec3 normal; +attribute vec2 texCoord0; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +void main() { + gl_Position = worldViewProjection * position; + v_uv = texCoord0; + v_normal = (world * vec4(normal, 0)).xyz; + vec3 worldPos = (world * position).xyz; + v_sun = sunPos - worldPos; + v_view = (view[3].xyz - worldPos); +} + +// #o3d SplitMarker + +uniform float time; + +uniform sampler2D daySampler; +uniform sampler2D nightSampler; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +vec4 lit(float l, float h, float m) { + return vec4(1.0, + max(l, 0.0), + (l > 0.0) ? pow(max(0.0, h), m) : 0.0, + 1.0); +} + +void main() { + vec3 norm = normalize(v_normal); + vec3 sun = normalize(v_sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1.0 - sqrt(abs(light)); + dayNight = dayNight * dayNight; + dayNight = (1.0 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0.0, 1.0); + vec3 view = normalize(v_view); + vec3 r = normalize(reflect(norm, sun)); + vec4 litR = vec4(lit(light, dot(r, view), 0.0).y); + vec3 earth = texture2D(daySampler, v_uv).xyz; + vec3 day = texture2D(daySampler, v_uv).xyz; + vec3 night = mix(day * 0.3, texture2D(nightSampler, v_uv).xyz, time); + day = day * litR.y + vec3(1,1,1) * litR.z; + gl_FragColor = vec4(mix(night, day, dayNight),1); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<!-- +This shader renders the ocean different then the non-ocean using a mask +stored in the alpha channel of the maskSampler +--> +<textarea id="mask" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 world; +uniform mat4 view; + +uniform vec3 sunPos; + +attribute vec4 position; +attribute vec3 normal; +attribute vec2 texCoord0; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +void main() { + gl_Position = worldViewProjection * position; + v_uv = texCoord0; + v_normal = (world * vec4(normal, 0)).xyz; + vec3 worldPos = (world * position).xyz; + v_sun = sunPos - worldPos; + v_view = (view[3].xyz - worldPos); +} + +// #o3d SplitMarker + +uniform float time; + +uniform sampler2D daySampler; +uniform sampler2D nightSampler; +uniform sampler2D maskSampler; + +varying vec2 v_uv; +varying vec3 v_normal; +varying vec3 v_sun; +varying vec3 v_view; + +vec4 lit(float l, float h, float m) { + return vec4(1.0, + max(l, 0.0), + (l > 0.0) ? pow(max(0.0, h), m) : 0.0, + 1.0); +} + +void main() { + vec3 norm = normalize(v_normal); + vec3 sun = normalize(v_sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1.0 - sqrt(abs(light)); + dayNight = dayNight * dayNight; + dayNight = (1.0 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0.0, 1.0); + vec3 view = normalize(v_view); + vec3 r = normalize(reflect(norm, sun)); + vec4 litR = vec4(lit(light, dot(r, view), 0.0).y); + vec3 earth = texture2D(daySampler, v_uv).xyz; + vec4 mask = texture2D(maskSampler, v_uv); + vec3 day = mix(texture2D(daySampler, v_uv).xyz, + mask.xyz, time); + vec3 night = texture2D(nightSampler, v_uv).xyz; + day = day * litR.y + vec3(1,1,1) * litR.z * (1.0 - mask.w * time); + vec3 color = mix(night, day, dayNight); + gl_FragColor = vec4(color, 1); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="energy" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; + +// time is used to scroll the UV coords +uniform float time; + +// offset is used to allow each shard to scroll over a different part of the +// texture. +uniform float offset; + +attribute vec4 position; +attribute vec4 color; +attribute vec2 texCoord0; + +varying vec4 v_color; +varying vec2 v_uv; + +void main() { + gl_Position = worldViewProjection * position; + v_uv = vec2(texCoord0.x, texCoord0.y + time + offset); + v_color = color; +} + +// #o3d SplitMarker + +// Sets the color of the shard. +uniform vec4 colorMult; + +// Provides the dots on the shard. +uniform sampler2D energySampler; + +varying vec4 v_color; +varying vec2 v_uv; + +void main() { + gl_FragColor = texture2D(energySampler, v_uv) * v_color * colorMult; +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="atmosphere" name="fx" cols="80" rows="20"> +uniform mat4 worldViewProjection; +uniform mat4 worldView; + +attribute vec4 position; +attribute vec3 normal; + +varying vec3 v_normal; + +void main() { + gl_Position = worldViewProjection * position; + v_normal = normalize((worldView * vec4(normal,0)).xyz); +} + +// #o3d SplitMarker + +varying vec3 v_normal; + +void main() { + float n = 1.0 - log(2.0 * normalize(v_normal).z); + gl_FragColor = vec4(0.3, 0.3, 1, n * n * n * n); +} + +// #o3d MatrixLoadOrder RowMajor +</textarea> +</div> +</body> +</html> + + diff --git a/o3d/samples/o3djs/particles.js b/o3d/samples/o3djs/particles.js index 66f604a..f6b7d4e 100644 --- a/o3d/samples/o3djs/particles.js +++ b/o3d/samples/o3djs/particles.js @@ -271,103 +271,10 @@ o3djs.particles.FX_STRINGS_CG = [ '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' + '// #o3d MatrixLoadOrder RowMajor\n'}]; -// Auto-generated by convert.py. o3djs.particles.FX_STRINGS_GLSL = [ { name: 'particle3d', fxString: '' + - '// glslv profile log:\n' + - '// (0) : warning C7011: implicit cast from "float1" to "float"\n' + - '// 109 lines, 1 warnings, 0 errors.\n' + - '\n' + - '// glslf profile log:\n' + - '// 109 lines, 0 errors.\n' + - '\n' + - '// glslv output by Cg compiler\n' + - '// cgc version 2.0.0010, build date Dec 12 2007\n' + - '// command line args: -profile glslv\n' + - '//vendor NVIDIA Corporation\n' + - '//version 2.0.0.10\n' + - '//profile glslv\n' + - '//program vertexShaderFunction\n' + - '//semantic worldViewProjection : WORLDVIEWPROJECTION\n' + - '//semantic world : WORLD\n' + - '//semantic worldVelocity\n' + - '//semantic worldAcceleration\n' + - '//semantic timeRange\n' + - '//semantic time\n' + - '//semantic timeOffset\n' + - '//semantic frameDuration\n' + - '//semantic numFrames\n' + - '//semantic rampSampler\n' + - '//semantic colorSampler\n' + - '//var float4x4 worldViewProjection : WORLDVIEWPROJECTION : _ZZ2SworldViewProjection[0], 4 : -1 : 1\n' + - '//var float4x4 world : WORLD : _ZZ2Sworld[0], 4 : -1 : 1\n' + - '//var float3 worldVelocity : : _ZZ2SworldVelocity : -1 : 1\n' + - '//var float3 worldAcceleration : : _ZZ2SworldAcceleration : -1 : 1\n' + - '//var float timeRange : : _ZZ2StimeRange : -1 : 1\n' + - '//var float time : : _ZZ2Stime : -1 : 1\n' + - '//var float timeOffset : : _ZZ2StimeOffset : -1 : 1\n' + - '//var float frameDuration : : _ZZ2SframeDuration : -1 : 1\n' + - '//var float numFrames : : _ZZ2SnumFrames : -1 : 1\n' + - '//var sampler rampSampler : : : -1 : 0\n' + - '//var sampler colorSampler : : : -1 : 0\n' + - '//var float4 input.uvLifeTimeFrameStart : $vin.POSITION : POSITION : 0 : 1\n' + - '//var float4 input.positionStartTime : $vin.TEXCOORD0 : TEXCOORD0 : 0 : 1\n' + - '//var float4 input.velocityStartSize : $vin.TEXCOORD1 : TEXCOORD1 : 0 : 1\n' + - '//var float4 input.accelerationEndSize : $vin.TEXCOORD2 : TEXCOORD2 : 0 : 1\n' + - '//var float4 input.spinStartSpinSpeed : $vin.TEXCOORD3 : TEXCOORD3 : 0 : 1\n' + - '//var float4 input.orientation : $vin.TEXCOORD4 : TEXCOORD4 : 0 : 1\n' + - '//var float4 input.colorMult : $vin.COLOR : COLOR : 0 : 1\n' + - '//var float4 vertexShaderFunction.position : $vout.POSITION : POSITION : -1 : 1\n' + - '//var float2 vertexShaderFunction.texcoord : $vout.TEXCOORD0 : TEXCOORD0 : -1 : 1\n' + - '//var float1 vertexShaderFunction.percentLife : $vout.TEXCOORD1 : TEXCOORD1 : -1 : 1\n' + - '//var float4 vertexShaderFunction.colorMult : $vout.TEXCOORD2 : TEXCOORD2 : -1 : 1\n' + - '\n' + - 'attribute vec4 position;\n' + - 'attribute vec4 texcoord0;\n' + - 'attribute vec4 texcoord1;\n' + - 'attribute vec4 texcoord2;\n' + - 'attribute vec4 texcoord3;\n' + - 'attribute vec4 texcoord4;\n' + - 'vec4 _glPositionTemp;\n' + - 'uniform vec4 dx_clipping;\n' + - '\n' + - 'struct VertexShaderInput {\n' + - ' vec4 uvLifeTimeFrameStart;\n' + - ' vec4 positionStartTime;\n' + - ' vec4 velocityStartSize;\n' + - ' vec4 accelerationEndSize;\n' + - ' vec4 spinStartSpinSpeed;\n' + - ' vec4 orientation;\n' + - ' vec4 colorMult;\n' + - '};\n' + - '\n' + - 'struct PixelShaderInput {\n' + - ' vec4 position;\n' + - ' vec2 texcoord;\n' + - ' float percentLife;\n' + - ' vec4 colorMult;\n' + - '};\n' + - '\n' + - 'PixelShaderInput _ZZ3Sret_0;\n' + - 'vec4 _ZZ3SrZh0027;\n' + - 'vec4 _ZZ3SvZh0027;\n' + - 'vec4 _ZZ3SrZh0029;\n' + - 'vec4 _ZZ3SvZh0029;\n' + - 'float _ZZ3ScZh0031;\n' + - 'float _ZZ3SaZh0031;\n' + - 'float _ZZ3SaZh0033;\n' + - 'float _ZZ3SxZh0035;\n' + - 'float _ZZ3SxZh0039;\n' + - 'float _ZZ3ScZh0041;\n' + - 'float _ZZ3SaZh0041;\n' + - 'float _ZZ3SaZh0043;\n' + - 'float _ZZ3SxZh0045;\n' + - 'float _ZZ3SaZh0051;\n' + - 'float _ZZ3SaZh0053;\n' + - 'vec4 _ZZ3SrZh0055;\n' + - 'vec4 _ZZ3SrZh0057;\n' + - 'uniform mat4 worldviewprojection;\n' + 'uniform mat4 world;\n' + + 'uniform mat4 worldViewProjection;\n' + 'uniform vec3 worldVelocity;\n' + 'uniform vec3 worldAcceleration;\n' + 'uniform float timeRange;\n' + @@ -376,271 +283,114 @@ o3djs.particles.FX_STRINGS_GLSL = [ 'uniform float frameDuration;\n' + 'uniform float numFrames;\n' + '\n' + - ' // main procedure, the original name was vertexShaderFunction\n' + - 'void main()\n' + - '{\n' + - '\n' + - ' PixelShaderInput _ZZ4Soutput;\n' + - ' vec3 _ZZ4Svelocity;\n' + - ' vec3 _ZZ4Sacceleration;\n' + - ' float _ZZ4SlocalTime;\n' + - ' float _ZZ4SpercentLife;\n' + - ' float _ZZ4Sframe;\n' + - ' float _ZZ4SuOffset;\n' + - ' float _ZZ4Su;\n' + - ' float _ZZ4Ssize;\n' + - ' float _ZZ4Ss;\n' + - ' float _ZZ4Sc;\n' + - ' vec4 _ZZ4SrotatedPoint;\n' + - ' vec3 _ZZ4Scenter;\n' + - ' vec4 _ZZ4Sq2;\n' + - ' vec4 _ZZ4Sqx;\n' + - ' vec4 _ZZ4Sqy;\n' + - ' vec4 _ZZ4Sqz;\n' + - ' vec4 _ZZ4SZaTMP9[4];\n' + - '\n' + - ' _ZZ3SvZh0027 = vec4(texcoord1.x, texcoord1.y, texcoord1.z, 0.00000000E+00);\n' + - ' _ZZ3SrZh0027 = _ZZ3SvZh0027.x*world[0];\n' + - ' _ZZ3SrZh0027 = _ZZ3SrZh0027 + _ZZ3SvZh0027.y*world[1];\n' + - ' _ZZ3SrZh0027 = _ZZ3SrZh0027 + _ZZ3SvZh0027.z*world[2];\n' + - ' _ZZ3SrZh0027 = _ZZ3SrZh0027 + _ZZ3SvZh0027.w*world[3];\n' + - ' _ZZ4Svelocity = _ZZ3SrZh0027.xyz + worldVelocity;\n' + - ' _ZZ3SvZh0029 = vec4(texcoord2.x, texcoord2.y, texcoord2.z, 0.00000000E+00);\n' + - ' _ZZ3SrZh0029 = _ZZ3SvZh0029.x*world[0];\n' + - ' _ZZ3SrZh0029 = _ZZ3SrZh0029 + _ZZ3SvZh0029.y*world[1];\n' + - ' _ZZ3SrZh0029 = _ZZ3SrZh0029 + _ZZ3SvZh0029.z*world[2];\n' + - ' _ZZ3SrZh0029 = _ZZ3SrZh0029 + _ZZ3SvZh0029.w*world[3];\n' + - ' _ZZ4Sacceleration = _ZZ3SrZh0029.xyz + worldAcceleration;\n' + - ' _ZZ3SaZh0031 = (time - timeOffset) - texcoord0.w;\n' + - ' _ZZ3SaZh0033 = _ZZ3SaZh0031/timeRange;\n' + - ' _ZZ3SxZh0035 = abs(_ZZ3SaZh0033);\n' + - ' _ZZ3ScZh0031 = fract(_ZZ3SxZh0035)*abs(timeRange);\n' + - ' _ZZ4SlocalTime = _ZZ3SaZh0031 < 0.00000000E+00 ? -_ZZ3ScZh0031 : _ZZ3ScZh0031;\n' + - ' _ZZ4SpercentLife = _ZZ4SlocalTime/position.z;\n' + - ' _ZZ3SxZh0039 = _ZZ4SlocalTime/frameDuration + position.w;\n' + - ' _ZZ3SaZh0041 = floor(_ZZ3SxZh0039);\n' + - ' _ZZ3SaZh0043 = _ZZ3SaZh0041/numFrames;\n' + - ' _ZZ3SxZh0045 = abs(_ZZ3SaZh0043);\n' + - ' _ZZ3ScZh0041 = fract(_ZZ3SxZh0045)*abs(numFrames);\n' + - ' _ZZ4Sframe = _ZZ3SaZh0041 < 0.00000000E+00 ? -_ZZ3ScZh0041 : _ZZ3ScZh0041;\n' + - ' _ZZ4SuOffset = _ZZ4Sframe/numFrames;\n' + - ' _ZZ4Su = _ZZ4SuOffset + (position.x + 5.00000000E-01)*(1.00000000E+00/numFrames);\n' + - ' _ZZ4Soutput.texcoord = vec2(_ZZ4Su, position.y + 5.00000000E-01);\n' + - ' _ZZ4Ssize = texcoord1.w + _ZZ4SpercentLife*(texcoord2.w - texcoord1.w);\n' + - ' _ZZ4Ssize = _ZZ4SpercentLife < 0.00000000E+00 || _ZZ4SpercentLife > 1.00000000E+00 ? 0.00000000E+00 : _ZZ4Ssize;\n' + - ' _ZZ3SaZh0051 = texcoord3.x + texcoord3.y*_ZZ4SlocalTime;\n' + - ' _ZZ4Ss = sin(_ZZ3SaZh0051);\n' + - ' _ZZ3SaZh0053 = texcoord3.x + texcoord3.y*_ZZ4SlocalTime;\n' + - ' _ZZ4Sc = cos(_ZZ3SaZh0053);\n' + - ' _ZZ4SrotatedPoint = vec4((position.x*_ZZ4Sc + position.y*_ZZ4Ss)*_ZZ4Ssize, 0.00000000E+00, (position.x*_ZZ4Ss - position.y*_ZZ4Sc)*_ZZ4Ssize, 1.00000000E+00);\n' + - ' _ZZ4Scenter = _ZZ4Svelocity*_ZZ4SlocalTime + _ZZ4Sacceleration*_ZZ4SlocalTime*_ZZ4SlocalTime + texcoord0.xyz;\n' + - ' _ZZ4Sq2 = texcoord4 + texcoord4;\n' + - ' _ZZ4Sqx = texcoord4.xxxw*_ZZ4Sq2.xyzx;\n' + - ' _ZZ4Sqy = texcoord4.xyyw*_ZZ4Sq2.xyzy;\n' + - ' _ZZ4Sqz = texcoord4.xxzw*_ZZ4Sq2.xxzz;\n' + - ' _ZZ4SZaTMP9[0] = vec4((1.00000000E+00 - _ZZ4Sqy.y) - _ZZ4Sqz.z, _ZZ4Sqx.y + _ZZ4Sqz.w, _ZZ4Sqx.z - _ZZ4Sqy.w, 0.00000000E+00);\n' + - ' _ZZ4SZaTMP9[1] = vec4(_ZZ4Sqx.y - _ZZ4Sqz.w, (1.00000000E+00 - _ZZ4Sqx.x) - _ZZ4Sqz.z, _ZZ4Sqy.z + _ZZ4Sqx.w, 0.00000000E+00);\n' + - ' _ZZ4SZaTMP9[2] = vec4(_ZZ4Sqx.z + _ZZ4Sqy.w, _ZZ4Sqy.z - _ZZ4Sqx.w, (1.00000000E+00 - _ZZ4Sqx.x) - _ZZ4Sqy.y, 0.00000000E+00);\n' + - ' _ZZ4SZaTMP9[3] = vec4(_ZZ4Scenter.x, _ZZ4Scenter.y, _ZZ4Scenter.z, 1.00000000E+00);\n' + - ' _ZZ3SrZh0055 = _ZZ4SrotatedPoint.x*_ZZ4SZaTMP9[0];\n' + - ' _ZZ3SrZh0055 = _ZZ3SrZh0055 + _ZZ4SrotatedPoint.y*_ZZ4SZaTMP9[1];\n' + - ' _ZZ3SrZh0055 = _ZZ3SrZh0055 + _ZZ4SrotatedPoint.z*_ZZ4SZaTMP9[2];\n' + - ' _ZZ3SrZh0055 = _ZZ3SrZh0055 + _ZZ4SrotatedPoint.w*_ZZ4SZaTMP9[3];\n' + - ' _ZZ3SrZh0057 = _ZZ3SrZh0055.x*worldviewprojection[0];\n' + - ' _ZZ3SrZh0057 = _ZZ3SrZh0057 + _ZZ3SrZh0055.y*worldviewprojection[1];\n' + - ' _ZZ3SrZh0057 = _ZZ3SrZh0057 + _ZZ3SrZh0055.z*worldviewprojection[2];\n' + - ' _ZZ3SrZh0057 = _ZZ3SrZh0057 + _ZZ3SrZh0055.w*worldviewprojection[3];\n' + - ' _ZZ4Soutput.percentLife = _ZZ4SpercentLife;\n' + - ' _ZZ3Sret_0.position = _ZZ3SrZh0057;\n' + - ' _ZZ3Sret_0.texcoord = _ZZ4Soutput.texcoord;\n' + - ' _ZZ3Sret_0.percentLife = _ZZ4Soutput.percentLife;\n' + - ' _ZZ3Sret_0.colorMult = gl_Color;\n' + - ' gl_TexCoord[0].xy = _ZZ4Soutput.texcoord;\n' + - ' gl_TexCoord[2] = gl_Color;\n' + - ' _glPositionTemp = _ZZ3SrZh0057; gl_Position = vec4(_glPositionTemp.x + _glPositionTemp.w * dx_clipping.x, dx_clipping.w * (_glPositionTemp.y + _glPositionTemp.w * dx_clipping.y), _glPositionTemp.z * 2 - _glPositionTemp.w, _glPositionTemp.w);\n' + - ' gl_TexCoord[1].x = _ZZ4Soutput.percentLife;\n' + - ' return;\n' + - '} // main end\n' + - '\n' + - '\n' + - '// #o3d SplitMarker\n' + - '// #o3d MatrixLoadOrder RowMajor\n' + - '\n' + - '// glslf output by Cg compiler\n' + - '// cgc version 2.0.0010, build date Dec 12 2007\n' + - '// command line args: -profile glslf\n' + - '//vendor NVIDIA Corporation\n' + - '//version 2.0.0.10\n' + - '//profile glslf\n' + - '//program pixelShaderFunction\n' + - '//semantic worldViewProjection : WORLDVIEWPROJECTION\n' + - '//semantic world : WORLD\n' + - '//semantic worldVelocity\n' + - '//semantic worldAcceleration\n' + - '//semantic timeRange\n' + - '//semantic time\n' + - '//semantic timeOffset\n' + - '//semantic frameDuration\n' + - '//semantic numFrames\n' + - '//semantic rampSampler\n' + - '//semantic colorSampler\n' + - '//var float4x4 worldViewProjection : WORLDVIEWPROJECTION : , 4 : -1 : 0\n' + - '//var float4x4 world : WORLD : , 4 : -1 : 0\n' + - '//var float3 worldVelocity : : : -1 : 0\n' + - '//var float3 worldAcceleration : : : -1 : 0\n' + - '//var float timeRange : : : -1 : 0\n' + - '//var float time : : : -1 : 0\n' + - '//var float timeOffset : : : -1 : 0\n' + - '//var float frameDuration : : : -1 : 0\n' + - '//var float numFrames : : : -1 : 0\n' + - '//var sampler rampSampler : : _ZZ2SrampSampler : -1 : 1\n' + - '//var sampler colorSampler : : _ZZ2ScolorSampler : -1 : 1\n' + - '//var float2 input.texcoord : $vin.TEXCOORD0 : TEXCOORD0 : 0 : 1\n' + - '//var float1 input.percentLife : $vin.TEXCOORD1 : TEXCOORD1 : 0 : 1\n' + - '//var float4 input.colorMult : $vin.TEXCOORD2 : TEXCOORD2 : 0 : 1\n' + - '//var float4 pixelShaderFunction : $vout.COLOR : COLOR : -1 : 1\n' + + 'attribute vec4 position; // uv, lifeTime, frameStart\n' + + 'attribute vec4 texCoord0; // position.xyz, startTime\n' + + 'attribute vec4 texCoord1; // velocity.xyz, startSize\n' + + 'attribute vec4 texCoord2; // acceleration.xyz, endSize\n' + + 'attribute vec4 texCoord3; // spinStart.x, spinSpeed.y\n' + + 'attribute vec4 texCoord4; // orientation\n' + + 'attribute vec4 color; //\n' + + '\n' + + 'varying vec4 v_position;\n' + + 'varying vec2 v_texcoord;\n' + + 'varying float v_percentLife;\n' + + 'varying vec4 v_colorMult;\n' + + '\n' + + 'void main() {\n' + + ' vec4 uvLifeTimeFrameStart = position;\n' + + ' vec4 positionStartTime = texCoord0;\n' + + ' vec4 velocityStartSize = texCoord1;\n' + + ' vec4 accelerationEndSize = texCoord2;\n' + + ' vec4 spinStartSpinSpeed = texCoord3;\n' + + ' vec4 orientation = texCoord4;\n' + + ' vec4 colorMult = color;\n' + + ' vec2 uv = uvLifeTimeFrameStart.xy;\n' + + ' float lifeTime = uvLifeTimeFrameStart.z;\n' + + ' float frameStart = uvLifeTimeFrameStart.w;\n' + + ' vec3 position = positionStartTime.xyz;\n' + + ' float startTime = positionStartTime.w;\n' + + ' vec3 velocity = (world * vec4(velocityStartSize.xyz, 0)).xyz\n' + + ' + worldVelocity;\n' + + ' float startSize = velocityStartSize.w;\n' + + ' vec3 acceleration = (world *\n' + + ' vec4(accelerationEndSize.xyz, 0)).xyz + worldAcceleration;\n' + + ' float endSize = accelerationEndSize.w;\n' + + ' float spinStart = spinStartSpinSpeed.x;\n' + + ' float spinSpeed = spinStartSpinSpeed.y;\n' + + '\n' + + ' float localTime = mod((time - timeOffset - startTime),\n' + + ' timeRange);\n' + + ' float percentLife = localTime / lifeTime;\n' + '\n' + + ' float frame = mod(floor(localTime / frameDuration + frameStart),\n' + + ' numFrames);\n' + + ' float uOffset = frame / numFrames;\n' + + ' float u = uOffset + (uv.x + 0.5) * (1.0 / numFrames);\n' + '\n' + + ' v_texcoord = vec2(u, uv.y + 0.5);\n' + + ' v_colorMult = colorMult;\n' + '\n' + - 'struct VertexShaderInput {\n' + - ' vec4 positionStartTime;\n' + - ' vec4 velocityStartSize;\n' + - ' vec4 accelerationEndSize;\n' + - ' vec4 spinStartSpinSpeed;\n' + - ' vec4 orientation;\n' + - ' vec4 colorMult;\n' + - '};\n' + + ' float size = mix(startSize, endSize, percentLife);\n' + + ' size = (percentLife < 0.0 || percentLife > 1.0) ? 0.0 : size;\n' + + ' float s = sin(spinStart + spinSpeed * localTime);\n' + + ' float c = cos(spinStart + spinSpeed * localTime);\n' + '\n' + - 'struct PixelShaderInput {\n' + - ' vec2 texcoord;\n' + - ' float percentLife;\n' + - ' vec4 colorMult;\n' + - '};\n' + + ' vec4 rotatedPoint = vec4((uv.x * c + uv.y * s) * size, 0.0,\n' + + ' (uv.x * s - uv.y * c) * size, 1.0);\n' + + ' vec3 center = velocity * localTime +\n' + + ' acceleration * localTime * localTime + \n' + + ' position;\n' + + ' \n' + + ' vec4 q2 = orientation + orientation;\n' + + ' vec4 qx = orientation.xxxw * q2.xyzx;\n' + + ' vec4 qy = orientation.xyyw * q2.xyzy;\n' + + ' vec4 qz = orientation.xxzw * q2.xxzz;\n' + + ' \n' + + ' mat4 localMatrix = mat4(\n' + + ' (1.0 - qy.y) - qz.z, \n' + + ' qx.y + qz.w, \n' + + ' qx.z - qy.w,\n' + + ' 0,\n' + + ' \n' + + ' qx.y - qz.w, \n' + + ' (1.0 - qx.x) - qz.z, \n' + + ' qy.z + qx.w,\n' + + ' 0,\n' + + ' \n' + + ' qx.z + qy.w, \n' + + ' qy.z - qx.w, \n' + + ' (1.0 - qx.x) - qy.y,\n' + + ' 0,\n' + + ' \n' + + ' center.x, center.y, center.z, 1.0);\n' + + ' rotatedPoint = localMatrix * rotatedPoint;\n' + + ' gl_Position = worldViewProjection * rotatedPoint;\n' + + ' v_percentLife = percentLife;\n' + + '}\n' + '\n' + - 'vec4 _ZZ3Sret_0;\n' + - 'sampler2D _ZZ3SsZh0016;\n' + - 'vec2 _ZZ3ScZh0016;\n' + - 'sampler2D _ZZ3SsZh0018;\n' + - 'uniform sampler rampSampler;\n' + - 'uniform sampler colorSampler;\n' + + '// #o3d SplitMarker\n' + '\n' + - ' // main procedure, the original name was pixelShaderFunction\n' + - 'void main()\n' + - '{\n' + + 'varying vec4 v_position;\n' + + 'varying vec2 v_texcoord;\n' + + 'varying float v_percentLife;\n' + + 'varying vec4 v_colorMult;\n' + '\n' + - ' PixelShaderInput _ZZ4Sinput;\n' + - ' vec4 _ZZ4ScolorMult;\n' + - ' vec4 _ZZ4Scolor;\n' + + '// We need to implement 1D!\n' + + 'uniform sampler2D rampSampler;\n' + + 'uniform sampler2D colorSampler;\n' + + '\n' + + 'void main() {\n' + + ' vec4 colorMult = texture2D(rampSampler, \n' + + ' vec2(v_percentLife, 0.5)) * v_colorMult;\n' + + ' vec4 color = texture2D(colorSampler, v_texcoord) * colorMult;\n' + + ' gl_FragColor = color;\n' + + '}\n' + '\n' + - ' _ZZ4Sinput.percentLife = gl_TexCoord[1].x;\n' + - ' _ZZ3SsZh0016 = sampler2D(rampSampler);\n' + - ' _ZZ3ScZh0016 = vec2(_ZZ4Sinput.percentLife, 5.00000000E-01);\n' + - ' _ZZ4ScolorMult = texture2D(_ZZ3SsZh0016, _ZZ3ScZh0016)*gl_TexCoord[2];\n' + - ' _ZZ3SsZh0018 = sampler2D(colorSampler);\n' + - ' _ZZ4Scolor = texture2D(_ZZ3SsZh0018, gl_TexCoord[0].xy)*_ZZ4ScolorMult;\n' + - ' _ZZ3Sret_0 = _ZZ4Scolor;\n' + - ' gl_FragColor = _ZZ4Scolor;\n' + - ' return;\n' + - '} // main end\n'}, + '// #o3d MatrixLoadOrder RowMajor\n'}, { name: 'particle2d', fxString: '' + - '// glslv profile log:\n' + - '// (0) : warning C7011: implicit cast from "float1" to "float"\n' + - '// 93 lines, 1 warnings, 0 errors.\n' + - '\n' + - '// glslf profile log:\n' + - '// 93 lines, 0 errors.\n' + - '\n' + - '// glslv output by Cg compiler\n' + - '// cgc version 2.0.0010, build date Dec 12 2007\n' + - '// command line args: -profile glslv\n' + - '//vendor NVIDIA Corporation\n' + - '//version 2.0.0.10\n' + - '//profile glslv\n' + - '//program vertexShaderFunction\n' + - '//semantic viewProjection : VIEWPROJECTION\n' + - '//semantic world : WORLD\n' + - '//semantic viewInverse : VIEWINVERSE\n' + - '//semantic worldVelocity\n' + - '//semantic worldAcceleration\n' + - '//semantic timeRange\n' + - '//semantic time\n' + - '//semantic timeOffset\n' + - '//semantic frameDuration\n' + - '//semantic numFrames\n' + - '//semantic rampSampler\n' + - '//semantic colorSampler\n' + - '//var float4x4 viewProjection : VIEWPROJECTION : _ZZ2SviewProjection[0], 4 : -1 : 1\n' + - '//var float4x4 world : WORLD : _ZZ2Sworld[0], 4 : -1 : 1\n' + - '//var float4x4 viewInverse : VIEWINVERSE : _ZZ2SviewInverse[0], 4 : -1 : 1\n' + - '//var float3 worldVelocity : : _ZZ2SworldVelocity : -1 : 1\n' + - '//var float3 worldAcceleration : : _ZZ2SworldAcceleration : -1 : 1\n' + - '//var float timeRange : : _ZZ2StimeRange : -1 : 1\n' + - '//var float time : : _ZZ2Stime : -1 : 1\n' + - '//var float timeOffset : : _ZZ2StimeOffset : -1 : 1\n' + - '//var float frameDuration : : _ZZ2SframeDuration : -1 : 1\n' + - '//var float numFrames : : _ZZ2SnumFrames : -1 : 1\n' + - '//var sampler rampSampler : : : -1 : 0\n' + - '//var sampler colorSampler : : : -1 : 0\n' + - '//var float4 input.uvLifeTimeFrameStart : $vin.POSITION : POSITION : 0 : 1\n' + - '//var float4 input.positionStartTime : $vin.TEXCOORD0 : TEXCOORD0 : 0 : 1\n' + - '//var float4 input.velocityStartSize : $vin.TEXCOORD1 : TEXCOORD1 : 0 : 1\n' + - '//var float4 input.accelerationEndSize : $vin.TEXCOORD2 : TEXCOORD2 : 0 : 1\n' + - '//var float4 input.spinStartSpinSpeed : $vin.TEXCOORD3 : TEXCOORD3 : 0 : 1\n' + - '//var float4 input.colorMult : $vin.COLOR : COLOR : 0 : 1\n' + - '//var float4 vertexShaderFunction.position : $vout.POSITION : POSITION : -1 : 1\n' + - '//var float2 vertexShaderFunction.texcoord : $vout.TEXCOORD0 : TEXCOORD0 : -1 : 1\n' + - '//var float1 vertexShaderFunction.percentLife : $vout.TEXCOORD1 : TEXCOORD1 : -1 : 1\n' + - '//var float4 vertexShaderFunction.colorMult : $vout.TEXCOORD2 : TEXCOORD2 : -1 : 1\n' + - '\n' + - 'attribute vec4 position;\n' + - 'attribute vec4 texcoord0;\n' + - 'attribute vec4 texcoord1;\n' + - 'attribute vec4 texcoord2;\n' + - 'attribute vec4 texcoord3;\n' + - 'vec4 _glPositionTemp;\n' + - 'uniform vec4 dx_clipping;\n' + - '\n' + - 'struct VertexShaderInput {\n' + - ' vec4 uvLifeTimeFrameStart;\n' + - ' vec4 positionStartTime;\n' + - ' vec4 velocityStartSize;\n' + - ' vec4 accelerationEndSize;\n' + - ' vec4 spinStartSpinSpeed;\n' + - ' vec4 colorMult;\n' + - '};\n' + - '\n' + - 'struct PixelShaderInput {\n' + - ' vec4 position;\n' + - ' vec2 texcoord;\n' + - ' float percentLife;\n' + - ' vec4 colorMult;\n' + - '};\n' + - '\n' + - 'PixelShaderInput _ZZ3Sret_0;\n' + - 'vec4 _ZZ3SrZh0027;\n' + - 'vec4 _ZZ3SvZh0027;\n' + - 'vec4 _ZZ3SrZh0029;\n' + - 'vec4 _ZZ3SvZh0029;\n' + - 'vec4 _ZZ3SrZh0031;\n' + - 'vec4 _ZZ3SvZh0031;\n' + - 'float _ZZ3ScZh0033;\n' + - 'float _ZZ3SaZh0033;\n' + - 'float _ZZ3SaZh0035;\n' + - 'float _ZZ3SxZh0037;\n' + - 'float _ZZ3SxZh0041;\n' + - 'float _ZZ3ScZh0043;\n' + - 'float _ZZ3SaZh0043;\n' + - 'float _ZZ3SaZh0045;\n' + - 'float _ZZ3SxZh0047;\n' + - 'float _ZZ3SaZh0053;\n' + - 'float _ZZ3SaZh0055;\n' + - 'vec4 _ZZ3SrZh0057;\n' + - 'vec4 _ZZ3SvZh0057;\n' + - 'vec3 _ZZ3SZaTMP58;\n' + - 'vec3 _ZZ3SZaTMP59;\n' + - 'uniform mat4 viewprojection;\n' + + 'uniform mat4 viewProjection;\n' + 'uniform mat4 world;\n' + - 'uniform mat4 viewinverse;\n' + + 'uniform mat4 viewInverse;\n' + 'uniform vec3 worldVelocity;\n' + 'uniform vec3 worldAcceleration;\n' + 'uniform float timeRange;\n' + @@ -649,169 +399,90 @@ o3djs.particles.FX_STRINGS_GLSL = [ 'uniform float frameDuration;\n' + 'uniform float numFrames;\n' + '\n' + - ' // main procedure, the original name was vertexShaderFunction\n' + - 'void main()\n' + - '{\n' + - '\n' + - ' PixelShaderInput _ZZ4Soutput;\n' + - ' vec3 _ZZ4Svelocity;\n' + - ' vec3 _ZZ4Sacceleration;\n' + - ' float _ZZ4SlocalTime;\n' + - ' float _ZZ4SpercentLife;\n' + - ' float _ZZ4Sframe;\n' + - ' float _ZZ4SuOffset;\n' + - ' float _ZZ4Su;\n' + - ' float _ZZ4Ssize;\n' + - ' float _ZZ4Ss;\n' + - ' float _ZZ4Sc;\n' + - ' vec2 _ZZ4SrotatedPoint;\n' + - ' vec3 _ZZ4SlocalPosition;\n' + - '\n' + - ' _ZZ3SvZh0027 = vec4(texcoord0.x, texcoord0.y, texcoord0.z, 1.00000000E+00);\n' + - ' _ZZ3SrZh0027 = _ZZ3SvZh0027.x*world[0];\n' + - ' _ZZ3SrZh0027 = _ZZ3SrZh0027 + _ZZ3SvZh0027.y*world[1];\n' + - ' _ZZ3SrZh0027 = _ZZ3SrZh0027 + _ZZ3SvZh0027.z*world[2];\n' + - ' _ZZ3SrZh0027 = _ZZ3SrZh0027 + _ZZ3SvZh0027.w*world[3];\n' + - ' _ZZ3SvZh0029 = vec4(texcoord1.x, texcoord1.y, texcoord1.z, 0.00000000E+00);\n' + - ' _ZZ3SrZh0029 = _ZZ3SvZh0029.x*world[0];\n' + - ' _ZZ3SrZh0029 = _ZZ3SrZh0029 + _ZZ3SvZh0029.y*world[1];\n' + - ' _ZZ3SrZh0029 = _ZZ3SrZh0029 + _ZZ3SvZh0029.z*world[2];\n' + - ' _ZZ3SrZh0029 = _ZZ3SrZh0029 + _ZZ3SvZh0029.w*world[3];\n' + - ' _ZZ4Svelocity = _ZZ3SrZh0029.xyz + worldVelocity;\n' + - ' _ZZ3SvZh0031 = vec4(texcoord2.x, texcoord2.y, texcoord2.z, 0.00000000E+00);\n' + - ' _ZZ3SrZh0031 = _ZZ3SvZh0031.x*world[0];\n' + - ' _ZZ3SrZh0031 = _ZZ3SrZh0031 + _ZZ3SvZh0031.y*world[1];\n' + - ' _ZZ3SrZh0031 = _ZZ3SrZh0031 + _ZZ3SvZh0031.z*world[2];\n' + - ' _ZZ3SrZh0031 = _ZZ3SrZh0031 + _ZZ3SvZh0031.w*world[3];\n' + - ' _ZZ4Sacceleration = _ZZ3SrZh0031.xyz + worldAcceleration;\n' + - ' _ZZ3SaZh0033 = (time - timeOffset) - texcoord0.w;\n' + - ' _ZZ3SaZh0035 = _ZZ3SaZh0033/timeRange;\n' + - ' _ZZ3SxZh0037 = abs(_ZZ3SaZh0035);\n' + - ' _ZZ3ScZh0033 = fract(_ZZ3SxZh0037)*abs(timeRange);\n' + - ' _ZZ4SlocalTime = _ZZ3SaZh0033 < 0.00000000E+00 ? -_ZZ3ScZh0033 : _ZZ3ScZh0033;\n' + - ' _ZZ4SpercentLife = _ZZ4SlocalTime/position.z;\n' + - ' _ZZ3SxZh0041 = _ZZ4SlocalTime/frameDuration + position.w;\n' + - ' _ZZ3SaZh0043 = floor(_ZZ3SxZh0041);\n' + - ' _ZZ3SaZh0045 = _ZZ3SaZh0043/numFrames;\n' + - ' _ZZ3SxZh0047 = abs(_ZZ3SaZh0045);\n' + - ' _ZZ3ScZh0043 = fract(_ZZ3SxZh0047)*abs(numFrames);\n' + - ' _ZZ4Sframe = _ZZ3SaZh0043 < 0.00000000E+00 ? -_ZZ3ScZh0043 : _ZZ3ScZh0043;\n' + - ' _ZZ4SuOffset = _ZZ4Sframe/numFrames;\n' + - ' _ZZ4Su = _ZZ4SuOffset + (position.x + 5.00000000E-01)*(1.00000000E+00/numFrames);\n' + - ' _ZZ4Soutput.texcoord = vec2(_ZZ4Su, position.y + 5.00000000E-01);\n' + - ' _ZZ4Ssize = texcoord1.w + _ZZ4SpercentLife*(texcoord2.w - texcoord1.w);\n' + - ' _ZZ4Ssize = _ZZ4SpercentLife < 0.00000000E+00 || _ZZ4SpercentLife > 1.00000000E+00 ? 0.00000000E+00 : _ZZ4Ssize;\n' + - ' _ZZ3SaZh0053 = texcoord3.x + texcoord3.y*_ZZ4SlocalTime;\n' + - ' _ZZ4Ss = sin(_ZZ3SaZh0053);\n' + - ' _ZZ3SaZh0055 = texcoord3.x + texcoord3.y*_ZZ4SlocalTime;\n' + - ' _ZZ4Sc = cos(_ZZ3SaZh0055);\n' + - ' _ZZ4SrotatedPoint = vec2(position.x*_ZZ4Sc + position.y*_ZZ4Ss, -position.x*_ZZ4Ss + position.y*_ZZ4Sc);\n' + - ' _ZZ3SZaTMP58.x = viewinverse[0].x;\n' + - ' _ZZ3SZaTMP58.y = viewinverse[0].y;\n' + - ' _ZZ3SZaTMP58.z = viewinverse[0].z;\n' + - ' _ZZ3SZaTMP59.x = viewinverse[1].x;\n' + - ' _ZZ3SZaTMP59.y = viewinverse[1].y;\n' + - ' _ZZ3SZaTMP59.z = viewinverse[1].z;\n' + - ' _ZZ4SlocalPosition = (_ZZ3SZaTMP58*_ZZ4SrotatedPoint.x + _ZZ3SZaTMP59*_ZZ4SrotatedPoint.y)*_ZZ4Ssize + _ZZ4Svelocity*_ZZ4SlocalTime + _ZZ4Sacceleration*_ZZ4SlocalTime*_ZZ4SlocalTime + _ZZ3SrZh0027.xyz;\n' + - ' _ZZ3SvZh0057 = vec4(_ZZ4SlocalPosition.x, _ZZ4SlocalPosition.y, _ZZ4SlocalPosition.z, 1.00000000E+00);\n' + - ' _ZZ3SrZh0057 = _ZZ3SvZh0057.x*viewprojection[0];\n' + - ' _ZZ3SrZh0057 = _ZZ3SrZh0057 + _ZZ3SvZh0057.y*viewprojection[1];\n' + - ' _ZZ3SrZh0057 = _ZZ3SrZh0057 + _ZZ3SvZh0057.z*viewprojection[2];\n' + - ' _ZZ3SrZh0057 = _ZZ3SrZh0057 + _ZZ3SvZh0057.w*viewprojection[3];\n' + - ' _ZZ4Soutput.percentLife = _ZZ4SpercentLife;\n' + - ' _ZZ3Sret_0.position = _ZZ3SrZh0057;\n' + - ' _ZZ3Sret_0.texcoord = _ZZ4Soutput.texcoord;\n' + - ' _ZZ3Sret_0.percentLife = _ZZ4Soutput.percentLife;\n' + - ' _ZZ3Sret_0.colorMult = gl_Color;\n' + - ' gl_TexCoord[0].xy = _ZZ4Soutput.texcoord;\n' + - ' gl_TexCoord[2] = gl_Color;\n' + - ' _glPositionTemp = _ZZ3SrZh0057; gl_Position = vec4(_glPositionTemp.x + _glPositionTemp.w * dx_clipping.x, dx_clipping.w * (_glPositionTemp.y + _glPositionTemp.w * dx_clipping.y), _glPositionTemp.z * 2 - _glPositionTemp.w, _glPositionTemp.w);\n' + - ' gl_TexCoord[1].x = _ZZ4Soutput.percentLife;\n' + - ' return;\n' + - '} // main end\n' + - '\n' + + 'attribute vec4 position; // uv, lifeTime, frameStart\n' + + 'attribute vec4 texCoord0; // position.xyz, startTime\n' + + 'attribute vec4 texCoord1; // velocity.xyz, startSize\n' + + 'attribute vec4 texCoord2; // acceleration.xyz, endSize\n' + + 'attribute vec4 texCoord3; // spinStart.x, spinSpeed.y\n' + + 'attribute vec4 color; //\n' + + '\n' + + 'varying vec4 v_position;\n' + + 'varying vec2 v_texcoord;\n' + + 'varying float v_percentLife;\n' + + 'varying vec4 v_colorMult;\n' + + '\n' + + 'void main() {\n' + + ' vec4 uvLifeTimeFrameStart = position;\n' + + ' vec4 positionStartTime = texCoord0;\n' + + ' vec4 velocityStartSize = texCoord1;\n' + + ' vec4 accelerationEndSize = texCoord2;\n' + + ' vec4 spinStartSpinSpeed = texCoord3;\n' + + ' vec4 colorMult = color;\n' + + ' vec2 uv = uvLifeTimeFrameStart.xy;\n' + + ' float lifeTime = uvLifeTimeFrameStart.z;\n' + + ' float frameStart = uvLifeTimeFrameStart.w;\n' + + ' vec3 position = (world * vec4(positionStartTime.xyz, 1.0)).xyz;\n' + + ' float startTime = positionStartTime.w;\n' + + ' vec3 velocity = (world * vec4(velocityStartSize.xyz, 0)).xyz \n' + + ' + worldVelocity;\n' + + ' float startSize = velocityStartSize.w;\n' + + ' vec3 acceleration = (world *\n' + + ' vec4(accelerationEndSize.xyz, 0)).xyz + worldAcceleration;\n' + + ' float endSize = accelerationEndSize.w;\n' + + ' float spinStart = spinStartSpinSpeed.x;\n' + + ' float spinSpeed = spinStartSpinSpeed.y;\n' + + '\n' + + ' float localTime = mod((time - timeOffset - startTime),\n' + + ' timeRange);\n' + + ' float percentLife = localTime / lifeTime;\n' + '\n' + - '// #o3d SplitMarker\n' + - '// #o3d MatrixLoadOrder RowMajor\n' + + ' float frame = mod(floor(localTime / frameDuration + frameStart),\n' + + ' numFrames);\n' + + ' float uOffset = frame / numFrames;\n' + + ' float u = uOffset + (uv.x + 0.5) * (1.0 / numFrames);\n' + '\n' + - '// glslf output by Cg compiler\n' + - '// cgc version 2.0.0010, build date Dec 12 2007\n' + - '// command line args: -profile glslf\n' + - '//vendor NVIDIA Corporation\n' + - '//version 2.0.0.10\n' + - '//profile glslf\n' + - '//program pixelShaderFunction\n' + - '//semantic viewProjection : VIEWPROJECTION\n' + - '//semantic world : WORLD\n' + - '//semantic viewInverse : VIEWINVERSE\n' + - '//semantic worldVelocity\n' + - '//semantic worldAcceleration\n' + - '//semantic timeRange\n' + - '//semantic time\n' + - '//semantic timeOffset\n' + - '//semantic frameDuration\n' + - '//semantic numFrames\n' + - '//semantic rampSampler\n' + - '//semantic colorSampler\n' + - '//var float4x4 viewProjection : VIEWPROJECTION : , 4 : -1 : 0\n' + - '//var float4x4 world : WORLD : , 4 : -1 : 0\n' + - '//var float4x4 viewInverse : VIEWINVERSE : , 4 : -1 : 0\n' + - '//var float3 worldVelocity : : : -1 : 0\n' + - '//var float3 worldAcceleration : : : -1 : 0\n' + - '//var float timeRange : : : -1 : 0\n' + - '//var float time : : : -1 : 0\n' + - '//var float timeOffset : : : -1 : 0\n' + - '//var float frameDuration : : : -1 : 0\n' + - '//var float numFrames : : : -1 : 0\n' + - '//var sampler rampSampler : : _ZZ2SrampSampler : -1 : 1\n' + - '//var sampler colorSampler : : _ZZ2ScolorSampler : -1 : 1\n' + - '//var float2 input.texcoord : $vin.TEXCOORD0 : TEXCOORD0 : 0 : 1\n' + - '//var float1 input.percentLife : $vin.TEXCOORD1 : TEXCOORD1 : 0 : 1\n' + - '//var float4 input.colorMult : $vin.TEXCOORD2 : TEXCOORD2 : 0 : 1\n' + - '//var float4 pixelShaderFunction : $vout.COLOR : COLOR : -1 : 1\n' + + ' v_texcoord = vec2(u, uv.y + 0.5);\n' + + ' v_colorMult = colorMult;\n' + '\n' + + ' vec3 basisX = viewInverse[0].xyz;\n' + + ' vec3 basisZ = viewInverse[1].xyz;\n' + '\n' + + ' float size = mix(startSize, endSize, percentLife);\n' + + ' size = (percentLife < 0.0 || percentLife > 1.0) ? 0.0 : size;\n' + + ' float s = sin(spinStart + spinSpeed * localTime);\n' + + ' float c = cos(spinStart + spinSpeed * localTime);\n' + '\n' + - 'struct VertexShaderInput {\n' + - ' vec4 positionStartTime;\n' + - ' vec4 velocityStartSize;\n' + - ' vec4 accelerationEndSize;\n' + - ' vec4 spinStartSpinSpeed;\n' + - ' vec4 colorMult;\n' + - '};\n' + + ' vec2 rotatedPoint = vec2(uv.x * c + uv.y * s, \n' + + ' -uv.x * s + uv.y * c);\n' + + ' vec3 localPosition = vec3(basisX * rotatedPoint.x +\n' + + ' basisZ * rotatedPoint.y) * size +\n' + + ' velocity * localTime +\n' + + ' acceleration * localTime * localTime + \n' + + ' position;\n' + '\n' + - 'struct PixelShaderInput {\n' + - ' vec2 texcoord;\n' + - ' float percentLife;\n' + - ' vec4 colorMult;\n' + - '};\n' + + ' gl_Position = (viewProjection * vec4(localPosition, 1.0));\n' + + ' v_percentLife = percentLife;\n' + + '}\n' + '\n' + - 'vec4 _ZZ3Sret_0;\n' + - 'sampler2D _ZZ3SsZh0017;\n' + - 'vec2 _ZZ3ScZh0017;\n' + - 'sampler2D _ZZ3SsZh0019;\n' + - 'uniform sampler rampSampler;\n' + - 'uniform sampler colorSampler;\n' + + '// #o3d SplitMarker\n' + '\n' + - ' // main procedure, the original name was pixelShaderFunction\n' + - 'void main()\n' + - '{\n' + + 'varying vec4 v_position;\n' + + 'varying vec2 v_texcoord;\n' + + 'varying float v_percentLife;\n' + + 'varying vec4 v_colorMult;\n' + '\n' + - ' PixelShaderInput _ZZ4Sinput;\n' + - ' vec4 _ZZ4ScolorMult;\n' + - ' vec4 _ZZ4Scolor;\n' + + '// We need to implement 1D!\n' + + 'uniform sampler2D rampSampler;\n' + + 'uniform sampler2D colorSampler;\n' + + '\n' + + 'void main() {\n' + + ' vec4 colorMult = texture2D(rampSampler, \n' + + ' vec2(v_percentLife, 0.5)) * v_colorMult;\n' + + ' vec4 color = texture2D(colorSampler, v_texcoord) * colorMult;\n' + + ' gl_FragColor = color;\n' + + '}\n' + '\n' + - ' _ZZ4Sinput.percentLife = gl_TexCoord[1].x;\n' + - ' _ZZ3SsZh0017 = sampler2D(rampSampler);\n' + - ' _ZZ3ScZh0017 = vec2(_ZZ4Sinput.percentLife, 5.00000000E-01);\n' + - ' _ZZ4ScolorMult = texture2D(_ZZ3SsZh0017, _ZZ3ScZh0017)*gl_TexCoord[2];\n' + - ' _ZZ3SsZh0019 = sampler2D(colorSampler);\n' + - ' _ZZ4Scolor = texture2D(_ZZ3SsZh0019, gl_TexCoord[0].xy)*_ZZ4ScolorMult;\n' + - ' _ZZ3Sret_0 = _ZZ4Scolor;\n' + - ' gl_FragColor = _ZZ4Scolor;\n' + - ' return;\n' + - '} // main end\n'}]; - + '// #o3d MatrixLoadOrder RowMajor\n'}]; /** * Sets the shader language used. Passing 'glsl' will cause all generated diff --git a/o3d/samples/trends/trends-with-particles.html b/o3d/samples/trends/trends-with-particles.html new file mode 100755 index 0000000..e80aa6a2 --- /dev/null +++ b/o3d/samples/trends/trends-with-particles.html @@ -0,0 +1,791 @@ +<!-- +Copyright 2009, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<!-- +TODO: + O Set Sun to correct location for time. + O Put in moon + O Put in Google satellite + O Put in Star Shader that uses star data from a texture + O Add Halo + O Add Sun Model + O with glowing rays. +--> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<title> +Google Trends Visualizer +</title> +<style> + html, body { + border: 0; + margin: 0; + height: 100%; + height: 100%; + text-align: center; + } +</style> +</head> +<body onload="init();" onunload="uninit();"> +<script type="text/javascript" src="../o3djs/base.js"></script> +<script type="text/javascript" id="o3dscript"> +o3djs.require('o3djs.util'); +o3djs.require('o3djs.math'); +o3djs.require('o3djs.quaternions'); +o3djs.require('o3djs.rendergraph'); +o3djs.require('o3djs.primitives'); +o3djs.require('o3djs.arcball'); +o3djs.require('o3djs.io'); +o3djs.require('o3djs.particles'); + +var g = { + EARTH_RADIUS: 25, + ENERGY_WIDTH: 0.5, + ENERGY_HEIGHT: 10 +}; + +g.camera = { + eye: [0, 0, 75], + target: [0, 0, 0] +}; + +var g_finished = false; // for selenium. +var dragging = false; + +function startDragging(e) { + g.lastRot = g.thisRot; + g.aball.click([e.x, e.y]); + dragging = true; +} + +function drag(e) { + if (dragging) { + var rotationQuat = g.aball.drag([e.x, e.y]); + var rot_mat = g.quaternions.quaternionToRotation(rotationQuat); + g.thisRot = g.math.matrix4.mul(g.lastRot, rot_mat); + + var m = g.root.localMatrix; + g.math.matrix4.setUpper3x3(m, g.thisRot); + g.root.localMatrix = m; + } +} + +function stopDragging(e) { + dragging = false; +} + +function updateViewFromCamera() { + var target = g.camera.target; + var eye = g.camera.eye; + var up = [0, 1, 0]; + g.viewInfo.drawContext.view = g.math.matrix4.lookAt(eye, target, up); + g.eyePosParam.value = eye; +} + +function scrollMe(e) { + if (e.deltaY > 0) { + g.camera.eye[0] *= 11 / 12; + g.camera.eye[1] *= 11 / 12; + g.camera.eye[2] *= 11 / 12; + + } else { + g.camera.eye[0] *= (1 + 1 / 12); + g.camera.eye[1] *= (1 + 1 / 12); + g.camera.eye[2] *= (1 + 1 / 12); + } + updateViewFromCamera(); +} + +function getURL(path) { + var base = window.location.href; + var index = base.lastIndexOf('/'); + base = base.substring(0, index + 1); + return base + path; +} + +function setClientSize() { + var newWidth = g.client.width; + var newHeight = g.client.height; + + if (newWidth != g.o3dWidth || newHeight != g.o3dHeight) { + g.o3dWidth = newWidth; + g.o3dHeight = newHeight; + + // Create a perspective projection matrix + g.viewInfo.drawContext.projection = g.math.matrix4.perspective( + g.math.degToRad(45), g.o3dWidth / g.o3dHeight, 0.1, 5000); + + // Sets a new area size for arcball. + g.aball.setAreaSize(g.o3dWidth, g.o3dHeight); + } +} + +function onRender() { + setClientSize(); +} + +// A geo is a float where the integer part is in degrees and the fractional +// part is in 60ths +function geoToRad(geo) { + var sign = geo >= 0 ? 1 : -1; + geo = Math.abs(geo); + var integerPart = Math.floor(geo); + var fractionalPart = (geo % 1) * 100; + fractionalPart = fractionalPart / 60; + return g.math.degToRad(integerPart + fractionalPart); +} + +function addEnergyShard(latitude, longitude, energy, height, color) { + // Decide how many particles we want in this shard. + g.trailParameters.numParticles = Math.floor(Math.random() * 10) + 1; + // Set the color for the shard's particles. + g.trailParameters.colorMult = color; + // Compute a base position for the shard and a velocity for the particles. + var matrix = g.math.matrix4.rotationZ(geoToRad(latitude)); + g.math.matrix4.rotateY(matrix, geoToRad(-longitude)); + g.math.matrix4.rotateZ(matrix, g.math.degToRad(90)); + g.shardStartPosition = + g.math.matrix4.transformDirection(matrix, [0, g.EARTH_RADIUS, 0]); + g.shardVelocity = g.math.matrix4.transformDirection(matrix, [0, 2.5, 0]); + // Birth the particles. NOTE: the position passed in here is overridden by + // our per particle function. + g.trail.birthParticles([0, 0, 0]); +} + +function shardPerParticleFunc(particleIndex, parameters) { + // This function sets parameters for each individual particle that is + // birthed. We'll calculate these in addEneryShard so all the + // particles genearted come out of the same position going in the + // same direction + parameters.position = g.shardStartPosition; + parameters.velocity = g.shardVelocity; + // Pick a random time for the particle to appear. + parameters.startTime = Math.random() * parameters.timeRange; +} + +/** + * Creates the client area. + */ +function init() { + o3djs.util.makeClients(initStep2); +} +/** + * Initializes o3d + * @param {Array} clientElements Array of o3d object elements. + */ +function initStep2(clientElements) { + var path = window.location.href; + var index = path.lastIndexOf('/'); + + g.o3dElement = clientElements[0]; + g.o3d = g.o3dElement.o3d; + g.math = o3djs.math; + g.quaternions = o3djs.quaternions; + g.client = g.o3dElement.client; + + g.pack = g.client.createPack(); + + // Create the render graph for a view. + g.viewInfo = o3djs.rendergraph.createBasicView( + g.pack, + g.client.root, + g.client.renderGraphRoot); + + // Set the background color to black. + g.viewInfo.clearBuffer.clearColor = [0, 0, 0, 0]; + + // Set states for shards. + g.viewInfo.zOrderedState.getStateParam('CullMode').value = + g.o3d.State.CULL_NONE; + g.viewInfo.zOrderedState.getStateParam('DestinationBlendFunction').value = + g.o3d.State.BLENDFUNC_ONE; + g.viewInfo.zOrderedState.getStateParam('ZWriteEnable').value = false; + + g.viewInfo.performanceDrawPass.sortMethod = g.o3d.DrawList.BY_PRIORITY; + + g.lastRot = g.math.matrix4.identity(); + g.thisRot = g.math.matrix4.identity(); + + var root = g.client.root; + + // Create a param for the sun and eye positions that we can bind + // to auto update a bunch of materials. + g.globalParams = g.pack.createObject('ParamObject'); + g.sunPosParam = g.globalParams.createParam('sunPos', 'ParamFloat3'); + g.sunPosParam.value = [1000, 200, 100]; + g.eyePosParam = g.globalParams.createParam('eyePos', 'ParamFloat3'); + + updateViewFromCamera(); + + g.aball = o3djs.arcball.create(100, 100); + setClientSize(); + + g.client.setRenderCallback(onRender); + + + // Create Materials. + var effectNames = [ + "noTexture", + "dayOnly", + "nightAndDay", + "mask", + "atmosphere" + ]; + g.materials = []; + for (var ii = 0; ii < effectNames.length; ++ii) { + var effectName = effectNames[ii]; + var effect = g.pack.createObject('Effect'); + effect.loadFromFXString(document.getElementById(effectName).value); + + // Create a Material for the effect. + var material = g.pack.createObject('Material'); + + // Apply our effect to this material. The effect tells the 3D hardware + // which shader to use. + material.effect = effect; + + // Set the material's drawList + material.drawList = g.viewInfo.performanceDrawList; + + // This will create the effects's params on the material. + effect.createUniformParameters(material); + + // Bind the sun position to a global value so we can easily change it + // globally. + var sunParam = material.getParam('sunPos'); + if (sunParam) { + sunParam.bind(g.sunPosParam); + } + + // Save off the material. + g.materials.push(material); + } + g.noTextureMaterial = g.materials[0]; + g.dayOnlyMaterial = g.materials[1]; + g.nightAndDayMaterial = g.materials[2]; + g.maskMaterial = g.materials[3]; + g.atmosphereMaterial = g.materials[4]; + + // create samplers + g.samplers = []; + for (var ii = 0; ii < 4; ++ii) { + var sampler = g.pack.createObject('Sampler'); + g.samplers[ii] = sampler; + } + + g.daySampler = g.samplers[0]; + g.nightSampler = g.samplers[1]; + g.maskSampler = g.samplers[2]; + + // set the material samplers. + g.dayOnlyMaterial.getParam('daySampler').value = g.daySampler; + g.nightAndDayMaterial.getParam('daySampler').value = g.daySampler; + g.nightAndDayMaterial.getParam('nightSampler').value = g.nightSampler; + g.maskMaterial.getParam('daySampler').value = g.daySampler; + g.maskMaterial.getParam('maskSampler').value = g.maskSampler; + g.maskMaterial.getParam('nightSampler').value = g.nightSampler; + + // Setup counters for shard animation. + g.shardCounter = g.pack.createObject('SecondCounter'); + + // Setup counters to fade in textures. + g.flatToDayCounter = g.pack.createObject('SecondCounter'); + g.flatToDayCounter.end = 1; + g.flatToDayCounter.multiplier = 0.5; + g.flatToDayCounter.countMode = g.o3d.Counter.ONCE; + g.flatToDayCounter.running = false; + g.flatToDayCounter.addCallback(1, loadNightTexture); + g.dayOnlyMaterial.getParam('mix').bind( + g.flatToDayCounter.getParam('count')); + + g.dayOnlyToNightCounter = g.pack.createObject('SecondCounter'); + g.dayOnlyToNightCounter.end = 1; + g.dayOnlyToNightCounter.multiplier = 0.5; + g.dayOnlyToNightCounter.countMode = g.o3d.Counter.ONCE; + g.dayOnlyToNightCounter.running = false; + g.dayOnlyToNightCounter.addCallback(1, loadMaskTexture); + g.nightAndDayMaterial.getParam('mix').bind( + g.dayOnlyToNightCounter.getParam('count')); + + g.noMaskToMaskCounter = g.pack.createObject('SecondCounter'); + g.noMaskToMaskCounter.end = 1; + g.noMaskToMaskCounter.multiplier = 0.5; + g.noMaskToMaskCounter.countMode = g.o3d.Counter.ONCE; + g.noMaskToMaskCounter.running = false; + g.maskMaterial.getParam('mix').bind( + g.noMaskToMaskCounter.getParam('count')); + + // Create a sphere at the origin for the earth. + var earth = o3djs.primitives.createSphere(g.pack, + g.noTextureMaterial, + 25, + 50, + 50); + + // Get a the element so we can set its material later. + g.earthPrimitive = earth.elements[0]; + g.atmosphereState = g.pack.createObject('State'); + g.atmosphereState.getStateParam('AlphaBlendEnable').value = true; + g.atmosphereState.getStateParam('SourceBlendFunction').value = + g.o3d.State.BLENDFUNC_SOURCE_ALPHA; + g.atmosphereState.getStateParam('DestinationBlendFunction').value = + g.o3d.State.BLENDFUNC_INVERSE_SOURCE_ALPHA; + g.atmosphereState.getStateParam('ZWriteEnable').value = false; + g.atmosphereMaterial.state = g.atmosphereState; + + g.root = g.pack.createObject('Transform'); + g.root.parent = g.client.root; + g.earth = g.pack.createObject('Transform'); + g.earth.addShape(earth); + g.earth.parent = g.root; + + // Create a sphere at the origin for the atmosphere. + var atmosphere = o3djs.primitives.createSphere(g.pack, + g.atmosphereMaterial, + 26, + 50, + 50); + g.atmospherePrimitive = atmosphere.elements[0]; + g.atmospherePrimitive.priority = 1; + g.atmosphere = g.pack.createObject('Transform'); + g.atmosphere.addShape(atmosphere); + g.atmosphere.parent = g.root; + + // Make a particle system + g.particleSystem = o3djs.particles.createParticleSystem( + g.pack, + g.viewInfo, + g.shardCounter.getParam('count'), + g.math.pseudoRandom); + + // Make a transform for the particle emitter. + var transform = g.pack.createObject('Transform'); + transform.parent = g.root; + // Make a single pixel white texture as our particle. + var texture = g.pack.createTexture2D(1, 1, g.o3d.Texture.ARGB8, 1, false); + texture.set(0, [1, 1, 1, 1]); + + // Setup some basic parameters for our particles. + g.trailParameters = { + lifeTime: 4, // each particle lasts 4 seconds + timeRange: 4, // The clock is modded by this so the *world* clock repeats + // every 4 seconds making each particle reappear + startSize: 0.1, // Size to start a particle + endSize: 0.1, // Size to end a particle + // (the particle lerps in side between start and end) + }; + + // Create a trail. Trails are just a particle system that lets us more + // easily birth individual particles. + g.trail = g.particleSystem.createTrail( + transform, // Transform for particles. + 10000, // Total number of particles in system. If 10001 + // particles are birthed, the oldest particle is + // reused. + g.trailParameters, // Our static birth parameters. + texture, // The texture to use. + shardPerParticleFunc); // A function to set parameters per particle. + g.trail.setState(o3djs.particles.ParticleStateIds.BLEND); + // This ramp makes the particles full bright for 4/5ths of their lifespan + // and they fade out during the last 1/5th. + g.trail.setColorRamp( + [1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 0]); + + + addEnergyShard(0, 0, 1, 1, [1, 1, 1, 1]); + + // Honolulu, Hawaii, 21, 18, 157, 50 + addEnergyShard(21.18, 157.50, 1, 1, [0, 1, 0, 1]); + // San Francisco, Calif. 37 47 122 26 + addEnergyShard(37.47, 122.26, 1, 1, [1, 0.5, 0.5, 1]); + + for (var ii = 0; ii < 24; ++ii) { + var longitude = Math.random() * 360; + var latitude = Math.random() * 360 - 180; + var color = [ Math.random() * 0.5 + 0.2, + Math.random() * 0.5 + 0.2, + Math.random() * 0.5 + 0.2, + 1 ]; + // Make a least 1 color component full bright. + color[Math.floor(Math.random() * 2.99)] = 1; + for (var jj = 0; jj < 24; ++jj) { + addEnergyShard(latitude + (Math.random() - 0.5) * 10, + longitude + (Math.random() - 0.5) * 10, + 1, + 1, + color); + } + } + + o3djs.event.addEventListener(g.o3dElement, 'mousedown', startDragging); + o3djs.event.addEventListener(g.o3dElement, 'mousemove', drag); + o3djs.event.addEventListener(g.o3dElement, 'mouseup', stopDragging); + o3djs.event.addEventListener(g.o3dElement, 'wheel', scrollMe); + + loadDayTexture(); +} + +function loadTexture(path, callback) { + var url = getURL(path); + o3djs.io.loadTexture(g.pack, url, function(texture, exception) { + if (exception) { + alert(exception); + } else { + callback(texture); + } + }); +} + +function loadDayTexture() { + loadTexture('assets/earth.jpg', function(texture) { + g.daySampler.texture = texture; + g.earthPrimitive.material = g.dayOnlyMaterial; + g.flatToDayCounter.running = true; + }); +} + +function loadNightTexture() { + loadTexture('assets/night.jpg', function(texture) { + g.nightSampler.texture = texture; + g.earthPrimitive.material = g.nightAndDayMaterial; + g.dayOnlyToNightCounter.running = true; + }); +} + +function loadMaskTexture() { + loadTexture('assets/earth-large-with-ocean-mask.png', function(texture) { + g.maskSampler.texture = texture; + g.earthPrimitive.material = g.maskMaterial; + g.noMaskToMaskCounter.running = true; + g_finished = true; // for selenium + }); +} + +function uninit() { + // TODO: We should clean up any counters that have callbacks here. + if (g.client) { + g.client.cleanup(); + } +} + +</script> +<!--<h1> +Google Trends Visualizer. +</h1>--> +<div id="o3d" style="width:100%; height: 100%;"></div> +<div style="display:none"> +<textarea id="noTexture" name="fx" cols="80" rows="20"> +float4x4 worldViewProjection : WorldViewProjection; +float4x4 world : World; +float4x4 view : View; + +float3 sunPos; + +struct a2v { + float4 pos : POSITION; + float3 normal : NORMAL; +}; + +struct v2f { + float4 pos : POSITION; + float3 normal : TEXCOORD0; + float3 sun : TEXCOORD1; + float3 view : TEXCOORD2; +}; + +v2f vsMain(a2v IN) { + v2f OUT; + + OUT.pos = mul(IN.pos, worldViewProjection); + OUT.normal = mul(float4(IN.normal, 0), world).xyz; + float3 worldPos = mul(IN.pos, world).xyz; + OUT.sun = sunPos - worldPos; + OUT.view = (view[3] - worldPos); + + return OUT; +} + +float4 psMain(v2f IN): COLOR { + float3 norm = normalize(IN.normal); + float3 sun = normalize(IN.sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1 - sqrt(light); + dayNight = dayNight * dayNight; + dayNight = (1 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0, 1); + float3 view = normalize(IN.view); + float3 r = normalize(reflect(norm, sun)); + float4 litR = lit(light, dot(r, view), 0.0).y; + float3 day = float3(0.5, 0.5, 1.0) * litR.y + float3(1,1,1) * litR.z; + float3 night = float3(0.2, 0.2, 0.5); + return float4(lerp(night, day, dayNight),1); +} + +// #o3d VertexShaderEntryPoint vsMain +// #o3d PixelShaderEntryPoint psMain +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="dayOnly" name="fx" cols="80" rows="20"> +float4x4 worldViewProjection : WorldViewProjection; +float4x4 world : World; +float4x4 view : View; + +float3 sunPos; +float mix; + +sampler2D daySampler; + +struct a2v { + float4 pos : POSITION; + float3 normal : NORMAL; + float2 uv : TEXCOORD0; +}; + +struct v2f { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + float3 normal : TEXCOORD1; + float3 sun : TEXCOORD2; + float3 view : TEXCOORD3; +}; + +v2f vsMain(a2v IN) { + v2f OUT; + + OUT.pos = mul(IN.pos, worldViewProjection); + OUT.uv = IN.uv; + OUT.normal = mul(float4(IN.normal, 0), world).xyz; + float3 worldPos = mul(IN.pos, world).xyz; + OUT.sun = sunPos - worldPos; + OUT.view = (view[3] - worldPos); + + return OUT; +} + +float4 psMain(v2f IN): COLOR { + float3 norm = normalize(IN.normal); + float3 sun = normalize(IN.sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1 - sqrt(light); + dayNight = dayNight * dayNight; + dayNight = (1 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0, 1); + float3 view = normalize(IN.view); + float3 r = normalize(reflect(norm, sun)); + float4 litR = lit(light, dot(r, view), 0.0).y; + float3 earth = tex2D(daySampler, IN.uv).xyz; + float3 day = lerp(float3(0.5, 0.5, 1.0), earth, mix); + day = day * litR.y + float3(1,1,1) * litR.z; + float3 night = lerp(float3(0.2, 0.2, 0.5), earth * 0.3, mix); + return float4(lerp(night, day, dayNight),1); +} + +// #o3d VertexShaderEntryPoint vsMain +// #o3d PixelShaderEntryPoint psMain +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="nightAndDay" name="fx" cols="80" rows="20"> +float4x4 worldViewProjection : WorldViewProjection; +float4x4 world : World; +float4x4 view : View; + +float3 sunPos; +float mix; + +sampler2D daySampler; +sampler2D nightSampler; + +struct a2v { + float4 pos : POSITION; + float3 normal : NORMAL; + float2 uv : TEXCOORD0; +}; + +struct v2f { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + float3 normal : TEXCOORD1; + float3 sun : TEXCOORD2; + float3 view : TEXCOORD3; +}; + +v2f vsMain(a2v IN) { + v2f OUT; + + OUT.pos = mul(IN.pos, worldViewProjection); + OUT.uv = IN.uv; + OUT.normal = mul(float4(IN.normal, 0), world).xyz; + float3 worldPos = mul(IN.pos, world).xyz; + OUT.sun = sunPos - worldPos; + OUT.view = (view[3] - worldPos); + + return OUT; +} + +float4 psMain(v2f IN): COLOR { + float3 norm = normalize(IN.normal); + float3 sun = normalize(IN.sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1 - sqrt(light); + dayNight = dayNight * dayNight; + dayNight = (1 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0, 1); + float3 view = normalize(IN.view); + float3 r = normalize(reflect(norm, sun)); + float4 litR = lit(light, dot(r, view), 0.0).y; + float3 earth = tex2D(daySampler, IN.uv).xyz; + float3 day = tex2D(daySampler, IN.uv).xyz; + float3 night = lerp(day * 0.3, tex2D(nightSampler, IN.uv).xyz, mix); + day = day * litR.y + float3(1,1,1) * litR.z; + return float4(lerp(night, day, dayNight),1); +} + +// #o3d VertexShaderEntryPoint vsMain +// #o3d PixelShaderEntryPoint psMain +// #o3d MatrixLoadOrder RowMajor +</textarea> +<!-- +This shader renders the ocean different then the non-ocean using a mask +stored in the alpha channel of the maskSampler +--> +<textarea id="mask" name="fx" cols="80" rows="20"> +float4x4 worldViewProjection : WorldViewProjection; +float4x4 world : World; +float4x4 view : View; + +float3 sunPos; +float mix; + +sampler2D daySampler; +sampler2D nightSampler; +sampler2D maskSampler; + +struct a2v { + float4 pos : POSITION; + float3 normal : NORMAL; + float2 uv : TEXCOORD0; +}; + +struct v2f { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + float3 normal : TEXCOORD1; + float3 sun : TEXCOORD2; + float3 view : TEXCOORD3; +}; + +v2f vsMain(a2v IN) { + v2f OUT; + + OUT.pos = mul(IN.pos, worldViewProjection); + OUT.uv = IN.uv; + OUT.normal = mul(float4(IN.normal, 0), world).xyz; + float3 worldPos = mul(IN.pos, world).xyz; + OUT.sun = sunPos - worldPos; + OUT.view = (view[3] - worldPos); + + return OUT; +} + +float4 psMain(v2f IN): COLOR { + float3 norm = normalize(IN.normal); + float3 sun = normalize(IN.sun); + float light = dot(norm, sun); + float lightSign = sign(light); + float dayNight = 1 - sqrt(light); + dayNight = dayNight * dayNight; + dayNight = (1 - dayNight) * lightSign; + dayNight = clamp(dayNight, 0, 1); + float3 view = normalize(IN.view); + float3 r = normalize(reflect(norm, sun)); + float4 litR = lit(light, dot(r, view), 0.0).y; + float3 earth = tex2D(daySampler, IN.uv).xyz; + float4 mask = tex2D(maskSampler, IN.uv); + float3 day = lerp(tex2D(daySampler, IN.uv).xyz, + mask.xyz, mix); + float3 night = tex2D(nightSampler, IN.uv).xyz; + day = day * litR.y + float3(1,1,1) * litR.z * (1 - mask.w * mix); + + float3 color = lerp(night, day, dayNight); + return float4(color,1); +} + +// #o3d VertexShaderEntryPoint vsMain +// #o3d PixelShaderEntryPoint psMain +// #o3d MatrixLoadOrder RowMajor +</textarea> +<textarea id="atmosphere" name="fx" cols="80" rows="20"> +float4x4 worldViewProjection : WorldViewProjection; +float4x4 worldView : WorldView; +float3 sunPos; +float3 eyePos; + +struct a2v { + float4 pos : POSITION; + float3 norm : NORMAL; +}; + +struct v2f { + float4 pos : POSITION; + float3 normal : TEXCOORD0; +}; + +v2f vsMain(a2v IN) { + v2f OUT; + + OUT.pos = mul(IN.pos, worldViewProjection); + OUT.normal = normalize(mul(float4(IN.norm,0), worldView).xyz); + return OUT; +} + +float4 psMain(v2f IN): COLOR { + float n = 1 - log(2 * normalize(IN.normal).z); + return float4(0.3, 0.3, 1, n * n * n * n); +} + +// #o3d VertexShaderEntryPoint vsMain +// #o3d PixelShaderEntryPoint psMain +// #o3d MatrixLoadOrder RowMajor +</textarea> +</div> +</body> +</html> + + |