Skip to content

Commit aac821d

Browse files
committed
docs(examples): update instanced vertex color routes
1 parent 7f17b05 commit aac821d

File tree

3 files changed

+150
-11
lines changed

3 files changed

+150
-11
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
2+
import { NgtCanvas, NgtCanvasContent } from 'angular-three/dom';
3+
import { SceneGraph } from './scene';
4+
5+
@Component({
6+
template: `
7+
<ngt-canvas [gl]="{ antialias: false }" [camera]="{ position: [0, 0, 15], near: 5, far: 20 }">
8+
<app-instanced-vertex-colors-scene-graph *canvasContent />
9+
</ngt-canvas>
10+
`,
11+
changeDetection: ChangeDetectionStrategy.OnPush,
12+
imports: [NgtCanvas, SceneGraph, NgtCanvasContent],
13+
host: { class: 'instanced-vertex-colors-soba' },
14+
})
15+
export default class InstancedVertexColors {}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
CUSTOM_ELEMENTS_SCHEMA,
5+
ElementRef,
6+
input,
7+
signal,
8+
untracked,
9+
viewChild,
10+
} from '@angular/core';
11+
import { injectBeforeRender, NgtArgs, NgtThreeEvent } from 'angular-three';
12+
import { NgtpBloom, NgtpEffectComposer } from 'angular-three-postprocessing';
13+
import { NgtpN8AO } from 'angular-three-postprocessing/n8ao';
14+
import { Color, InstancedMesh, Object3D } from 'three';
15+
import niceColors from '../../colors';
16+
17+
/* credit: https://pmndrs.github.io/examples/demos/instanced-vertex-colors */
18+
19+
const tempObject = new Object3D();
20+
const tempColor = new Color();
21+
const data = Array.from({ length: 1000 }, () => ({ color: niceColors[Math.floor(Math.random() * 5)], scale: 1 }));
22+
23+
@Component({
24+
selector: 'app-boxes',
25+
template: `
26+
<ngt-instanced-mesh
27+
#mesh
28+
*args="[undefined, undefined, 1000]"
29+
(pointermove)="onPointerMove($any($event))"
30+
(pointerout)="onPointerOut($any($event))"
31+
>
32+
<ngt-box-geometry *args="[0.6, 0.6, 0.6]">
33+
<ngt-instanced-buffer-attribute attach="attributes.color" *args="[colors, 3]" />
34+
</ngt-box-geometry>
35+
<ngt-mesh-basic-material vertexColors [toneMapped]="false" />
36+
</ngt-instanced-mesh>
37+
`,
38+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
39+
changeDetection: ChangeDetectionStrategy.OnPush,
40+
imports: [NgtArgs],
41+
})
42+
export class Boxes {
43+
private meshRef = viewChild<ElementRef<InstancedMesh>>('mesh');
44+
45+
protected colors = Float32Array.from(
46+
Array.from({ length: 1000 }, (_, i) => i).flatMap((_, i) => tempColor.set(data[i].color).toArray()),
47+
);
48+
49+
protected hovered = signal<number | undefined>(undefined);
50+
protected prev?: number;
51+
52+
constructor() {
53+
injectBeforeRender(({ clock }) => {
54+
const instanced = this.meshRef()?.nativeElement;
55+
if (!instanced) return;
56+
57+
const time = clock.getElapsedTime();
58+
instanced.rotation.x = Math.sin(time / 4);
59+
instanced.rotation.y = Math.sin(time / 2);
60+
61+
const hovered = this.hovered();
62+
63+
let i = 0;
64+
for (let x = 0; x < 10; x++) {
65+
for (let y = 0; y < 10; y++) {
66+
for (let z = 0; z < 10; z++) {
67+
const id = i++;
68+
tempObject.position.set(5 - x, 5 - y, 5 - z);
69+
tempObject.rotation.y = Math.sin(x / 4 + time) + Math.sin(y / 4 + time) + Math.sin(z / 4 + time);
70+
tempObject.rotation.z = tempObject.rotation.y * 2;
71+
72+
if (hovered !== this.prev) {
73+
(id === hovered ? tempColor.setRGB(10, 10, 10) : tempColor.set(data[id].color)).toArray(
74+
this.colors,
75+
id * 3,
76+
);
77+
instanced.geometry.attributes['color'].needsUpdate = true;
78+
}
79+
80+
tempObject.updateMatrix();
81+
instanced.setMatrixAt(id, tempObject.matrix);
82+
}
83+
}
84+
}
85+
86+
instanced.instanceMatrix.needsUpdate = true;
87+
});
88+
}
89+
90+
onPointerMove(event: NgtThreeEvent<PointerEvent>) {
91+
event.stopPropagation();
92+
this.prev = untracked(this.hovered);
93+
this.hovered.set(event.instanceId);
94+
}
95+
96+
onPointerOut(event: NgtThreeEvent<PointerEvent>) {
97+
event.stopPropagation();
98+
this.prev = untracked(this.hovered);
99+
this.hovered.set(undefined);
100+
}
101+
}
102+
103+
@Component({
104+
selector: 'app-instanced-vertex-colors-scene-graph',
105+
template: `
106+
<ngt-color attach="background" *args="['#282828']" />
107+
<app-boxes />
108+
@if (!asRenderTexture()) {
109+
<ngtp-effect-composer [options]="{ enableNormalPass: false }">
110+
<ngtp-n8ao [options]="{ aoRadius: 0.5, intensity: Math.PI }" />
111+
<ngtp-bloom [options]="{ luminanceThreshold: 1, intensity: 0.5 * Math.PI, levels: 9, mipmapBlur: true }" />
112+
</ngtp-effect-composer>
113+
}
114+
`,
115+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
116+
changeDetection: ChangeDetectionStrategy.OnPush,
117+
host: { class: 'instanced-vertex-colors-soba-experience' },
118+
imports: [NgtArgs, Boxes, NgtpEffectComposer, NgtpN8AO, NgtpBloom],
119+
})
120+
export class SceneGraph {
121+
protected readonly Math = Math;
122+
123+
asRenderTexture = input(false);
124+
}

apps/kitchen-sink-new/src/app/soba/soba.routes.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,17 @@ const routes: Routes = [
153153
},
154154
},
155155
},
156-
// {
157-
// path: 'instanced-vertex-colors',
158-
// loadComponent: () => import('./instanced-vertex-colors/instanced-vertex-colors'),
159-
// data: {
160-
// credits: {
161-
// title: 'Instanced Vertex Colors',
162-
// link: 'https://pmndrs.github.io/examples/demos/instanced-vertex-colors',
163-
// class: 'text-white',
164-
// },
165-
// },
166-
// },
156+
{
157+
path: 'instanced-vertex-colors',
158+
loadComponent: () => import('./instanced-vertex-colors/instanced-vertex-colors'),
159+
data: {
160+
credits: {
161+
title: 'Instanced Vertex Colors',
162+
link: 'https://pmndrs.github.io/examples/demos/instanced-vertex-colors',
163+
class: 'text-white',
164+
},
165+
},
166+
},
167167
// {
168168
// path: 'portal-shapes',
169169
// loadComponent: () => import('./portal-shapes/portal-shapes'),

0 commit comments

Comments
 (0)