@woosh/meep-engine 2.109.24 → 2.109.26

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 (93) hide show
  1. package/build/meep.cjs +248 -117
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +248 -117
  4. package/package.json +1 -1
  5. package/src/core/collection/heap/{FastBinaryHeap.d.ts → BinaryHeap.d.ts} +16 -9
  6. package/src/core/collection/heap/BinaryHeap.d.ts.map +1 -0
  7. package/src/core/collection/heap/{FastBinaryHeap.js → BinaryHeap.js} +31 -21
  8. package/src/core/collection/heap/BinaryHeap.spec.d.ts +2 -0
  9. package/src/core/collection/heap/BinaryHeap.spec.d.ts.map +1 -0
  10. package/src/core/collection/heap/{FastBinaryHeap.spec.js → BinaryHeap.spec.js} +1 -1
  11. package/src/core/collection/heap/Uint32Heap.spec.d.ts +2 -0
  12. package/src/core/collection/heap/Uint32Heap.spec.d.ts.map +1 -0
  13. package/src/core/collection/table/RowFirstTable.d.ts +10 -7
  14. package/src/core/collection/table/RowFirstTable.d.ts.map +1 -1
  15. package/src/core/collection/table/RowFirstTable.js +23 -6
  16. package/src/core/geom/3d/normal/octahedron/encode_unit_to_octahedron.js +2 -2
  17. package/src/core/geom/3d/topology/simplify/simplifyTopoMesh.d.ts +1 -0
  18. package/src/core/geom/3d/topology/simplify/simplifyTopoMesh.d.ts.map +1 -1
  19. package/src/core/geom/3d/topology/simplify/simplifyTopoMesh.js +5 -5
  20. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.d.ts.map +1 -1
  21. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +14 -8
  22. package/src/core/geom/packing/max-rect/MaxRectanglesPacker.js +1 -1
  23. package/src/core/graph/Edge.d.ts +1 -0
  24. package/src/core/graph/Edge.d.ts.map +1 -1
  25. package/src/core/graph/Edge.js +5 -0
  26. package/src/core/graph/graph_compute_distance_matrix.js +2 -2
  27. package/src/core/graph/metis/cluster_mesh_metis.d.ts +9 -0
  28. package/src/core/graph/metis/cluster_mesh_metis.d.ts.map +1 -0
  29. package/src/core/graph/metis/cluster_mesh_metis.js +31 -0
  30. package/src/core/graph/metis/mesh_to_metis_graph.d.ts +10 -0
  31. package/src/core/graph/metis/mesh_to_metis_graph.d.ts.map +1 -0
  32. package/src/core/graph/metis/mesh_to_metis_graph.js +64 -0
  33. package/src/core/graph/metis/metis_cluster_bs.d.ts +12 -0
  34. package/src/core/graph/metis/metis_cluster_bs.d.ts.map +1 -0
  35. package/src/core/graph/{cluster_mesh_metis.js → metis/metis_cluster_bs.js} +12 -98
  36. package/src/core/graph/mn_graph_coarsen.d.ts.map +1 -1
  37. package/src/core/graph/mn_graph_coarsen.js +7 -3
  38. package/src/core/graph/mn_graph_coarsen.spec.js +2 -0
  39. package/src/engine/animation/async/TimeSeries.d.ts.map +1 -1
  40. package/src/engine/animation/async/TimeSeries.js +6 -2
  41. package/src/engine/animation/async/table_find_min_index_in_ordered_column.d.ts +9 -0
  42. package/src/engine/animation/async/table_find_min_index_in_ordered_column.d.ts.map +1 -0
  43. package/src/engine/animation/async/{findSampleIndex.js → table_find_min_index_in_ordered_column.js} +5 -4
  44. package/src/engine/asset/AssetManager.js +2 -2
  45. package/src/engine/graphics/sh3/gi/material/common.glsl +46 -55
  46. package/src/engine/graphics/sh3/gi/material/makeOctahedralDepthAtlas.d.ts.map +1 -1
  47. package/src/engine/graphics/sh3/gi/material/makeOctahedralDepthAtlas.js +5 -3
  48. package/src/engine/graphics/sh3/lpv/LightProbeVolume.js +1 -1
  49. package/src/engine/graphics/sh3/lpv/LightProbeVolumeBaker.js +1 -1
  50. package/src/engine/graphics/sh3/lpv/PathTracerProbeRenderer.d.ts.map +1 -1
  51. package/src/engine/graphics/sh3/lpv/PathTracerProbeRenderer.js +3 -2
  52. package/src/engine/graphics/sh3/lpv/depth/octahedral/bake_octahedral_depth_map.d.ts.map +1 -1
  53. package/src/engine/graphics/sh3/lpv/depth/octahedral/bake_octahedral_depth_map.js +19 -7
  54. package/src/engine/graphics/sh3/lpv/depth/octahedral/v2/visualise.frag.glsl +17 -15
  55. package/src/engine/graphics/sh3/lpv/probe_volume_to_textures.d.ts.map +1 -1
  56. package/src/engine/graphics/sh3/lpv/probe_volume_to_textures.js +6 -2
  57. package/src/engine/graphics/sh3/lpv/serialization/LightProbeVolumeSerializationAdapter.js +2 -2
  58. package/src/engine/graphics/sh3/path_tracer/PathTracedScene.d.ts.map +1 -1
  59. package/src/engine/graphics/sh3/path_tracer/PathTracedScene.js +10 -0
  60. package/src/engine/graphics/sh3/prototypeSH3Probe.js +3 -3
  61. package/src/engine/input/devices/InputDeviceSwitch.d.ts.map +1 -1
  62. package/src/engine/input/devices/InputDeviceSwitch.js +18 -0
  63. package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
  64. package/src/engine/input/devices/KeyboardDevice.js +4 -41
  65. package/src/engine/input/devices/LocationalInteractionMetadata.d.ts +11 -0
  66. package/src/engine/input/devices/LocationalInteractionMetadata.d.ts.map +1 -0
  67. package/src/engine/input/devices/LocationalInteractionMetadata.js +18 -0
  68. package/src/engine/input/devices/PointerDevice.d.ts.map +1 -1
  69. package/src/engine/input/devices/PointerDevice.js +90 -37
  70. package/src/engine/input/devices/events/eventToSourceIdentifier.d.ts +7 -0
  71. package/src/engine/input/devices/events/eventToSourceIdentifier.d.ts.map +1 -0
  72. package/src/engine/input/devices/events/eventToSourceIdentifier.js +36 -0
  73. package/src/engine/input/devices/isHTMLElementFocusable.d.ts +6 -0
  74. package/src/engine/input/devices/isHTMLElementFocusable.d.ts.map +1 -0
  75. package/src/engine/input/devices/isHTMLElementFocusable.js +34 -0
  76. package/src/engine/network/PriorityFetch.d.ts.map +1 -1
  77. package/src/engine/network/PriorityFetch.js +2 -2
  78. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +1 -1
  79. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.d.ts.map +1 -1
  80. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +4 -4
  81. package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.d.ts.map +1 -1
  82. package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +2 -2
  83. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +1 -1
  84. package/src/core/collection/heap/FastBinaryHeap.d.ts.map +0 -1
  85. package/src/core/collection/heap/FastBinaryHeap.spec.d.ts +0 -2
  86. package/src/core/collection/heap/FastBinaryHeap.spec.d.ts.map +0 -1
  87. package/src/core/collection/heap/Uin32Heap.spec.d.ts +0 -2
  88. package/src/core/collection/heap/Uin32Heap.spec.d.ts.map +0 -1
  89. package/src/core/graph/cluster_mesh_metis.d.ts +0 -28
  90. package/src/core/graph/cluster_mesh_metis.d.ts.map +0 -1
  91. package/src/engine/animation/async/findSampleIndex.d.ts +0 -9
  92. package/src/engine/animation/async/findSampleIndex.d.ts.map +0 -1
  93. /package/src/core/collection/heap/{Uin32Heap.spec.js → Uint32Heap.spec.js} +0 -0
@@ -1,5 +1,5 @@
1
- import { Metis } from "./metis/metis.js";
2
- import { metis_options } from "./metis/metis_options.js";
1
+ import { Metis } from "./metis.js";
2
+ import { metis_options } from "./metis_options.js";
3
3
 
4
4
  /**
5
5
  * How many times to retry partitioning before giving up
@@ -17,7 +17,14 @@ const MAX_STEPS = 50;
17
17
  * @param {number} patch_size
18
18
  * @returns {Promise<number>}
19
19
  */
20
- export async function metis_cluster_bs(result, node_count, edge_addresses, adjacency_uint32, edge_weights_uint32, patch_size) {
20
+ export async function metis_cluster_bs(
21
+ result,
22
+ node_count,
23
+ edge_addresses,
24
+ adjacency_uint32,
25
+ edge_weights_uint32,
26
+ patch_size
27
+ ) {
21
28
 
22
29
  const metis = Metis.INSTANCE;
23
30
 
@@ -35,7 +42,7 @@ export async function metis_cluster_bs(result, node_count, edge_addresses, adjac
35
42
  const metisOptions = new metis_options();
36
43
  metisOptions.seed = 0xCAFE;
37
44
 
38
- partition_loop: for (; ;) {
45
+ for (; ;) {
39
46
  passes++;
40
47
 
41
48
  if (passes > MAX_STEPS) {
@@ -97,9 +104,6 @@ export async function metis_cluster_bs(result, node_count, edge_addresses, adjac
97
104
  }
98
105
 
99
106
  // console.log(`${partition_count}`);
100
-
101
- continue partition_loop;
102
-
103
107
  }
104
108
 
105
109
  // remap P values. Metis assigns unique unsigned integer values to each cluster, but they don't necessarily start at 0, to fix this we remap values
@@ -120,94 +124,4 @@ export async function metis_cluster_bs(result, node_count, edge_addresses, adjac
120
124
 
121
125
  result.set(p);
122
126
  return partition_count;
123
- }
124
-
125
- /**
126
- * @param {TopoTriangle[]} face_array
127
- */
128
- export function mesh_to_metis_graph(face_array) {
129
- const input_face_count = face_array.length;
130
-
131
-
132
- const edge_addresses = new Uint32Array(input_face_count + 1);
133
- const adjacency = [];
134
- const edge_weights = [];
135
-
136
- const face_index_map = new Map();
137
-
138
- for (let i = 0; i < input_face_count; i++) {
139
- const face = face_array[i];
140
- face_index_map.set(face, i);
141
- }
142
-
143
- let offset = 0;
144
- edge_addresses[0] = 0;
145
- for (let i = 0; i < input_face_count; i++) {
146
- const face = face_array[i];
147
-
148
- const edges = face.edges;
149
-
150
- const edge_count = edges.length;
151
- for (let j = 0; j < edge_count; j++) {
152
- const topoEdge = edges[j];
153
-
154
- const edge_faces = topoEdge.faces;
155
-
156
- const edge_face_count = edge_faces.length;
157
- for (let k = 0; k < edge_face_count; k++) {
158
- const neighbour = edge_faces[k];
159
-
160
- if (neighbour === face) {
161
- //skip self
162
- continue;
163
- }
164
-
165
- adjacency[offset] = face_index_map.get(neighbour);
166
- edge_weights[offset] = 1;
167
-
168
- offset++;
169
- }
170
- }
171
-
172
- edge_addresses[i + 1] = offset;
173
- }
174
-
175
- const adjecency_uint32 = new Uint32Array(adjacency);
176
- const edge_weights_uint32 = new Uint32Array(edge_weights);
177
-
178
-
179
- return {
180
- edge_addresses: edge_addresses,
181
- adjacency: adjecency_uint32,
182
- edge_weights: edge_weights_uint32
183
- };
184
- }
185
-
186
- /**
187
- *
188
- * @param {Uint32Array} result
189
- * @param {TopoMesh} mesh
190
- * @param {number} patch_size
191
- * @returns {number}
192
- */
193
- export async function cluster_mesh_metis(result, mesh, patch_size) {
194
-
195
- const face_set = mesh.getFaces();
196
- const input_face_count = face_set.size;
197
-
198
- const face_array = Array.from(face_set);
199
-
200
- const metis_graph = mesh_to_metis_graph(face_array);
201
-
202
- const partition_count = await metis_cluster_bs(
203
- result,
204
- input_face_count,
205
- metis_graph.edge_addresses,
206
- metis_graph.adjacency,
207
- metis_graph.edge_weights,
208
- patch_size
209
- );
210
-
211
- return partition_count;
212
- }
213
-
127
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"mn_graph_coarsen.d.ts","sourceRoot":"","sources":["../../../../src/core/graph/mn_graph_coarsen.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,gFAFW,MAAM,QAuBhB"}
1
+ {"version":3,"file":"mn_graph_coarsen.d.ts","sourceRoot":"","sources":["../../../../src/core/graph/mn_graph_coarsen.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,gFAFW,MAAM,QA2BhB"}
@@ -1,4 +1,4 @@
1
- import FastBinaryHeap from "../collection/heap/FastBinaryHeap.js";
1
+ import BinaryHeap from "../collection/heap/BinaryHeap.js";
2
2
  import { mn_graph_collapse_weighted_edge } from "./mn_graph_collapse_weighted_edge.js";
3
3
  import { WeightedEdge } from "./WeightedEdge.js";
4
4
 
@@ -15,7 +15,7 @@ export function mn_graph_coarsen(graph, max_node_limit) {
15
15
  *
16
16
  * @type {BinaryHeap<WeightedEdge>}
17
17
  */
18
- const open_set = new FastBinaryHeap(WeightedEdge.extractNegativeWeight);
18
+ const open_set = new BinaryHeap(WeightedEdge.extractNegativeWeight);
19
19
 
20
20
  // add all edges to the heap
21
21
  const edges = graph.getEdges();
@@ -28,6 +28,10 @@ export function mn_graph_coarsen(graph, max_node_limit) {
28
28
  const edge = open_set.pop();
29
29
 
30
30
  // attempt collapse of the heaviest edge
31
- mn_graph_collapse_weighted_edge(graph, edge, max_node_limit, open_set);
31
+ const collapsed = mn_graph_collapse_weighted_edge(graph, edge, max_node_limit, open_set);
32
+
33
+ if(!collapsed){
34
+ throw new Error(`Failed to collapse edge ${edge}`);
35
+ }
32
36
  }
33
37
  }
@@ -14,6 +14,8 @@ test('coarsen 2 node graph with 1 edge', () => {
14
14
  graph.addEdge(new WeightedEdge(n0, n1));
15
15
 
16
16
  mn_graph_coarsen(graph, 2);
17
+
18
+ expect(graph.getNodeCount()).toBe(1);
17
19
  });
18
20
 
19
21
  test('coarsen chain, all nodes must still be linked', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"TimeSeries.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/async/TimeSeries.js"],"names":[],"mappings":"AAaA;;GAEG;AACH;IA+BI;;;;OAIG;IACH,4CAFW,MAAM,EAuChB;IAxED;;OAEG;IACH,MAFU,iBAAiB,CAEvB;IAEJ;;OAEG;IACH,OAFU,aAAa,CAElB;IAEL,0BAAsB;IAyHtB;;;;OAIG;IACH,8BAHW,MAAM,OAOhB;IAED;;;OAGG;IACH,2BAEC;IAED;;;OAGG;IACH,6BAWC;IAED,oCAcC;IAED;;;OAGG;IACH,gBAFW,MAAM,EAAE,QAQlB;IAED;;;OAGG;IACH,mCAIC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,SACR,MAAM,QAIhB;IAED;;;;OAIG;IACH,+BAHW,MAAM,GACJ,MAAM,CAMlB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,EAAE,iBACR,MAAM,QACN,MAAM,QAuBhB;IAED;;;;OAIG;IACH,yBAHW,MAAM,OAShB;;CAEJ;kCAzRiC,qDAAqD;8BADzD,iDAAiD"}
1
+ {"version":3,"file":"TimeSeries.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/async/TimeSeries.js"],"names":[],"mappings":"AAiBA;;GAEG;AACH;IA+BI;;;;OAIG;IACH,4CAFW,MAAM,EAuChB;IAxED;;OAEG;IACH,MAFU,iBAAiB,CAEvB;IAEJ;;OAEG;IACH,OAFU,aAAa,CAElB;IAEL,0BAAsB;IAyHtB;;;;OAIG;IACH,8BAHW,MAAM,OAOhB;IAED;;;OAGG;IACH,2BAEC;IAED;;;OAGG;IACH,6BAWC;IAED,oCAcC;IAED;;;OAGG;IACH,gBAFW,MAAM,EAAE,QAQlB;IAED;;;OAGG;IACH,mCAIC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,SACR,MAAM,QAIhB;IAED;;;;OAIG;IACH,+BAHW,MAAM,GACJ,MAAM,CAMlB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,EAAE,iBACR,MAAM,QACN,MAAM,QAuBhB;IAED;;;;OAIG;IACH,yBAHW,MAAM,OAShB;;CAEJ;kCA7RiC,qDAAqD;8BADzD,iDAAiD"}
@@ -7,8 +7,12 @@ import { lerp } from "../../../core/math/lerp.js";
7
7
  import { max2 } from "../../../core/math/max2.js";
8
8
  import { min2 } from "../../../core/math/min2.js";
9
9
  import { validate_enum_schema } from "../../../core/model/validate_enum_schema.js";
10
- import { findSampleIndex } from "./findSampleIndex.js";
10
+ import { table_find_min_index_in_ordered_column } from "./table_find_min_index_in_ordered_column.js";
11
11
 
12
+ /**
13
+ *
14
+ * @type {number[]}
15
+ */
12
16
  const scratch_row = [];
13
17
 
14
18
  /**
@@ -237,7 +241,7 @@ export class TimeSeries {
237
241
  findLowSampleIndexByTime(time) {
238
242
  const table = this.table;
239
243
  const time_column_index = this.time_column_index;
240
- return max2(0, findSampleIndex(table, time, time_column_index))
244
+ return max2(0, table_find_min_index_in_ordered_column(table, time, time_column_index))
241
245
  }
242
246
 
243
247
  /**
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Given a column of ordered values in increasing order, returns low index of matching value
3
+ * @param {RowFirstTable} table
4
+ * @param {number} time
5
+ * @param {number} [column_index]
6
+ * @return {number}
7
+ */
8
+ export function table_find_min_index_in_ordered_column(table: RowFirstTable, time: number, column_index?: number): number;
9
+ //# sourceMappingURL=table_find_min_index_in_ordered_column.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table_find_min_index_in_ordered_column.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/async/table_find_min_index_in_ordered_column.js"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,mFAJW,MAAM,iBACN,MAAM,GACL,MAAM,CAwBjB"}
@@ -1,19 +1,20 @@
1
1
  import { min2 } from "../../../core/math/min2.js";
2
2
 
3
3
  /**
4
- *
4
+ * Given a column of ordered values in increasing order, returns low index of matching value
5
5
  * @param {RowFirstTable} table
6
6
  * @param {number} time
7
7
  * @param {number} [column_index]
8
8
  * @return {number}
9
9
  */
10
- export function findSampleIndex(table, time, column_index = 0) {
10
+ export function table_find_min_index_in_ordered_column(table, time, column_index = 0) {
11
11
  let minIndex = 0;
12
12
  let maxIndex = table.length - 1;
13
13
 
14
14
  while (minIndex <= maxIndex) {
15
15
 
16
- const pivotIndex = (minIndex + maxIndex) >> 1;
16
+ // low midpoint, this is essentially Math.floor( (minIndex + maxIndex) / 2 )
17
+ const pivotIndex = (minIndex + maxIndex) >>> 1;
17
18
 
18
19
  const cmp = time - table.readCellValue(pivotIndex, column_index);
19
20
 
@@ -22,7 +23,7 @@ export function findSampleIndex(table, time, column_index = 0) {
22
23
  } else if (cmp < 0) {
23
24
  maxIndex = pivotIndex - 1;
24
25
  } else {
25
- //set low boundary for next step based on assumption that upper bound is higher than lower bound
26
+ // exactly on the pivot sample
26
27
  return pivotIndex;
27
28
  }
28
29
  }
@@ -1,7 +1,7 @@
1
1
  import { assert } from "../../core/assert.js";
2
2
  import { array_push_if_unique } from "../../core/collection/array/array_push_if_unique.js";
3
3
  import { array_remove_first } from "../../core/collection/array/array_remove_first.js";
4
- import FastBinaryHeap from "../../core/collection/heap/FastBinaryHeap.js";
4
+ import BinaryHeap from "../../core/collection/heap/BinaryHeap.js";
5
5
  import { HashMap } from "../../core/collection/map/HashMap.js";
6
6
  import { ObservedMap } from "../../core/collection/map/ObservedMap.js";
7
7
  import { Deque } from "../../core/collection/queue/Deque.js";
@@ -68,7 +68,7 @@ export class AssetManager {
68
68
  * @type {BinaryHeap<PendingAsset>}
69
69
  * @private
70
70
  */
71
- #pending_asset_wait_queue = new FastBinaryHeap(get_pending_asset_priority_score);
71
+ #pending_asset_wait_queue = new BinaryHeap(get_pending_asset_priority_score);
72
72
  /**
73
73
  * Assets currently being processed by #loaders
74
74
  * @type {Set<PendingAsset>}
@@ -24,6 +24,13 @@ const float lpv_max_thickness = 0.50; // in Meters
24
24
  #define SEARCH_STEP_LIMIT 32u
25
25
  #define INVALID_TET 1073741823u
26
26
 
27
+
28
+ /** Slightly bump the location of the shadow test point away from the shadow casting surface.
29
+ The shadow casting surface is the boundary for shadow, so the nearer an imprecise value is
30
+ to it the more the light leaks.
31
+ */
32
+ #define LPV_NORMAL_BIAS 0.0001f
33
+
27
34
  ivec2 lpv_index_to_256_coordinate(uint index) {
28
35
 
29
36
  uint pixel_x = index % 256u;
@@ -160,18 +167,15 @@ vec2 lpv_probe_getDepthTriangular(uint probe_index, vec3 direction) {
160
167
  frame1 += tile_offset;
161
168
  frame2 += tile_offset;
162
169
 
163
- float samp0 = texelFetch(lpv_t_probe_depth, ivec2(frame0), 0).r;
164
- float samp1 = texelFetch(lpv_t_probe_depth, ivec2(frame1), 0).r;
165
- float samp2 = texelFetch(lpv_t_probe_depth, ivec2(frame2), 0).r;
170
+ vec2 samp0 = texelFetch(lpv_t_probe_depth, ivec2(frame0), 0).rg;
171
+ vec2 samp1 = texelFetch(lpv_t_probe_depth, ivec2(frame1), 0).rg;
172
+ vec2 samp2 = texelFetch(lpv_t_probe_depth, ivec2(frame2), 0).rg;
166
173
 
167
- float d0 = samp0 * weights.x;
168
- float d1 = samp1 * weights.y;
169
- float d2 = samp2 * weights.z;
174
+ vec2 d0 = samp0 * weights.x;
175
+ vec2 d1 = samp1 * weights.y;
176
+ vec2 d2 = samp2 * weights.z;
170
177
 
171
- float mean = d0 + d1 + d2;
172
- float mean2 = samp0 * d0 + samp1 * d1 + samp2 * d2;
173
-
174
- return vec2(mean, mean2);
178
+ return (d0 + d1 + d2);
175
179
  }
176
180
 
177
181
  float lpv_bilinear_lerp(float v00, float v01, float v10, float v11, vec2 fraction) {
@@ -182,6 +186,14 @@ float lpv_bilinear_lerp(float v00, float v01, float v10, float v11, vec2 fractio
182
186
  return mix(x0, x1, fraction.y);
183
187
  }
184
188
 
189
+ vec2 lpv_bilinear_lerp(vec2 v00, vec2 v01, vec2 v10, vec2 v11, vec2 fraction) {
190
+
191
+ vec2 x0 = mix(v00, v01, fraction.x);
192
+ vec2 x1 = mix(v10, v11, fraction.x);
193
+
194
+ return mix(x0, x1, fraction.y);
195
+ }
196
+
185
197
  vec2 lpv_sample_bilinear(sampler2D tex, ivec2 texel_position, vec2 fraction) {
186
198
 
187
199
  float texel_00 = texelFetch(tex, texel_position, 0).r;
@@ -191,13 +203,13 @@ vec2 lpv_sample_bilinear(sampler2D tex, ivec2 texel_position, vec2 fraction) {
191
203
 
192
204
  return vec2(
193
205
  lpv_bilinear_lerp(
194
- texel_00, texel_01,
195
- texel_10, texel_11,
196
- fraction
197
- ),
206
+ texel_00, texel_01,
207
+ texel_10, texel_11,
208
+ fraction
209
+ ),
198
210
  lpv_bilinear_lerp(
199
- texel_00*texel_00, texel_01*texel_01,
200
- texel_10*texel_10, texel_11*texel_11,
211
+ texel_00 * texel_00, texel_01 * texel_01,
212
+ texel_10 * texel_10, texel_11 * texel_11,
201
213
  fraction
202
214
  )
203
215
  );
@@ -246,27 +258,20 @@ vec2 lpv_probe_getDepthBilinear(uint probe_index, vec3 direction) {
246
258
  ivec2 tile_p_10;
247
259
  ivec2 tile_p_11;
248
260
 
249
- tile_p_00 = wrapOctahedralTexelCoordinates(texel_position , depth_tile_resolution);
261
+ tile_p_00 = wrapOctahedralTexelCoordinates(texel_position, depth_tile_resolution);
250
262
  tile_p_01 = wrapOctahedralTexelCoordinates(texel_position + ivec2(1, 0), depth_tile_resolution);
251
263
  tile_p_10 = wrapOctahedralTexelCoordinates(texel_position + ivec2(0, 1), depth_tile_resolution);
252
264
  tile_p_11 = wrapOctahedralTexelCoordinates(texel_position + ivec2(1, 1), depth_tile_resolution);
253
265
 
254
- float texel_00 = texelFetch(lpv_t_probe_depth, tile_offset + tile_p_00, 0).r;
255
- float texel_01 = texelFetch(lpv_t_probe_depth, tile_offset + tile_p_01, 0).r;
256
- float texel_10 = texelFetch(lpv_t_probe_depth, tile_offset + tile_p_10, 0).r;
257
- float texel_11 = texelFetch(lpv_t_probe_depth, tile_offset + tile_p_11, 0).r;
266
+ vec2 texel_00 = texelFetch(lpv_t_probe_depth, tile_offset + tile_p_00, 0).rg;
267
+ vec2 texel_01 = texelFetch(lpv_t_probe_depth, tile_offset + tile_p_01, 0).rg;
268
+ vec2 texel_10 = texelFetch(lpv_t_probe_depth, tile_offset + tile_p_10, 0).rg;
269
+ vec2 texel_11 = texelFetch(lpv_t_probe_depth, tile_offset + tile_p_11, 0).rg;
258
270
 
259
- return vec2(
260
- lpv_bilinear_lerp(
261
- texel_00, texel_01,
262
- texel_10, texel_11,
263
- gridFrac
264
- ),
265
- lpv_bilinear_lerp(
266
- texel_00 * texel_00, texel_01 * texel_01,
267
- texel_10 * texel_10, texel_11 * texel_11,
268
- gridFrac
269
- )
271
+ return lpv_bilinear_lerp(
272
+ texel_00, texel_01,
273
+ texel_10, texel_11,
274
+ gridFrac
270
275
  );
271
276
  }
272
277
 
@@ -353,7 +358,9 @@ float lpv_probe_getVisibilityMask(vec3 position, uint probe_index) {
353
358
  vec2 temp = lpv_probe_getDepthBilinear(probe_index, direction);
354
359
 
355
360
  float mean = temp.x;
356
- float variance = abs(mean * mean - temp.y);
361
+ float mean2 = temp.y; // mean of squared distances
362
+
363
+ float variance = abs(mean * mean - mean2);
357
364
 
358
365
  // http://www.punkuser.net/vsm/vsm_paper.pdf; equation 5
359
366
  // Need the max in the denominator because biasing can cause a negative displacement
@@ -362,7 +369,7 @@ float lpv_probe_getVisibilityMask(vec3 position, uint probe_index) {
362
369
  float chebyshevWeight = variance / (variance + distance_delta * distance_delta);
363
370
 
364
371
  // Increase contrast in the weight
365
- // chebyshevWeight = max(chebyshevWeight * chebyshevWeight * chebyshevWeight, 0.0);
372
+ chebyshevWeight = max(chebyshevWeight * chebyshevWeight * chebyshevWeight, 0.0);
366
373
 
367
374
  return (distToProbe <= mean) ? 1.0 : chebyshevWeight;
368
375
  }
@@ -400,12 +407,6 @@ vec4 lvp_mask_weights_by_visibility_by_normal(vec3 position, vec3 normal, uint t
400
407
  }
401
408
 
402
409
 
403
- /** Slightly bump the location of the shadow test point away from the shadow casting surface.
404
- The shadow casting surface is the boundary for shadow, so the nearer an imprecise value is
405
- to it the more the light leaks.
406
- */
407
- #define LPV_NORMAL_BIAS 0.01f
408
-
409
410
  vec4 lvp_mask_weights_by_visibility(in vec3 position, in vec3 normal, in vec3 view_direction, in uint tet_index, in vec4 barycentric) {
410
411
 
411
412
  uvec4 vertices = lpv_mesh_getVertices(tet_index);
@@ -451,7 +452,7 @@ vec4 lvp_mask_weights_by_visibility(in vec3 position, in vec3 normal, in vec3 vi
451
452
  // The small offset at the end reduces the "going to zero" impact
452
453
  // where this is really close to exactly opposite
453
454
  float backface_term = max(0.0001, (dot(direction_to_probe, normal) + 1.0) * 0.5);
454
- weight *= backface_term * backface_term + 0.2;
455
+ weight *= backface_term * backface_term + 0.05;
455
456
 
456
457
  }
457
458
 
@@ -559,30 +560,20 @@ vec4 lpv_renormalize_weights(in vec4 source) {
559
560
 
560
561
  vec3 lpv_sample_irradiance(vec3 position, vec3 normal, vec3 view_direction) {
561
562
 
562
- // Bias the position at which visibility is computed; this
563
- // avoids performing a shadow test *at* a surface, which is a
564
- // dangerous location because that is exactly the line between
565
- // shadowed and unshadowed. If the normal bias is too small,
566
- // there will be light and dark leaks. If it is too large,
567
- // then samples can pass through thin occluders to the other
568
- // side (this can only happen if there are MULTIPLE occluders
569
- // near each other, a wall surface won't pass through itself.)
570
- vec3 lookup_position = position + (normal + view_direction * 3.0) * LPV_NORMAL_BIAS;
571
-
572
563
  // lookup nearby tet
573
564
  vec3 lpv_mesh_bounds_min = lpv_v3_bounds_min;
574
565
  vec3 lpv_mesh_bounds_max = lpv_v3_bounds_max;
575
- vec3 lookup_coordinates = (lookup_position - lpv_mesh_bounds_min) / (lpv_mesh_bounds_max - lpv_mesh_bounds_min);
566
+ vec3 lookup_coordinates = (position - lpv_mesh_bounds_min) / (lpv_mesh_bounds_max - lpv_mesh_bounds_min);
576
567
 
577
568
 
578
- uint nearest_tet = lpv_guess_initial_tet(lookup_position);
569
+ uint nearest_tet = lpv_guess_initial_tet(position);
579
570
 
580
571
  uint tet;
581
572
  vec4 barycentric_coordinates;
582
- lpv_walk_to_tetrahedron(lookup_position, nearest_tet, tet, barycentric_coordinates);
573
+ lpv_walk_to_tetrahedron(position, nearest_tet, tet, barycentric_coordinates);
583
574
 
584
575
  // apply visibility term
585
- vec4 weights = lvp_mask_weights_by_visibility(lookup_position, normal, view_direction, tet, barycentric_coordinates);
576
+ vec4 weights = lvp_mask_weights_by_visibility(position, normal, view_direction, tet, barycentric_coordinates);
586
577
 
587
578
  if (tet == INVALID_TET) {
588
579
  // do nothing
@@ -1 +1 @@
1
- {"version":3,"file":"makeOctahedralDepthAtlas.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/sh3/gi/material/makeOctahedralDepthAtlas.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,sDAHW,MAAM,GACJ,WAAW,CAsBvB;4BA3BqF,OAAO"}
1
+ {"version":3,"file":"makeOctahedralDepthAtlas.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/sh3/gi/material/makeOctahedralDepthAtlas.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,sDAHW,MAAM,GACJ,WAAW,CAwBvB;4BA7BoF,OAAO"}
@@ -1,4 +1,4 @@
1
- import { ClampToEdgeWrapping, DataTexture, FloatType, NearestFilter, RedFormat } from "three";
1
+ import { ClampToEdgeWrapping, DataTexture, FloatType, NearestFilter, RGFormat } from "three";
2
2
 
3
3
  /**
4
4
  *
@@ -7,10 +7,10 @@ import { ClampToEdgeWrapping, DataTexture, FloatType, NearestFilter, RedFormat }
7
7
  */
8
8
  export function makeOctahedralDepthAtlas(resolution = 4096) {
9
9
  const texture = new DataTexture(
10
- new Float32Array(resolution * resolution),
10
+ new Float32Array(resolution * resolution * 2),
11
11
  resolution,
12
12
  resolution,
13
- RedFormat,
13
+ RGFormat,
14
14
  FloatType
15
15
  );
16
16
 
@@ -24,5 +24,7 @@ export function makeOctahedralDepthAtlas(resolution = 4096) {
24
24
 
25
25
  texture.needsUpdate = true;
26
26
 
27
+ texture.internalFormat = "RG32F";
28
+
27
29
  return texture;
28
30
  }
@@ -38,7 +38,7 @@ export class LightProbeVolume {
38
38
  #probe_depth_resolution = 16;
39
39
 
40
40
  /**
41
- * Octahedral-encoded depth map for each probe
41
+ * Octahedral-encoded depth map for each probe, 2 channels for mean and mean squared for variance recovery in the shader
42
42
  * @type {number[]}
43
43
  */
44
44
  #probe_depth = [];
@@ -90,7 +90,7 @@ export class LightProbeVolumeBaker {
90
90
  depth_resolution,
91
91
  max_depth,
92
92
  lpv.points, position_offset,
93
- lpv.depth, probe_index * probe_element_count
93
+ lpv.depth, probe_index * probe_element_count * 2
94
94
  );
95
95
  }
96
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PathTracerProbeRenderer.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/sh3/lpv/PathTracerProbeRenderer.js"],"names":[],"mappings":"AAuBA;IACI,mBAA0B;IAC1B,yBAAqB;IACrB,qBAAoB;IACpB,qBAAyB;IAEzB,uBAA6B;IAE7B;;;;;;;;OAQG;IACH,kCAPW,MAAM,aACN,MAAM,YACN,MAAM,EAAE,mBACR,MAAM,UACN,MAAM,EAAE,iBACR,MAAM,QAahB;IAED,iFAuCC;IAKD,mBACC;IAED,4BAKC;CACJ;8BA5F6B,oBAAoB;2BAHvB,8BAA8B;gCADzB,mCAAmC"}
1
+ {"version":3,"file":"PathTracerProbeRenderer.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/sh3/lpv/PathTracerProbeRenderer.js"],"names":[],"mappings":"AAuBA;IACI,mBAA0B;IAC1B,yBAAqB;IAErB,qBAAoB;IACpB,qBAAyB;IAEzB,uBAA6B;IAE7B;;;;;;;;OAQG;IACH,kCAPW,MAAM,aACN,MAAM,YACN,MAAM,EAAE,mBACR,MAAM,UACN,MAAM,EAAE,iBACR,MAAM,QAahB;IAED,iFAuCC;IAKD,mBACC;IAED,4BAKC;CACJ;8BA7F6B,oBAAoB;2BAHvB,8BAA8B;gCADzB,mCAAmC"}
@@ -23,8 +23,9 @@ const sampled_irradiance = new Float32Array(3);
23
23
 
24
24
  export class PathTracerProbeRenderer extends ProbeRenderer {
25
25
  tracer = new PathTracer();
26
- max_bounce_count = 7;
27
- sample_count = 1024;
26
+ max_bounce_count = 5;
27
+ // sample_count = 190;
28
+ sample_count = 4096;
28
29
  random = seededRandom(0);
29
30
 
30
31
  scene = new PathTracedScene()
@@ -1 +1 @@
1
- {"version":3,"file":"bake_octahedral_depth_map.d.ts","sourceRoot":"","sources":["../../../../../../../../src/engine/graphics/sh3/lpv/depth/octahedral/bake_octahedral_depth_map.js"],"names":[],"mappings":"AAiCA;;;;;;;;;GASG;AACH,kDARW,MAAM,EAAE,iBACR,MAAM,oCAEN,MAAM,EAAE,UAAQ,mBAChB,MAAM,cACN,MAAM,aACN,MAAM,QAuHhB"}
1
+ {"version":3,"file":"bake_octahedral_depth_map.d.ts","sourceRoot":"","sources":["../../../../../../../../src/engine/graphics/sh3/lpv/depth/octahedral/bake_octahedral_depth_map.js"],"names":[],"mappings":"AAkCA;;;;;;;;;GASG;AACH,kDARW,MAAM,EAAE,iBACR,MAAM,oCAEN,MAAM,EAAE,UAAQ,mBAChB,MAAM,cACN,MAAM,aACN,MAAM,QAkIhB"}
@@ -7,6 +7,7 @@ import {
7
7
  import { Ray3 } from "../../../../../../core/geom/3d/Ray3.js";
8
8
  import { v3_distance } from "../../../../../../core/geom/vec3/v3_distance.js";
9
9
  import { v3_dot_array_array } from "../../../../../../core/geom/vec3/v3_dot_array_array.js";
10
+ import { clamp } from "../../../../../../core/math/clamp.js";
10
11
  import { max2 } from "../../../../../../core/math/max2.js";
11
12
  import { generate_hammersley_jitter } from "../../../../../../core/math/statistics/generate_hammersley_jitter.js";
12
13
 
@@ -14,7 +15,7 @@ import { generate_hammersley_jitter } from "../../../../../../core/math/statisti
14
15
  * Weights of rays that are aligned with the probe direction get exponentially weighted by this exponent
15
16
  * @type {number}
16
17
  */
17
- const DEPTH_SHARPNESS = 40;
18
+ const DEPTH_SHARPNESS = 3;
18
19
 
19
20
  const scratch_ray = new Ray3();
20
21
 
@@ -28,7 +29,7 @@ const ray_hit = [];
28
29
  *
29
30
  * @type {number}
30
31
  */
31
- const SUB_SAMPLE_COUNT = 4;
32
+ const SUB_SAMPLE_COUNT = 16;
32
33
 
33
34
 
34
35
  /**
@@ -71,7 +72,9 @@ export function bake_octahedral_depth_map(
71
72
  */
72
73
  const RESOLUTION_BIAS = Math.sin(texel_angular_coverage) * Math.SQRT2 * 2;
73
74
 
74
- const NORMAL_BIAS = max2(0.01, max_depth * 0.01) + 1e-6;
75
+ // const NORMAL_BIAS = max2(1e-6, max_depth * 0.01);
76
+ const NORMAL_BIAS = 1e-6;
77
+ // const NORMAL_BIAS = clamp(max_depth * Math.sin(texel_angular_coverage),1e-6, max_depth*0.1);
75
78
 
76
79
  const ray_direction = scratch_ray.direction;
77
80
 
@@ -86,12 +89,18 @@ export function bake_octahedral_depth_map(
86
89
  for (let oct_y = 0; oct_y < resolution; oct_y++) {
87
90
 
88
91
  let distance_sum = 0;
92
+ let distance2_sum = 0;
89
93
  let weight_sum = 0;
90
94
 
91
95
  // offset position by half a pixel, as we are storing values for pixel centers
92
96
  const u = (oct_x + 0.5) / (resolution);
93
97
  const v = (oct_y + 0.5) / (resolution);
94
98
 
99
+ decode_octahedron_to_unit(
100
+ probe_direction, 0,
101
+ u * 2 - 1, v * 2 - 1
102
+ );
103
+
95
104
  for (let sub_sample_index = 0; sub_sample_index < SUB_SAMPLE_COUNT; sub_sample_index++) {
96
105
 
97
106
  const sample_index2 = sub_sample_index * 2;
@@ -121,7 +130,7 @@ export function bake_octahedral_depth_map(
121
130
  const surface_position_y = ray_hit[1];
122
131
  const surface_position_z = ray_hit[2];
123
132
 
124
- const hit_normal_bias = -NORMAL_BIAS;
133
+ const hit_normal_bias = NORMAL_BIAS;
125
134
 
126
135
  // sink the contact into the surface along the hit normal
127
136
  const biased_hit_x = surface_position_x + surface_normal_x * hit_normal_bias;
@@ -145,16 +154,19 @@ export function bake_octahedral_depth_map(
145
154
  );
146
155
 
147
156
  distance_sum += distance * weight;
157
+ distance2_sum += distance * distance * weight;
148
158
  weight_sum += weight;
149
159
  }
150
160
 
151
161
  const pixel_index = oct_y * resolution + oct_x;
152
162
 
153
- const address = result_offset + pixel_index;
163
+ const address = result_offset + pixel_index * 2;
154
164
 
155
- const distance = distance_sum / weight_sum;
165
+ const mean = distance_sum / weight_sum;
166
+ const mean2 = distance2_sum / weight_sum;
156
167
 
157
- result[address] = distance;
168
+ result[address] = mean;
169
+ result[address + 1] = mean2;
158
170
  }
159
171
  }
160
172