Files
max-richter.dev/src/content/projects/plantarium/_components/leaves.ts
Max Richter 1e04a7be6f
Some checks failed
Deploy to GitHub Pages / build (push) Failing after 14m41s
Deploy to GitHub Pages / deploy (push) Has been skipped
feat: some stuff
2024-04-03 21:09:50 +02:00

87 lines
2.3 KiB
TypeScript

import { Camera, Color, Geometry, GLTFLoader, Mesh, Program, Renderer, Transform } from 'ogl';
import { rand, randMinMax } from "./random";
import fragment from "./Leaf.frag";
import vertex from "./Leaf.vert";
let rotation = 0;
export function setRotation(r: number) {
rotation = r;
}
export function createLeaves({ canvas, num = 20, color, minZ = -1, maxZ = 1 }: { canvas: HTMLCanvasElement, num?: number, color?: Color, minZ?: number, maxZ?: number }) {
const renderer = new Renderer({ dpr: 1, canvas, alpha: true });
const gl = renderer.gl;
const camera = new Camera(gl, { fov: 15 });
camera.position.z = 5;
function resize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.perspective({ aspect: gl.canvas.width / gl.canvas.height });
}
window.addEventListener('resize', resize, false);
resize();
const scene = new Transform();
const program = new Program(gl, {
vertex,
fragment,
cullFace: gl.NONE,
depthTest: true,
uniforms: {
uTime: { value: 0 },
uRot: { value: 0 },
uBackground: { value: color },
},
});
let mesh: Mesh;
loadModel();
async function loadModel() {
const model = await GLTFLoader.load(gl, "/models/leaf.glb");
// @ts-ignore
const data = model.nodes[0].children[0].geometry.attributes;
let offset = new Float32Array(num * 3);
let random = new Float32Array(num * 3);
for (let i = 0; i < num; i++) {
offset.set([rand(8), rand(4), randMinMax(minZ, maxZ)], i * 3);
// unique random values are always handy for instances.
// Here they will be used for rotation, scale and movement.
random.set([Math.random(), Math.random(), Math.random()], i * 3);
}
const geometry = new Geometry(gl, {
...data,
// simply add the 'instanced' property to flag as an instanced attribute.
// set the value as the divisor number
offset: { instanced: 1, size: 3, data: offset },
random: { instanced: 1, size: 3, data: random },
});
mesh = new Mesh(gl, { geometry, program });
mesh.scale.set(0.2, 0.2, 0.2)
mesh.setParent(scene);
}
requestAnimationFrame(update);
function update(t: number) {
requestAnimationFrame(update);
program.uniforms.uTime.value = t * 0.001;
program.uniforms.uRot.value = rotation;
renderer.render({ scene, camera });
}
}