Skip to content

Commit

Permalink
workerize try
Browse files Browse the repository at this point in the history
  • Loading branch information
jerzakm committed Mar 7, 2024
1 parent dff30ef commit 43b5e5f
Show file tree
Hide file tree
Showing 8 changed files with 765 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<script lang="ts">
import { onMount } from 'svelte';
import { initDemonBench } from './mainDemons';
import { page } from '$app/stores';
import { initBunBench } from './mainBunnies';
const url = $page.url;
const param = url.searchParams.get('count');
const count = parseInt(param) || 1000;
const mode = url.searchParams.get('mode') || 'bunnies';
onMount(() => {
if (mode === 'bunnies') {
initBunBench(count);
} else {
initDemonBench(count);
}
});
const countOptions = [500, 2000, 10000, 50000, 100000, 200000, 400000, 600000, 800000, 1000000];
</script>

<div class="menu">
<div>
Bunmark for <a href="https://github.com/jerzakm/threejs-kit"
>@threejs-kit/instanced-sprite-mesh.</a
>
</div>
<span>
Displaying <b>{count}</b>
{mode}.
</span>
<ul>
<span style="width: 140px;">Bunnies (static):</span>
{#each countOptions as c}
<li>
<a
data-sveltekit-reload
href={`/instanced-sprite-bunny-mark-workerized?count=${c}&mode=bunnies`}>{c}</a
>
</li>
{/each}
</ul>
<ul>
<span style="width: 140px;">Demons (animated):</span>
{#each countOptions as c}
<li>
<a
data-sveltekit-reload
href={`/instanced-sprite-bunny-mark-workerized?count=${c}&mode=demons`}>{c}</a
>
</li>
{/each}
</ul>
{#if mode === 'demons'}
Each demon has a random animation (idle, death, fly, attack) that changes each time it hits the
screen boundary, a separate animation progression and changes flipX based on the direction.
{/if}
</div>

<canvas id="three-canvas" />

<style>
a {
color: white;
}
b {
color: orange;
}
ul {
display: flex;
flex-wrap: wrap;
margin: 0;
padding: 0;
gap: 1rem;
list-style: none;
}
.menu {
display: flex;
flex-direction: column;
gap: 0.5rem;
background-color: rgba(0, 0, 0, 0.35);
color: #cccccc;
padding: 0.15rem 0.2rem;
position: fixed;
top: 0;
left: 100px;
z-index: 9999;
}
canvas {
position: fixed;
top: 0;
left: 0;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
let lastTime = performance.now();

let positions: Float32Array;
let velocity: Float32Array;

onmessage = function (e) {
const { positionsBuffer, velocityBuffer, gravity, count, bounds, type, from, to } = e.data;

if (type == 'setup') {
// x,y
positions = new Float32Array(positionsBuffer);

// vX, vY
velocity = new Float32Array(velocityBuffer);
}

function update() {
// Example update: move instances along their velocity vector
const currentTime = performance.now();
const delta = ((currentTime - lastTime) / 1000) * 200; // Convert to seconds
for (let i = from; i < to; i++) {
positions[i * 2] += velocity[i * 2]; // x += vx
positions[i * 2 + 1] += velocity[i * 2 + 1]; // y += vy

velocity[i * 2 + 1] += gravity * delta;

// roll new behaviour if bunny gets out of bounds

if (positions[i * 2] > bounds.right) {
velocity[i * 2] *= -1;
positions[i * 2] = bounds.right;
} else if (positions[i * 2] < bounds.left) {
velocity[i * 2] *= -1;
positions[i * 2] = bounds.left;
}

if (positions[i * 2 + 1] > bounds.top) {
velocity[i * 2 + 1] *= -0.85;
positions[i * 2 + 1] = bounds.top;
if (Math.random() > 0.5) {
velocity[i * 2 + 1] -= Math.random() * 6;
}
} else if (positions[i * 2 + 1] < bounds.bottom) {
velocity[i * 2 + 1] *= -1;
positions[i * 2 + 1] = bounds.top;
}
}
lastTime = currentTime * 1;

// Schedule the next update
setTimeout(update, 0); // roughly 60fps
}
update();
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { InstancedSpriteMesh, createSpritesheet } from '@threejs-kit/instanced-sprite-mesh';
import {
DoubleSide,
Matrix4,
MeshBasicMaterial,
MeshStandardMaterial,
Vector2,
type Scene,
type Vector3Tuple,
type WebGLRenderer
} from 'three';

export const initBunnies = async (renderer: WebGLRenderer, scene: Scene, count: number) => {
const bunnies = [
'rabbitv3_ash',
'rabbitv3_batman',
'rabbitv3_bb8',
'rabbitv3_frankenstein',
'rabbitv3_neo',
'rabbitv3_sonic',
'rabbitv3_spidey',
'rabbitv3_stormtrooper',
'rabbitv3_superman',
'rabbitv3_tron',
'rabbitv3_wolverine',
'rabbitv3'
];

const bunnySpritesheet = createSpritesheet();

for (const bunny of bunnies) {
bunnySpritesheet.add(
`/pixi_bunnies/${bunny}.png`,
{
type: 'rowColumn',
width: 1,
height: 1
},
[{ name: bunny, frameRange: [0, 0] }]
);
}

const { spritesheet, texture } = await bunnySpritesheet.build();

const baseMaterial = new MeshBasicMaterial({
transparent: true,
alphaTest: 0.01,
// needs to be double side for shading
side: DoubleSide,
map: texture
});

const sprite = new InstancedSpriteMesh(baseMaterial, count, renderer);

sprite.fps = 9;

sprite.hueShift.setGlobal({
h: 0,
s: 1.1,
v: 1.9
});

sprite.spritesheet = spritesheet;
scene.add(sprite);

sprite.castShadow = true;

// UPDATING AND MOVING SPRITES
let dirtyInstanceMatrix = false;

const tempMatrix = new Matrix4();
function updatePosition(id: number, [x, y, z]: Vector3Tuple) {
tempMatrix.makeScale(25, 32, 1);
tempMatrix.setPosition(x, bounds.top - y, z);
sprite.setMatrixAt(id, tempMatrix);
// dirtyInstanceMatrix = true;
}

const gravity = 0.75;

const positionX: number[] = new Array(count).fill(0);
const positionY: number[] = new Array(count).fill(0);
const zIndex: number[] = new Array(count).fill(0);

const speedX: number[] = new Array(count).fill(0);
const speedY: number[] = new Array(count).fill(0);

const { updateAgents } = setupRandomAgents();

const bounds = {
left: 0,
right: window.innerWidth,
bottom: 0,
top: window.innerHeight
};

function setupRandomAgents() {
for (let i = 0; i < count; i++) {
positionX[i] = 0;
positionY[i] = 0;
zIndex[i] = -Math.random() * 10;

speedX[i] = Math.random() * 10;
speedY[i] = Math.random() * 10 - 5;

sprite.animation.setAt(i, bunnies[Math.floor(Math.random() * bunnies.length)]);
}

const updateAgents = (delta: number) => {
for (let i = 0; i < count; i++) {
delta = 1;
// timer
// apply gravity

// apply velocity
positionX[i] += speedX[i] * delta;
positionY[i] += speedY[i] * delta;
speedY[i] += gravity * delta;

// roll new behaviour if bunny gets out of bounds

if (positionX[i] > bounds.right) {
speedX[i] *= -1;
positionX[i] = bounds.right;
} else if (positionX[i] < bounds.left) {
speedX[i] *= -1;
positionX[i] = bounds.left;
}

if (positionY[i] > bounds.top) {
speedY[i] *= -0.85;
positionY[i] = bounds.top;
if (Math.random() > 0.5) {
speedY[i] -= Math.random() * 6;
}
} else if (positionY[i] < bounds.bottom) {
speedY[i] *= -1;
positionY[i] = bounds.top;
}
}

for (let i = 0; i < count; i++) {
updatePosition(i, [positionX[i], positionY[i], zIndex[i]]);
}
};
sprite.update();

return { updateAgents };
}

let initialized = false;

const update = (delta: number) => {
updateAgents(delta);

// sprite.update();

if (dirtyInstanceMatrix) {
sprite.instanceMatrix.needsUpdate = true;
dirtyInstanceMatrix = false;
}

if (!initialized) {
sprite.update();
initialized = true;
}
};

return { update, sprite, updatePosition };
};
Loading

0 comments on commit 43b5e5f

Please sign in to comment.