reze-engine 0.11.1 → 0.11.3

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 (110) hide show
  1. package/dist/engine.d.ts +5 -3
  2. package/dist/engine.d.ts.map +1 -1
  3. package/dist/engine.js +72 -425
  4. package/dist/index.d.ts +1 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/shaders/body.d.ts +1 -1
  7. package/dist/shaders/body.d.ts.map +1 -1
  8. package/dist/shaders/body.js +27 -60
  9. package/dist/shaders/cloth_rough.d.ts +1 -1
  10. package/dist/shaders/cloth_rough.d.ts.map +1 -1
  11. package/dist/shaders/cloth_rough.js +4 -16
  12. package/dist/shaders/cloth_smooth.d.ts +1 -1
  13. package/dist/shaders/cloth_smooth.d.ts.map +1 -1
  14. package/dist/shaders/cloth_smooth.js +5 -17
  15. package/dist/shaders/default.d.ts +1 -1
  16. package/dist/shaders/default.d.ts.map +1 -1
  17. package/dist/shaders/default.js +20 -34
  18. package/dist/shaders/dfg_lut.d.ts +1 -1
  19. package/dist/shaders/dfg_lut.d.ts.map +1 -1
  20. package/dist/shaders/dfg_lut.js +1 -1
  21. package/dist/shaders/eye.d.ts +1 -1
  22. package/dist/shaders/eye.d.ts.map +1 -1
  23. package/dist/shaders/eye.js +22 -35
  24. package/dist/shaders/face.d.ts +1 -1
  25. package/dist/shaders/face.d.ts.map +1 -1
  26. package/dist/shaders/face.js +21 -57
  27. package/dist/shaders/hair.d.ts +1 -1
  28. package/dist/shaders/hair.d.ts.map +1 -1
  29. package/dist/shaders/hair.js +7 -27
  30. package/dist/shaders/materials/body.d.ts +2 -0
  31. package/dist/shaders/materials/body.d.ts.map +1 -0
  32. package/dist/shaders/materials/body.js +199 -0
  33. package/dist/shaders/materials/cloth_rough.d.ts +2 -0
  34. package/dist/shaders/materials/cloth_rough.d.ts.map +1 -0
  35. package/dist/shaders/materials/cloth_rough.js +178 -0
  36. package/dist/shaders/materials/cloth_smooth.d.ts +2 -0
  37. package/dist/shaders/materials/cloth_smooth.d.ts.map +1 -0
  38. package/dist/shaders/materials/cloth_smooth.js +174 -0
  39. package/dist/shaders/materials/default.d.ts +2 -0
  40. package/dist/shaders/materials/default.d.ts.map +1 -0
  41. package/dist/shaders/materials/default.js +171 -0
  42. package/dist/shaders/materials/eye.d.ts +2 -0
  43. package/dist/shaders/materials/eye.d.ts.map +1 -0
  44. package/dist/shaders/materials/eye.js +146 -0
  45. package/dist/shaders/materials/face.d.ts +2 -0
  46. package/dist/shaders/materials/face.d.ts.map +1 -0
  47. package/dist/shaders/materials/face.js +199 -0
  48. package/dist/shaders/materials/hair.d.ts +2 -0
  49. package/dist/shaders/materials/hair.d.ts.map +1 -0
  50. package/dist/shaders/materials/hair.js +176 -0
  51. package/dist/shaders/materials/metal.d.ts +2 -0
  52. package/dist/shaders/materials/metal.d.ts.map +1 -0
  53. package/dist/shaders/materials/metal.js +183 -0
  54. package/dist/shaders/materials/nodes.d.ts +2 -0
  55. package/dist/shaders/materials/nodes.d.ts.map +1 -0
  56. package/{src/shaders/nodes.ts → dist/shaders/materials/nodes.js} +32 -16
  57. package/dist/shaders/materials/stockings.d.ts +2 -0
  58. package/dist/shaders/materials/stockings.d.ts.map +1 -0
  59. package/dist/shaders/materials/stockings.js +244 -0
  60. package/dist/shaders/metal.d.ts +1 -1
  61. package/dist/shaders/metal.d.ts.map +1 -1
  62. package/dist/shaders/metal.js +4 -17
  63. package/dist/shaders/nodes.d.ts +1 -1
  64. package/dist/shaders/nodes.d.ts.map +1 -1
  65. package/dist/shaders/nodes.js +0 -9
  66. package/dist/shaders/passes/bloom.d.ts +4 -0
  67. package/dist/shaders/passes/bloom.d.ts.map +1 -0
  68. package/dist/shaders/passes/bloom.js +117 -0
  69. package/dist/shaders/passes/composite.d.ts +2 -0
  70. package/dist/shaders/passes/composite.d.ts.map +1 -0
  71. package/dist/shaders/passes/composite.js +61 -0
  72. package/dist/shaders/passes/ground.d.ts +2 -0
  73. package/dist/shaders/passes/ground.d.ts.map +1 -0
  74. package/dist/shaders/passes/ground.js +93 -0
  75. package/dist/shaders/passes/mipmap.d.ts +2 -0
  76. package/dist/shaders/passes/mipmap.d.ts.map +1 -0
  77. package/dist/shaders/passes/mipmap.js +16 -0
  78. package/dist/shaders/passes/outline.d.ts +2 -0
  79. package/dist/shaders/passes/outline.d.ts.map +1 -0
  80. package/dist/shaders/passes/outline.js +83 -0
  81. package/dist/shaders/passes/pick.d.ts +2 -0
  82. package/dist/shaders/passes/pick.d.ts.map +1 -0
  83. package/dist/shaders/passes/pick.js +39 -0
  84. package/dist/shaders/passes/shadow.d.ts +2 -0
  85. package/dist/shaders/passes/shadow.d.ts.map +1 -0
  86. package/dist/shaders/passes/shadow.js +16 -0
  87. package/dist/shaders/stockings.d.ts +1 -1
  88. package/dist/shaders/stockings.d.ts.map +1 -1
  89. package/package.json +2 -2
  90. package/src/engine.ts +112 -449
  91. package/src/index.ts +3 -2
  92. package/src/shaders/dfg_lut.ts +1 -1
  93. package/src/shaders/{body.ts → materials/body.ts} +27 -60
  94. package/src/shaders/{cloth_rough.ts → materials/cloth_rough.ts} +4 -16
  95. package/src/shaders/{cloth_smooth.ts → materials/cloth_smooth.ts} +5 -17
  96. package/src/shaders/{default.ts → materials/default.ts} +21 -34
  97. package/src/shaders/{eye.ts → materials/eye.ts} +23 -35
  98. package/src/shaders/{face.ts → materials/face.ts} +21 -57
  99. package/src/shaders/{hair.ts → materials/hair.ts} +7 -27
  100. package/src/shaders/{metal.ts → materials/metal.ts} +15 -19
  101. package/src/shaders/materials/nodes.ts +483 -0
  102. package/src/shaders/passes/bloom.ts +121 -0
  103. package/src/shaders/passes/composite.ts +62 -0
  104. package/src/shaders/passes/ground.ts +94 -0
  105. package/src/shaders/passes/mipmap.ts +17 -0
  106. package/src/shaders/passes/outline.ts +84 -0
  107. package/src/shaders/passes/pick.ts +40 -0
  108. package/src/shaders/passes/shadow.ts +17 -0
  109. package/src/shaders/classify.ts +0 -25
  110. /package/src/shaders/{stockings.ts → materials/stockings.ts} +0 -0
package/dist/engine.js CHANGED
@@ -3,18 +3,33 @@ import { Mat4, Vec3 } from "./math";
3
3
  import { PmxLoader } from "./pmx-loader";
4
4
  import { Physics } from "./physics";
5
5
  import { createFetchAssetReader, createFileMapAssetReader, deriveBasePathFromPmxPath, fileListToMap, findFirstPmxFileInList, joinAssetPath, normalizeAssetPath, } from "./asset-reader";
6
- import { DEFAULT_SHADER_WGSL } from "./shaders/default";
6
+ import { DEFAULT_SHADER_WGSL } from "./shaders/materials/default";
7
+ import { FACE_SHADER_WGSL } from "./shaders/materials/face";
8
+ import { HAIR_SHADER_WGSL } from "./shaders/materials/hair";
9
+ import { CLOTH_SMOOTH_SHADER_WGSL } from "./shaders/materials/cloth_smooth";
10
+ import { CLOTH_ROUGH_SHADER_WGSL } from "./shaders/materials/cloth_rough";
11
+ import { METAL_SHADER_WGSL } from "./shaders/materials/metal";
12
+ import { BODY_SHADER_WGSL } from "./shaders/materials/body";
13
+ import { EYE_SHADER_WGSL } from "./shaders/materials/eye";
14
+ import { STOCKINGS_SHADER_WGSL } from "./shaders/materials/stockings";
7
15
  import { BRDF_LUT_SIZE, BRDF_LUT_BAKE_WGSL } from "./shaders/dfg_lut";
8
16
  import { LTC_MAG_LUT_SIZE, LTC_MAG_LUT_DATA } from "./shaders/ltc_mag_lut";
9
- import { FACE_SHADER_WGSL } from "./shaders/face";
10
- import { HAIR_SHADER_WGSL } from "./shaders/hair";
11
- import { CLOTH_SMOOTH_SHADER_WGSL } from "./shaders/cloth_smooth";
12
- import { CLOTH_ROUGH_SHADER_WGSL } from "./shaders/cloth_rough";
13
- import { METAL_SHADER_WGSL } from "./shaders/metal";
14
- import { BODY_SHADER_WGSL } from "./shaders/body";
15
- import { EYE_SHADER_WGSL } from "./shaders/eye";
16
- import { STOCKINGS_SHADER_WGSL } from "./shaders/stockings";
17
- import { resolvePreset } from "./shaders/classify";
17
+ import { SHADOW_DEPTH_SHADER_WGSL } from "./shaders/passes/shadow";
18
+ import { GROUND_SHADOW_SHADER_WGSL } from "./shaders/passes/ground";
19
+ import { OUTLINE_SHADER_WGSL } from "./shaders/passes/outline";
20
+ import { BLOOM_BLIT_SHADER_WGSL, BLOOM_DOWNSAMPLE_SHADER_WGSL, BLOOM_UPSAMPLE_SHADER_WGSL, } from "./shaders/passes/bloom";
21
+ import { COMPOSITE_SHADER_WGSL } from "./shaders/passes/composite";
22
+ import { PICK_SHADER_WGSL } from "./shaders/passes/pick";
23
+ import { MIPMAP_BLIT_SHADER_WGSL } from "./shaders/passes/mipmap";
24
+ function resolvePreset(materialName, map) {
25
+ if (!map)
26
+ return "default";
27
+ for (const [preset, names] of Object.entries(map)) {
28
+ if (names && names.includes(materialName))
29
+ return preset;
30
+ }
31
+ return "default";
32
+ }
18
33
  export const DEFAULT_BLOOM_OPTIONS = {
19
34
  enabled: true,
20
35
  threshold: 0.5,
@@ -24,8 +39,10 @@ export const DEFAULT_BLOOM_OPTIONS = {
24
39
  intensity: 0.05,
25
40
  clamp: 0.0,
26
41
  };
42
+ // Matches the reference Blender project: Filmic view, Medium High Contrast look,
43
+ // exposure 0.3, gamma 1.0, sRGB display, no curves.
27
44
  export const DEFAULT_VIEW_TRANSFORM = {
28
- exposure: -0.30000001192092896,
45
+ exposure: 0.6,
29
46
  gamma: 1.0,
30
47
  look: "medium_high_contrast",
31
48
  };
@@ -48,7 +65,7 @@ export class Engine {
48
65
  this.lightData = new Float32Array(64);
49
66
  this.lightCount = 0;
50
67
  this.resizeObserver = null;
51
- // [exposure, gamma, _, _, bloomTint.x, bloomTint.y, bloomTint.z, bloomIntensity]
68
+ // [exposure, invGamma, _, _, bloomTint.x, bloomTint.y, bloomTint.z, bloomIntensity]
52
69
  this.compositeUniformData = new Float32Array(8);
53
70
  this.bloomBlitUniformData = new Float32Array(4);
54
71
  this.bloomUpsampleUniformData = new Float32Array(4);
@@ -198,7 +215,10 @@ export class Engine {
198
215
  const effIntensity = b.enabled ? b.intensity : 0.0;
199
216
  const u = this.compositeUniformData;
200
217
  u[0] = v.exposure;
201
- u[1] = Math.max(v.gamma, 1e-4);
218
+ // Store 1/gamma so the shader avoids a per-pixel divide. Safari's Metal
219
+ // compiler doesn't fold `pow(x, 1/g)` into identity when g=1, so also emit
220
+ // a uniform branch that skips the pow entirely in the common case.
221
+ u[1] = 1.0 / Math.max(v.gamma, 1e-4);
202
222
  u[2] = 0.0;
203
223
  u[3] = 0.0;
204
224
  u[4] = b.color.x;
@@ -236,9 +256,12 @@ export class Engine {
236
256
  writeBloomUniforms() {
237
257
  const b = this.bloomSettings;
238
258
  const bu = this.bloomBlitUniformData;
239
- // EEVEE prefilter: threshold, knee, clamp (0 → disabled), _unused
259
+ // EEVEE prefilter: threshold, knee_half, clamp (0 → disabled), _unused
260
+ // Blender halves the knee before passing to the shader (eevee_bloom.c: knee * 0.5f).
261
+ // The blit shader's quadratic soft-knee curve uses knee_half as the offset from threshold,
262
+ // so the soft ramp spans [threshold - knee/2 .. threshold + knee/2] — NOT [threshold - knee .. threshold + knee].
240
263
  bu[0] = b.threshold;
241
- bu[1] = b.knee;
264
+ bu[1] = b.knee * 0.5;
242
265
  bu[2] = b.clamp;
243
266
  bu[3] = 0.0;
244
267
  this.device.queue.writeBuffer(this.bloomBlitUniformBuffer, 0, bu);
@@ -635,21 +658,7 @@ export class Engine {
635
658
  });
636
659
  const shadowShader = this.device.createShaderModule({
637
660
  label: "shadow depth",
638
- code: /* wgsl */ `
639
- struct LightVP { viewProj: mat4x4f, };
640
- @group(0) @binding(0) var<uniform> lp: LightVP;
641
- @group(0) @binding(1) var<storage, read> skinMats: array<mat4x4f>;
642
- @vertex fn vs(@location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f,
643
- @location(3) joints0: vec4<u32>, @location(4) weights0: vec4<f32>) -> @builtin(position) vec4f {
644
- let pos4 = vec4f(position, 1.0);
645
- let ws = weights0.x + weights0.y + weights0.z + weights0.w;
646
- let inv = select(1.0, 1.0 / ws, ws > 0.0001);
647
- let nw = select(vec4f(1.0,0.0,0.0,0.0), weights0 * inv, ws > 0.0001);
648
- var sp = vec4f(0.0);
649
- for (var i = 0u; i < 4u; i++) { sp += (skinMats[joints0[i]] * pos4) * nw[i]; }
650
- return lp.viewProj * vec4f(sp.xyz, 1.0);
651
- }
652
- `,
661
+ code: SHADOW_DEPTH_SHADER_WGSL,
653
662
  });
654
663
  this.shadowDepthPipeline = this.device.createRenderPipeline({
655
664
  label: "shadow depth pipeline",
@@ -706,99 +715,7 @@ export class Engine {
706
715
  });
707
716
  const groundShadowShader = this.device.createShaderModule({
708
717
  label: "ground shadow",
709
- code: /* wgsl */ `
710
- struct CameraUniforms { view: mat4x4f, projection: mat4x4f, viewPos: vec3f, _p: f32, };
711
- struct Light { direction: vec4f, color: vec4f, };
712
- struct LightUniforms { ambientColor: vec4f, lights: array<Light, 4>, };
713
- struct GroundShadowMat {
714
- diffuseColor: vec3f, fadeStart: f32,
715
- fadeEnd: f32, shadowStrength: f32, pcfTexel: f32, gridSpacing: f32,
716
- gridLineWidth: f32, gridLineOpacity: f32, noiseStrength: f32, _pad: f32,
717
- gridLineColor: vec3f, _pad2: f32,
718
- };
719
- struct LightVP { viewProj: mat4x4f, };
720
- @group(0) @binding(0) var<uniform> camera: CameraUniforms;
721
- @group(0) @binding(1) var<uniform> light: LightUniforms;
722
- @group(0) @binding(2) var shadowMap: texture_depth_2d;
723
- @group(0) @binding(3) var shadowSampler: sampler_comparison;
724
- @group(0) @binding(4) var<uniform> material: GroundShadowMat;
725
- @group(0) @binding(5) var<uniform> lightVP: LightVP;
726
-
727
- // Hash-based noise for frosted/matte surface
728
- fn hash2(p: vec2f) -> f32 {
729
- var p3 = fract(vec3f(p.x, p.y, p.x) * 0.1031);
730
- p3 += dot(p3, vec3f(p3.y + 33.33, p3.z + 33.33, p3.x + 33.33));
731
- return fract((p3.x + p3.y) * p3.z);
732
- }
733
- fn valueNoise(p: vec2f) -> f32 {
734
- let i = floor(p);
735
- let f = fract(p);
736
- let u = f * f * (3.0 - 2.0 * f);
737
- return mix(mix(hash2(i), hash2(i + vec2f(1.0, 0.0)), u.x),
738
- mix(hash2(i + vec2f(0.0, 1.0)), hash2(i + vec2f(1.0, 1.0)), u.x), u.y);
739
- }
740
- fn fbmNoise(p: vec2f) -> f32 {
741
- var v = 0.0;
742
- var a = 0.5;
743
- var pp = p;
744
- for (var i = 0; i < 4; i++) {
745
- v += a * valueNoise(pp);
746
- pp *= 2.0;
747
- a *= 0.5;
748
- }
749
- return v;
750
- }
751
-
752
- struct VO { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, };
753
- @vertex fn vs(@location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f) -> VO {
754
- var o: VO; o.worldPos = position; o.normal = normal;
755
- o.position = camera.projection * camera.view * vec4f(position, 1.0); return o;
756
- }
757
- struct FSOut { @location(0) color: vec4f, @location(1) mask: f32 };
758
- @fragment fn fs(i: VO) -> FSOut {
759
- let n = normalize(i.normal);
760
- let centerDist = length(i.worldPos.xz);
761
- let edgeFade = 1.0 - smoothstep(0.0, 1.0, clamp((centerDist - material.fadeStart) / max(material.fadeEnd - material.fadeStart, 0.001), 0.0, 1.0));
762
-
763
- // Shadow sampling
764
- let lclip = lightVP.viewProj * vec4f(i.worldPos, 1.0);
765
- let ndc = lclip.xyz / max(lclip.w, 1e-6);
766
- let suv = vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);
767
- let suv_c = clamp(suv, vec2f(0.02), vec2f(0.98));
768
- let st = material.pcfTexel;
769
- let compareZ = ndc.z - 0.0035;
770
- var vis = 0.0;
771
- for (var y = -2; y <= 2; y++) {
772
- for (var x = -2; x <= 2; x++) {
773
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(f32(x), f32(y)) * st, compareZ);
774
- }
775
- }
776
- vis *= 0.04;
777
-
778
- // Frosted/matte micro-texture (磨砂)
779
- let noiseVal = fbmNoise(i.worldPos.xz * 3.0);
780
- let noiseTint = 1.0 + (noiseVal - 0.5) * material.noiseStrength;
781
-
782
- // Grid lines — anti-aliased via screen-space derivatives
783
- let gp = i.worldPos.xz / material.gridSpacing;
784
- let gridFrac = abs(fract(gp - 0.5) - 0.5);
785
- let gridDeriv = fwidth(gp);
786
- let halfLine = material.gridLineWidth * 0.5;
787
- let gridLine = 1.0 - min(
788
- smoothstep(halfLine - gridDeriv.x, halfLine + gridDeriv.x, gridFrac.x),
789
- smoothstep(halfLine - gridDeriv.y, halfLine + gridDeriv.y, gridFrac.y)
790
- );
791
- let sun = light.ambientColor.xyz + light.lights[0].color.xyz * light.lights[0].color.w * max(dot(n, -light.lights[0].direction.xyz), 0.0);
792
- let dark = (1.0 - vis) * material.shadowStrength;
793
- var baseColor = material.diffuseColor * sun * (1.0 - dark * 0.65);
794
- baseColor *= noiseTint;
795
- let finalColor = mix(baseColor, material.gridLineColor, gridLine * material.gridLineOpacity * edgeFade);
796
- var out: FSOut;
797
- out.color = vec4f(finalColor * edgeFade, edgeFade);
798
- out.mask = 0.0;
799
- return out;
800
- }
801
- `,
718
+ code: GROUND_SHADOW_SHADER_WGSL,
802
719
  });
803
720
  this.groundShadowPipeline = this.createRenderPipeline({
804
721
  label: "ground shadow pipeline",
@@ -838,90 +755,7 @@ export class Engine {
838
755
  });
839
756
  const outlineShaderModule = this.device.createShaderModule({
840
757
  label: "outline shaders",
841
- code: /* wgsl */ `
842
- struct CameraUniforms {
843
- view: mat4x4f,
844
- projection: mat4x4f,
845
- viewPos: vec3f,
846
- _padding: f32,
847
- };
848
-
849
- struct MaterialUniforms {
850
- edgeColor: vec4f,
851
- edgeSize: f32,
852
- _padding1: f32,
853
- _padding2: f32,
854
- _padding3: f32,
855
- };
856
-
857
- // group 0: per-frame
858
- @group(0) @binding(0) var<uniform> camera: CameraUniforms;
859
- // group 1: per-instance
860
- @group(1) @binding(0) var<storage, read> skinMats: array<mat4x4f>;
861
- // group 2: per-material
862
- @group(2) @binding(0) var<uniform> material: MaterialUniforms;
863
-
864
- struct VertexOutput {
865
- @builtin(position) position: vec4f,
866
- };
867
-
868
- @vertex fn vs(
869
- @location(0) position: vec3f,
870
- @location(1) normal: vec3f,
871
- @location(3) joints0: vec4<u32>,
872
- @location(4) weights0: vec4<f32>
873
- ) -> VertexOutput {
874
- var output: VertexOutput;
875
- let pos4 = vec4f(position, 1.0);
876
-
877
- let weightSum = weights0.x + weights0.y + weights0.z + weights0.w;
878
- let invWeightSum = select(1.0, 1.0 / weightSum, weightSum > 0.0001);
879
- let normalizedWeights = select(vec4f(1.0, 0.0, 0.0, 0.0), weights0 * invWeightSum, weightSum > 0.0001);
880
-
881
- var skinnedPos = vec4f(0.0, 0.0, 0.0, 0.0);
882
- var skinnedNrm = vec3f(0.0, 0.0, 0.0);
883
- for (var i = 0u; i < 4u; i++) {
884
- let j = joints0[i];
885
- let w = normalizedWeights[i];
886
- let m = skinMats[j];
887
- skinnedPos += (m * pos4) * w;
888
- let r3 = mat3x3f(m[0].xyz, m[1].xyz, m[2].xyz);
889
- skinnedNrm += (r3 * normal) * w;
890
- }
891
- let worldPos = skinnedPos.xyz;
892
- let worldNormal = normalize(skinnedNrm);
893
-
894
- // Screen-space outline extrusion — MMD-style pixel-stable edge line.
895
- // 1. Project position and normal-as-direction to clip space.
896
- // 2. Normalize the 2D clip-space normal, aspect-compensated so "one pixel horizontally"
897
- // matches "one pixel vertically" (otherwise wide viewports squash the outline in X).
898
- // 3. Offset clip-space xy by (normal * edgeSize * edgeScale), then multiply by w
899
- // so the perspective divide cancels out → offset stays constant in NDC regardless
900
- // of depth, matching how MMD / babylon-mmd style outlines look identical when zooming.
901
- // 4. edgeScale is in NDC-y units per PMX edgeSize. ≈ 0.006 gives ~3px at 1080p; it's
902
- // tied to viewport HEIGHT so resizing the window keeps pixel thickness stable.
903
- let viewProj = camera.projection * camera.view;
904
- let clipPos = viewProj * vec4f(worldPos, 1.0);
905
- let clipNormal = (viewProj * vec4f(worldNormal, 0.0)).xy;
906
- // projection is column-major: proj[0][0] = 1/(aspect·tan(fov/2)), proj[1][1] = 1/tan(fov/2).
907
- // Ratio proj[1][1]/proj[0][0] recovers the viewport aspect (width/height).
908
- let aspect = camera.projection[1][1] / camera.projection[0][0];
909
- let pixelDir = normalize(vec2f(clipNormal.x * aspect, clipNormal.y));
910
- let ndcDir = vec2f(pixelDir.x / aspect, pixelDir.y);
911
- let edgeScale = 0.0016;
912
- let offset = ndcDir * material.edgeSize * edgeScale * clipPos.w;
913
- output.position = vec4f(clipPos.xy + offset, clipPos.z, clipPos.w);
914
- return output;
915
- }
916
-
917
- struct FSOut { @location(0) color: vec4f, @location(1) mask: f32 };
918
- @fragment fn fs() -> FSOut {
919
- var out: FSOut;
920
- out.color = material.edgeColor;
921
- out.mask = 1.0;
922
- return out;
923
- }
924
- `,
758
+ code: OUTLINE_SHADER_WGSL,
925
759
  });
926
760
  this.outlinePipeline = this.createRenderPipeline({
927
761
  label: "outline pipeline",
@@ -982,130 +816,22 @@ export class Engine {
982
816
  { binding: 3, visibility: GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
983
817
  ],
984
818
  });
985
- const bloomFullscreenVs = /* wgsl */ `
986
- @vertex fn vs(@builtin(vertex_index) vi: u32) -> @builtin(position) vec4f {
987
- let x = f32((vi & 1u) << 2u) - 1.0;
988
- let y = f32((vi & 2u) << 1u) - 1.0;
989
- return vec4f(x, y, 0.0, 1.0);
990
- }
991
- `;
992
- // Blit: full-res HDR → half-res. Karis 4-tap firefly average + EEVEE quadratic knee threshold + clamp.
993
819
  const bloomBlitShader = this.device.createShaderModule({
994
820
  label: "bloom blit (Karis prefilter)",
995
- code: `${bloomFullscreenVs}
996
- @group(0) @binding(0) var hdrTex: texture_2d<f32>;
997
- @group(0) @binding(1) var<uniform> prefilter: vec4<f32>; // threshold, knee, clamp, _unused
998
- @group(0) @binding(2) var maskTex: texture_2d<f32>;
999
-
1000
- fn luminance(c: vec3f) -> f32 {
1001
- return dot(max(c, vec3f(0.0)), vec3f(0.2126, 0.7152, 0.0722));
1002
- }
1003
- fn fetch(c: vec2<i32>, clampV: f32) -> vec3f {
1004
- let d = vec2<i32>(textureDimensions(hdrTex));
1005
- let cc = clamp(c, vec2<i32>(0), d - vec2<i32>(1));
1006
- let s = textureLoad(hdrTex, cc, 0);
1007
- // Scene pass uses src-alpha blend with clear alpha 0 → premultiplied. Unpremultiply.
1008
- let rgb = max(s.rgb / max(s.a, 1e-6), vec3f(0.0));
1009
- // Bloom mask: MRT r8unorm written by material shaders (1.0 = bloom, 0.0 = skip).
1010
- let mask = textureLoad(maskTex, cc, 0).r;
1011
- let masked = rgb * mask;
1012
- // Blender: clamp each tap BEFORE Karis average (eevee_bloom: color = min(clampIntensity, color)).
1013
- return select(masked, min(masked, vec3f(clampV)), clampV > 0.0);
1014
- }
1015
-
1016
- @fragment fn fs(@builtin(position) p: vec4f) -> @location(0) vec4f {
1017
- let dst = vec2<i32>(p.xy - vec2f(0.5));
1018
- let base = dst * 2;
1019
- let clampV = prefilter.z;
1020
- let a = fetch(base + vec2<i32>(0, 0), clampV);
1021
- let b = fetch(base + vec2<i32>(1, 0), clampV);
1022
- let c = fetch(base + vec2<i32>(0, 1), clampV);
1023
- let d = fetch(base + vec2<i32>(1, 1), clampV);
1024
- // Karis partial average: weight each tap by 1/(1+luma) — suppresses fireflies.
1025
- let wa = 1.0 / (1.0 + luminance(a));
1026
- let wb = 1.0 / (1.0 + luminance(b));
1027
- let wc = 1.0 / (1.0 + luminance(c));
1028
- let wd = 1.0 / (1.0 + luminance(d));
1029
- let avg = (a * wa + b * wb + c * wc + d * wd) / max(wa + wb + wc + wd, 1e-6);
1030
- // EEVEE quadratic threshold (brightness = max-channel, then soft-knee curve).
1031
- let bright = max(avg.r, max(avg.g, avg.b));
1032
- let soft = clamp(bright - prefilter.x + prefilter.y, 0.0, 2.0 * prefilter.y);
1033
- let q = (soft * soft) / (4.0 * max(prefilter.y, 1e-4) + 1e-6);
1034
- let contrib = max(q, bright - prefilter.x) / max(bright, 1e-4);
1035
- return vec4f(max(avg * contrib, vec3f(0.0)), 1.0);
1036
- }
1037
- `,
821
+ code: BLOOM_BLIT_SHADER_WGSL,
1038
822
  });
1039
- // Downsample: Jimenez/COD 13-tap dual-box — 5 weighted 2×2 averages, rejects nyquist ringing.
1040
823
  const bloomDownsampleShader = this.device.createShaderModule({
1041
824
  label: "bloom downsample 13-tap",
1042
- code: `${bloomFullscreenVs}
1043
- @group(0) @binding(0) var srcTex: texture_2d<f32>;
1044
- @group(0) @binding(1) var srcSamp: sampler;
1045
-
1046
- fn samp(uv: vec2f, off: vec2f) -> vec3f {
1047
- return textureSampleLevel(srcTex, srcSamp, uv + off, 0.0).rgb;
1048
- }
1049
-
1050
- @fragment fn fs(@builtin(position) p: vec4f) -> @location(0) vec4f {
1051
- let srcDims = vec2f(textureDimensions(srcTex));
1052
- let t = 1.0 / srcDims;
1053
- // fragCoord.xy reports pixel centers (e.g. 0.5,0.5 for first pixel) — divide by dst dims directly.
1054
- let dstDims = srcDims * 0.5;
1055
- let uv = p.xy / max(dstDims, vec2f(1.0));
1056
- let A = samp(uv, t * vec2f(-2.0, -2.0));
1057
- let B = samp(uv, t * vec2f( 0.0, -2.0));
1058
- let C = samp(uv, t * vec2f( 2.0, -2.0));
1059
- let D = samp(uv, t * vec2f(-1.0, -1.0));
1060
- let E = samp(uv, t * vec2f( 1.0, -1.0));
1061
- let F = samp(uv, t * vec2f(-2.0, 0.0));
1062
- let G = samp(uv, t * vec2f( 0.0, 0.0));
1063
- let H = samp(uv, t * vec2f( 2.0, 0.0));
1064
- let I = samp(uv, t * vec2f(-1.0, 1.0));
1065
- let J = samp(uv, t * vec2f( 1.0, 1.0));
1066
- let K = samp(uv, t * vec2f(-2.0, 2.0));
1067
- let L = samp(uv, t * vec2f( 0.0, 2.0));
1068
- let M = samp(uv, t * vec2f( 2.0, 2.0));
1069
- var o = (D + E + I + J) * (0.5 / 4.0);
1070
- o = o + (A + B + G + F) * (0.125 / 4.0);
1071
- o = o + (B + C + H + G) * (0.125 / 4.0);
1072
- o = o + (F + G + L + K) * (0.125 / 4.0);
1073
- o = o + (G + H + M + L) * (0.125 / 4.0);
1074
- return vec4f(o, 1.0);
1075
- }
1076
- `,
825
+ code: BLOOM_DOWNSAMPLE_SHADER_WGSL,
1077
826
  });
1078
- // Upsample: 9-tap tent, progressively added to matching downsample mip. Blender radius = sample scale.
1079
827
  const bloomUpsampleShader = this.device.createShaderModule({
1080
828
  label: "bloom upsample 9-tap tent",
1081
- code: `${bloomFullscreenVs}
1082
- @group(0) @binding(0) var srcTex: texture_2d<f32>; // coarser accumulator
1083
- @group(0) @binding(1) var baseTex: texture_2d<f32>; // matching downsample mip
1084
- @group(0) @binding(2) var srcSamp: sampler;
1085
- @group(0) @binding(3) var<uniform> upU: vec4<f32>; // sampleScale, _, _, _
1086
-
1087
- @fragment fn fs(@builtin(position) p: vec4f) -> @location(0) vec4f {
1088
- let srcDims = vec2f(textureDimensions(srcTex));
1089
- let baseDims = vec2f(textureDimensions(baseTex));
1090
- let uv = p.xy / max(baseDims, vec2f(1.0));
1091
- let t = upU.x / srcDims;
1092
- var o = textureSampleLevel(srcTex, srcSamp, uv + t * vec2f(-1.0, -1.0), 0.0).rgb * 1.0;
1093
- o = o + textureSampleLevel(srcTex, srcSamp, uv + t * vec2f( 0.0, -1.0), 0.0).rgb * 2.0;
1094
- o = o + textureSampleLevel(srcTex, srcSamp, uv + t * vec2f( 1.0, -1.0), 0.0).rgb * 1.0;
1095
- o = o + textureSampleLevel(srcTex, srcSamp, uv + t * vec2f(-1.0, 0.0), 0.0).rgb * 2.0;
1096
- o = o + textureSampleLevel(srcTex, srcSamp, uv + t * vec2f( 0.0, 0.0), 0.0).rgb * 4.0;
1097
- o = o + textureSampleLevel(srcTex, srcSamp, uv + t * vec2f( 1.0, 0.0), 0.0).rgb * 2.0;
1098
- o = o + textureSampleLevel(srcTex, srcSamp, uv + t * vec2f(-1.0, 1.0), 0.0).rgb * 1.0;
1099
- o = o + textureSampleLevel(srcTex, srcSamp, uv + t * vec2f( 0.0, 1.0), 0.0).rgb * 2.0;
1100
- o = o + textureSampleLevel(srcTex, srcSamp, uv + t * vec2f( 1.0, 1.0), 0.0).rgb * 1.0;
1101
- o = o * (1.0 / 16.0);
1102
- let base = textureSampleLevel(baseTex, srcSamp, uv, 0.0).rgb;
1103
- return vec4f(o + base, 1.0);
1104
- }
1105
- `,
829
+ code: BLOOM_UPSAMPLE_SHADER_WGSL,
1106
830
  });
1107
831
  const bloomBlitLayout = this.device.createPipelineLayout({ bindGroupLayouts: [this.bloomBlitBindGroupLayout] });
1108
- const bloomDownLayout = this.device.createPipelineLayout({ bindGroupLayouts: [this.bloomDownsampleBindGroupLayout] });
832
+ const bloomDownLayout = this.device.createPipelineLayout({
833
+ bindGroupLayouts: [this.bloomDownsampleBindGroupLayout],
834
+ });
1109
835
  const bloomUpLayout = this.device.createPipelineLayout({ bindGroupLayouts: [this.bloomUpsampleBindGroupLayout] });
1110
836
  this.bloomBlitPipeline = this.device.createRenderPipeline({
1111
837
  label: "bloom blit pipeline",
@@ -1147,61 +873,25 @@ export class Engine {
1147
873
  });
1148
874
  const compositeShader = this.device.createShaderModule({
1149
875
  label: "composite shader",
1150
- code: /* wgsl */ `
1151
- @group(0) @binding(0) var hdrTex: texture_2d<f32>;
1152
- @group(0) @binding(1) var bloomTex: texture_2d<f32>; // bloomUpTexture mip 0 (full pyramid top)
1153
- @group(0) @binding(2) var bloomSamp: sampler;
1154
- @group(0) @binding(3) var<uniform> viewU: array<vec4<f32>, 2>;
1155
- // viewU[0] = (exposure, gamma, _, _); viewU[1] = (tint.rgb, intensity)
1156
-
1157
- fn filmic(x: f32) -> f32 {
1158
- var lut = array<f32, 14>(
1159
- 0.0067, 0.0141, 0.0272, 0.0499, 0.0885, 0.1512, 0.2462,
1160
- 0.3753, 0.5273, 0.6776, 0.8031, 0.8929, 0.9495, 0.9814
1161
- );
1162
- let t = clamp(log2(max(x, 1e-10)) + 10.0, 0.0, 13.0);
1163
- let i = u32(t);
1164
- let j = min(i + 1u, 13u);
1165
- return mix(lut[i], lut[j], t - f32(i));
1166
- }
1167
-
1168
- @vertex fn vs(@builtin(vertex_index) vi: u32) -> @builtin(position) vec4f {
1169
- let x = f32((vi & 1u) << 2u) - 1.0;
1170
- let y = f32((vi & 2u) << 1u) - 1.0;
1171
- return vec4f(x, y, 0.0, 1.0);
1172
- }
1173
-
1174
- @fragment fn fs(@builtin(position) fragCoord: vec4f) -> @location(0) vec4f {
1175
- let hdr = textureLoad(hdrTex, vec2<i32>(fragCoord.xy), 0);
1176
- let a = max(hdr.a, 1e-6);
1177
- let straight = hdr.rgb / a;
1178
- let fullSz = vec2f(textureDimensions(hdrTex));
1179
- let bloomSz = vec2f(textureDimensions(bloomTex));
1180
- // Bloom is at half-res (pyramid mip 0). Sampler interpolates back to full-res UVs.
1181
- let bloomUv = (fragCoord.xy + vec2f(0.5)) / max(fullSz, vec2f(1.0));
1182
- let tint = viewU[1].xyz;
1183
- let intensity = viewU[1].w;
1184
- let bloom = textureSampleLevel(bloomTex, bloomSamp, bloomUv, 0.0).rgb * tint * intensity;
1185
- let combined = straight + bloom;
1186
- let exposed = combined * exp2(viewU[0].x);
1187
- let tm = vec3f(filmic(exposed.r), filmic(exposed.g), filmic(exposed.b));
1188
- let g = max(viewU[0].y, 1e-4);
1189
- let disp = pow(max(tm, vec3f(0.0)), vec3f(1.0 / g));
1190
- return vec4f(disp * hdr.a, hdr.a);
1191
- }
1192
- `,
876
+ code: COMPOSITE_SHADER_WGSL,
877
+ });
878
+ const compositePipelineLayout = this.device.createPipelineLayout({
879
+ bindGroupLayouts: [this.compositeBindGroupLayout],
1193
880
  });
1194
- this.compositePipeline = this.device.createRenderPipeline({
1195
- label: "composite pipeline",
1196
- layout: this.device.createPipelineLayout({ bindGroupLayouts: [this.compositeBindGroupLayout] }),
881
+ const makeCompositePipeline = (applyGamma, label) => this.device.createRenderPipeline({
882
+ label,
883
+ layout: compositePipelineLayout,
1197
884
  vertex: { module: compositeShader, entryPoint: "vs" },
1198
885
  fragment: {
1199
886
  module: compositeShader,
1200
887
  entryPoint: "fs",
888
+ constants: { APPLY_GAMMA: applyGamma ? 1 : 0 },
1201
889
  targets: [{ format: this.presentationFormat }],
1202
890
  },
1203
891
  primitive: { topology: "triangle-list" },
1204
892
  });
893
+ this.compositePipelineIdentity = makeCompositePipeline(false, "composite pipeline (gamma=1)");
894
+ this.compositePipelineGamma = makeCompositePipeline(true, "composite pipeline (gamma!=1)");
1205
895
  this.bloomPassDescriptor = {
1206
896
  label: "bloom pass",
1207
897
  colorAttachments: [
@@ -1213,47 +903,9 @@ export class Engine {
1213
903
  },
1214
904
  ],
1215
905
  };
1216
- // GPU picking: encode (modelIndex, materialIndex) as color
1217
906
  const pickShaderModule = this.device.createShaderModule({
1218
907
  label: "pick shader",
1219
- code: /* wgsl */ `
1220
- struct CameraUniforms {
1221
- view: mat4x4f,
1222
- projection: mat4x4f,
1223
- viewPos: vec3f,
1224
- _padding: f32,
1225
- };
1226
- struct PickId {
1227
- modelId: f32,
1228
- materialId: f32,
1229
- _p1: f32,
1230
- _p2: f32,
1231
- };
1232
-
1233
- @group(0) @binding(0) var<uniform> camera: CameraUniforms;
1234
- @group(1) @binding(0) var<storage, read> skinMats: array<mat4x4f>;
1235
- @group(2) @binding(0) var<uniform> pickId: PickId;
1236
-
1237
- @vertex fn vs(
1238
- @location(0) position: vec3f,
1239
- @location(1) normal: vec3f,
1240
- @location(2) uv: vec2f,
1241
- @location(3) joints0: vec4<u32>,
1242
- @location(4) weights0: vec4<f32>
1243
- ) -> @builtin(position) vec4f {
1244
- let pos4 = vec4f(position, 1.0);
1245
- let weightSum = weights0.x + weights0.y + weights0.z + weights0.w;
1246
- let invWeightSum = select(1.0, 1.0 / weightSum, weightSum > 0.0001);
1247
- let nw = select(vec4f(1.0, 0.0, 0.0, 0.0), weights0 * invWeightSum, weightSum > 0.0001);
1248
- var sp = vec4f(0.0);
1249
- for (var i = 0u; i < 4u; i++) { sp += (skinMats[joints0[i]] * pos4) * nw[i]; }
1250
- return camera.projection * camera.view * vec4f(sp.xyz, 1.0);
1251
- }
1252
-
1253
- @fragment fn fs() -> @location(0) vec4f {
1254
- return vec4f(pickId.modelId / 255.0, pickId.materialId / 255.0, 0.0, 1.0);
1255
- }
1256
- `,
908
+ code: PICK_SHADER_WGSL,
1257
909
  });
1258
910
  this.pickPerFrameBindGroupLayout = this.device.createBindGroupLayout({
1259
911
  label: "pick per-frame layout",
@@ -1387,19 +1039,23 @@ export class Engine {
1387
1039
  usage: GPUTextureUsage.RENDER_ATTACHMENT,
1388
1040
  });
1389
1041
  const depthTextureView = this.depthTexture.createView();
1042
+ // storeOp="discard" on MSAA views keeps per-sample data in Apple TBDR tile memory —
1043
+ // only the resolveTarget (hdrResolveTexture / maskResolveView) gets written to RAM.
1044
+ // With storeOp="store" Safari's Metal backend spills the full MS buffer every frame
1045
+ // (rgba16f × 4 samples on a 4K canvas ≈ 256 MB/frame of dead bandwidth).
1390
1046
  const colorAttachment = {
1391
1047
  view: this.multisampleTexture.createView(),
1392
1048
  resolveTarget: this.hdrResolveTexture.createView(),
1393
1049
  clearValue: { r: 0, g: 0, b: 0, a: 0 },
1394
1050
  loadOp: "clear",
1395
- storeOp: "store",
1051
+ storeOp: "discard",
1396
1052
  };
1397
1053
  const maskAttachment = {
1398
1054
  view: this.multisampleMaskTexture.createView(),
1399
1055
  resolveTarget: this.maskResolveView,
1400
1056
  clearValue: { r: 0, g: 0, b: 0, a: 0 },
1401
1057
  loadOp: "clear",
1402
- storeOp: "store",
1058
+ storeOp: "discard",
1403
1059
  };
1404
1060
  this.renderPassDescriptor = {
1405
1061
  label: "renderPass",
@@ -1408,7 +1064,8 @@ export class Engine {
1408
1064
  view: depthTextureView,
1409
1065
  depthClearValue: 1.0,
1410
1066
  depthLoadOp: "clear",
1411
- depthStoreOp: "store",
1067
+ // Main-pass depth is not sampled later (shadow uses its own map, composite is depthless).
1068
+ depthStoreOp: "discard",
1412
1069
  stencilClearValue: 0,
1413
1070
  stencilLoadOp: "clear",
1414
1071
  stencilStoreOp: "discard",
@@ -2200,20 +1857,7 @@ export class Engine {
2200
1857
  });
2201
1858
  const module = this.device.createShaderModule({
2202
1859
  label: "mipmap blit",
2203
- code: /* wgsl */ `
2204
- @group(0) @binding(0) var src: texture_2d<f32>;
2205
- @group(0) @binding(1) var samp: sampler;
2206
- @vertex fn vs(@builtin(vertex_index) vi: u32) -> @builtin(position) vec4f {
2207
- let x = f32((vi & 1u) << 2u) - 1.0;
2208
- let y = f32((vi & 2u) << 1u) - 1.0;
2209
- return vec4f(x, y, 0.0, 1.0);
2210
- }
2211
- @fragment fn fs(@builtin(position) p: vec4f) -> @location(0) vec4f {
2212
- let dstDims = vec2f(textureDimensions(src)) * 0.5;
2213
- let uv = p.xy / max(dstDims, vec2f(1.0));
2214
- return textureSampleLevel(src, samp, uv, 0.0);
2215
- }
2216
- `,
1860
+ code: MIPMAP_BLIT_SHADER_WGSL,
2217
1861
  });
2218
1862
  this.mipBlitPipeline = this.device.createRenderPipeline({
2219
1863
  label: "mipmap blit pipeline",
@@ -2235,7 +1879,9 @@ export class Engine {
2235
1879
  ],
2236
1880
  });
2237
1881
  const pass = encoder.beginRenderPass({
2238
- colorAttachments: [{ view: dstView, clearValue: { r: 0, g: 0, b: 0, a: 0 }, loadOp: "clear", storeOp: "store" }],
1882
+ colorAttachments: [
1883
+ { view: dstView, clearValue: { r: 0, g: 0, b: 0, a: 0 }, loadOp: "clear", storeOp: "store" },
1884
+ ],
2239
1885
  });
2240
1886
  pass.setPipeline(this.mipBlitPipeline);
2241
1887
  pass.setBindGroup(0, bindGroup);
@@ -2426,7 +2072,8 @@ export class Engine {
2426
2072
  const compositeAttachment = this.compositePassDescriptor.colorAttachments[0];
2427
2073
  compositeAttachment.view = this.context.getCurrentTexture().createView();
2428
2074
  const cpass = encoder.beginRenderPass(this.compositePassDescriptor);
2429
- cpass.setPipeline(this.compositePipeline);
2075
+ const compositePipeline = this.viewTransform.gamma === 1.0 ? this.compositePipelineIdentity : this.compositePipelineGamma;
2076
+ cpass.setPipeline(compositePipeline);
2430
2077
  cpass.setBindGroup(0, this.compositeBindGroup);
2431
2078
  cpass.draw(3);
2432
2079
  cpass.end();
package/dist/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
- export { Engine, DEFAULT_BLOOM_OPTIONS, DEFAULT_VIEW_TRANSFORM, type EngineStats, type EngineOptions, type BloomOptions, type ViewTransformOptions, type LoadModelFromFilesOptions, } from "./engine";
1
+ export { Engine, DEFAULT_BLOOM_OPTIONS, DEFAULT_VIEW_TRANSFORM, type EngineStats, type EngineOptions, type BloomOptions, type ViewTransformOptions, type LoadModelFromFilesOptions, type MaterialPreset, type MaterialPresetMap, } from "./engine";
2
2
  export { parsePmxFolderInput, pmxFileAtRelativePath, type PmxFolderInputResult } from "./folder-upload";
3
3
  export { Model } from "./model";
4
4
  export { Vec3, Quat, Mat4 } from "./math";
5
5
  export type { AnimationClip, AnimationPlayOptions, AnimationProgress, BoneKeyframe, MorphKeyframe, BoneInterpolation, ControlPoint, } from "./animation";
6
6
  export { FPS } from "./animation";
7
7
  export { Physics, type PhysicsOptions } from "./physics";
8
- export type { MaterialPreset, MaterialPresetMap } from "./shaders/classify";
9
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,GAC/B,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACvG,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,YAAY,GACb,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AACxD,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACvG,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,YAAY,GACb,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA"}