abstract-3d 4.0.3 → 4.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,10 +8,12 @@ import { getShadowCasters } from "./shadow.js";
8
8
  */
9
9
 
10
10
  const direction = new Vector3(-1, 2, 1.2).normalize();
11
- const intensity = 1.6;
12
- const mapSize = 2048;
11
+ const intensity = 1.2;
12
+ const mapSize = 1024;
13
13
  /** Of the key light kept out of its shadows, so faces under an overhang, e.g. a recessed base frame, aren't black */
14
- const shadowIntensity = 0.6;
14
+ const shadowIntensity = 0.45;
15
+ /** The penumbra's reach, in shadow map texels */
16
+ const penumbra = 16;
15
17
 
16
18
  /** The light and its target, to add to the scene, with or without shadows; undefined for a scene without solids */
17
19
  export function createKeyLight(built: BuiltScene, shadows: boolean): Group | undefined {
@@ -29,7 +31,7 @@ export function createKeyLight(built: BuiltScene, shadows: boolean): Group | und
29
31
  light.shadow.camera.updateProjectionMatrix();
30
32
  light.shadow.mapSize.set(mapSize, mapSize);
31
33
  // Offsets along the normal by three texels, against shadow acne on the lit faces
32
- Object.assign(light.shadow, { bias: -0.0005, normalBias: (radius * 6) / mapSize, radius: 3, intensity: shadowIntensity });
34
+ Object.assign(light.shadow, { bias: -0.0005, normalBias: (radius * 6) / mapSize, radius: penumbra, intensity: shadowIntensity });
33
35
  return new Group().add(light, light.target);
34
36
  }
35
37
 
@@ -38,7 +38,7 @@ const shadowLayer = 1;
38
38
  const resolution = 512;
39
39
  /** The blur's reach, of the solids' height */
40
40
  const softness = 0.22;
41
- const opacity = 1;
41
+ const opacity = 0.8;
42
42
  /** A pool of light on the floor the shadow lies in, so it shows on a dark background, which a shadow alone can't darken; on white it's invisible */
43
43
  const floorLight = 0.06;
44
44
  /** The pool's reach beyond the solids, of their height */
@@ -41,14 +41,14 @@ export type ViewerOptions<Content> = {
41
41
  readonly fitPadding?: number;
42
42
  readonly controls?: ControlsOptions;
43
43
  readonly gizmo?: ControlsHelper;
44
- /** Lights added to the photographed studio and key light that light the scene; none by default */
44
+ /** Lights added to the studio and key light that light the scene; none by default */
45
45
  readonly lights?: ReadonlyArray<Object3D> | ((scene: Scene) => ReadonlyArray<Object3D>);
46
- /** Of the studio's light, or without the studio of its plain light, 0.6 by default, the key light giving the rest */
46
+ /** Of the studio's light, 0.45 by default, or without the studio of its plain light, 0.6 by default, the key light giving the rest */
47
47
  readonly environmentIntensity?: number;
48
48
  /**
49
- * The photographed studio's light and reflections, on by default. Off, three-point lighting emulates it, a weak sky and floor light, the key light,
50
- * a fill and a rim light, without reflections, so metals are satin at most; a first visit then shows the scene about 400 ms sooner, as its shaders
51
- * compile without the reflection code. Changing it rebuilds the scene
49
+ * The studio's light and reflections, a room with soft area lights, on by default. Off, three-point lighting emulates it, a weak sky and floor
50
+ * light, the key light, a fill and a rim light, without reflections, so metals are satin at most; a first visit then shows the scene about 400 ms
51
+ * sooner, as its shaders compile without the reflection code. Changing it rebuilds the scene
52
52
  */
53
53
  readonly studio?: boolean;
54
54
  /** A soft shadow on the ground under the scene, rendered once per build; on by default */
@@ -8,10 +8,10 @@ import {
8
8
  PerspectiveCamera,
9
9
  Raycaster,
10
10
  Scene as ThreeScene,
11
- type Texture,
12
11
  Vector2,
13
12
  Vector3,
14
13
  WebGLRenderer,
14
+ type WebGLRenderTarget,
15
15
  } from "three";
16
16
  import type { ViewportGizmo } from "three-viewport-gizmo";
17
17
  import type { StructureState } from "../appearance/appearance.js";
@@ -81,7 +81,7 @@ export type Viewer<Content> = {
81
81
  keyLight?: Group;
82
82
  governor?: TierGovernor;
83
83
  /** The studio environment, loading and once loaded */
84
- readonly studio: { loading?: Promise<unknown>; texture?: Texture };
84
+ readonly studio: { loading?: Promise<unknown>; target?: WebGLRenderTarget };
85
85
  /** The scene is built and its shaders compiled */
86
86
  loaded: boolean;
87
87
  fitted: boolean;
@@ -183,7 +183,7 @@ export function disposeViewer<Content>(v: Viewer<Content>): void {
183
183
  if (v.keyLight) {
184
184
  disposeKeyLight(v.keyLight);
185
185
  }
186
- v.studio.texture?.dispose();
186
+ v.studio.target?.dispose();
187
187
  v.geometries.forEach((g) => g.dispose());
188
188
  v.atlas.texture.dispose();
189
189
  disposeTextures(v.textures);
@@ -521,13 +521,13 @@ function getGroupArgs<Content>(
521
521
  }
522
522
  }
523
523
 
524
- /** The scene is lit by a photographed studio as its environment, or without it by a plain sky and floor light; apps can add their own lights */
524
+ /** The scene is lit by a studio room as its environment, or without it by a plain sky and floor light; apps can add their own lights */
525
525
  function updateLights<Content>(v: Viewer<Content>): void {
526
- const { scene, lights, environmentIntensity = studioIntensity, studio = true } = v.options;
526
+ const { scene, lights, studio = true, environmentIntensity = studio ? studioIntensity : plainIntensity } = v.options;
527
527
  v.lights.clear();
528
528
  (typeof lights === "function" ? (scene ? lights(scene) : []) : (lights ?? [])).forEach((o) => v.lights.add(o));
529
529
  v.scene.environmentIntensity = environmentIntensity;
530
- v.scene.environment = studio ? (v.studio.texture ?? null) : null;
530
+ v.scene.environment = studio ? (v.studio.target?.texture ?? null) : null;
531
531
  if (studio) {
532
532
  loadStudio(v).catch(() => undefined);
533
533
  } else {
@@ -545,18 +545,16 @@ function updateLights<Content>(v: Viewer<Content>): void {
545
545
 
546
546
  /** The studio, loaded once, its own chunk; set when it arrives, so the scene's shaders are compiled after it, with it */
547
547
  function loadStudio<Content>(v: Viewer<Content>): Promise<unknown> {
548
- v.studio.loading ??= import("../environment/studio.js")
549
- .then(({ loadStudio: load }) => load())
550
- .then((texture) => {
551
- if (v.disposed) {
552
- texture.dispose();
553
- return texture;
554
- }
555
- v.studio.texture = texture;
556
- v.scene.environment = v.options.studio === false ? null : texture;
557
- invalidate(v);
558
- return texture;
559
- });
548
+ v.studio.loading ??= import("../environment/studio.js").then(({ createStudio }) => {
549
+ if (v.disposed) {
550
+ return undefined;
551
+ }
552
+ const target = createStudio(v.renderer);
553
+ v.studio.target = target;
554
+ v.scene.environment = v.options.studio === false ? null : target.texture;
555
+ invalidate(v);
556
+ return target;
557
+ });
560
558
  return v.studio.loading;
561
559
  }
562
560
 
@@ -582,7 +580,8 @@ function updateOverlays<Content>(v: Viewer<Content>): void {
582
580
  }
583
581
 
584
582
  /** The studio's share of the light, the key light giving the rest, so the key light's shadows show */
585
- const studioIntensity = 0.6;
583
+ const studioIntensity = 0.45;
584
+ const plainIntensity = 0.6;
586
585
  /** Without the studio, of its three-point lighting, by the environment's intensity; the key light is the studio's, the floor as the studio's */
587
586
  const skyIntensity = 2.5;
588
587
  const fillIntensity = 2;