summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorluchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-22 18:23:55 +0000
committerluchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-22 18:23:55 +0000
commita94ede07c59c3be79641234930638be4ae40947c (patch)
tree26f1053c2d982c7edd33893f8b4719fd208bb495 /o3d
parent23781f7eda2276973b2da5e7bf34fb455af825e5 (diff)
downloadchromium_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.jpgbin0 -> 107460 bytes
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/assets/earth-large-with-ocean-mask.pngbin0 -> 2367738 bytes
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/assets/earth-large.jpgbin0 -> 586564 bytes
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/assets/earth.jpgbin0 -> 46696 bytes
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/assets/energy.pngbin0 -> 136 bytes
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/assets/moon.jpgbin0 -> 67152 bytes
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/assets/night-large.jpgbin0 -> 313629 bytes
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/assets/night.jpgbin0 -> 86315 bytes
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/trends-with-particles.html803
-rw-r--r--o3d/samples/o3d-webgl-samples/trends/trends.html869
-rw-r--r--o3d/samples/o3djs/particles.js675
-rwxr-xr-xo3d/samples/trends/trends-with-particles.html791
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
new file mode 100644
index 0000000..8767681
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/trends/assets/clouds.jpg
Binary files differ
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
new file mode 100644
index 0000000..850d0ff
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/trends/assets/earth-large-with-ocean-mask.png
Binary files differ
diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/earth-large.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/earth-large.jpg
new file mode 100644
index 0000000..ce797dc
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/trends/assets/earth-large.jpg
Binary files differ
diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/earth.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/earth.jpg
new file mode 100644
index 0000000..f04b09d
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/trends/assets/earth.jpg
Binary files differ
diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/energy.png b/o3d/samples/o3d-webgl-samples/trends/assets/energy.png
new file mode 100644
index 0000000..576ddbb
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/trends/assets/energy.png
Binary files differ
diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/moon.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/moon.jpg
new file mode 100644
index 0000000..f916c70
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/trends/assets/moon.jpg
Binary files differ
diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/night-large.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/night-large.jpg
new file mode 100644
index 0000000..4979d6e
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/trends/assets/night-large.jpg
Binary files differ
diff --git a/o3d/samples/o3d-webgl-samples/trends/assets/night.jpg b/o3d/samples/o3d-webgl-samples/trends/assets/night.jpg
new file mode 100644
index 0000000..2bfb99e
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/trends/assets/night.jpg
Binary files differ
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>
+
+