diff options
Diffstat (limited to 'o3d/samples/o3d-webgl-samples/trends/trends-with-particles.html')
-rw-r--r-- | o3d/samples/o3d-webgl-samples/trends/trends-with-particles.html | 803 |
1 files changed, 803 insertions, 0 deletions
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> + + |