@aura3d/rendering 1.0.6 → 1.3.0

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.
Files changed (86) hide show
  1. package/dist/ForwardPass.js +18 -13
  2. package/dist/ForwardPass.js.map +1 -1
  3. package/dist/FrameVisualMetrics.d.ts +19 -0
  4. package/dist/FrameVisualMetrics.d.ts.map +1 -1
  5. package/dist/FrameVisualMetrics.js +57 -0
  6. package/dist/FrameVisualMetrics.js.map +1 -1
  7. package/dist/MorphTargetPlan.d.ts +42 -0
  8. package/dist/MorphTargetPlan.d.ts.map +1 -0
  9. package/dist/MorphTargetPlan.js +129 -0
  10. package/dist/MorphTargetPlan.js.map +1 -0
  11. package/dist/MorphUnlitMaterial.d.ts.map +1 -1
  12. package/dist/MorphUnlitMaterial.js +7 -1
  13. package/dist/MorphUnlitMaterial.js.map +1 -1
  14. package/dist/ShaderLibrary.d.ts.map +1 -1
  15. package/dist/ShaderLibrary.js +34 -6
  16. package/dist/ShaderLibrary.js.map +1 -1
  17. package/dist/WebGPUDevice.d.ts +2 -0
  18. package/dist/WebGPUDevice.d.ts.map +1 -1
  19. package/dist/WebGPUDevice.js +69 -12
  20. package/dist/WebGPUDevice.js.map +1 -1
  21. package/dist/animation/AnimationMaterialStyle.d.ts +19 -0
  22. package/dist/animation/AnimationMaterialStyle.d.ts.map +1 -0
  23. package/dist/animation/AnimationMaterialStyle.js +13 -0
  24. package/dist/animation/AnimationMaterialStyle.js.map +1 -0
  25. package/dist/animation/AnimationRenderPreset.d.ts +36 -0
  26. package/dist/animation/AnimationRenderPreset.d.ts.map +1 -0
  27. package/dist/animation/AnimationRenderPreset.js +23 -0
  28. package/dist/animation/AnimationRenderPreset.js.map +1 -0
  29. package/dist/animation/AnimationToonMaterial.d.ts +130 -0
  30. package/dist/animation/AnimationToonMaterial.d.ts.map +1 -0
  31. package/dist/animation/AnimationToonMaterial.js +303 -0
  32. package/dist/animation/AnimationToonMaterial.js.map +1 -0
  33. package/dist/animation/AnimationVisualQuality.d.ts +28 -0
  34. package/dist/animation/AnimationVisualQuality.d.ts.map +1 -0
  35. package/dist/animation/AnimationVisualQuality.js +39 -0
  36. package/dist/animation/AnimationVisualQuality.js.map +1 -0
  37. package/dist/animation/applyAnimationRenderPreset.d.ts +79 -0
  38. package/dist/animation/applyAnimationRenderPreset.d.ts.map +1 -0
  39. package/dist/animation/applyAnimationRenderPreset.js +88 -0
  40. package/dist/animation/applyAnimationRenderPreset.js.map +1 -0
  41. package/dist/animation/index.d.ts +6 -0
  42. package/dist/animation/index.d.ts.map +1 -0
  43. package/dist/animation/index.js +6 -0
  44. package/dist/animation/index.js.map +1 -0
  45. package/dist/cartoon/CartoonMaterialStyle.d.ts +19 -0
  46. package/dist/cartoon/CartoonMaterialStyle.d.ts.map +1 -0
  47. package/dist/cartoon/CartoonMaterialStyle.js +13 -0
  48. package/dist/cartoon/CartoonMaterialStyle.js.map +1 -0
  49. package/dist/cartoon/CartoonRenderPreset.d.ts +36 -0
  50. package/dist/cartoon/CartoonRenderPreset.d.ts.map +1 -0
  51. package/dist/cartoon/CartoonRenderPreset.js +23 -0
  52. package/dist/cartoon/CartoonRenderPreset.js.map +1 -0
  53. package/dist/cartoon/CartoonToonMaterial.d.ts +130 -0
  54. package/dist/cartoon/CartoonToonMaterial.d.ts.map +1 -0
  55. package/dist/cartoon/CartoonToonMaterial.js +303 -0
  56. package/dist/cartoon/CartoonToonMaterial.js.map +1 -0
  57. package/dist/cartoon/CartoonVisualQuality.d.ts +28 -0
  58. package/dist/cartoon/CartoonVisualQuality.d.ts.map +1 -0
  59. package/dist/cartoon/CartoonVisualQuality.js +39 -0
  60. package/dist/cartoon/CartoonVisualQuality.js.map +1 -0
  61. package/dist/cartoon/applyCartoonRenderPreset.d.ts +79 -0
  62. package/dist/cartoon/applyCartoonRenderPreset.d.ts.map +1 -0
  63. package/dist/cartoon/applyCartoonRenderPreset.js +88 -0
  64. package/dist/cartoon/applyCartoonRenderPreset.js.map +1 -0
  65. package/dist/cartoon/index.d.ts +6 -0
  66. package/dist/cartoon/index.d.ts.map +1 -0
  67. package/dist/cartoon/index.js +6 -0
  68. package/dist/cartoon/index.js.map +1 -0
  69. package/dist/index.d.ts +6 -3
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +4 -2
  72. package/dist/index.js.map +1 -1
  73. package/package.json +4 -4
  74. package/src/ForwardPass.ts +18 -13
  75. package/src/FrameVisualMetrics.ts +83 -0
  76. package/src/MorphTargetPlan.ts +178 -0
  77. package/src/MorphUnlitMaterial.ts +7 -1
  78. package/src/ShaderLibrary.ts +34 -6
  79. package/src/WebGPUDevice.ts +83 -12
  80. package/src/animation/AnimationMaterialStyle.ts +32 -0
  81. package/src/animation/AnimationRenderPreset.ts +45 -0
  82. package/src/animation/AnimationToonMaterial.ts +387 -0
  83. package/src/animation/AnimationVisualQuality.ts +71 -0
  84. package/src/animation/applyAnimationRenderPreset.ts +180 -0
  85. package/src/animation/index.ts +5 -0
  86. package/src/index.ts +13 -2
@@ -0,0 +1,71 @@
1
+ import { evaluateFrameVisualQuality, type FrameVisualMetrics, type FrameVisualQualityThresholds } from "../FrameVisualMetrics.js";
2
+
3
+ export interface AnimationFrameVisualInput {
4
+ readonly id: string;
5
+ readonly metrics: FrameVisualMetrics;
6
+ readonly characterCount?: number | undefined;
7
+ readonly captionOccluded?: boolean | undefined;
8
+ readonly routeChromeVisible?: boolean | undefined;
9
+ readonly debugOverlayVisible?: boolean | undefined;
10
+ }
11
+
12
+ export interface AnimationFrameVisualQuality {
13
+ readonly id: string;
14
+ readonly ok: boolean;
15
+ readonly failures: readonly string[];
16
+ }
17
+
18
+ export interface AnimationVisualQualityReport {
19
+ readonly kind: "animation-visual-quality";
20
+ readonly ok: boolean;
21
+ readonly frames: readonly AnimationFrameVisualQuality[];
22
+ readonly visibleCharacterCount: number;
23
+ readonly blockers: readonly string[];
24
+ }
25
+
26
+ export interface AnimationVisualQualityOptions {
27
+ readonly thresholds?: FrameVisualQualityThresholds | undefined;
28
+ readonly minVisibleCharacters?: number | undefined;
29
+ }
30
+
31
+ export function createAnimationVisualQualityReport(
32
+ frames: readonly AnimationFrameVisualInput[],
33
+ options: AnimationVisualQualityOptions = {}
34
+ ): AnimationVisualQualityReport {
35
+ const thresholds = options.thresholds ?? defaultAnimationVisualQualityThresholds;
36
+ const frameResults = frames.map((frame): AnimationFrameVisualQuality => {
37
+ const base = evaluateFrameVisualQuality(frame.metrics, thresholds);
38
+ const failures = [
39
+ ...base.failures,
40
+ frame.captionOccluded ? "caption occludes important action" : undefined,
41
+ frame.routeChromeVisible ? "route chrome is visible" : undefined,
42
+ frame.debugOverlayVisible ? "debug overlay is visible" : undefined
43
+ ].filter((failure): failure is string => Boolean(failure));
44
+ return { id: frame.id, ok: failures.length === 0, failures };
45
+ });
46
+ const visibleCharacterCount = Math.max(0, ...frames.map((frame) => frame.characterCount ?? 0));
47
+ const blockers = [
48
+ ...frameResults.flatMap((frame) => frame.failures.map((failure) => `${frame.id}: ${failure}`)),
49
+ visibleCharacterCount < (options.minVisibleCharacters ?? 2)
50
+ ? `visibleCharacterCount ${visibleCharacterCount} < ${options.minVisibleCharacters ?? 2}`
51
+ : undefined
52
+ ].filter((blocker): blocker is string => Boolean(blocker));
53
+ return {
54
+ kind: "animation-visual-quality",
55
+ ok: blockers.length === 0,
56
+ frames: frameResults,
57
+ visibleCharacterCount,
58
+ blockers
59
+ };
60
+ }
61
+
62
+ export const defaultAnimationVisualQualityThresholds: FrameVisualQualityThresholds = {
63
+ minNonDarkRatio: 0.08,
64
+ minSalientRatio: 0.035,
65
+ minOccupiedAreaRatio: 0.08,
66
+ minOccupiedQuadrants: 2,
67
+ minColorBuckets: 6,
68
+ maxDominantBucketRatio: 0.92,
69
+ maxFlatPixelRatio: 0.98,
70
+ minLocalContrastRatio: 0.002
71
+ };
@@ -0,0 +1,180 @@
1
+ import { AnimationToonMaterial, type AnimationToonMaterialOptions } from "./AnimationToonMaterial.js";
2
+ import type { AnimationRenderPresetEvidence } from "./AnimationRenderPreset.js";
3
+ import type { AnimationMaterialStyle } from "./AnimationMaterialStyle.js";
4
+ import { colorGradePixels, outlinePixels, type ColorGradeResult, type OutlineResult } from "../PostProcessPass.js";
5
+
6
+ /**
7
+ * applyAnimationRenderPreset — turns a (metadata) AnimationRenderPreset into the
8
+ * concrete, pixel-affecting treatment it describes:
9
+ *
10
+ * 1. MATERIAL: builds a real `AnimationToonMaterial` (banded N·L ramp + rim) from
11
+ * the preset's `materialStyle`. The band count comes from `materialStyle.rampSteps`.
12
+ * 2. OUTLINE: runs the existing Sobel `outlinePixels()` post-pass when the style
13
+ * requests outlines.
14
+ * 3. COLOR GRADE: pushes a stylized, slightly-saturated, gently-contrasted grade
15
+ * consistent with the preset (storybook look), honoring `reducedFlash`.
16
+ *
17
+ * WHAT ACTUALLY AFFECTS PIXELS (honest accounting):
18
+ * - `material` is a fully-wired engine material. Assigning it to scene meshes and
19
+ * rendering with a ShaderLibrary that has the animation program registered produces
20
+ * banded toon shading on real fragments. THIS FUNCTION DOES NOT REASSIGN SCENE
21
+ * MESH MATERIALS — there is no scene-graph type imported here — it RETURNS the
22
+ * material so the caller (which owns the scene) can assign it. That assignment
23
+ * step is the one piece that is the caller's responsibility, not this function's.
24
+ * - `outline` (when present) is a real OutlineResult whose `.pixels` ARE modified
25
+ * image bytes. If you pass a frame buffer, the returned bytes are drawn pixels.
26
+ * - `colorGrade` (when a frame is passed) is a real ColorGradeResult — modified
27
+ * pixels.
28
+ *
29
+ * WHAT IS NOT WIRED:
30
+ * - Lights / shadows from the preset are reflected in the returned `lighting`
31
+ * descriptor and fed into the toon material's single key-light uniforms, but the
32
+ * multi-light rig (`preset.lights`) is descriptive — the toon program consumes one
33
+ * directional key light, not the full named rig.
34
+ * - Bloom/fog from the preset are NOT applied here (they belong to the HDR pipeline);
35
+ * only outline + color grade run as post-passes in this function.
36
+ */
37
+
38
+ export interface ApplyAnimationRenderPresetFrame {
39
+ /** RGBA8 pixel buffer (length === width * height * 4). */
40
+ readonly pixels: Uint8Array;
41
+ readonly width: number;
42
+ readonly height: number;
43
+ }
44
+
45
+ export interface AnimationRenderPresetLightingDescriptor {
46
+ readonly keyLightDirection: readonly [number, number, number];
47
+ readonly keyLightColor: readonly [number, number, number];
48
+ readonly softShadows: boolean;
49
+ readonly contactShadows: boolean;
50
+ /** The full named rig from the preset (descriptive — not all consumed by the toon program). */
51
+ readonly namedRig: readonly string[];
52
+ }
53
+
54
+ export interface ApplyAnimationRenderPresetOptions {
55
+ /** Optional explicit base color override for the toon material. */
56
+ readonly baseColor?: readonly [number, number, number, number] | undefined;
57
+ /** Optional toon material override knobs (light direction/colors/rim). */
58
+ readonly material?: Partial<AnimationToonMaterialOptions> | undefined;
59
+ /** Optional frame to run the outline + color-grade post-passes against. */
60
+ readonly frame?: ApplyAnimationRenderPresetFrame | undefined;
61
+ }
62
+
63
+ export interface ApplyAnimationRenderPresetResult {
64
+ readonly kind: "animation-render-preset-application";
65
+ /** Real engine material — assign to scene meshes to get banded toon pixels. */
66
+ readonly material: AnimationToonMaterial;
67
+ readonly materialStyle: AnimationMaterialStyle;
68
+ /** Key-light descriptor derived from the preset, also baked into the material. */
69
+ readonly lighting: AnimationRenderPresetLightingDescriptor;
70
+ /** True when the Sobel outline pass is enabled for this preset. */
71
+ readonly outlineEnabled: boolean;
72
+ /** Present only when a frame was supplied AND outlines are enabled. Real modified pixels. */
73
+ readonly outline?: OutlineResult | undefined;
74
+ /** Present only when a frame was supplied. Real modified pixels. */
75
+ readonly colorGrade?: ColorGradeResult | undefined;
76
+ /** Honest per-stage record of what touched pixels. */
77
+ readonly appliedToPixels: {
78
+ readonly toonMaterial: "returned-for-caller-assignment";
79
+ readonly outline: boolean;
80
+ readonly colorGrade: boolean;
81
+ };
82
+ }
83
+
84
+ const DEFAULT_KEY_LIGHT_DIRECTION: readonly [number, number, number] = [0.3, 0.8, 0.5];
85
+
86
+ /**
87
+ * Map a AnimationMaterialStyle.treatment to a shadow-floor that keeps the chosen
88
+ * look readable: flatter treatments use a higher floor (less contrast between bands).
89
+ */
90
+ function shadowFloorForTreatment(style: AnimationMaterialStyle): number {
91
+ switch (style.treatment) {
92
+ case "flat-readable":
93
+ return 0.6;
94
+ case "soft-toon":
95
+ return 0.45;
96
+ case "cel":
97
+ return 0.3;
98
+ case "preserve-pbr":
99
+ default:
100
+ return 0.4;
101
+ }
102
+ }
103
+
104
+ export function applyAnimationRenderPreset(
105
+ preset: AnimationRenderPresetEvidence,
106
+ options: ApplyAnimationRenderPresetOptions = {}
107
+ ): ApplyAnimationRenderPresetResult {
108
+ const style = preset.materialStyle;
109
+
110
+ const keyLightDirection = options.material?.lightDirection ?? DEFAULT_KEY_LIGHT_DIRECTION;
111
+ const keyLightColor = options.material?.lightColor ?? [1, 0.97, 0.9];
112
+
113
+ // 1. MATERIAL — band count comes straight from the style's rampSteps (clamped to
114
+ // the toon material's supported [2, 16] range).
115
+ const bands = Math.max(2, Math.min(16, Math.round(style.rampSteps)));
116
+ const material = new AnimationToonMaterial({
117
+ name: `${preset.name}-toon`,
118
+ baseColor: options.baseColor ?? options.material?.baseColor ?? [0.92, 0.58, 0.16, 1],
119
+ bands,
120
+ shadowFloor: options.material?.shadowFloor ?? shadowFloorForTreatment(style),
121
+ lightDirection: keyLightDirection,
122
+ lightColor: keyLightColor as readonly [number, number, number],
123
+ rimColor: options.material?.rimColor ?? [0.6, 0.72, 1],
124
+ rimPower: options.material?.rimPower ?? 3,
125
+ // Cel treatment leans on a stronger rim for graphic edges.
126
+ rimIntensity: options.material?.rimIntensity ?? (style.treatment === "cel" ? 0.6 : 0.4)
127
+ });
128
+
129
+ const lighting: AnimationRenderPresetLightingDescriptor = {
130
+ keyLightDirection,
131
+ keyLightColor: keyLightColor as readonly [number, number, number],
132
+ softShadows: preset.shadows.soft,
133
+ contactShadows: preset.shadows.contact,
134
+ namedRig: preset.lights
135
+ };
136
+
137
+ const outlineEnabled = style.outline;
138
+
139
+ let outline: OutlineResult | undefined;
140
+ let colorGrade: ColorGradeResult | undefined;
141
+
142
+ if (options.frame) {
143
+ const { pixels, width, height } = options.frame;
144
+ // 2. OUTLINE — real Sobel edge pass over the supplied frame.
145
+ let working = pixels;
146
+ if (outlineEnabled) {
147
+ outline = outlinePixels(working, width, height, {
148
+ // Warm storybook ink that reads against the night palette.
149
+ color: [24, 18, 12, 255],
150
+ width: 1,
151
+ threshold: 0.22,
152
+ opacity: 0.85
153
+ });
154
+ working = outline.pixels;
155
+ }
156
+ // 3. COLOR GRADE — stylized grade; reducedFlash trims saturation/contrast.
157
+ const punch = preset.reducedFlash ? 1 : 1.05;
158
+ colorGrade = colorGradePixels(working, width, height, {
159
+ contrast: punch,
160
+ saturation: 1 + style.saturationBoost,
161
+ vibrance: preset.reducedFlash ? 0.05 : 0.12,
162
+ vignette: 0.18
163
+ });
164
+ }
165
+
166
+ return {
167
+ kind: "animation-render-preset-application",
168
+ material,
169
+ materialStyle: style,
170
+ lighting,
171
+ outlineEnabled,
172
+ outline,
173
+ colorGrade,
174
+ appliedToPixels: {
175
+ toonMaterial: "returned-for-caller-assignment",
176
+ outline: outline !== undefined,
177
+ colorGrade: colorGrade !== undefined
178
+ }
179
+ };
180
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./AnimationMaterialStyle.js";
2
+ export * from "./AnimationRenderPreset.js";
3
+ export * from "./AnimationVisualQuality.js";
4
+ export * from "./AnimationToonMaterial.js";
5
+ export * from "./applyAnimationRenderPreset.js";
package/src/index.ts CHANGED
@@ -25,7 +25,7 @@ export { WebGL2Device } from "./WebGL2Device";
25
25
  export type { WebGL2DeviceOptions } from "./WebGL2Device";
26
26
  export { WebGL2StateCache } from "./WebGL2StateCache";
27
27
  export type { WebGL2StateCacheDescriptor, WebGL2StateCacheSnapshot, WebGL2StateCacheStats } from "./WebGL2StateCache";
28
- export { WebGPUDevice } from "./WebGPUDevice";
28
+ export { WebGPUDevice, MAX_WEBGPU_SKINNING_JOINTS } from "./WebGPUDevice";
29
29
  export type {
30
30
  WebGPUAdapterLike,
31
31
  WebGPUBufferDescriptorLike,
@@ -549,6 +549,14 @@ export type {
549
549
  } from "./RendererTiming";
550
550
  export { ForwardPass } from "./ForwardPass";
551
551
  export { MAX_GPU_INSTANCES, MAX_GPU_MORPH_TARGETS, MAX_GPU_MORPH_VERTICES } from "./ForwardPass";
552
+ export {
553
+ createMorphTargetPlan,
554
+ planMorphTargets,
555
+ DEFAULT_MORPH_DEVICE_LIMITS,
556
+ MORPH_UNIFORM_MAX_TARGETS,
557
+ MORPH_UNIFORM_MAX_VERTICES
558
+ } from "./MorphTargetPlan";
559
+ export type { MorphDeviceLimits, MorphPlanDecision, MorphPlanMode, MorphTargetPlan } from "./MorphTargetPlan";
552
560
  export type { EnvironmentLightingOptions, ForwardEnvironmentFogMode, ForwardEnvironmentFogOptions, ForwardPassOptions, ForwardShadowMapOptions, RenderItem, RenderItemDrawRange, RenderMaterial, SkinningPaletteBinding } from "./ForwardPass";
553
561
  export { batchStaticRenderItems, buildStaticBoundsBvh, queryStaticBoundsBvh, raycastStaticBoundsBvh, selectLodLevel, updateStaticBoundsBvh } from "./SceneOptimization";
554
562
  export type {
@@ -580,11 +588,13 @@ export type { StereoCameraRig, StereoCameraRigOptions, StereoEye, StereoEyeView,
580
588
  export { createAnaglyphCompositePlan, createAnaglyphPixelComposite, createParallaxBarrierInterleavePlan, createParallaxBarrierPixelComposite, createStereoEffectPlan } from "./StereoEffects";
581
589
  export * from "./cinematic/index";
582
590
  export type { AnaglyphCompositePlan, AnaglyphPixelComposite, AnaglyphPixelCompositeOptions, ParallaxBarrierInterleavePlan, ParallaxBarrierPixelComposite, ParallaxBarrierPixelCompositeOptions, StereoEffectMode, StereoEffectPlan, StereoEffectPlanOptions } from "./StereoEffects";
583
- export { analyzeRgbaFrameVisualMetrics, evaluateFrameVisualQuality } from "./FrameVisualMetrics";
591
+ export { analyzeRgbaFrameMotionRegions, analyzeRgbaFrameVisualMetrics, evaluateFrameVisualQuality } from "./FrameVisualMetrics";
584
592
  export type {
585
593
  FrameVisualBounds,
586
594
  FrameVisualMetrics,
587
595
  FrameVisualMetricsOptions,
596
+ FrameMotionRegion,
597
+ FrameMotionRegionMetrics,
588
598
  FrameVisualQualityResult,
589
599
  FrameVisualQualityThresholds
590
600
  } from "./FrameVisualMetrics";
@@ -912,3 +922,4 @@ export * from "./effects/GPUParticleBackend.js";
912
922
  export * from "./effects/ParticleSystem.js";
913
923
  export * from "./effects/ParticleEffectPresets.js";
914
924
  export * from "./effects/ParticleDiagnostics.js";
925
+ export * from "./animation/index.js";