Skip to content

Commit 0d5422e

Browse files
committed
docs(examples): update inverted stencil buffer routes
1 parent a598e30 commit 0d5422e

File tree

6 files changed

+351
-11
lines changed

6 files changed

+351
-11
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';
2+
import { injectGLTF } from 'angular-three-soba/loaders';
3+
import { mask } from 'angular-three-soba/staging';
4+
import { Mesh, MeshPhongMaterial, MeshStandardMaterial } from 'three';
5+
import { GLTF } from 'three-stdlib';
6+
7+
type AngularGLTF = GLTF & {
8+
nodes: { Curve: Mesh; Curve001: Mesh; Curve002: Mesh; Curve003: Mesh };
9+
materials: { SVGMat: MeshStandardMaterial };
10+
};
11+
12+
@Component({
13+
selector: 'app-angular',
14+
template: `
15+
@if (gltf(); as gltf) {
16+
<ngt-group [dispose]="null" [scale]="scale()" [position]="[-2.75, -3, 0]" [rotation]="[Math.PI / 2, 0, 0]">
17+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve.geometry" [material]="material()" />
18+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve001.geometry" [material]="material()" />
19+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve002.geometry" [material]="material()" />
20+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve003.geometry" [material]="material()" />
21+
</ngt-group>
22+
}
23+
`,
24+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
25+
changeDetection: ChangeDetectionStrategy.OnPush,
26+
})
27+
export class Angular {
28+
protected readonly Math = Math;
29+
30+
invert = input(false);
31+
scale = input(1);
32+
33+
protected gltf = injectGLTF<AngularGLTF>(() => './angular.glb');
34+
protected stencilParameters = mask(() => 1, this.invert);
35+
36+
protected material = computed(() => {
37+
const stencilParameters = this.stencilParameters();
38+
return new MeshPhongMaterial({ color: '#E72BAA', ...stencilParameters });
39+
});
40+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
2+
import { NgtCanvas, NgtCanvasContent } from 'angular-three/dom';
3+
import { SceneGraph, invert, logo } from './scene';
4+
5+
@Component({
6+
template: `
7+
<ngt-canvas shadows [gl]="{ stencil: true }">
8+
<app-inverted-stencil-buffer-scene-graph *canvasContent />
9+
</ngt-canvas>
10+
<div
11+
class="absolute top-2 right-2 p-4 flex flex-col gap-4 items-center rounded border border-black border-dotted font-mono"
12+
>
13+
<label class="flex gap-2 items-center">
14+
<input type="checkbox" [value]="invert()" (change)="onInvertChange($event)" />
15+
invert
16+
</label>
17+
<select [value]="logo()" (change)="onLogoChange($event)">
18+
<option value="angular">Angular</option>
19+
<option value="nx">Nx</option>
20+
<option value="nx-cloud">Nx Cloud</option>
21+
</select>
22+
</div>
23+
`,
24+
host: { class: 'inverted-stencil-buffer-soba' },
25+
changeDetection: ChangeDetectionStrategy.OnPush,
26+
imports: [NgtCanvas, NgtCanvasContent, SceneGraph],
27+
})
28+
export default class InvertedStencilBuffer {
29+
protected invert = invert;
30+
protected logo = logo;
31+
32+
onInvertChange(event: Event) {
33+
const target = event.target as HTMLInputElement;
34+
this.invert.set(target.checked);
35+
}
36+
37+
onLogoChange(event: Event) {
38+
const target = event.target as HTMLSelectElement;
39+
this.logo.set(target.value as 'angular' | 'nx' | 'nx-cloud');
40+
}
41+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';
2+
import { injectGLTF } from 'angular-three-soba/loaders';
3+
import { mask } from 'angular-three-soba/staging';
4+
import { Mesh, MeshPhongMaterial, MeshStandardMaterial } from 'three';
5+
import { GLTF } from 'three-stdlib';
6+
7+
type NxCloudGLTF = GLTF & {
8+
nodes: {
9+
Curve012: Mesh;
10+
Curve013: Mesh;
11+
Curve014: Mesh;
12+
Curve015: Mesh;
13+
Curve016: Mesh;
14+
Curve017: Mesh;
15+
Curve018: Mesh;
16+
Curve019: Mesh;
17+
};
18+
materials: { 'SVGMat.007': MeshStandardMaterial };
19+
};
20+
@Component({
21+
selector: 'app-nx-cloud',
22+
template: `
23+
@if (gltf(); as gltf) {
24+
<ngt-group [dispose]="null" [scale]="scale()" [position]="[-3, -0.5, 0]" [rotation]="[Math.PI / 2, 0, 0]">
25+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve012.geometry" [material]="material()" />
26+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve013.geometry" [material]="material()" />
27+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve014.geometry" [material]="material()" />
28+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve015.geometry" [material]="material()" />
29+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve016.geometry" [material]="material()" />
30+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve017.geometry" [material]="material()" />
31+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve018.geometry" [material]="material()" />
32+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.Curve019.geometry" [material]="material()" />
33+
</ngt-group>
34+
}
35+
`,
36+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
37+
changeDetection: ChangeDetectionStrategy.OnPush,
38+
})
39+
export class NxCloud {
40+
protected readonly Math = Math;
41+
42+
invert = input(false);
43+
scale = input(1);
44+
45+
protected gltf = injectGLTF<NxCloudGLTF>(() => './nx-cloud.glb');
46+
protected stencilParameters = mask(() => 1, this.invert);
47+
48+
protected material = computed(() => {
49+
const stencilParameters = this.stencilParameters();
50+
return new MeshPhongMaterial({ color: '#002f56', ...stencilParameters });
51+
});
52+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';
2+
import { injectGLTF } from 'angular-three-soba/loaders';
3+
import { mask } from 'angular-three-soba/staging';
4+
import { Mesh, MeshPhongMaterial, MeshStandardMaterial } from 'three';
5+
import { GLTF } from 'three-stdlib';
6+
7+
type NxGLTF = GLTF & {
8+
nodes: { Curve004: Mesh; Curve005: Mesh; Curve006: Mesh; Curve007: Mesh; Curve008: Mesh; Curve009: Mesh };
9+
materials: { 'SVGMat.001': MeshStandardMaterial };
10+
};
11+
12+
@Component({
13+
selector: 'app-nx',
14+
template: `
15+
@if (gltf(); as gltf) {
16+
@let nodes = gltf.nodes;
17+
@let _material = material();
18+
@let meshParameters = { castShadow: true, receiveShadow: true };
19+
20+
<ngt-group [dispose]="null" [scale]="scale()" [position]="[-3, -3, 0]" [rotation]="[Math.PI / 2, 0, 0]">
21+
<ngt-mesh [parameters]="meshParameters" [geometry]="nodes.Curve004.geometry" [material]="_material" />
22+
<ngt-mesh [parameters]="meshParameters" [geometry]="nodes.Curve005.geometry" [material]="_material" />
23+
<ngt-mesh [parameters]="meshParameters" [geometry]="nodes.Curve006.geometry" [material]="_material" />
24+
<ngt-mesh [parameters]="meshParameters" [geometry]="nodes.Curve007.geometry" [material]="_material" />
25+
<ngt-mesh [parameters]="meshParameters" [geometry]="nodes.Curve008.geometry" [material]="_material" />
26+
<ngt-mesh [parameters]="meshParameters" [geometry]="nodes.Curve009.geometry" [material]="_material" />
27+
</ngt-group>
28+
}
29+
`,
30+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
31+
changeDetection: ChangeDetectionStrategy.OnPush,
32+
})
33+
export class Nx {
34+
protected readonly Math = Math;
35+
36+
invert = input(false);
37+
scale = input(1);
38+
39+
protected gltf = injectGLTF<NxGLTF>(() => './nx.glb');
40+
protected stencilParameters = mask(() => 1, this.invert);
41+
42+
protected material = computed(() => {
43+
const stencilParameters = this.stencilParameters();
44+
return new MeshPhongMaterial({ color: '#002f56', ...stencilParameters });
45+
});
46+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import { NgTemplateOutlet } from '@angular/common';
2+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input, signal } from '@angular/core';
3+
import { NgtArgs, NgtEuler, NgtVector3 } from 'angular-three';
4+
import { NgtsRoundedBox } from 'angular-three-soba/abstractions';
5+
import { NgtsOrbitControls } from 'angular-three-soba/controls';
6+
import { NgtsPivotControls } from 'angular-three-soba/gizmos';
7+
import { NgtsBounds, NgtsEnvironment, NgtsFloat, NgtsMask } from 'angular-three-soba/staging';
8+
import { ColorRepresentation } from 'three';
9+
import { Angular } from './angular';
10+
import { Nx } from './nx';
11+
import { NxCloud } from './nx-cloud';
12+
13+
export const invert = signal(false);
14+
export const logo = signal<'angular' | 'nx' | 'nx-cloud'>('nx');
15+
16+
@Component({
17+
selector: 'app-frame',
18+
template: `
19+
<ngt-mesh [position]="position()">
20+
<ngt-ring-geometry *args="[1.095, 1.155, 64]" />
21+
<ngt-mesh-phong-material color="black" />
22+
</ngt-mesh>
23+
`,
24+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
25+
changeDetection: ChangeDetectionStrategy.OnPush,
26+
imports: [NgtArgs],
27+
})
28+
export class Frame {
29+
position = input<NgtVector3>([0, 0, 0]);
30+
}
31+
32+
@Component({
33+
selector: 'app-circular-mask',
34+
template: `
35+
<ngt-group [position]="position()">
36+
<ngts-pivot-controls
37+
[options]="{ offset: [0, 0, 1], activeAxes: [true, true, false], disableRotations: true, depthTest: false }"
38+
>
39+
<app-frame [position]="[0, 0, 1]" />
40+
<ngts-mask id="1" [options]="{ position: [0, 0, 0.95] }">
41+
<ngt-circle-geometry *args="[1.15, 64]" />
42+
</ngts-mask>
43+
</ngts-pivot-controls>
44+
</ngt-group>
45+
`,
46+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
47+
changeDetection: ChangeDetectionStrategy.OnPush,
48+
imports: [NgtsPivotControls, Frame, NgtsMask, NgtArgs],
49+
})
50+
export class CircularMask {
51+
position = input<NgtVector3>([0, 0, 0]);
52+
}
53+
54+
@Component({
55+
selector: 'app-box',
56+
template: `
57+
<ngts-rounded-box
58+
[options]="{
59+
width: width(),
60+
height: height(),
61+
depth: depth(),
62+
radius: 0.05,
63+
smoothness: 4,
64+
position: position(),
65+
rotation: rotation(),
66+
}"
67+
>
68+
<ngt-mesh-phong-material [color]="color()" />
69+
</ngts-rounded-box>
70+
`,
71+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
72+
changeDetection: ChangeDetectionStrategy.OnPush,
73+
imports: [NgtsRoundedBox],
74+
})
75+
export class Box {
76+
width = input.required<number>();
77+
height = input.required<number>();
78+
depth = input.required<number>();
79+
color = input.required<ColorRepresentation>();
80+
position = input<NgtVector3>([0, 0, 0]);
81+
rotation = input<NgtEuler>([0, 0, 0]);
82+
}
83+
84+
@Component({
85+
selector: 'app-inverted-stencil-buffer-scene-graph',
86+
template: `
87+
<ngt-color attach="background" *args="['#e0e0e0']" />
88+
89+
<ngt-directional-light [position]="[1, 2, 1.5]" [intensity]="Math.PI * 0.5" castShadow />
90+
<ngt-hemisphere-light [intensity]="Math.PI * 1.5" groundColor="red" />
91+
92+
<app-circular-mask />
93+
94+
@if (!asRenderTexture()) {
95+
<ngts-bounds [options]="{ fit: true, clip: true, observe: true }">
96+
<ngts-float [options]="{ floatIntensity: 4, rotationIntensity: 0, speed: 4 }">
97+
<ng-container [ngTemplateOutlet]="logos" />
98+
</ngts-float>
99+
<ng-container [ngTemplateOutlet]="boxes" />
100+
</ngts-bounds>
101+
} @else {
102+
<ng-container [ngTemplateOutlet]="logos" />
103+
<ng-container [ngTemplateOutlet]="boxes" />
104+
}
105+
106+
<ngts-environment [options]="{ preset: 'city' }" />
107+
@if (!asRenderTexture()) {
108+
<ngts-orbit-controls [options]="{ makeDefault: true }" />
109+
}
110+
111+
<ng-template #logos>
112+
@switch (logo()) {
113+
@case ('angular') {
114+
<app-angular [invert]="invert()" [scale]="20" />
115+
}
116+
@case ('nx') {
117+
<app-nx [invert]="invert()" [scale]="20" />
118+
}
119+
@case ('nx-cloud') {
120+
<app-nx-cloud [invert]="invert()" [scale]="160" />
121+
}
122+
}
123+
</ng-template>
124+
125+
<ng-template #boxes>
126+
<app-box
127+
color="#EAC435"
128+
[width]="1"
129+
[height]="5"
130+
[depth]="1"
131+
[rotation]="[0, Math.PI / 4, 0]"
132+
[position]="[0, 0, -2]"
133+
/>
134+
<app-box color="#03CEA4" [width]="2" [height]="2" [depth]="2" [position]="[-2, 0, -2]" />
135+
<app-box color="#FB4D3D" [width]="2" [height]="2" [depth]="2" [position]="[2, 0, -2]" />
136+
</ng-template>
137+
`,
138+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
139+
changeDetection: ChangeDetectionStrategy.OnPush,
140+
host: { class: 'inverted-stencil-buffer-soba-experience' },
141+
imports: [
142+
NgTemplateOutlet,
143+
CircularMask,
144+
NgtsBounds,
145+
NgtsFloat,
146+
Box,
147+
NgtsEnvironment,
148+
NgtsOrbitControls,
149+
NgtArgs,
150+
Nx,
151+
Angular,
152+
NxCloud,
153+
],
154+
})
155+
export class SceneGraph {
156+
protected readonly Math = Math;
157+
protected invert = invert;
158+
protected logo = logo;
159+
160+
asRenderTexture = input(false);
161+
}

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,17 @@ const routes: Routes = [
112112
},
113113
},
114114
},
115-
// {
116-
// path: 'inverted-stencil-buffer',
117-
// loadComponent: () => import('./inverted-stencil-buffer/inverted-stencil-buffer'),
118-
// data: {
119-
// credits: {
120-
// title: 'Inverted Stencil Buffer',
121-
// link: 'https://pmndrs.github.io/examples/demos/inverted-stencil-buffer',
122-
// class: 'left-2',
123-
// },
124-
// },
125-
// },
115+
{
116+
path: 'inverted-stencil-buffer',
117+
loadComponent: () => import('./inverted-stencil-buffer/inverted-stencil-buffer'),
118+
data: {
119+
credits: {
120+
title: 'Inverted Stencil Buffer',
121+
link: 'https://pmndrs.github.io/examples/demos/inverted-stencil-buffer',
122+
class: 'left-2',
123+
},
124+
},
125+
},
126126
// {
127127
// path: 'simple-sound-analyser',
128128
// loadComponent: () => import('./simple-sound-analyser/simple-sound-analyser'),

0 commit comments

Comments
 (0)