Skip to content

Commit

Permalink
Merge pull request #24 from jerzakm/plane-to-triangle
Browse files Browse the repository at this point in the history
Plane to triangle
  • Loading branch information
jerzakm authored Dec 2, 2023
2 parents f0e162c + 55c1caa commit ef9b39e
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 23 deletions.
5 changes: 5 additions & 0 deletions .changeset/blue-eyes-remain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@threejs-kit/instanced-sprite-mesh": minor
---

Option to use a triangle instead of a plane for the sprite geometry
18 changes: 12 additions & 6 deletions apps/docs/src/content/docs/instancedSprite/02-reference-sheet.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@ which in turn extends [THREE.InstancedMesh](https://threejs.org/docs/?q=instance

## Constructor
```ts
type InstancedSpriteOptions = {
spritesheet?: SpritesheetFormat;
triGeometry?: boolean;
};

new InstancedSpriteMesh (
baseMaterial: T extends Material,
count: number,
spritesheet?: SpritesheetFormat,
options?: InstancedSpriteOptions
options: InstancedSpriteOptions = {}
)
```

**baseMaterial** - Threejs material (recommended THREE.MeshBasicMaterial or THREE.MeshStandardMaterial) - more on this here -> (TODO)
**count** - number of instances
**spritesheet** - spritesheet metadata
**options** - (none atm, placeholder)
- **baseMaterial** - Threejs material (recommended THREE.MeshBasicMaterial or THREE.MeshStandardMaterial) - more on this here -> (TODO)
- **count** - number of instances
- **options** - (none atm, placeholder)
- **spritesheet** - spritesheet metadata
- **triGeometry** - use triangles instead of PlaneGeometry for sprites



## Properties and Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@
const mesh: InstancedSpriteMesh<MeshBasicMaterial, SpriteAnimations> = new InstancedSpriteMesh(
baseMaterial,
count
count,
{
triGeometry: true
}
);
const textureStore = texture
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
for (let i = 0; i < count; i++) {
// $camera.position.set(0 + (posX[0] || 0), 7, 15 + (posZ[0] || 0))
updatePosition(i, [posX[i] || 0, 0.5, posZ[i] || 0]);
updatePosition(i, [posX[i] || 0, 1, posZ[i] || 0]);
}
});
Expand Down
32 changes: 25 additions & 7 deletions packages/instanced-sprite-mesh/src/InstancedSpriteMesh.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { Material, PlaneGeometry, ShaderMaterial, Vector4 } from "three";
import {
BufferGeometry,
Material,
PlaneGeometry,
ShaderMaterial,
Vector4,
} from "three";
import { InstancedUniformsMesh } from "three-instanced-uniforms-mesh";
import {
SpritesheetFormat,
constructSpriteMaterial,
makeDataTexture,
} from "./material";
import { createSpriteTriangle } from "./triangle";

type InstancedSpriteOptions = {
// geometry?: BufferGeometry
spritesheet?: SpritesheetFormat;
triGeometry?: boolean;
};

export class InstancedSpriteMesh<
Expand All @@ -23,16 +31,26 @@ export class InstancedSpriteMesh<
constructor(
baseMaterial: T,
count: number,
spritesheet?: SpritesheetFormat,
options?: InstancedSpriteOptions
options: InstancedSpriteOptions = {}
) {
const geometry = new PlaneGeometry(1, 1);
const spriteMaterial = constructSpriteMaterial(baseMaterial);
let geometry: BufferGeometry<any> | PlaneGeometry;

if (options?.triGeometry) {
console.log("tri geo");
geometry = createSpriteTriangle();
} else {
geometry = new PlaneGeometry(1, 1) as any;
}

const spriteMaterial = constructSpriteMaterial(
baseMaterial,
options?.triGeometry
);
super(geometry, spriteMaterial as any, count);

this._animationMap = new Map();
this._spriteMaterial = spriteMaterial as any;
if (spritesheet) this.updateSpritesheet(spritesheet);
if (options.spritesheet) this.updateSpritesheet(options.spritesheet);
}

private updateSpritesheet(spritesheet: SpritesheetFormat) {
Expand Down
44 changes: 36 additions & 8 deletions packages/instanced-sprite-mesh/src/material.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,20 @@ const replaceUVs = (text: string, replacement: string) => {
};

// TODO TYPE GENERICS
export const constructSpriteMaterial = (baseMaterial: Material): Material => {
export const constructSpriteMaterial = (
baseMaterial: Material,
triGeometry: boolean | undefined
): Material => {
const defines: Record<string, any> = {
USE_UV: "",
};

if (triGeometry) {
defines["TRI_GEOMETRY"] = "";
}

const customMaterial = createDerivedMaterial(baseMaterial, {
defines: {
USE_UV: "",
},
defines,
uniforms: {
/** active animation */
animationId: { value: 0 },
Expand Down Expand Up @@ -131,11 +140,13 @@ export const constructSpriteMaterial = (baseMaterial: Material): Material => {
float hStep = 1.f / dataSize.y;
float hHalfStep = 1.f / dataSize.y * 0.5f;
return texture2D(spritesheetData, vec2(col * wStep + wHalfStep, row * hStep + hHalfStep));
}
}
`;

// calculate sprite UV
const spriteUv = /*glsl*/ `
float animLength = readData(animationId, 1.f).r;
float totalTime = animLength / fps;
Expand All @@ -156,16 +167,33 @@ export const constructSpriteMaterial = (baseMaterial: Material): Material => {
vec2 fSize = frameMeta.zw;
vec2 fOffset = vec2(frameMeta.xy);
vec2 transformedPlaneUv = vUv;
vec2 transformedPlaneUv = vUv + vec2(0.,0.);
if(flipX == 1.){
transformedPlaneUv.x = 1. - transformedPlaneUv.x;
}
if(flipY == 1.){
transformedPlaneUv.y = 1. - transformedPlaneUv.y;
}
}
vec2 spriteUv = fSize * transformedPlaneUv + fOffset;
vec2 spriteUv = fSize * transformedPlaneUv + fOffset ;
#ifdef TRI_GEOMETRY
// Shift UVs if mesh uses triangle geometry
// TODO optimize ugly math
if(vUv.y>0.5 || vUv.x<0.25 || vUv.x>0.75){
discard;
}
vec2 zoomCenter = vec2(fSize.x * 0.5,0.);
float zoomFactor = 2.;
vec2 shiftedUV = spriteUv - zoomCenter;
shiftedUV *= zoomFactor;
shiftedUV += zoomCenter;
spriteUv = shiftedUV;
#endif
`;
fragmentShader = fragmentShader.replace(
Expand Down
29 changes: 29 additions & 0 deletions packages/instanced-sprite-mesh/src/triangle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { BufferGeometry, BufferAttribute } from "three";

export const createSpriteTriangle = () => {
const geometry = new BufferGeometry();

const vertices = new Float32Array([
// top
0.0, 1.0, 0.0,
// bot-left
-1.0, -1.0, 0.0,
// bot-right
1.0, -1.0, 0.0,
]);
geometry.setAttribute("position", new BufferAttribute(vertices, 3));

const uvs = new Float32Array([
// top
0.5, 1,
// bot-left
0, 0.0,
// bot-right
1, 0.0,
]);

geometry.setAttribute("uv", new BufferAttribute(uvs, 2));
geometry.computeVertexNormals();

return geometry;
};

1 comment on commit ef9b39e

@vercel
Copy link

@vercel vercel bot commented on ef9b39e Dec 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

threejs-kit-playground – ./apps/playground

threejs-kit-playground-jerzakm.vercel.app
threejs-kit-playground.vercel.app
threejs-kit-playground-git-main-jerzakm.vercel.app

Please sign in to comment.