From 296a66898916b5b3daa94cbbcc1450a336453904 Mon Sep 17 00:00:00 2001 From: Marcin Jerzak Date: Sat, 18 Nov 2023 19:26:05 +0100 Subject: [PATCH 1/2] docs setup for sprite mesh --- .changeset/light-foxes-perform.md | 5 + apps/docs/astro.config.mjs | 4 +- apps/docs/src/assets/sprite/typescript1.png | Bin 0 -> 14257 bytes .../01-instanced-sprite-mesh.mdx | 119 ++++++++++++++++++ .../instancedSprite/02-reference-sheet.mdx | 6 + .../instancedSprite/03-spritesheet-format.mdx | 23 ++++ .../04-instanced-sprite-building.mdx | 18 +++ .../05-spritesheet-aseprite.mdx | 10 ++ .../docs/sprites/instanced-sprite-mesh.mdx | 7 -- apps/docs/tailwind.config.cjs | 24 ++-- .../vanilla/instancedSprite.ts | 1 - .../src/InstancedSpriteMesh.ts | 10 ++ 12 files changed, 205 insertions(+), 22 deletions(-) create mode 100644 .changeset/light-foxes-perform.md create mode 100644 apps/docs/src/assets/sprite/typescript1.png create mode 100644 apps/docs/src/content/docs/instancedSprite/01-instanced-sprite-mesh.mdx create mode 100644 apps/docs/src/content/docs/instancedSprite/02-reference-sheet.mdx create mode 100644 apps/docs/src/content/docs/instancedSprite/03-spritesheet-format.mdx create mode 100644 apps/docs/src/content/docs/instancedSprite/04-instanced-sprite-building.mdx create mode 100644 apps/docs/src/content/docs/instancedSprite/05-spritesheet-aseprite.mdx delete mode 100644 apps/docs/src/content/docs/sprites/instanced-sprite-mesh.mdx diff --git a/.changeset/light-foxes-perform.md b/.changeset/light-foxes-perform.md new file mode 100644 index 0000000..b870f64 --- /dev/null +++ b/.changeset/light-foxes-perform.md @@ -0,0 +1,5 @@ +--- +"@threejs-kit/instanced-sprite-mesh": minor +--- + +Docs sketch for sprites, fps setter diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs index 9dc6ea0..d1bb14a 100644 --- a/apps/docs/astro.config.mjs +++ b/apps/docs/astro.config.mjs @@ -23,8 +23,8 @@ export default defineConfig({ autogenerate: { directory: 'intro' }, }, { - label: 'Sprites', - autogenerate: { directory: 'sprites' }, + label: 'Instanced Sprite', + autogenerate: { directory: 'instancedSprite' }, }, { label: 'Materials', diff --git a/apps/docs/src/assets/sprite/typescript1.png b/apps/docs/src/assets/sprite/typescript1.png new file mode 100644 index 0000000000000000000000000000000000000000..bd1ed8ea4ea8d8c932c12e133c87d26d3a84cdea GIT binary patch literal 14257 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 literal 0 HcmV?d00001 diff --git a/apps/docs/src/content/docs/instancedSprite/01-instanced-sprite-mesh.mdx b/apps/docs/src/content/docs/instancedSprite/01-instanced-sprite-mesh.mdx new file mode 100644 index 0000000..6a15cdf --- /dev/null +++ b/apps/docs/src/content/docs/instancedSprite/01-instanced-sprite-mesh.mdx @@ -0,0 +1,119 @@ +--- +title: Overview +description: Installation and reference sheet for InstancedSpriteMesh +--- + + +import { Image } from "astro:assets"; + +`InstancedSpriteMesh` was created to enabled high performant instancing of animated sprites in threejs. Current solutions do not fare well with very high instance counts. This package aims to resolve that, boasting the capability to render tens of thousands individually animated sprites even on low/medium power devices. + + +## Installation + +Package is published as `@threejs-kit/instanced-sprite-mesh` and you can add it to your project by installing it as such: + +```bash +npm i @threejs-kit/instanced-sprite-mesh +``` + + + +## Getting started +At it's core `InstancedSpriteMesh` is built on top of, and extends [InstancedUniformsMesh](https://protectwise.github.io/troika/three-instanced-uniforms-mesh/) so any of their documentation might be helpful to you - it's recommended to get familiar with it as well. + +### Basic example + +InstancedSpriteMesh needs spritesheet texture and spritesheet metadata provided to it (imported from Aseprite, others or generated on the fly) + +- load texture +- create a base material +- make instanced sprite mesh +- add spritesheet to mesh + +```js +const texture = new THREE.TextureLoader().load('/spritesheet.png'); +texture.minFilter = THREE.NearestFilter; +texture.magFilter = THREE.NearestFilter; + +const baseMaterial = new THREE.MeshBasicMaterial({ + transparent: true, + alphaTest: 0.01, + side: THREE.DoubleSide, + map: texture +}); + +const mesh = new InstancedSpriteMesh(baseMaterial, INSTANCE_COUNT); + +mesh.fps = 15 + +const spritesheet = parseAseprite(JSON.parse(rawSpritesheet)); +mesh.spritesheet = spritesheet; +``` + +### Quick api preview + + +```js + // set global FPS for updating + mesh.fps = 15 + + // loop one animation globally for all sprites without indivudually set animation + mesh.play('IdleBackward', true).global(); + // play this animation once for sprite at instanceId 0 + mesh.play('RunLeft').at(0); + + // only set animation + mesh.animation.setGlobal('IdleRight'); + mesh.animation.setAt(0, 'RunBackward'); + + // defined looping behaviour + mesh.loop.setGlobal(true); + mesh.loop.setAt(0, false); + + // billboarding + mesh.billboarding.setGlobal(true); + mesh.billboarding.setAt(0, true); + + // tint, only global for now + mesh.tint.setGlobal({h:2, s:0.8, v: 0.8}) + ``` + +## Updating sprite animations + +Currently the sprites are only animated based on provided FPS and a timer. Either: + +- `mesh.updateTime();` has to be called to update the animations - manually or in RAF (performance.now()) +- `mesh.time = 100` can be set manually + + + +Support for animations independent on time and setting specific frameIDs will be coming soon + + +## Typescript support +Yes, wip. + +import materialPreview from "../../../assets/sprite/typescript1.png"; + + + + +```ts +type SpriteAnimations = + | 'RunRight' + | 'RunLeft' + | 'RunForward' + | 'IdleRight' + | 'IdleLeft' + | 'IdleForward' + | 'RunBackward' + | 'IdleBackward'; + +const mesh: InstancedSpriteMesh = + new InstancedSpriteMesh(baseMaterial, INSTANCE_COUNT); + ``` + +for example, the above will allow for autocompletion of animation names + +shows how glint material looks like \ No newline at end of file diff --git a/apps/docs/src/content/docs/instancedSprite/02-reference-sheet.mdx b/apps/docs/src/content/docs/instancedSprite/02-reference-sheet.mdx new file mode 100644 index 0000000..1a74ce0 --- /dev/null +++ b/apps/docs/src/content/docs/instancedSprite/02-reference-sheet.mdx @@ -0,0 +1,6 @@ +--- +title: Reference sheet +description: InstancedSpriteMesh +--- + +## \ No newline at end of file diff --git a/apps/docs/src/content/docs/instancedSprite/03-spritesheet-format.mdx b/apps/docs/src/content/docs/instancedSprite/03-spritesheet-format.mdx new file mode 100644 index 0000000..0b3243c --- /dev/null +++ b/apps/docs/src/content/docs/instancedSprite/03-spritesheet-format.mdx @@ -0,0 +1,23 @@ +--- +title: Spritesheet metadata +description: InstancedSpriteMesh +--- + +## Spritesheet format + +Each instanced mesh has to be provided with a spritesheet formatted like this. The library provides utilities to parse aseprite json metadata and to generate it from a image file, but you can (should?) write your own + + +```ts +type SpritesheetFormat = { + frames: [x: number, y: number, w: number, h: number][]; + animations: Record; + sheetSize: [w: number, h: number][]; + animationLengths: number[]; +}; +``` + +- `frames`: each frame of the spritesheet has its cooridnates and size specified separately - this will allow for non-uniform sized frames +- `animations`: `Map` of named animations. Each animation is defined by an array of frames it consists of (frameId is the index of a frame in `frames`) +- `sheetSize` - size of an image +- `animationLengths` - util, how many frames does each animation have \ No newline at end of file diff --git a/apps/docs/src/content/docs/instancedSprite/04-instanced-sprite-building.mdx b/apps/docs/src/content/docs/instancedSprite/04-instanced-sprite-building.mdx new file mode 100644 index 0000000..f1936a7 --- /dev/null +++ b/apps/docs/src/content/docs/instancedSprite/04-instanced-sprite-building.mdx @@ -0,0 +1,18 @@ +--- +title: Making spritesheet from images +description: InstancedSpriteMesh +--- + + +### InstancedSpriteMesh + +tutorial on how to make spritesheet metadata with just images: + +Sprites from +https://luizmelo.itch.io/monsters-creatures-fantasy + + +1. load images +2. 1 img file = 1 animation +3. Name animations and Combine img files into one spritesheet via html canvas so there's only one texture +4. Generate meta \ No newline at end of file diff --git a/apps/docs/src/content/docs/instancedSprite/05-spritesheet-aseprite.mdx b/apps/docs/src/content/docs/instancedSprite/05-spritesheet-aseprite.mdx new file mode 100644 index 0000000..de690bd --- /dev/null +++ b/apps/docs/src/content/docs/instancedSprite/05-spritesheet-aseprite.mdx @@ -0,0 +1,10 @@ +--- +title: Importing from aseprite +description: InstancedSpriteMesh +--- + + +### InstancedSpriteMesh + + +`parseAseprite` helper function docs. \ No newline at end of file diff --git a/apps/docs/src/content/docs/sprites/instanced-sprite-mesh.mdx b/apps/docs/src/content/docs/sprites/instanced-sprite-mesh.mdx deleted file mode 100644 index 1af0637..0000000 --- a/apps/docs/src/content/docs/sprites/instanced-sprite-mesh.mdx +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: InstancedSpriteMesh -description: InstancedSpriteMesh ---- - - -### InstancedSpriteMesh diff --git a/apps/docs/tailwind.config.cjs b/apps/docs/tailwind.config.cjs index 474874c..8ab70a3 100644 --- a/apps/docs/tailwind.config.cjs +++ b/apps/docs/tailwind.config.cjs @@ -1,18 +1,18 @@ const colors = require('tailwindcss/colors'); const starlightPlugin = require('@astrojs/starlight-tailwind'); +// Generated color palettes +const accent = { 200: '#dcc78c', 600: '#836800', 900: '#3f3000', 950: '#2d2200' }; +const gray = { 100: '#f6f6f6', 200: '#eeeded', 300: '#c2c2c1', 400: '#8c8b8b', 500: '#585857', 700: '#383838', 800: '#272726', 900: '#181818' }; + /** @type {import('tailwindcss').Config} */ module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // Your preferred accent color. Indigo is closest to Starlight’s defaults. - accent: colors.indigo, - // Your preferred gray scale. Zinc is closest to Starlight’s defaults. - gray: colors.zinc, - }, - }, - }, - plugins: [starlightPlugin()], + content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], + theme: { + extend: { + colors: { accent, gray } + }, + }, + plugins: [starlightPlugin()], }; + diff --git a/apps/playground/src/routes/instanced-sprite/vanilla/instancedSprite.ts b/apps/playground/src/routes/instanced-sprite/vanilla/instancedSprite.ts index 8ccd8e8..04d68ca 100644 --- a/apps/playground/src/routes/instanced-sprite/vanilla/instancedSprite.ts +++ b/apps/playground/src/routes/instanced-sprite/vanilla/instancedSprite.ts @@ -285,7 +285,6 @@ export const start = async () => { playerIndicator.position.set(posX[0], 2, posZ[0]); updateAgents(0.01); - sprite.updateTime(); if (dirtyInstanceMatrix) { sprite.instanceMatrix.needsUpdate = true; dirtyInstanceMatrix = false; diff --git a/packages/instanced-sprite-mesh/src/InstancedSpriteMesh.ts b/packages/instanced-sprite-mesh/src/InstancedSpriteMesh.ts index cde5ef6..abd73e3 100644 --- a/packages/instanced-sprite-mesh/src/InstancedSpriteMesh.ts +++ b/packages/instanced-sprite-mesh/src/InstancedSpriteMesh.ts @@ -18,6 +18,7 @@ export class InstancedSpriteMesh< private _spritesheet?: SpritesheetFormat | undefined; private _animationMap: Map; private _time: number = 0; + private _fps: number = 15; constructor( baseMaterial: T, @@ -165,6 +166,15 @@ export class InstancedSpriteMesh< this._time = value; } + public get fps(): number { + return this._fps; + } + + public set fps(value: number) { + this._spriteMaterial.uniforms.fps.value = value; + this._fps = value; + } + public updateTime() { const value = performance.now() * 0.001; this._spriteMaterial.uniforms.time.value = value; From b4309f4349e6f6480701359df380f978ca39273a Mon Sep 17 00:00:00 2001 From: Marcin Jerzak Date: Sat, 18 Nov 2023 19:28:13 +0100 Subject: [PATCH 2/2] lockfile fix? --- pnpm-lock.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e2f9101..2edbdd8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,13 +159,14 @@ importers: version: 4.5.0 packages/instanced-sprite-mesh: + dependencies: + three: + specifier: '>=0.158.0' + version: 0.158.0 devDependencies: '@types/three': specifier: ^0.158.2 version: 0.158.2 - three: - specifier: ^0.158.0 - version: 0.158.0 three-instanced-uniforms-mesh: specifier: ^0.49.0 version: 0.49.0(three@0.158.0)