87 lines
2.3 KiB
TypeScript
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 });
|
|
}
|
|
|
|
}
|