reze-engine 0.9.3 → 0.9.5

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.
package/README.md CHANGED
@@ -14,7 +14,7 @@ npm install reze-engine
14
14
  - VMD animation with IK solver and Bullet physics
15
15
  - Orbit camera with bone-follow mode
16
16
  - GPU picking (double-click/tap)
17
- - Ground plane with PCF shadow mapping
17
+ - Ground plane with PCF shadow mapping, grid lines, and frosted texture
18
18
  - Multi-model support
19
19
 
20
20
  ## Quick Start
@@ -97,14 +97,36 @@ engine.runRenderLoop()
97
97
  cameraTarget: Vec3,
98
98
  cameraFov: number,
99
99
  onRaycast: (modelName, material, screenX, screenY) => void,
100
+ shadowLightDirection: Vec3,
100
101
  physicsOptions: {
101
102
  constraintSolverKeywords: string[],
102
103
  },
103
104
  }
104
105
  ```
105
106
 
107
+ `shadowLightDirection` — direction of the shadow-only light, independent of the visible directional light. Default `(0.12, -1, 0.16)` casts a near-top-down shadow with a slight offset so extended limbs still project visible shadows.
108
+
106
109
  `constraintSolverKeywords` — joints whose name contains any keyword use the Bullet 2.75 constraint solver; all others keep the stable Ammo 2.82+ default. See [babylon-mmd: Fix Constraint Behavior](https://noname0310.github.io/babylon-mmd/docs/reference/runtime/apply-physics-to-mmd-models/#fix-constraint-behavior) for details.
107
110
 
111
+ ### Ground Options
112
+
113
+ ```javascript
114
+ engine.addGround({
115
+ width: 100, // ground plane width
116
+ height: 100, // ground plane depth
117
+ diffuseColor: Vec3, // base color (default: 0.8, 0.1, 1.0)
118
+ fadeStart: 5.0, // distance where edge fade begins
119
+ fadeEnd: 60.0, // distance where ground fully fades out
120
+ shadowMapSize: 4096, // shadow map resolution
121
+ shadowStrength: 1.0, // shadow darkness
122
+ gridSpacing: 5.0, // world-space distance between grid lines
123
+ gridLineWidth: 0.012, // thickness of grid lines
124
+ gridLineOpacity: 0.4, // grid line visibility (0–1)
125
+ gridLineColor: Vec3, // grid line color (default: 0.8, 0.8, 0.8)
126
+ noiseStrength: 0.08, // frosted/matte micro-texture intensity
127
+ })
128
+ ```
129
+
108
130
  ## Projects Using This Engine
109
131
 
110
132
  - **[MiKaPo](https://mikapo.vercel.app)** — Real-time motion capture for MMD
package/dist/engine.d.ts CHANGED
@@ -142,6 +142,11 @@ export declare class Engine {
142
142
  fadeEnd?: number;
143
143
  shadowMapSize?: number;
144
144
  shadowStrength?: number;
145
+ gridSpacing?: number;
146
+ gridLineWidth?: number;
147
+ gridLineOpacity?: number;
148
+ gridLineColor?: Vec3;
149
+ noiseStrength?: number;
145
150
  }): void;
146
151
  private updateLightBuffer;
147
152
  getStats(): EngineStats;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/engine.js CHANGED
@@ -446,7 +446,12 @@ export class Engine {
446
446
  struct CameraUniforms { view: mat4x4f, projection: mat4x4f, viewPos: vec3f, _p: f32, };
447
447
  struct Light { direction: vec4f, color: vec4f, };
448
448
  struct LightUniforms { ambientColor: vec4f, lights: array<Light, 4>, };
449
- struct GroundShadowMat { diffuseColor: vec3f, fadeStart: f32, fadeEnd: f32, shadowStrength: f32, pcfTexel: f32, _y: f32, };
449
+ struct GroundShadowMat {
450
+ diffuseColor: vec3f, fadeStart: f32,
451
+ fadeEnd: f32, shadowStrength: f32, pcfTexel: f32, gridSpacing: f32,
452
+ gridLineWidth: f32, gridLineOpacity: f32, noiseStrength: f32, _pad: f32,
453
+ gridLineColor: vec3f, _pad2: f32,
454
+ };
450
455
  struct LightVP { viewProj: mat4x4f, };
451
456
  @group(0) @binding(0) var<uniform> camera: CameraUniforms;
452
457
  @group(0) @binding(1) var<uniform> light: LightUniforms;
@@ -454,6 +459,32 @@ export class Engine {
454
459
  @group(0) @binding(3) var shadowSampler: sampler_comparison;
455
460
  @group(0) @binding(4) var<uniform> material: GroundShadowMat;
456
461
  @group(0) @binding(5) var<uniform> lightVP: LightVP;
462
+
463
+ // Hash-based noise for frosted/matte surface
464
+ fn hash2(p: vec2f) -> f32 {
465
+ var p3 = fract(vec3f(p.x, p.y, p.x) * 0.1031);
466
+ p3 += dot(p3, vec3f(p3.y + 33.33, p3.z + 33.33, p3.x + 33.33));
467
+ return fract((p3.x + p3.y) * p3.z);
468
+ }
469
+ fn valueNoise(p: vec2f) -> f32 {
470
+ let i = floor(p);
471
+ let f = fract(p);
472
+ let u = f * f * (3.0 - 2.0 * f);
473
+ return mix(mix(hash2(i), hash2(i + vec2f(1.0, 0.0)), u.x),
474
+ mix(hash2(i + vec2f(0.0, 1.0)), hash2(i + vec2f(1.0, 1.0)), u.x), u.y);
475
+ }
476
+ fn fbmNoise(p: vec2f) -> f32 {
477
+ var v = 0.0;
478
+ var a = 0.5;
479
+ var pp = p;
480
+ for (var i = 0; i < 4; i++) {
481
+ v += a * valueNoise(pp);
482
+ pp *= 2.0;
483
+ a *= 0.5;
484
+ }
485
+ return v;
486
+ }
487
+
457
488
  struct VO { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, };
458
489
  @vertex fn vs(@location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f) -> VO {
459
490
  var o: VO; o.worldPos = position; o.normal = normal;
@@ -463,6 +494,8 @@ export class Engine {
463
494
  let n = normalize(i.normal);
464
495
  let centerDist = length(i.worldPos.xz);
465
496
  let edgeFade = 1.0 - smoothstep(0.0, 1.0, clamp((centerDist - material.fadeStart) / max(material.fadeEnd - material.fadeStart, 0.001), 0.0, 1.0));
497
+
498
+ // Shadow sampling
466
499
  let lclip = lightVP.viewProj * vec4f(i.worldPos, 1.0);
467
500
  let ndc = lclip.xyz / max(lclip.w, 1e-6);
468
501
  let suv = vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);
@@ -470,20 +503,32 @@ export class Engine {
470
503
  let st = material.pcfTexel;
471
504
  let compareZ = ndc.z - 0.0035;
472
505
  var vis = 0.0;
473
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(-st, -st), compareZ);
474
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(0.0, -st), compareZ);
475
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(st, -st), compareZ);
476
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(-st, 0.0), compareZ);
477
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c, compareZ);
478
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(st, 0.0), compareZ);
479
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(-st, st), compareZ);
480
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(0.0, st), compareZ);
481
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(st, st), compareZ);
482
- vis *= 0.1111111;
506
+ for (var y = -2; y <= 2; y++) {
507
+ for (var x = -2; x <= 2; x++) {
508
+ vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(f32(x), f32(y)) * st, compareZ);
509
+ }
510
+ }
511
+ vis *= 0.04;
512
+
513
+ // Frosted/matte micro-texture (磨砂)
514
+ let noiseVal = fbmNoise(i.worldPos.xz * 3.0);
515
+ let noiseTint = 1.0 + (noiseVal - 0.5) * material.noiseStrength;
516
+
517
+ // Grid lines — anti-aliased via screen-space derivatives
518
+ let gp = i.worldPos.xz / material.gridSpacing;
519
+ let gridFrac = abs(fract(gp - 0.5) - 0.5);
520
+ let gridDeriv = fwidth(gp);
521
+ let halfLine = material.gridLineWidth * 0.5;
522
+ let gridLine = 1.0 - min(
523
+ smoothstep(halfLine - gridDeriv.x, halfLine + gridDeriv.x, gridFrac.x),
524
+ smoothstep(halfLine - gridDeriv.y, halfLine + gridDeriv.y, gridFrac.y)
525
+ );
483
526
  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);
484
527
  let dark = (1.0 - vis) * material.shadowStrength;
485
- let lit = material.diffuseColor * sun * (1.0 - dark * 0.65);
486
- return vec4f(lit * edgeFade, edgeFade);
528
+ var baseColor = material.diffuseColor * sun * (1.0 - dark * 0.65);
529
+ baseColor *= noiseTint;
530
+ let finalColor = mix(baseColor, material.gridLineColor, gridLine * material.gridLineOpacity * edgeFade);
531
+ return vec4f(finalColor * edgeFade, edgeFade);
487
532
  }
488
533
  `,
489
534
  });
@@ -578,7 +623,7 @@ export class Engine {
578
623
  // Screen-stable edgeline: extrusion ∝ camera distance (same idea as MMD viewers / babylon-mmd-style scaling)
579
624
  let camDist = max(length(camera.viewPos - worldPos), 0.25);
580
625
  let refDist = 30.0;
581
- let edgeScale = 0.03;
626
+ let edgeScale = 0.032;
582
627
  let expandedPos = worldPos + worldNormal * material.edgeSize * edgeScale * (camDist / refDist);
583
628
  output.position = camera.projection * camera.view * vec4f(expandedPos, 1.0);
584
629
  return output;
@@ -863,17 +908,22 @@ export class Engine {
863
908
  }
864
909
  addGround(options) {
865
910
  const opts = {
866
- width: 100,
867
- height: 100,
868
- diffuseColor: new Vec3(1, 1, 1),
869
- fadeStart: 5.0,
870
- fadeEnd: 60.0,
911
+ width: 160,
912
+ height: 160,
913
+ diffuseColor: new Vec3(0.8, 0.1, 1.0),
914
+ fadeStart: 10.0,
915
+ fadeEnd: 80.0,
871
916
  shadowMapSize: 4096,
872
917
  shadowStrength: 1.0,
918
+ gridSpacing: 4.2,
919
+ gridLineWidth: 0.012,
920
+ gridLineOpacity: 0.4,
921
+ gridLineColor: new Vec3(0.85, 0.85, 0.85),
922
+ noiseStrength: 0.05,
873
923
  ...options,
874
924
  };
875
925
  this.createGroundGeometry(opts.width, opts.height);
876
- this.createShadowGroundResources(opts.shadowMapSize, opts.diffuseColor, opts.fadeStart, opts.fadeEnd, opts.shadowStrength);
926
+ this.createShadowGroundResources(opts);
877
927
  this.hasGround = true;
878
928
  this.groundDrawCall = {
879
929
  type: "ground",
@@ -1175,7 +1225,8 @@ export class Engine {
1175
1225
  });
1176
1226
  this.device.queue.writeBuffer(this.groundIndexBuffer, 0, indices);
1177
1227
  }
1178
- createShadowGroundResources(shadowMapSize, diffuseColor, fadeStart, fadeEnd, shadowStrength) {
1228
+ createShadowGroundResources(opts) {
1229
+ const { shadowMapSize, diffuseColor, fadeStart, fadeEnd, shadowStrength, gridSpacing, gridLineWidth, gridLineOpacity, gridLineColor, noiseStrength } = opts;
1179
1230
  this.shadowMapTexture = this.device.createTexture({
1180
1231
  label: "shadow map",
1181
1232
  size: [shadowMapSize, shadowMapSize],
@@ -1183,16 +1234,25 @@ export class Engine {
1183
1234
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1184
1235
  });
1185
1236
  this.shadowMapDepthView = this.shadowMapTexture.createView();
1186
- const gb = new Float32Array(8);
1237
+ // Layout: diffuseColor(3f) fadeStart(1f) | fadeEnd(1f) shadowStrength(1f) pcfTexel(1f) gridSpacing(1f) | gridLineWidth(1f) gridOpacity(1f) noiseStrength(1f) _pad(1f) | gridColor(3f) _pad2(1f)
1238
+ const gb = new Float32Array(16);
1187
1239
  gb[0] = diffuseColor.x;
1188
1240
  gb[1] = diffuseColor.y;
1189
1241
  gb[2] = diffuseColor.z;
1190
1242
  gb[3] = fadeStart;
1191
1243
  gb[4] = fadeEnd;
1192
1244
  gb[5] = shadowStrength;
1193
- gb[6] = 1.2 / shadowMapSize;
1194
- gb[7] = 0;
1195
- this.groundShadowMaterialBuffer = this.device.createBuffer({ size: 64, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
1245
+ gb[6] = 1 / shadowMapSize;
1246
+ gb[7] = gridSpacing;
1247
+ gb[8] = gridLineWidth;
1248
+ gb[9] = gridLineOpacity;
1249
+ gb[10] = noiseStrength;
1250
+ gb[11] = 0;
1251
+ gb[12] = gridLineColor.x;
1252
+ gb[13] = gridLineColor.y;
1253
+ gb[14] = gridLineColor.z;
1254
+ gb[15] = 0;
1255
+ this.groundShadowMaterialBuffer = this.device.createBuffer({ size: gb.byteLength, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
1196
1256
  this.device.queue.writeBuffer(this.groundShadowMaterialBuffer, 0, gb);
1197
1257
  this.groundShadowBindGroup = this.device.createBindGroup({
1198
1258
  label: "ground shadow bind",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reze-engine",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "A lightweight WebGPU engine for real-time 3D MMD/PMX model rendering",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/src/engine.ts CHANGED
@@ -566,7 +566,12 @@ export class Engine {
566
566
  struct CameraUniforms { view: mat4x4f, projection: mat4x4f, viewPos: vec3f, _p: f32, };
567
567
  struct Light { direction: vec4f, color: vec4f, };
568
568
  struct LightUniforms { ambientColor: vec4f, lights: array<Light, 4>, };
569
- struct GroundShadowMat { diffuseColor: vec3f, fadeStart: f32, fadeEnd: f32, shadowStrength: f32, pcfTexel: f32, _y: f32, };
569
+ struct GroundShadowMat {
570
+ diffuseColor: vec3f, fadeStart: f32,
571
+ fadeEnd: f32, shadowStrength: f32, pcfTexel: f32, gridSpacing: f32,
572
+ gridLineWidth: f32, gridLineOpacity: f32, noiseStrength: f32, _pad: f32,
573
+ gridLineColor: vec3f, _pad2: f32,
574
+ };
570
575
  struct LightVP { viewProj: mat4x4f, };
571
576
  @group(0) @binding(0) var<uniform> camera: CameraUniforms;
572
577
  @group(0) @binding(1) var<uniform> light: LightUniforms;
@@ -574,6 +579,32 @@ export class Engine {
574
579
  @group(0) @binding(3) var shadowSampler: sampler_comparison;
575
580
  @group(0) @binding(4) var<uniform> material: GroundShadowMat;
576
581
  @group(0) @binding(5) var<uniform> lightVP: LightVP;
582
+
583
+ // Hash-based noise for frosted/matte surface
584
+ fn hash2(p: vec2f) -> f32 {
585
+ var p3 = fract(vec3f(p.x, p.y, p.x) * 0.1031);
586
+ p3 += dot(p3, vec3f(p3.y + 33.33, p3.z + 33.33, p3.x + 33.33));
587
+ return fract((p3.x + p3.y) * p3.z);
588
+ }
589
+ fn valueNoise(p: vec2f) -> f32 {
590
+ let i = floor(p);
591
+ let f = fract(p);
592
+ let u = f * f * (3.0 - 2.0 * f);
593
+ return mix(mix(hash2(i), hash2(i + vec2f(1.0, 0.0)), u.x),
594
+ mix(hash2(i + vec2f(0.0, 1.0)), hash2(i + vec2f(1.0, 1.0)), u.x), u.y);
595
+ }
596
+ fn fbmNoise(p: vec2f) -> f32 {
597
+ var v = 0.0;
598
+ var a = 0.5;
599
+ var pp = p;
600
+ for (var i = 0; i < 4; i++) {
601
+ v += a * valueNoise(pp);
602
+ pp *= 2.0;
603
+ a *= 0.5;
604
+ }
605
+ return v;
606
+ }
607
+
577
608
  struct VO { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, };
578
609
  @vertex fn vs(@location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f) -> VO {
579
610
  var o: VO; o.worldPos = position; o.normal = normal;
@@ -583,6 +614,8 @@ export class Engine {
583
614
  let n = normalize(i.normal);
584
615
  let centerDist = length(i.worldPos.xz);
585
616
  let edgeFade = 1.0 - smoothstep(0.0, 1.0, clamp((centerDist - material.fadeStart) / max(material.fadeEnd - material.fadeStart, 0.001), 0.0, 1.0));
617
+
618
+ // Shadow sampling
586
619
  let lclip = lightVP.viewProj * vec4f(i.worldPos, 1.0);
587
620
  let ndc = lclip.xyz / max(lclip.w, 1e-6);
588
621
  let suv = vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);
@@ -590,20 +623,32 @@ export class Engine {
590
623
  let st = material.pcfTexel;
591
624
  let compareZ = ndc.z - 0.0035;
592
625
  var vis = 0.0;
593
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(-st, -st), compareZ);
594
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(0.0, -st), compareZ);
595
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(st, -st), compareZ);
596
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(-st, 0.0), compareZ);
597
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c, compareZ);
598
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(st, 0.0), compareZ);
599
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(-st, st), compareZ);
600
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(0.0, st), compareZ);
601
- vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(st, st), compareZ);
602
- vis *= 0.1111111;
626
+ for (var y = -2; y <= 2; y++) {
627
+ for (var x = -2; x <= 2; x++) {
628
+ vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(f32(x), f32(y)) * st, compareZ);
629
+ }
630
+ }
631
+ vis *= 0.04;
632
+
633
+ // Frosted/matte micro-texture (磨砂)
634
+ let noiseVal = fbmNoise(i.worldPos.xz * 3.0);
635
+ let noiseTint = 1.0 + (noiseVal - 0.5) * material.noiseStrength;
636
+
637
+ // Grid lines — anti-aliased via screen-space derivatives
638
+ let gp = i.worldPos.xz / material.gridSpacing;
639
+ let gridFrac = abs(fract(gp - 0.5) - 0.5);
640
+ let gridDeriv = fwidth(gp);
641
+ let halfLine = material.gridLineWidth * 0.5;
642
+ let gridLine = 1.0 - min(
643
+ smoothstep(halfLine - gridDeriv.x, halfLine + gridDeriv.x, gridFrac.x),
644
+ smoothstep(halfLine - gridDeriv.y, halfLine + gridDeriv.y, gridFrac.y)
645
+ );
603
646
  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);
604
647
  let dark = (1.0 - vis) * material.shadowStrength;
605
- let lit = material.diffuseColor * sun * (1.0 - dark * 0.65);
606
- return vec4f(lit * edgeFade, edgeFade);
648
+ var baseColor = material.diffuseColor * sun * (1.0 - dark * 0.65);
649
+ baseColor *= noiseTint;
650
+ let finalColor = mix(baseColor, material.gridLineColor, gridLine * material.gridLineOpacity * edgeFade);
651
+ return vec4f(finalColor * edgeFade, edgeFade);
607
652
  }
608
653
  `,
609
654
  })
@@ -702,7 +747,7 @@ export class Engine {
702
747
  // Screen-stable edgeline: extrusion ∝ camera distance (same idea as MMD viewers / babylon-mmd-style scaling)
703
748
  let camDist = max(length(camera.viewPos - worldPos), 0.25);
704
749
  let refDist = 30.0;
705
- let edgeScale = 0.03;
750
+ let edgeScale = 0.032;
706
751
  let expandedPos = worldPos + worldNormal * material.edgeSize * edgeScale * (camDist / refDist);
707
752
  output.position = camera.projection * camera.view * vec4f(expandedPos, 1.0);
708
753
  return output;
@@ -1031,19 +1076,29 @@ export class Engine {
1031
1076
  fadeEnd?: number
1032
1077
  shadowMapSize?: number
1033
1078
  shadowStrength?: number
1079
+ gridSpacing?: number
1080
+ gridLineWidth?: number
1081
+ gridLineOpacity?: number
1082
+ gridLineColor?: Vec3
1083
+ noiseStrength?: number
1034
1084
  }): void {
1035
1085
  const opts = {
1036
- width: 100,
1037
- height: 100,
1038
- diffuseColor: new Vec3(1, 1, 1),
1039
- fadeStart: 5.0,
1040
- fadeEnd: 60.0,
1086
+ width: 160,
1087
+ height: 160,
1088
+ diffuseColor: new Vec3(0.8, 0.1, 1.0),
1089
+ fadeStart: 10.0,
1090
+ fadeEnd: 80.0,
1041
1091
  shadowMapSize: 4096,
1042
1092
  shadowStrength: 1.0,
1093
+ gridSpacing: 4.2,
1094
+ gridLineWidth: 0.012,
1095
+ gridLineOpacity: 0.4,
1096
+ gridLineColor: new Vec3(0.85, 0.85, 0.85),
1097
+ noiseStrength: 0.05,
1043
1098
  ...options,
1044
1099
  }
1045
1100
  this.createGroundGeometry(opts.width, opts.height)
1046
- this.createShadowGroundResources(opts.shadowMapSize, opts.diffuseColor, opts.fadeStart, opts.fadeEnd, opts.shadowStrength)
1101
+ this.createShadowGroundResources(opts)
1047
1102
  this.hasGround = true
1048
1103
  this.groundDrawCall = {
1049
1104
  type: "ground",
@@ -1395,13 +1450,19 @@ export class Engine {
1395
1450
  this.device.queue.writeBuffer(this.groundIndexBuffer, 0, indices)
1396
1451
  }
1397
1452
 
1398
- private createShadowGroundResources(
1399
- shadowMapSize: number,
1400
- diffuseColor: Vec3,
1401
- fadeStart: number,
1402
- fadeEnd: number,
1453
+ private createShadowGroundResources(opts: {
1454
+ shadowMapSize: number
1455
+ diffuseColor: Vec3
1456
+ fadeStart: number
1457
+ fadeEnd: number
1403
1458
  shadowStrength: number
1404
- ) {
1459
+ gridSpacing: number
1460
+ gridLineWidth: number
1461
+ gridLineOpacity: number
1462
+ gridLineColor: Vec3
1463
+ noiseStrength: number
1464
+ }) {
1465
+ const { shadowMapSize, diffuseColor, fadeStart, fadeEnd, shadowStrength, gridSpacing, gridLineWidth, gridLineOpacity, gridLineColor, noiseStrength } = opts
1405
1466
  this.shadowMapTexture = this.device.createTexture({
1406
1467
  label: "shadow map",
1407
1468
  size: [shadowMapSize, shadowMapSize],
@@ -1409,16 +1470,13 @@ export class Engine {
1409
1470
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1410
1471
  })
1411
1472
  this.shadowMapDepthView = this.shadowMapTexture.createView()
1412
- const gb = new Float32Array(8)
1413
- gb[0] = diffuseColor.x
1414
- gb[1] = diffuseColor.y
1415
- gb[2] = diffuseColor.z
1416
- gb[3] = fadeStart
1417
- gb[4] = fadeEnd
1418
- gb[5] = shadowStrength
1419
- gb[6] = 1.2 / shadowMapSize
1420
- gb[7] = 0
1421
- this.groundShadowMaterialBuffer = this.device.createBuffer({ size: 64, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST })
1473
+ // Layout: diffuseColor(3f) fadeStart(1f) | fadeEnd(1f) shadowStrength(1f) pcfTexel(1f) gridSpacing(1f) | gridLineWidth(1f) gridOpacity(1f) noiseStrength(1f) _pad(1f) | gridColor(3f) _pad2(1f)
1474
+ const gb = new Float32Array(16)
1475
+ gb[0] = diffuseColor.x; gb[1] = diffuseColor.y; gb[2] = diffuseColor.z; gb[3] = fadeStart
1476
+ gb[4] = fadeEnd; gb[5] = shadowStrength; gb[6] = 1 / shadowMapSize; gb[7] = gridSpacing
1477
+ gb[8] = gridLineWidth; gb[9] = gridLineOpacity; gb[10] = noiseStrength; gb[11] = 0
1478
+ gb[12] = gridLineColor.x; gb[13] = gridLineColor.y; gb[14] = gridLineColor.z; gb[15] = 0
1479
+ this.groundShadowMaterialBuffer = this.device.createBuffer({ size: gb.byteLength, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST })
1422
1480
  this.device.queue.writeBuffer(this.groundShadowMaterialBuffer, 0, gb)
1423
1481
  this.groundShadowBindGroup = this.device.createBindGroup({
1424
1482
  label: "ground shadow bind",