mirror of
https://github.com/storytold/spark.git
synced 2026-10-09 00:09:53 +00:00
Simplify example names
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Forge • VFX Dynamic Lighting</title>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
header {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
margin: 1rem 2rem;
|
||||
}
|
||||
|
||||
label {
|
||||
font-family: sans-serif;
|
||||
font-size: 20px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
margin-right: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<label><input type="checkbox" id="debug" autocomplete="off"> Debug Light SDFs</label>
|
||||
<label><input type="checkbox" id="daynight" checked="checked" autocomplete="off"> Enable Lighting</label>
|
||||
</header>
|
||||
|
||||
<canvas id="canvas"></canvas>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"three": "/examples/js/vendor/three/build/three.module.js",
|
||||
"@forge-gfx/forge": "/dist/forge.module.js"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import * as THREE from "three";
|
||||
import {
|
||||
SplatMesh,
|
||||
SplatEdit,
|
||||
ForgeRenderer,
|
||||
SplatEditSdf,
|
||||
SplatEditSdfType,
|
||||
SplatEditRgbaBlendMode,
|
||||
FpsMovement,
|
||||
PointerControls,
|
||||
} from "@forge-gfx/forge";
|
||||
import { getAssetFileURL } from "/examples/js/get-asset-url.js";
|
||||
|
||||
const canvas = document.getElementById("canvas");
|
||||
const scene = new THREE.Scene();
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100);
|
||||
camera.position.set(0, 0.3, -2.5);
|
||||
|
||||
const renderer = new THREE.WebGLRenderer();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
document.body.appendChild(renderer.domElement)
|
||||
|
||||
// Create a ForgeRenderer and add it to the scene to render all the Gsplats.
|
||||
const forge = new ForgeRenderer({ renderer });
|
||||
scene.add(forge);
|
||||
|
||||
const splatURL = await getAssetFileURL("fireplace.spz");
|
||||
const fireplace = new SplatMesh({ url: splatURL });
|
||||
fireplace.quaternion.set(1, 0, 0, 0);
|
||||
fireplace.position.set(0, -1, -10);
|
||||
scene.add(fireplace);
|
||||
|
||||
const fpsMovement = new FpsMovement({ moveSpeed: 2 });
|
||||
const pointerControls = new PointerControls({ canvas });
|
||||
|
||||
let night = true;
|
||||
const lights = [];
|
||||
// Debug SDF spheres
|
||||
const helpers = [];
|
||||
|
||||
function createLight(scene, lightingLayer, position, color, radius, opacity) {
|
||||
const light = new SplatEditSdf({
|
||||
type: SplatEditSdfType.SPHERE,
|
||||
color: color,
|
||||
radius: radius,
|
||||
opacity: opacity,
|
||||
});
|
||||
light.position.copy(position);
|
||||
|
||||
// create a wireframe helper
|
||||
const helper = new THREE.Mesh(
|
||||
new THREE.SphereGeometry(radius, 16, 16),
|
||||
new THREE.MeshBasicMaterial({ wireframe: true, color: color }),
|
||||
);
|
||||
helper.position.copy(light.position);
|
||||
helper.visible = false;
|
||||
scene.add(helper);
|
||||
helpers.push(helper);
|
||||
|
||||
lightingLayer.add(light);
|
||||
lights.push(light);
|
||||
}
|
||||
|
||||
// Create lighting layer
|
||||
const emberLayer = new SplatEdit({
|
||||
rgbaBlendMode: SplatEditRgbaBlendMode.ADD_RGBA,
|
||||
sdfSmooth: 0.1,
|
||||
softEdge: 0.8,
|
||||
});
|
||||
scene.add(emberLayer);
|
||||
|
||||
const lightingLayer = new SplatEdit({
|
||||
rgbaBlendMode: SplatEditRgbaBlendMode.ADD_RGBA,
|
||||
sdfSmooth: 0.1,
|
||||
softEdge: 1.4,
|
||||
});
|
||||
scene.add(lightingLayer);
|
||||
|
||||
const ambientLayer = new SplatEdit({
|
||||
rgbaBlendMode: SplatEditRgbaBlendMode.DARKEN,
|
||||
sdfSmooth: 0.1,
|
||||
softEdge: 0.05,
|
||||
});
|
||||
scene.add(ambientLayer);
|
||||
|
||||
// glowing embers at the base of the fire
|
||||
createLight(
|
||||
scene,
|
||||
emberLayer,
|
||||
new THREE.Vector3(0.5, -1.0, -10.5),
|
||||
new THREE.Color(1, 0.6, 0.4),
|
||||
0.75,
|
||||
1,
|
||||
);
|
||||
|
||||
// light in the fireplace
|
||||
createLight(
|
||||
scene,
|
||||
lightingLayer,
|
||||
new THREE.Vector3(0.3, -1.1, -10.6),
|
||||
new THREE.Color(1, 0.95, 0.2),
|
||||
1.6,
|
||||
0,
|
||||
);
|
||||
|
||||
// ambient light throughout the full room
|
||||
createLight(
|
||||
scene,
|
||||
ambientLayer,
|
||||
new THREE.Vector3(0, 1, -11),
|
||||
new THREE.Color(1, 0.8, 0.6),
|
||||
6,
|
||||
0.8,
|
||||
);
|
||||
console.log(helpers);
|
||||
|
||||
let lastTime;
|
||||
|
||||
renderer.setAnimationLoop(time => {
|
||||
const timeSeconds = time * 0.0005;
|
||||
const deltaTime = timeSeconds - (lastTime ?? timeSeconds);
|
||||
lastTime = timeSeconds;
|
||||
|
||||
// fpsMovement.update(deltaTime, camera);
|
||||
pointerControls.update(deltaTime, camera);
|
||||
camera.position.z = -2.5 - Math.sin(timeSeconds * 0.1) * 2;
|
||||
renderer.render(scene, camera);
|
||||
|
||||
// Create flickering fire effect
|
||||
const baseHue = 0.04; // Orange-red base hue
|
||||
const fireHue = 0.03; // Yellow base hue
|
||||
const hueVariation = 0.03; // Slight variation in hue
|
||||
|
||||
// Add some randomness to the flicker
|
||||
const randomFlicker = Math.sin(timeSeconds * 4) * 0.5 + 0.5;
|
||||
|
||||
// we'll combine these to make a more natural flickering effect
|
||||
const mediumFlicker = Math.sin(timeSeconds * 13) * 0.1 + 0.1; // Medium flicker
|
||||
const fastFlicker = Math.sin(timeSeconds * 20) * 0.1 + 0.1; // Fast flicker
|
||||
const slowFlicker = Math.sin(timeSeconds * 6) * 0.04 + 0.5; // Slow base flicker
|
||||
// Combine the flickers
|
||||
const combinedFlicker = (slowFlicker + mediumFlicker + fastFlicker) / 3;
|
||||
|
||||
for (let i = 0; i < lights.length - 1; i++) {
|
||||
const h = baseHue + combinedFlicker * hueVariation; // Slightly varying orange-red hue
|
||||
const s = 0.5 + randomFlicker * 0.3; // High saturation with slight variation
|
||||
const l = 0.5 + combinedFlicker * 0.2; // Varying brightness
|
||||
lights[i].color.setHSL(h, s, l);
|
||||
lights[i].visible = night;
|
||||
}
|
||||
|
||||
lights[lights.length - 1].visible = night;
|
||||
lights[lights.length - 1].color.setHSL(baseHue, 0.5, combinedFlicker);
|
||||
});
|
||||
|
||||
document.getElementById('debug').addEventListener('change', ev => {
|
||||
const visible = ev.target.checked;
|
||||
for (let helper of helpers) {
|
||||
helper.visible = visible;
|
||||
}
|
||||
});
|
||||
document.getElementById('daynight').addEventListener('change', ev => {
|
||||
night = !night;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user