Skip to content

Commit ef706a3

Browse files
committed
sky
1 parent c13b9bb commit ef706a3

File tree

4 files changed

+257
-1
lines changed

4 files changed

+257
-1
lines changed

libs/soba/src/staging/sky.stories.ts

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import { CUSTOM_ELEMENTS_SCHEMA, Component, Input, signal } from '@angular/core';
2+
import { Meta } from '@storybook/angular';
3+
import { NgtArgs, injectBeforeRender } from 'angular-three';
4+
import { NgtsSky } from 'angular-three-soba/staging';
5+
import { makeDecorators, makeStoryObject, number } from '../setup-canvas';
6+
7+
@Component({
8+
standalone: true,
9+
template: `
10+
<ngts-sky
11+
[distance]="3000"
12+
[turbidity]="turbidity"
13+
[rayleigh]="rayleigh"
14+
[mieCoefficient]="mieCoefficient"
15+
[mieDirectionalG]="mieDirectionalG"
16+
[inclination]="inclination()"
17+
[azimuth]="azimuth"
18+
/>
19+
<ngt-mesh [rotation]="[Math.PI / 2, 0, 0]">
20+
<ngt-plane-geometry *args="[100, 100, 4, 4]" />
21+
<ngt-mesh-basic-material color="black" [wireframe]="true" />
22+
</ngt-mesh>
23+
<ngt-axes-helper />
24+
`,
25+
imports: [NgtsSky, NgtArgs],
26+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
27+
})
28+
class RotationSkyStory {
29+
readonly Math = Math;
30+
@Input() turbidity = 8;
31+
@Input() rayleigh = 6;
32+
@Input() mieCoefficient = 0.005;
33+
@Input() mieDirectionalG = 0.8;
34+
@Input() azimuth = 0.25;
35+
36+
readonly inclination = signal(0);
37+
38+
constructor() {
39+
injectBeforeRender(() => {
40+
this.inclination.update((prev) => prev + 0.0015);
41+
});
42+
}
43+
}
44+
45+
@Component({
46+
standalone: true,
47+
template: `
48+
<ngts-sky
49+
[distance]="3000"
50+
[turbidity]="turbidity"
51+
[rayleigh]="rayleigh"
52+
[mieCoefficient]="mieCoefficient"
53+
[mieDirectionalG]="mieDirectionalG"
54+
[inclination]="inclination"
55+
[azimuth]="azimuth"
56+
/>
57+
<ngt-mesh [rotation]="[Math.PI / 2, 0, 0]">
58+
<ngt-plane-geometry *args="[100, 100, 4, 4]" />
59+
<ngt-mesh-basic-material color="black" [wireframe]="true" />
60+
</ngt-mesh>
61+
<ngt-axes-helper />
62+
`,
63+
imports: [NgtsSky, NgtArgs],
64+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
65+
})
66+
class CustomAnglesSkyStory {
67+
readonly Math = Math;
68+
@Input() turbidity = 8;
69+
@Input() rayleigh = 6;
70+
@Input() mieCoefficient = 0.005;
71+
@Input() mieDirectionalG = 0.8;
72+
@Input() inclination = 0.49;
73+
@Input() azimuth = 0.25;
74+
}
75+
76+
@Component({
77+
standalone: true,
78+
template: `
79+
<ngts-sky
80+
[turbidity]="turbidity"
81+
[rayleigh]="rayleigh"
82+
[mieCoefficient]="mieCoefficient"
83+
[mieDirectionalG]="mieDirectionalG"
84+
[sunPosition]="[sunPositionX, sunPositionY, sunPositionZ]"
85+
/>
86+
<ngt-mesh [rotation]="[Math.PI / 2, 0, 0]">
87+
<ngt-plane-geometry *args="[100, 100, 4, 4]" />
88+
<ngt-mesh-basic-material color="black" [wireframe]="true" />
89+
</ngt-mesh>
90+
<ngt-axes-helper />
91+
`,
92+
imports: [NgtsSky, NgtArgs],
93+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
94+
})
95+
class DefaultSkyStory {
96+
readonly Math = Math;
97+
@Input() turbidity = 8;
98+
@Input() rayleigh = 6;
99+
@Input() mieCoefficient = 0.005;
100+
@Input() mieDirectionalG = 0.8;
101+
@Input() sunPositionX = 1;
102+
@Input() sunPositionY = 0;
103+
@Input() sunPositionZ = 0;
104+
}
105+
106+
export default {
107+
title: 'Staging/Sky',
108+
decorators: makeDecorators(),
109+
} as Meta;
110+
111+
export const Default = makeStoryObject(DefaultSkyStory, {
112+
argsOptions: {
113+
turbidity: number(8, { min: 0, max: 10, step: 0.1, range: true }),
114+
rayleigh: number(6, { min: 0, max: 10, step: 0.1, range: true }),
115+
mieCoefficient: number(0.005, { min: 0, max: 0.1, step: 0.001, range: true }),
116+
mieDirectionalG: number(0.8, { min: 0, max: 1, step: 0.01, range: true }),
117+
sunPositionX: number(1),
118+
sunPositionY: number(0),
119+
sunPositionZ: number(0),
120+
},
121+
});
122+
123+
export const CustomAngles = makeStoryObject(CustomAnglesSkyStory, {
124+
argsOptions: {
125+
turbidity: number(8, { min: 0, max: 10, step: 0.1, range: true }),
126+
rayleigh: number(6, { min: 0, max: 10, step: 0.1, range: true }),
127+
mieCoefficient: number(0.005, { min: 0, max: 0.1, step: 0.001, range: true }),
128+
mieDirectionalG: number(0.8, { min: 0, max: 1, step: 0.01, range: true }),
129+
inclination: number(0.49, { min: 0, max: 1, step: 0.01, range: true }),
130+
azimuth: number(0.25, { min: 0, max: 1, step: 0.01, range: true }),
131+
},
132+
});
133+
134+
export const Rotation = makeStoryObject(RotationSkyStory, {
135+
argsOptions: {
136+
turbidity: number(8, { min: 0, max: 10, step: 0.1, range: true }),
137+
rayleigh: number(6, { min: 0, max: 10, step: 0.1, range: true }),
138+
mieCoefficient: number(0.005, { min: 0, max: 0.1, step: 0.001, range: true }),
139+
mieDirectionalG: number(0.8, { min: 0, max: 1, step: 0.01, range: true }),
140+
azimuth: number(0.25, { min: 0, max: 1, step: 0.01, range: true }),
141+
},
142+
});

libs/soba/staging/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export * from './cloud/cloud';
44
export * from './contact-shadows/contact-shadows';
55
export * from './float/float';
66
export * from './matcap-texture/matcap-texture';
7+
export * from './sky/sky';
78
export * from './sparkles/sparkles';

libs/soba/staging/src/sky/sky.ts

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { CUSTOM_ELEMENTS_SCHEMA, Component, Input, computed } from '@angular/core';
2+
import { NgtArgs, injectNgtRef, signalStore, type NgtMesh } from 'angular-three';
3+
import * as THREE from 'three';
4+
import { Sky } from 'three-stdlib';
5+
6+
function calcPosFromAngles(inclination: number, azimuth: number, vector = new THREE.Vector3()) {
7+
const theta = Math.PI * (inclination - 0.5);
8+
const phi = 2 * Math.PI * (azimuth - 0.5);
9+
10+
vector.x = Math.cos(phi);
11+
vector.y = Math.sin(theta);
12+
vector.z = Math.sin(phi);
13+
14+
return vector;
15+
}
16+
17+
export interface NgtsSkyState {
18+
distance: number;
19+
sunPosition: THREE.Vector3 | Parameters<THREE.Vector3['set']>;
20+
inclination: number;
21+
azimuth: number;
22+
mieCoefficient: number;
23+
mieDirectionalG: number;
24+
rayleigh: number;
25+
turbidity: number;
26+
}
27+
28+
declare global {
29+
interface HTMLElementTagNameMap {
30+
/**
31+
* @extends three-stdlib|Sky
32+
* @extends ngt-mesh
33+
*/
34+
'ngts-sky': NgtsSkyState & Sky & NgtMesh;
35+
}
36+
}
37+
38+
@Component({
39+
selector: 'ngts-sky',
40+
standalone: true,
41+
template: `
42+
<ngt-primitive *args="[sky]" [ref]="skyRef" [scale]="scale()" ngtCompound>
43+
<ngt-value [rawValue]="mieCoefficient()" attach="material.uniforms.mieCoefficient.value" />
44+
<ngt-value [rawValue]="mieDirectionalG()" attach="material.uniforms.mieDirectionalG.value" />
45+
<ngt-value [rawValue]="rayleigh()" attach="material.uniforms.rayleigh.value" />
46+
<ngt-value [rawValue]="sunPosition()" attach="material.uniforms.sunPosition.value" />
47+
<ngt-value [rawValue]="turbidity()" attach="material.uniforms.turbidity.value" />
48+
<ng-content />
49+
</ngt-primitive>
50+
`,
51+
imports: [NgtArgs],
52+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
53+
})
54+
export class NgtsSky {
55+
private inputs = signalStore<NgtsSkyState>({
56+
inclination: 0.6,
57+
azimuth: 0.1,
58+
distance: 1000,
59+
mieCoefficient: 0.005,
60+
mieDirectionalG: 0.8,
61+
rayleigh: 0.5,
62+
turbidity: 10,
63+
});
64+
65+
@Input() skyRef = injectNgtRef<Sky>();
66+
67+
@Input({ alias: 'distance' }) set _distance(distance: number) {
68+
this.inputs.set({ distance });
69+
}
70+
71+
@Input({ alias: 'sunPosition' }) set _sunPosition(sunPosition: THREE.Vector3 | Parameters<THREE.Vector3['set']>) {
72+
this.inputs.set({ sunPosition });
73+
}
74+
75+
@Input({ alias: 'inclination' }) set _inclination(inclination: number) {
76+
this.inputs.set({ inclination });
77+
}
78+
79+
@Input({ alias: 'azimuth' }) set _azimuth(azimuth: number) {
80+
this.inputs.set({ azimuth });
81+
}
82+
83+
@Input({ alias: 'mieCoefficient' }) set _mieCoefficient(mieCoefficient: number) {
84+
this.inputs.set({ mieCoefficient });
85+
}
86+
87+
@Input({ alias: 'mieDirectionalG' }) set _mieDirectionalG(mieDirectionalG: number) {
88+
this.inputs.set({ mieDirectionalG });
89+
}
90+
91+
@Input({ alias: 'rayleigh' }) set _rayleigh(rayleigh: number) {
92+
this.inputs.set({ rayleigh });
93+
}
94+
95+
@Input({ alias: 'turbidity' }) set _turbidity(turbidity: number) {
96+
this.inputs.set({ turbidity });
97+
}
98+
99+
private inclination = this.inputs.select('inclination');
100+
private azimuth = this.inputs.select('azimuth');
101+
private sunPos = this.inputs.select('sunPosition');
102+
private distance = this.inputs.select('distance');
103+
104+
sunPosition = computed(() => this.sunPos() || calcPosFromAngles(this.inclination(), this.azimuth()));
105+
scale = computed(() => new THREE.Vector3().setScalar(this.distance()));
106+
mieCoefficient = this.inputs.select('mieCoefficient');
107+
mieDirectionalG = this.inputs.select('mieDirectionalG');
108+
rayleigh = this.inputs.select('rayleigh');
109+
turbidity = this.inputs.select('turbidity');
110+
111+
sky = new Sky();
112+
}

tools/scripts/generate-soba-json.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const externals = ['three-stdlib'];
1818
const externalsMap = {
1919
OrbitControls: 'node_modules/three-stdlib/controls/OrbitControls.d.ts',
2020
TextGeometryParameters: 'node_modules/three-stdlib/geometries/TextGeometry.d.ts',
21+
Sky: 'node_modules/three-stdlib/objects/Sky.d.ts',
2122
};
2223

2324
const sobaMap = {
@@ -30,7 +31,7 @@ const entryPoints = {
3031
controls: ['orbit-controls'],
3132
abstractions: ['billboard', 'text', 'grid', 'text-3d'],
3233
cameras: ['perspective-camera', 'orthographic-camera', 'cube-camera'],
33-
staging: ['center', 'float', 'camera-shake', 'cloud', 'contact-shadows'],
34+
staging: ['center', 'float', 'camera-shake', 'cloud', 'contact-shadows', 'sparkles', 'sky'],
3435
};
3536

3637
const paths = [];

0 commit comments

Comments
 (0)