You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
7.4 KiB
257 lines
7.4 KiB
6 months ago
|
var flatSurface = $('#surface-shader');
|
||
|
|
||
|
if (flatSurface.length) {
|
||
|
var MESH = {
|
||
|
width: 1.2,
|
||
|
height: 1.2,
|
||
|
depth: 0,
|
||
|
segments: 16,
|
||
|
slices: 8,
|
||
|
xRange: 0.8,
|
||
|
yRange: 0.1,
|
||
|
zRange: 1.0,
|
||
|
ambient: '#555555',
|
||
|
diffuse: '#ffffff',
|
||
|
speed: 0.002
|
||
|
};
|
||
|
|
||
|
var LIGHT = {
|
||
|
count: 2,
|
||
|
xyScalar: 1,
|
||
|
zOffset: 100,
|
||
|
ambient: flatSurface.data('ambient-color'),
|
||
|
diffuse: flatSurface.data('diffuse-color'),
|
||
|
speed: 0.002,
|
||
|
gravity: 500,
|
||
|
dampening: 0.95,
|
||
|
minLimit: 10,
|
||
|
maxLimit: null,
|
||
|
minDistance: 20,
|
||
|
maxDistance: 800,
|
||
|
autopilot: true,
|
||
|
draw: false,
|
||
|
bounds: FSS.Vector3.create(),
|
||
|
step: FSS.Vector3.create(
|
||
|
Math.randomInRange(0.2, 1.0),
|
||
|
Math.randomInRange(0.2, 1.0),
|
||
|
Math.randomInRange(0.2, 1.0)
|
||
|
)
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
var RENDER = {
|
||
|
renderer: 'canvas'
|
||
|
};
|
||
|
|
||
|
var now, start = Date.now();
|
||
|
var center = FSS.Vector3.create();
|
||
|
var attractor = FSS.Vector3.create();
|
||
|
var containerFSS = flatSurface[0];
|
||
|
var output = flatSurface[0];
|
||
|
var rendererFSS, sceneFSS, mesh, geometry, material;
|
||
|
var canvasRenderer;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
function initialise() {
|
||
|
createRenderer();
|
||
|
createScene();
|
||
|
createMesh();
|
||
|
createLights();
|
||
|
addEventListeners();
|
||
|
resize(containerFSS.offsetWidth, containerFSS.offsetHeight);
|
||
|
animateFSS();
|
||
|
}
|
||
|
|
||
|
function createRenderer() {
|
||
|
canvasRenderer = new FSS.CanvasRenderer();
|
||
|
setRenderer(RENDER.renderer);
|
||
|
}
|
||
|
|
||
|
function setRenderer() {
|
||
|
if (rendererFSS) {
|
||
|
output.removeChild(rendererFSS.element);
|
||
|
}
|
||
|
|
||
|
rendererFSS = canvasRenderer;
|
||
|
|
||
|
rendererFSS.setSize(containerFSS.offsetWidth, containerFSS.offsetHeight);
|
||
|
output.appendChild(rendererFSS.element);
|
||
|
}
|
||
|
|
||
|
function createScene() {
|
||
|
sceneFSS = new FSS.Scene();
|
||
|
}
|
||
|
|
||
|
function createMesh() {
|
||
|
sceneFSS.remove(mesh);
|
||
|
rendererFSS.clear();
|
||
|
geometry = new FSS.Plane(MESH.width * rendererFSS.width, MESH.height * rendererFSS.height, MESH.segments, MESH.slices);
|
||
|
material = new FSS.Material(MESH.ambient, MESH.diffuse);
|
||
|
mesh = new FSS.Mesh(geometry, material);
|
||
|
sceneFSS.add(mesh);
|
||
|
|
||
|
// Augment vertices for animation
|
||
|
var v, vertex;
|
||
|
for (v = geometry.vertices.length - 1; v >= 0; v--) {
|
||
|
vertex = geometry.vertices[v];
|
||
|
vertex.anchor = FSS.Vector3.clone(vertex.position);
|
||
|
vertex.step = FSS.Vector3.create(
|
||
|
Math.randomInRange(0.2, 1.0),
|
||
|
Math.randomInRange(0.2, 1.0),
|
||
|
Math.randomInRange(0.2, 1.0)
|
||
|
);
|
||
|
vertex.time = Math.randomInRange(0, Math.PIM2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function createLights() {
|
||
|
var l, light;
|
||
|
for (l = sceneFSS.lights.length - 1; l >= 0; l--) {
|
||
|
light = sceneFSS.lights[l];
|
||
|
sceneFSS.remove(light);
|
||
|
}
|
||
|
rendererFSS.clear();
|
||
|
for (l = 0; l < LIGHT.count; l++) {
|
||
|
light = new FSS.Light(LIGHT.ambient, LIGHT.diffuse);
|
||
|
light.ambientHex = light.ambient.format();
|
||
|
light.diffuseHex = light.diffuse.format();
|
||
|
sceneFSS.add(light);
|
||
|
|
||
|
// Augment light for animation
|
||
|
light.mass = Math.randomInRange(0.5, 1);
|
||
|
light.velocity = FSS.Vector3.create();
|
||
|
light.acceleration = FSS.Vector3.create();
|
||
|
light.force = FSS.Vector3.create();
|
||
|
|
||
|
// Ring SVG Circle
|
||
|
light.ring = document.createElementNS(FSS.SVGNS, 'circle');
|
||
|
light.ring.setAttributeNS(null, 'stroke', light.ambientHex);
|
||
|
light.ring.setAttributeNS(null, 'stroke-width', '0.5');
|
||
|
light.ring.setAttributeNS(null, 'fill', 'none');
|
||
|
light.ring.setAttributeNS(null, 'r', '10');
|
||
|
|
||
|
// Core SVG Circle
|
||
|
light.core = document.createElementNS(FSS.SVGNS, 'circle');
|
||
|
light.core.setAttributeNS(null, 'fill', light.diffuseHex);
|
||
|
light.core.setAttributeNS(null, 'r', '4');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function resize(width, height) {
|
||
|
rendererFSS.setSize(width, height);
|
||
|
FSS.Vector3.set(center, rendererFSS.halfWidth, rendererFSS.halfHeight);
|
||
|
createMesh();
|
||
|
}
|
||
|
|
||
|
function animateFSS() {
|
||
|
now = Date.now() - start;
|
||
|
update();
|
||
|
renderFSS();
|
||
|
requestAnimationFrame(animateFSS);
|
||
|
}
|
||
|
|
||
|
function update() {
|
||
|
var ox, oy, oz, l, light, v, vertex, offset = MESH.depth / 2;
|
||
|
|
||
|
// Update Bounds
|
||
|
FSS.Vector3.copy(LIGHT.bounds, center);
|
||
|
FSS.Vector3.multiplyScalar(LIGHT.bounds, LIGHT.xyScalar);
|
||
|
|
||
|
// Update Attractor
|
||
|
FSS.Vector3.setZ(attractor, LIGHT.zOffset);
|
||
|
|
||
|
// Overwrite the Attractor position
|
||
|
if (LIGHT.autopilot) {
|
||
|
ox = Math.sin(LIGHT.step[0] * now * LIGHT.speed);
|
||
|
oy = Math.cos(LIGHT.step[1] * now * LIGHT.speed);
|
||
|
FSS.Vector3.set(attractor,
|
||
|
LIGHT.bounds[0] * ox,
|
||
|
LIGHT.bounds[1] * oy,
|
||
|
LIGHT.zOffset);
|
||
|
}
|
||
|
|
||
|
// Animate Lights
|
||
|
for (l = sceneFSS.lights.length - 1; l >= 0; l--) {
|
||
|
light = sceneFSS.lights[l];
|
||
|
|
||
|
// Reset the z position of the light
|
||
|
FSS.Vector3.setZ(light.position, LIGHT.zOffset);
|
||
|
|
||
|
// Calculate the force Luke!
|
||
|
var D = Math.clamp(FSS.Vector3.distanceSquared(light.position, attractor), LIGHT.minDistance, LIGHT.maxDistance);
|
||
|
var F = LIGHT.gravity * light.mass / D;
|
||
|
FSS.Vector3.subtractVectors(light.force, attractor, light.position);
|
||
|
FSS.Vector3.normalise(light.force);
|
||
|
FSS.Vector3.multiplyScalar(light.force, F);
|
||
|
|
||
|
// Update the light position
|
||
|
FSS.Vector3.set(light.acceleration);
|
||
|
FSS.Vector3.add(light.acceleration, light.force);
|
||
|
FSS.Vector3.add(light.velocity, light.acceleration);
|
||
|
FSS.Vector3.multiplyScalar(light.velocity, LIGHT.dampening);
|
||
|
FSS.Vector3.limit(light.velocity, LIGHT.minLimit, LIGHT.maxLimit);
|
||
|
FSS.Vector3.add(light.position, light.velocity);
|
||
|
}
|
||
|
|
||
|
// Animate Vertices
|
||
|
for (v = geometry.vertices.length - 1; v >= 0; v--) {
|
||
|
vertex = geometry.vertices[v];
|
||
|
ox = Math.sin(vertex.time + vertex.step[0] * now * MESH.speed);
|
||
|
oy = Math.cos(vertex.time + vertex.step[1] * now * MESH.speed);
|
||
|
oz = Math.sin(vertex.time + vertex.step[2] * now * MESH.speed);
|
||
|
FSS.Vector3.set(vertex.position,
|
||
|
MESH.xRange * geometry.segmentWidth * ox,
|
||
|
MESH.yRange * geometry.sliceHeight * oy,
|
||
|
MESH.zRange * offset * oz - offset);
|
||
|
FSS.Vector3.add(vertex.position, vertex.anchor);
|
||
|
}
|
||
|
|
||
|
// Set the Geometry to dirty
|
||
|
geometry.dirty = true;
|
||
|
}
|
||
|
|
||
|
function renderFSS() {
|
||
|
rendererFSS.render(sceneFSS);
|
||
|
|
||
|
// Draw Lights
|
||
|
if (LIGHT.draw) {
|
||
|
var l, lx, ly, light;
|
||
|
for (l = sceneFSS.lights.length - 1; l >= 0; l--) {
|
||
|
light = sceneFSS.lights[l];
|
||
|
lx = light.position[0];
|
||
|
ly = light.position[1];
|
||
|
rendererFSS.context.lineWidth = 0.5;
|
||
|
rendererFSS.context.beginPath();
|
||
|
rendererFSS.context.arc(lx, ly, 10, 0, Math.PIM2);
|
||
|
rendererFSS.context.strokeStyle = light.ambientHex;
|
||
|
rendererFSS.context.stroke();
|
||
|
rendererFSS.context.beginPath();
|
||
|
rendererFSS.context.arc(lx, ly, 4, 0, Math.PIM2);
|
||
|
rendererFSS.context.fillStyle = light.diffuseHex;
|
||
|
rendererFSS.context.fill();
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function addEventListeners() {
|
||
|
window.addEventListener('resize', onWindowResizFSS);
|
||
|
}
|
||
|
|
||
|
// Callbacks
|
||
|
|
||
|
function onWindowResizFSS() {
|
||
|
resize(containerFSS.offsetWidth, containerFSS.offsetHeight);
|
||
|
renderFSS();
|
||
|
}
|
||
|
|
||
|
|
||
|
// Init
|
||
|
if (flatSurface.length) {
|
||
|
initialise();
|
||
|
}
|