Skip to content

Commit af271e2

Browse files
committed
caustics story
1 parent 0c14c0c commit af271e2

File tree

4 files changed

+222
-4
lines changed

4 files changed

+222
-4
lines changed
Binary file not shown.

libs/soba/src/materials/mesh-refraction-materials.stories.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ class Diamond {
7272
standalone: true,
7373
template: `
7474
<ngt-ambient-light [intensity]="0.5" />
75-
<ngt-spot-light [position]="[5, 5, -10]" [angle]="0.15" [penumbra]="1" />
75+
<ngt-spot-light #spotLight [position]="[5, 5, -10]" [angle]="0.15" [penumbra]="1" />
7676
<ngt-point-light [position]="[-10, -10, -10]" />
7777
7878
<diamond-flat [rotation]="[0, 0, 0.715]" [position]="[0, -0.175 + 0.5, 0]" [options]="options()" />
7979
8080
<ngts-caustics
8181
[options]="{
8282
position: [0, -0.5, 0],
83-
lightSource: [5, 5, -10],
83+
lightSource: spotLight,
8484
color: '#FF8F20',
8585
worldRadius: 0.003,
8686
ior: 1.16,
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
CUSTOM_ELEMENTS_SCHEMA,
5+
ElementRef,
6+
Signal,
7+
viewChild,
8+
} from '@angular/core';
9+
import { Meta } from '@storybook/angular';
10+
import { injectBeforeRender } from 'angular-three';
11+
import { injectGLTF } from 'angular-three-soba/loaders';
12+
import { NgtsMeshTransmissionMaterial } from 'angular-three-soba/materials';
13+
import {
14+
NgtsAccumulativeShadows,
15+
NgtsCaustics,
16+
NgtsCenter,
17+
NgtsEnvironment,
18+
NgtsLightformer,
19+
NgtsRandomizedLights,
20+
} from 'angular-three-soba/staging';
21+
import { easing } from 'maath';
22+
import { AdditiveBlending, Color, FrontSide, Group, MeshStandardMaterial } from 'three';
23+
import { makeDecorators, makeStoryFunction } from '../setup-canvas';
24+
25+
@Component({
26+
selector: 'caustics-scene',
27+
standalone: true,
28+
template: `
29+
@if (gltf(); as gltf) {
30+
<ngt-group [dispose]="null">
31+
<ngts-center [options]="{ top: true, position: [-1, -0.01, -2], rotation: [0, -0.4, 0] }">
32+
<ngt-mesh
33+
[castShadow]="true"
34+
[scale]="1.2"
35+
[geometry]="gltf.nodes.flowers.geometry"
36+
[material]="gltf.materials['draifrawer_u1_v1.001']"
37+
/>
38+
</ngts-center>
39+
40+
<ngts-caustics
41+
[options]="{
42+
backfaces: true,
43+
color,
44+
focus: [0, -1.2, 0],
45+
lightSource: [-1.2, 3, -2],
46+
intensity: 0.003,
47+
worldRadius: 0.26 / 10,
48+
ior: 0.9,
49+
backfaceIor: 1.26,
50+
}"
51+
>
52+
<ngt-mesh [castShadow]="true" [receiveShadow]="true" [geometry]="gltf.nodes.glass.geometry">
53+
<ngts-mesh-transmission-material
54+
[options]="{
55+
backside: true,
56+
backsideThickness: 0.1,
57+
thickness: 0.05,
58+
chromaticAberration: 0.05,
59+
anisotropicBlur: 1,
60+
clearcoat: 1,
61+
clearcoatRoughness: 1,
62+
envMapIntensity: 2,
63+
}"
64+
/>
65+
</ngt-mesh>
66+
</ngts-caustics>
67+
68+
<ngt-mesh [scale]="[0.95, 1, 0.95]" [geometry]="gltf.nodes.glass_back.geometry" [material]="innerMaterial" />
69+
<ngt-mesh [geometry]="gltf.nodes.glass_inner.geometry" [material]="innerMaterial" />
70+
</ngt-group>
71+
}
72+
`,
73+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
74+
changeDetection: ChangeDetectionStrategy.OnPush,
75+
imports: [NgtsCenter, NgtsCaustics, NgtsMeshTransmissionMaterial],
76+
})
77+
class Scene {
78+
gltf = injectGLTF(() => './glass-transformed.glb') as Signal<any>;
79+
color = new Color(1, 0.8, 0.8);
80+
innerMaterial = new MeshStandardMaterial({
81+
transparent: true,
82+
opacity: 1,
83+
color: 'black',
84+
roughness: 0,
85+
side: FrontSide,
86+
blending: AdditiveBlending,
87+
polygonOffset: true,
88+
polygonOffsetFactor: 1,
89+
envMapIntensity: 2,
90+
});
91+
}
92+
93+
@Component({
94+
selector: 'caustics-env',
95+
standalone: true,
96+
template: `
97+
<ngts-environment
98+
[options]="{
99+
frames: Infinity,
100+
preset: 'city',
101+
resolution: 256,
102+
background: true,
103+
blur: 0.8,
104+
}"
105+
>
106+
<ng-template>
107+
<ngts-lightformer
108+
[options]="{ intensity: 4, rotation: [Math.PI / 2, 0, 0], position: [0, 5, -9], scale: [10, 10, 1] }"
109+
/>
110+
<ngts-lightformer
111+
[options]="{ intensity: 4, rotation: [Math.PI / 2, 0, 0], position: [0, 5, -9], scale: [10, 10, 1] }"
112+
/>
113+
<ngt-group [rotation]="[Math.PI / 2, 1, 0]">
114+
@for (positionX of positions; track $index) {
115+
<ngts-lightformer
116+
[options]="{
117+
intensity: 1,
118+
rotation: [Math.PI / 4, 0, 0],
119+
position: [positionX, 4, $index * 4],
120+
scale: [4, 1, 1],
121+
}"
122+
/>
123+
}
124+
125+
<ngts-lightformer
126+
[options]="{ intensity: 0.5, rotation: [0, Math.PI / 2, 0], position: [-5, 1, -1], scale: [50, 2, 1] }"
127+
/>
128+
<ngts-lightformer
129+
[options]="{ intensity: 0.5, rotation: [0, Math.PI / 2, 0], position: [-5, -1, -1], scale: [50, 2, 1] }"
130+
/>
131+
<ngts-lightformer
132+
[options]="{ intensity: 0.5, rotation: [0, -Math.PI / 2, 0], position: [10, 1, 0], scale: [50, 2, 1] }"
133+
/>
134+
</ngt-group>
135+
<ngt-group #group>
136+
<ngts-lightformer
137+
[options]="{
138+
intensity: 5,
139+
form: 'ring',
140+
color: 'red',
141+
rotation: [0, Math.PI / 2, 0],
142+
position: [-5, 2, -1],
143+
scale: [10, 10, 1],
144+
}"
145+
/>
146+
</ngt-group>
147+
</ng-template>
148+
</ngts-environment>
149+
`,
150+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
151+
changeDetection: ChangeDetectionStrategy.OnPush,
152+
imports: [NgtsEnvironment, NgtsLightformer],
153+
})
154+
class Env {
155+
protected readonly Infinity = Infinity;
156+
protected readonly Math = Math;
157+
158+
positions = [2, -2, 2, -4, 2, -5, 2, -9];
159+
160+
groupRef = viewChild<ElementRef<Group>>('group');
161+
162+
constructor() {
163+
injectBeforeRender(({ delta, clock, pointer, camera }) => {
164+
const group = this.groupRef()?.nativeElement;
165+
if (!group) return;
166+
167+
easing.damp3(group.rotation as any, [Math.PI / 2, 0, clock.elapsedTime / 5 + pointer.x], 0.2, delta);
168+
easing.damp3(
169+
camera.position,
170+
[Math.sin(pointer.x / 4) * 9, 1.25 + pointer.y, Math.cos(pointer.x / 4) * 9],
171+
0.5,
172+
delta,
173+
);
174+
camera.lookAt(0, 0, 0);
175+
});
176+
}
177+
}
178+
179+
@Component({
180+
standalone: true,
181+
template: `
182+
<ngt-group [position]="[0, -0.5, 0]" [rotation]="[0, -0.75, 0]">
183+
<caustics-scene />
184+
<ngts-accumulative-shadows
185+
[options]="{ frames: 100, alphaTest: 0.85, opacity: 0.8, color: 'red', scale: 20, position: [0, -0.005, 0] }"
186+
>
187+
<ngts-randomized-lights
188+
[options]="{
189+
amount: 8,
190+
radius: 6,
191+
ambient: 0.5,
192+
intensity: Math.PI,
193+
position: [-1.5, 2.5, -2.5],
194+
bias: 0.001,
195+
}"
196+
/>
197+
</ngts-accumulative-shadows>
198+
<caustics-env />
199+
</ngt-group>
200+
`,
201+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
202+
changeDetection: ChangeDetectionStrategy.OnPush,
203+
imports: [NgtsAccumulativeShadows, NgtsRandomizedLights, Env, Scene],
204+
})
205+
class DefaultCausticsStory {
206+
protected readonly Math = Math;
207+
}
208+
209+
export default {
210+
title: 'Staging/Caustics',
211+
decorators: makeDecorators(),
212+
} as Meta;
213+
214+
// https://codesandbox.io/p/sandbox/caustics-forked-tfvz8j?file=/src/App.js:42,13
215+
export const Default = makeStoryFunction(DefaultCausticsStory, {
216+
camera: { position: [20, 0.9, 20], fov: 26 },
217+
background: '#f0f0f0',
218+
controls: false,
219+
});

libs/soba/staging/src/lib/caustics.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export class NgtsCaustics {
181181

182182
const autoEffect = injectAutoEffect();
183183

184-
const updateParams = computed(() => {
184+
const update = createCausticsUpdate(() => {
185185
const { lightSource, ...rest } = this.options();
186186

187187
return {
@@ -200,7 +200,6 @@ export class NgtsCaustics {
200200
};
201201
});
202202

203-
const update = createCausticsUpdate(updateParams);
204203
injectBeforeRender(({ gl }) => update(gl));
205204

206205
afterNextRender(() => {

0 commit comments

Comments
 (0)