@woosh/meep-engine 3.11.1 → 3.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.
- package/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +294 -290
- package/src/engine/graphics3/ParticipatingMedia.d.ts +111 -0
- package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMedia.js +203 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts +34 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.js +73 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts +87 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.js +184 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts +16 -2
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +28 -4
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +1 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +5 -2
- package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +564 -451
- package/src/shade/device/ShadeGPUCommandContext.d.ts +18 -2
- package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
- package/src/shade/device/ShadeGPUCommandContext.js +994 -940
- package/src/shade/device/immediate_data_supported.d.ts +33 -0
- package/src/shade/device/immediate_data_supported.d.ts.map +1 -0
- package/src/shade/device/immediate_data_supported.js +53 -0
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.d.ts +18 -0
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.js +24 -0
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.d.ts +7 -0
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.js +49 -1
- package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUDevice.js +20 -2
- package/src/shade/device/mock/SoftwareGPUImmediateData.d.ts +65 -0
- package/src/shade/device/mock/SoftwareGPUImmediateData.d.ts.map +1 -0
- package/src/shade/device/mock/SoftwareGPUImmediateData.js +160 -0
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts +7 -0
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.js +50 -0
- package/src/shade/device/mock/pipeline_immediate_size.d.ts +11 -0
- package/src/shade/device/mock/pipeline_immediate_size.d.ts.map +1 -0
- package/src/shade/device/mock/pipeline_immediate_size.js +18 -0
- package/src/shade/device/pipeline/PipelineLayoutManager.d.ts.map +1 -1
- package/src/shade/device/pipeline/PipelineLayoutManager.js +1 -0
- package/src/shade/playground/volumetrics_froxel/README.md +104 -1
- package/src/shade/playground/volumetrics_froxel/index.html +20 -1
- package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/main.js +298 -0
- package/src/shade/playground/volumetrics_froxel/measure.d.ts +119 -0
- package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -0
- package/src/shade/playground/volumetrics_froxel/measure.js +559 -0
- package/src/shade/renderer/GraphicsContext.d.ts +9 -2
- package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
- package/src/shade/renderer/GraphicsContext.js +13 -1
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +22 -18
- package/src/shade/renderer/atmosphere/GPUSky.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/GPUSky.js +145 -142
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts +34 -0
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.js +36 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.d.ts +20 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.js +25 -0
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts +14 -1
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.js +163 -177
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.d.ts +20 -0
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.js +46 -0
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.d.ts +11 -1
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.js +57 -27
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.d.ts +19 -1
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.js +69 -33
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.d.ts +13 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.js +35 -35
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.d.ts +13 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.js +38 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.d.ts +17 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.js +29 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.d.ts +21 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.js +42 -0
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts +2 -2
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.js +165 -84
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.js +215 -204
- package/src/shade/renderer/atmosphere/shader_transmittance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +79 -67
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +6 -2
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/GTAO.js +4 -0
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +341 -345
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +0 -2
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +58 -57
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +7 -3
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +77 -81
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +5 -1
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +6 -2
- package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ImageShader.js +4 -1
- package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/ShaderDescriptor.js +26 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.d.ts +18 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.js +32 -0
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.d.ts +7 -0
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.js +17 -6
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.d.ts +21 -0
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.js +69 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.d.ts +9 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.js +22 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.d.ts +16 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.js +41 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.d.ts +11 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.js +15 -19
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.d.ts +23 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.js +44 -0
- package/src/shade/renderer/shader/chunk/geometry/octahedron/chunk_uv_octahedral_unit_decode.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/octahedron/chunk_uv_octahedral_unit_decode.js +1 -4
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts +7 -1
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts.map +1 -1
- package/src/shade/renderer/shader/compiler/CodeChunk.js +37 -2
- package/src/shade/renderer/shader/graph/compute/compute_binding_read_names.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/compute/compute_binding_read_names.js +6 -0
- package/src/shade/renderer/shader/graph/compute/graph_compute_indirect_pass.js +1 -1
- package/src/shade/renderer/shader/graph/compute/graph_compute_pass.js +1 -1
- package/src/shade/renderer/shader/graph/graph_image_pass.js +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_bindings.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_bindings.js +7 -0
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts +3 -1
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.js +12 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +1 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.d.ts +21 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.d.ts.map +1 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.js +21 -0
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts +59 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +195 -2
- package/src/shade/renderer/shader/type/type_has_arrays.d.ts +14 -0
- package/src/shade/renderer/shader/type/type_has_arrays.d.ts.map +1 -0
- package/src/shade/renderer/shader/type/type_has_arrays.js +33 -0
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts +14 -13
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.js +133 -129
- package/src/shade/renderer/view/GPUViewSkyContext.d.ts.map +1 -1
- package/src/shade/renderer/view/GPUViewSkyContext.js +169 -173
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +480 -315
- package/src/shade/renderer/volumetrics/NOTES.md +887 -8
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +5 -0
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +21 -2
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts +26 -0
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/SceneVolumetrics.js +64 -21
- package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js +84 -28
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts +98 -0
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.js +111 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts +84 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.js +252 -0
- package/src/shade/renderer/volumetrics/chunk_integrate_optical_depth.js +75 -75
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.d.ts +43 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.js +145 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts +20 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.js +48 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts +38 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.js +130 -0
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +18 -3
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +193 -70
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts +16 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +83 -15
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.js +29 -18
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_scattering_lut.js +260 -260
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts +58 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.js +290 -0
- package/src/shade/wgsl/emulator/CPUBitmapData.d.ts +25 -0
- package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/CPUBitmapData.js +33 -0
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +2228 -2215
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +210 -2
- package/src/shade/wgsl/emulator/cpu_texture_gather.d.ts +69 -0
- package/src/shade/wgsl/emulator/cpu_texture_gather.d.ts.map +1 -0
- package/src/shade/wgsl/emulator/cpu_texture_gather.js +148 -0
- package/src/shade/wgsl/emulator/cpu_texture_sample.d.ts +16 -0
- package/src/shade/wgsl/emulator/cpu_texture_sample.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/cpu_texture_sample.js +176 -172
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.d.ts +0 -2
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.d.ts.map +0 -1
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WGSLLanguageCore.d.ts","sourceRoot":"","sources":["../../../../../src/shade/wgsl/emulator/WGSLLanguageCore.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WGSLLanguageCore.d.ts","sourceRoot":"","sources":["../../../../../src/shade/wgsl/emulator/WGSLLanguageCore.js"],"names":[],"mappings":"AA0PA;;;;;;;;;;;;GAYG;AACH,+BAFU,MAAM,CAm+Bd"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../../core/assert.js";
|
|
2
|
+
import { cpu_texture_gather, evaluate_gpu_compare_function } from "./cpu_texture_gather.js";
|
|
2
3
|
import { cpu_texture_sample } from "./cpu_texture_sample.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -15,6 +16,20 @@ const FALLBACK_LINEAR_CLAMP_SAMPLER = Object.freeze({
|
|
|
15
16
|
mipmapFilter: "nearest",
|
|
16
17
|
});
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Normalised UV -> texel space, for the gather intrinsics. {@link cpu_texture_gather} takes
|
|
21
|
+
* texel-space coordinates, the same convention {@link cpu_texture_sample} documents, so the
|
|
22
|
+
* shader-facing side does the conversion — `textureGather` has no 3D or 1D overload in WGSL,
|
|
23
|
+
* so only the two axes are ever needed.
|
|
24
|
+
*
|
|
25
|
+
* @param {Float32Array | number[]} coords — normalised uv
|
|
26
|
+
* @param {import("./CPUBitmapData.js").CPUBitmapData} texture
|
|
27
|
+
* @returns {number[]}
|
|
28
|
+
*/
|
|
29
|
+
function gather_texel_coord(coords, texture) {
|
|
30
|
+
return [coords[0] * texture.size[0], coords[1] * texture.size[1]];
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
/**
|
|
19
34
|
* Single-element scratch view used to round a number to IEEE 754 binary16 precision.
|
|
20
35
|
* @type {Float16Array}
|
|
@@ -411,6 +426,34 @@ export const WGSLLanguageCore = {
|
|
|
411
426
|
throw new Error(`determinant: unsupported matrix length ${m.length}`);
|
|
412
427
|
},
|
|
413
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Transpose of a square matrix stored as a flat column-major typed array.
|
|
431
|
+
*
|
|
432
|
+
* WGSL's `transpose` also accepts non-square `matCxR`, returning `matRxC`. Matrices here are
|
|
433
|
+
* flat arrays carrying no shape, so a 2x3 and a 3x2 are indistinguishable at runtime and only
|
|
434
|
+
* the square sizes can be answered — the same restriction {@link determinant} works under, for
|
|
435
|
+
* the same reason.
|
|
436
|
+
*
|
|
437
|
+
* @param {Float32Array|Float16Array} m
|
|
438
|
+
*/
|
|
439
|
+
transpose(m) {
|
|
440
|
+
const n = Math.round(Math.sqrt(m.length));
|
|
441
|
+
|
|
442
|
+
if (n * n !== m.length || n < 2 || n > 4) {
|
|
443
|
+
throw new Error(`transpose: unsupported matrix length ${m.length}, expected a square 2x2, 3x3 or 4x4`);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const out = new m.constructor(m.length);
|
|
447
|
+
|
|
448
|
+
for (let col = 0; col < n; col++) {
|
|
449
|
+
for (let row = 0; row < n; row++) {
|
|
450
|
+
out[col * n + row] = m[row * n + col];
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return out;
|
|
455
|
+
},
|
|
456
|
+
|
|
414
457
|
// ---------------------------------------------------------------------
|
|
415
458
|
// Arithmetic helpers (work on scalars and vectors element-wise)
|
|
416
459
|
// ---------------------------------------------------------------------
|
|
@@ -761,10 +804,15 @@ export const WGSLLanguageCore = {
|
|
|
761
804
|
* across all channels (with alpha defaulting to 1.0 for textures with
|
|
762
805
|
* fewer than 4 channels - matches WGSL semantics).
|
|
763
806
|
*
|
|
807
|
+
* A texture flagged `is_depth` returns a bare `f32` instead, matching WGSL: `textureLoad` on a
|
|
808
|
+
* `texture_depth_*` is declared to yield a scalar, and shader code written against one uses it
|
|
809
|
+
* as such. Handing that code a vec4 would turn every use into a component-wise broadcast that
|
|
810
|
+
* neither throws nor matches the device.
|
|
811
|
+
*
|
|
764
812
|
* @param {import("./CPUBitmapData.js").CPUBitmapData} t
|
|
765
813
|
* @param {Int32Array | Uint32Array | number[] | number} coords
|
|
766
814
|
* @param {number} [_level] - ignored, mipmaps are not modelled
|
|
767
|
-
* @returns {Float32Array}
|
|
815
|
+
* @returns {Float32Array | number}
|
|
768
816
|
*/
|
|
769
817
|
textureLoad(t, coords, _level_or_index = 0, _array_level = undefined) {
|
|
770
818
|
assert.defined(t, 'texture');
|
|
@@ -780,8 +828,14 @@ export const WGSLLanguageCore = {
|
|
|
780
828
|
*/
|
|
781
829
|
const z = (_array_level !== undefined ? _level_or_index : (dim >= 3 ? coords[2] : 0)) | 0;
|
|
782
830
|
const item_size = t.item_size;
|
|
831
|
+
const out_of_bounds = x < 0 || x >= t.size[0] || y < 0 || y >= t.size[1] || z < 0 || z >= t.size[2];
|
|
832
|
+
|
|
833
|
+
if (t.is_depth === true) {
|
|
834
|
+
return out_of_bounds ? 0.0 : t.data[t.pixel_offset(x, y, z)];
|
|
835
|
+
}
|
|
836
|
+
|
|
783
837
|
if (item_size < 4) out[3] = 1.0;
|
|
784
|
-
if (
|
|
838
|
+
if (out_of_bounds) {
|
|
785
839
|
return out;
|
|
786
840
|
}
|
|
787
841
|
const base = t.pixel_offset(x, y, z);
|
|
@@ -878,6 +932,160 @@ export const WGSLLanguageCore = {
|
|
|
878
932
|
return WGSLLanguageCore.textureSampleLevel(t, sampler, coords, 0);
|
|
879
933
|
},
|
|
880
934
|
|
|
935
|
+
/**
|
|
936
|
+
* `textureGather(component, t, s, coords[, array_index][, offset]) -> vec4<f32>` and the
|
|
937
|
+
* depth-texture overloads `textureGather(t, s, coords[, array_index][, offset])`, which carry
|
|
938
|
+
* no `component` argument because a `texture_depth_*` has a single channel.
|
|
939
|
+
*
|
|
940
|
+
* Returns the four texels of the bilinear footprint unblended, in WGSL's order —
|
|
941
|
+
* counter-clockwise from the lower-left, so `.wzxy` is row-major. See
|
|
942
|
+
* {@link cpu_texture_gather} for the footprint derivation, the component order in full, and
|
|
943
|
+
* why `magFilter` is ignored here (a gather never filters).
|
|
944
|
+
*
|
|
945
|
+
* Overloads are told apart by argument SHAPE, the way `textureLoad` and `textureSampleLevel`
|
|
946
|
+
* already tell their array forms apart: a leading number is the `component` of a colour
|
|
947
|
+
* gather, a leading texture means the depth overload; among the trailing arguments a number
|
|
948
|
+
* is an `array_index` and a vector is the const `offset`.
|
|
949
|
+
*
|
|
950
|
+
* **Cube textures are not supported** and throw rather than returning something. The emulator
|
|
951
|
+
* models no cube layout at all — {@link CPUBitmapData} is a flat 1D/2D/3D grid — so there is
|
|
952
|
+
* no face selection to gather across. A cube gather is recognisable by its `vec3` direction
|
|
953
|
+
* coordinate (`texture_3d` has no gather overload in WGSL at all).
|
|
954
|
+
*
|
|
955
|
+
* @param {number | import("./CPUBitmapData.js").CPUBitmapData} p0 — `component`, or the
|
|
956
|
+
* texture in the depth overloads
|
|
957
|
+
* @param {*} p1
|
|
958
|
+
* @param {*} p2
|
|
959
|
+
* @param {*} p3
|
|
960
|
+
* @param {*} [p4]
|
|
961
|
+
* @param {*} [p5]
|
|
962
|
+
* @returns {Float32Array}
|
|
963
|
+
*/
|
|
964
|
+
textureGather(p0, p1, p2, p3, p4 = undefined, p5 = undefined) {
|
|
965
|
+
const has_component = typeof p0 === 'number';
|
|
966
|
+
|
|
967
|
+
const t = has_component ? p1 : p0;
|
|
968
|
+
const sampler = has_component ? p2 : p1;
|
|
969
|
+
const coords = has_component ? p3 : p2;
|
|
970
|
+
|
|
971
|
+
assert.defined(t, 'texture');
|
|
972
|
+
|
|
973
|
+
if (coords !== null && coords !== undefined && coords.length >= 3) {
|
|
974
|
+
throw new Error("textureGather: cube textures are not supported — the emulator has no cube layout to gather a face out of (CPUBitmapData is a flat 1D/2D/3D grid). Remap to an octahedral or array atlas, as the engine's shadow path does, and gather from that.");
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
const component = has_component ? (p0 | 0) : 0;
|
|
978
|
+
|
|
979
|
+
let array_index = 0;
|
|
980
|
+
let offset_x = 0;
|
|
981
|
+
let offset_y = 0;
|
|
982
|
+
|
|
983
|
+
const extra_a = has_component ? p4 : p3;
|
|
984
|
+
const extra_b = has_component ? p5 : p4;
|
|
985
|
+
|
|
986
|
+
if (typeof extra_a === 'number') array_index = extra_a;
|
|
987
|
+
else if (extra_a !== undefined) { offset_x = extra_a[0]; offset_y = extra_a[1]; }
|
|
988
|
+
|
|
989
|
+
if (extra_b !== undefined) { offset_x = extra_b[0]; offset_y = extra_b[1]; }
|
|
990
|
+
|
|
991
|
+
const result = new Float32Array(4);
|
|
992
|
+
|
|
993
|
+
cpu_texture_gather(
|
|
994
|
+
result,
|
|
995
|
+
sampler ?? FALLBACK_LINEAR_CLAMP_SAMPLER,
|
|
996
|
+
t,
|
|
997
|
+
gather_texel_coord(coords, t),
|
|
998
|
+
component,
|
|
999
|
+
offset_x,
|
|
1000
|
+
offset_y,
|
|
1001
|
+
array_index
|
|
1002
|
+
);
|
|
1003
|
+
|
|
1004
|
+
return result;
|
|
1005
|
+
},
|
|
1006
|
+
|
|
1007
|
+
/**
|
|
1008
|
+
* `textureGatherCompare(t, s, coords[, array_index], depth_ref[, offset]) -> vec4<f32>`
|
|
1009
|
+
*
|
|
1010
|
+
* The comparison form: each of the four gathered texels is tested against `depth_ref` and
|
|
1011
|
+
* yields 1.0 or 0.0 — unfiltered, per texel. The blend is the shader's job, which is exactly
|
|
1012
|
+
* what `shadowmap_sample_filtered` does with the result (`.wzxy` into
|
|
1013
|
+
* `interpolate_bilinear_f32`).
|
|
1014
|
+
*
|
|
1015
|
+
* The comparison itself comes from the bound sampler's `compare`, evaluated as
|
|
1016
|
+
* `compare(depth_ref, texel)` — see {@link evaluate_gpu_compare_function} for why that order
|
|
1017
|
+
* is load-bearing. A sampler with no `compare` set is an error rather than a defaulted one:
|
|
1018
|
+
* WGSL requires a `sampler_comparison` here, and picking a direction on the caller's behalf
|
|
1019
|
+
* would invert shadows silently.
|
|
1020
|
+
*
|
|
1021
|
+
* Overload disambiguation is by shape, as in {@link textureGather}: a trailing vector is the
|
|
1022
|
+
* const `offset`, and a fourth argument that is followed by another number is the
|
|
1023
|
+
* `array_index` rather than the reference depth.
|
|
1024
|
+
*
|
|
1025
|
+
* @param {import("./CPUBitmapData.js").CPUBitmapData} t
|
|
1026
|
+
* @param {import("../../descriptor/texture/SamplerDescriptor.js").SamplerDescriptor} sampler
|
|
1027
|
+
* @param {Float32Array | number[]} coords
|
|
1028
|
+
* @param {*} p3 — `depth_ref`, or the `array_index` in the array forms
|
|
1029
|
+
* @param {*} [p4]
|
|
1030
|
+
* @param {*} [p5]
|
|
1031
|
+
* @returns {Float32Array}
|
|
1032
|
+
*/
|
|
1033
|
+
textureGatherCompare(t, sampler, coords, p3, p4 = undefined, p5 = undefined) {
|
|
1034
|
+
assert.defined(t, 'texture');
|
|
1035
|
+
|
|
1036
|
+
if (coords !== null && coords !== undefined && coords.length >= 3) {
|
|
1037
|
+
throw new Error("textureGatherCompare: cube textures are not supported — the emulator has no cube layout to gather a face out of (CPUBitmapData is a flat 1D/2D/3D grid). Remap to an octahedral or array atlas, as the engine's shadow path does, and gather from that.");
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
let array_index = 0;
|
|
1041
|
+
let depth_ref;
|
|
1042
|
+
let offset = undefined;
|
|
1043
|
+
|
|
1044
|
+
if (p5 !== undefined) {
|
|
1045
|
+
// (t, s, coords, array_index, depth_ref, offset)
|
|
1046
|
+
array_index = p3;
|
|
1047
|
+
depth_ref = p4;
|
|
1048
|
+
offset = p5;
|
|
1049
|
+
} else if (p4 === undefined) {
|
|
1050
|
+
// (t, s, coords, depth_ref)
|
|
1051
|
+
depth_ref = p3;
|
|
1052
|
+
} else if (typeof p4 === 'number') {
|
|
1053
|
+
// (t, s, coords, array_index, depth_ref) — a scalar in the 5th slot is the reference
|
|
1054
|
+
array_index = p3;
|
|
1055
|
+
depth_ref = p4;
|
|
1056
|
+
} else {
|
|
1057
|
+
// (t, s, coords, depth_ref, offset) — a vector in the 5th slot is the offset
|
|
1058
|
+
depth_ref = p3;
|
|
1059
|
+
offset = p4;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
const effective_sampler = sampler ?? FALLBACK_LINEAR_CLAMP_SAMPLER;
|
|
1063
|
+
const compare = effective_sampler.compare;
|
|
1064
|
+
|
|
1065
|
+
if (compare === undefined || compare === null) {
|
|
1066
|
+
throw new Error("textureGatherCompare: the bound sampler has no 'compare' function — WGSL requires a sampler_comparison here. Bind a SamplerDescriptor with `compare` set (the engine's shadow path uses SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR, `compare: \"greater\"` for reverse-Z).");
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
const result = new Float32Array(4);
|
|
1070
|
+
|
|
1071
|
+
cpu_texture_gather(
|
|
1072
|
+
result,
|
|
1073
|
+
effective_sampler,
|
|
1074
|
+
t,
|
|
1075
|
+
gather_texel_coord(coords, t),
|
|
1076
|
+
0,
|
|
1077
|
+
offset !== undefined ? offset[0] : 0,
|
|
1078
|
+
offset !== undefined ? offset[1] : 0,
|
|
1079
|
+
array_index
|
|
1080
|
+
);
|
|
1081
|
+
|
|
1082
|
+
for (let i = 0; i < 4; i++) {
|
|
1083
|
+
result[i] = evaluate_gpu_compare_function(compare, depth_ref, result[i]);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
return result;
|
|
1087
|
+
},
|
|
1088
|
+
|
|
881
1089
|
/**
|
|
882
1090
|
* `textureStore(t, coords, value) -> ()`
|
|
883
1091
|
*
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read the four texels of a bilinear footprint out of a {@link CPUBitmapData} without
|
|
3
|
+
* blending them — the CPU side of WGSL's `textureGather` / `textureGatherCompare`.
|
|
4
|
+
*
|
|
5
|
+
* **The footprint is the linear filter's footprint.** `cpu_texture_sample` derives it as
|
|
6
|
+
* `px = texel_coord - 0.5`, then `floor(px)` and `floor(px) + 1` on each axis, each index
|
|
7
|
+
* passed through {@link wrap_int} for the address mode. A gather covers exactly those four
|
|
8
|
+
* texels, so this function reuses that arithmetic rather than restating it.
|
|
9
|
+
*
|
|
10
|
+
* **`magFilter` is deliberately ignored.** A gather always returns four texels — the
|
|
11
|
+
* sampler's filter mode selects nothing, because no filtering happens. This is the one
|
|
12
|
+
* place `cpu_texture_sample` cannot simply be called: under `magFilter: "nearest"` it
|
|
13
|
+
* collapses to a single texel, which is right for a sample and wrong for a gather. The
|
|
14
|
+
* address modes still apply, and they are the only part of the sampler this reads.
|
|
15
|
+
*
|
|
16
|
+
* **Mipmaps are not modelled — LOD 0 only.** Same stance, and for the same reason, as
|
|
17
|
+
* {@link cpu_texture_sample}; see its header. `textureGather` has no LOD parameter in WGSL
|
|
18
|
+
* anyway, so here the restriction costs nothing.
|
|
19
|
+
*
|
|
20
|
+
* Convention for `texel_coord`, as in {@link cpu_texture_sample}: **texel-space**
|
|
21
|
+
* coordinates (UV * size), not normalised UV. The shader-facing intrinsics in
|
|
22
|
+
* {@link WGSLLanguageCore} do the conversion before calling.
|
|
23
|
+
*
|
|
24
|
+
* Component order is WGSL's, counter-clockwise from the lower-left texel — the same order
|
|
25
|
+
* D3D and Vulkan use:
|
|
26
|
+
*
|
|
27
|
+
* ```
|
|
28
|
+
* output[0] = (u_min, v_max) lower-left
|
|
29
|
+
* output[1] = (u_max, v_max) lower-right
|
|
30
|
+
* output[2] = (u_max, v_min) upper-right
|
|
31
|
+
* output[3] = (u_min, v_min) upper-left
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* so `gathered.wzxy` is the row-major (x0y0, x1y0, x0y1, x1y1) order a bilinear blend
|
|
35
|
+
* wants — which is exactly the swizzle `shadowmap_sample_filtered` applies before handing
|
|
36
|
+
* the result to `interpolate_bilinear_f32`.
|
|
37
|
+
*
|
|
38
|
+
* @param {Float32Array | number[]} output — receives the 4 gathered texel values
|
|
39
|
+
* @param {import("../../descriptor/texture/SamplerDescriptor.js").SamplerDescriptor} sampler
|
|
40
|
+
* @param {import("./CPUBitmapData.js").CPUBitmapData} texture
|
|
41
|
+
* @param {Float32Array | number[]} texel_coord — `[x, y]` in texel space
|
|
42
|
+
* @param {number} [component] — channel to read, 0..3. Forced to 0 for a depth texture,
|
|
43
|
+
* which has a single channel and whose WGSL overloads take no component argument.
|
|
44
|
+
* @param {number} [offset_x] — const `vec2<i32>` offset, applied to the integer texel
|
|
45
|
+
* indices *before* the address mode, per WGSL
|
|
46
|
+
* @param {number} [offset_y]
|
|
47
|
+
* @param {number} [layer] — array slice for the `_2d_array` forms; clamped to the
|
|
48
|
+
* texture's depth
|
|
49
|
+
*/
|
|
50
|
+
export function cpu_texture_gather(output: Float32Array | number[], sampler: import("../../descriptor/texture/SamplerDescriptor.js").SamplerDescriptor, texture: import("./CPUBitmapData.js").CPUBitmapData, texel_coord: Float32Array | number[], component?: number, offset_x?: number, offset_y?: number, layer?: number): void;
|
|
51
|
+
/**
|
|
52
|
+
* Evaluate a `GPUCompareFunction` the way a comparison sampler does.
|
|
53
|
+
*
|
|
54
|
+
* **Argument order matters and is easy to invert.** WebGPU evaluates
|
|
55
|
+
* `compare(reference, sampled)` — the shader's `depth_ref` is the LEFT operand, the value
|
|
56
|
+
* read out of the depth texture is the right one. So under `"greater"` (what the engine's
|
|
57
|
+
* {@link SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR} uses, because shadow maps are reverse-Z) a
|
|
58
|
+
* receiver passes — result 1.0, "lit" — when its own depth is *greater* than the stored
|
|
59
|
+
* occluder depth, i.e. when it is nearer to the light. Swapping the operands inverts every
|
|
60
|
+
* shadow in the engine while still producing plausible-looking output, which is why
|
|
61
|
+
* `cpu_texture_gather.spec.js` pins the direction explicitly.
|
|
62
|
+
*
|
|
63
|
+
* @param {GPUCompareFunction} compare
|
|
64
|
+
* @param {number} reference — the shader's `depth_ref`
|
|
65
|
+
* @param {number} sampled — the texel read from the depth texture
|
|
66
|
+
* @returns {number} 1.0 when the comparison passes, 0.0 when it fails
|
|
67
|
+
*/
|
|
68
|
+
export function evaluate_gpu_compare_function(compare: GPUCompareFunction, reference: number, sampled: number): number;
|
|
69
|
+
//# sourceMappingURL=cpu_texture_gather.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpu_texture_gather.d.ts","sourceRoot":"","sources":["../../../../../src/shade/wgsl/emulator/cpu_texture_gather.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,2CAZW,YAAY,GAAG,MAAM,EAAE,WACvB,OAAO,+CAA+C,EAAE,iBAAiB,WACzE,OAAO,oBAAoB,EAAE,aAAa,eAC1C,YAAY,GAAG,MAAM,EAAE,cACvB,MAAM,aAEN,MAAM,aAEN,MAAM,UACN,MAAM,QAqChB;AAwBD;;;;;;;;;;;;;;;;GAgBG;AACH,sFAJW,MAAM,WACN,MAAM,GACJ,MAAM,CAuBlB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { wrap_int } from "./cpu_texture_sample.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Read the four texels of a bilinear footprint out of a {@link CPUBitmapData} without
|
|
5
|
+
* blending them — the CPU side of WGSL's `textureGather` / `textureGatherCompare`.
|
|
6
|
+
*
|
|
7
|
+
* **The footprint is the linear filter's footprint.** `cpu_texture_sample` derives it as
|
|
8
|
+
* `px = texel_coord - 0.5`, then `floor(px)` and `floor(px) + 1` on each axis, each index
|
|
9
|
+
* passed through {@link wrap_int} for the address mode. A gather covers exactly those four
|
|
10
|
+
* texels, so this function reuses that arithmetic rather than restating it.
|
|
11
|
+
*
|
|
12
|
+
* **`magFilter` is deliberately ignored.** A gather always returns four texels — the
|
|
13
|
+
* sampler's filter mode selects nothing, because no filtering happens. This is the one
|
|
14
|
+
* place `cpu_texture_sample` cannot simply be called: under `magFilter: "nearest"` it
|
|
15
|
+
* collapses to a single texel, which is right for a sample and wrong for a gather. The
|
|
16
|
+
* address modes still apply, and they are the only part of the sampler this reads.
|
|
17
|
+
*
|
|
18
|
+
* **Mipmaps are not modelled — LOD 0 only.** Same stance, and for the same reason, as
|
|
19
|
+
* {@link cpu_texture_sample}; see its header. `textureGather` has no LOD parameter in WGSL
|
|
20
|
+
* anyway, so here the restriction costs nothing.
|
|
21
|
+
*
|
|
22
|
+
* Convention for `texel_coord`, as in {@link cpu_texture_sample}: **texel-space**
|
|
23
|
+
* coordinates (UV * size), not normalised UV. The shader-facing intrinsics in
|
|
24
|
+
* {@link WGSLLanguageCore} do the conversion before calling.
|
|
25
|
+
*
|
|
26
|
+
* Component order is WGSL's, counter-clockwise from the lower-left texel — the same order
|
|
27
|
+
* D3D and Vulkan use:
|
|
28
|
+
*
|
|
29
|
+
* ```
|
|
30
|
+
* output[0] = (u_min, v_max) lower-left
|
|
31
|
+
* output[1] = (u_max, v_max) lower-right
|
|
32
|
+
* output[2] = (u_max, v_min) upper-right
|
|
33
|
+
* output[3] = (u_min, v_min) upper-left
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* so `gathered.wzxy` is the row-major (x0y0, x1y0, x0y1, x1y1) order a bilinear blend
|
|
37
|
+
* wants — which is exactly the swizzle `shadowmap_sample_filtered` applies before handing
|
|
38
|
+
* the result to `interpolate_bilinear_f32`.
|
|
39
|
+
*
|
|
40
|
+
* @param {Float32Array | number[]} output — receives the 4 gathered texel values
|
|
41
|
+
* @param {import("../../descriptor/texture/SamplerDescriptor.js").SamplerDescriptor} sampler
|
|
42
|
+
* @param {import("./CPUBitmapData.js").CPUBitmapData} texture
|
|
43
|
+
* @param {Float32Array | number[]} texel_coord — `[x, y]` in texel space
|
|
44
|
+
* @param {number} [component] — channel to read, 0..3. Forced to 0 for a depth texture,
|
|
45
|
+
* which has a single channel and whose WGSL overloads take no component argument.
|
|
46
|
+
* @param {number} [offset_x] — const `vec2<i32>` offset, applied to the integer texel
|
|
47
|
+
* indices *before* the address mode, per WGSL
|
|
48
|
+
* @param {number} [offset_y]
|
|
49
|
+
* @param {number} [layer] — array slice for the `_2d_array` forms; clamped to the
|
|
50
|
+
* texture's depth
|
|
51
|
+
*/
|
|
52
|
+
export function cpu_texture_gather(
|
|
53
|
+
output,
|
|
54
|
+
sampler,
|
|
55
|
+
texture,
|
|
56
|
+
texel_coord,
|
|
57
|
+
component = 0,
|
|
58
|
+
offset_x = 0,
|
|
59
|
+
offset_y = 0,
|
|
60
|
+
layer = 0
|
|
61
|
+
) {
|
|
62
|
+
const w = texture.size[0];
|
|
63
|
+
const h = texture.size[1];
|
|
64
|
+
const d = texture.size[2];
|
|
65
|
+
|
|
66
|
+
// A depth texture is single-channel; its gather overloads carry no component argument.
|
|
67
|
+
const channel = texture.is_depth === true ? 0 : (component | 0);
|
|
68
|
+
|
|
69
|
+
// Same derivation as the linear branch of `cpu_texture_sample`: shift by half a texel so
|
|
70
|
+
// the footprint is anchored on texel CENTRES, then floor.
|
|
71
|
+
const x_floor = Math.floor(texel_coord[0] - 0.5) + (offset_x | 0);
|
|
72
|
+
const y_floor = Math.floor(texel_coord[1] - 0.5) + (offset_y | 0);
|
|
73
|
+
|
|
74
|
+
const x0 = wrap_int(x_floor, w, sampler.addressModeU);
|
|
75
|
+
const x1 = wrap_int(x_floor + 1, w, sampler.addressModeU);
|
|
76
|
+
const y0 = wrap_int(y_floor, h, sampler.addressModeV);
|
|
77
|
+
const y1 = wrap_int(y_floor + 1, h, sampler.addressModeV);
|
|
78
|
+
|
|
79
|
+
// The array index is not an address-mode axis — WGSL clamps it to the layer count.
|
|
80
|
+
const z = d <= 0 ? 0 : Math.min(Math.max(layer | 0, 0), d - 1);
|
|
81
|
+
|
|
82
|
+
output[0] = read_channel(texture, x0, y1, z, channel);
|
|
83
|
+
output[1] = read_channel(texture, x1, y1, z, channel);
|
|
84
|
+
output[2] = read_channel(texture, x1, y0, z, channel);
|
|
85
|
+
output[3] = read_channel(texture, x0, y0, z, channel);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* One channel of one texel. Channels past the texture's `item_size` follow the same
|
|
90
|
+
* convention `cpu_texture_sample` uses for its output vector: zero, with alpha defaulting
|
|
91
|
+
* to 1 — matching WGSL's rule for formats with fewer than four channels.
|
|
92
|
+
*
|
|
93
|
+
* Coordinates arrive already wrapped by {@link wrap_int}, so no bounds check is needed.
|
|
94
|
+
*
|
|
95
|
+
* @param {import("./CPUBitmapData.js").CPUBitmapData} texture
|
|
96
|
+
* @param {number} x
|
|
97
|
+
* @param {number} y
|
|
98
|
+
* @param {number} z
|
|
99
|
+
* @param {number} component
|
|
100
|
+
* @returns {number}
|
|
101
|
+
*/
|
|
102
|
+
function read_channel(texture, x, y, z, component) {
|
|
103
|
+
if (component >= texture.item_size) {
|
|
104
|
+
return component === 3 ? 1 : 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return texture.data[texture.pixel_offset(x, y, z) + component];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Evaluate a `GPUCompareFunction` the way a comparison sampler does.
|
|
112
|
+
*
|
|
113
|
+
* **Argument order matters and is easy to invert.** WebGPU evaluates
|
|
114
|
+
* `compare(reference, sampled)` — the shader's `depth_ref` is the LEFT operand, the value
|
|
115
|
+
* read out of the depth texture is the right one. So under `"greater"` (what the engine's
|
|
116
|
+
* {@link SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR} uses, because shadow maps are reverse-Z) a
|
|
117
|
+
* receiver passes — result 1.0, "lit" — when its own depth is *greater* than the stored
|
|
118
|
+
* occluder depth, i.e. when it is nearer to the light. Swapping the operands inverts every
|
|
119
|
+
* shadow in the engine while still producing plausible-looking output, which is why
|
|
120
|
+
* `cpu_texture_gather.spec.js` pins the direction explicitly.
|
|
121
|
+
*
|
|
122
|
+
* @param {GPUCompareFunction} compare
|
|
123
|
+
* @param {number} reference — the shader's `depth_ref`
|
|
124
|
+
* @param {number} sampled — the texel read from the depth texture
|
|
125
|
+
* @returns {number} 1.0 when the comparison passes, 0.0 when it fails
|
|
126
|
+
*/
|
|
127
|
+
export function evaluate_gpu_compare_function(compare, reference, sampled) {
|
|
128
|
+
switch (compare) {
|
|
129
|
+
case "never":
|
|
130
|
+
return 0;
|
|
131
|
+
case "less":
|
|
132
|
+
return reference < sampled ? 1 : 0;
|
|
133
|
+
case "equal":
|
|
134
|
+
return reference === sampled ? 1 : 0;
|
|
135
|
+
case "less-equal":
|
|
136
|
+
return reference <= sampled ? 1 : 0;
|
|
137
|
+
case "greater":
|
|
138
|
+
return reference > sampled ? 1 : 0;
|
|
139
|
+
case "not-equal":
|
|
140
|
+
return reference !== sampled ? 1 : 0;
|
|
141
|
+
case "greater-equal":
|
|
142
|
+
return reference >= sampled ? 1 : 0;
|
|
143
|
+
case "always":
|
|
144
|
+
return 1;
|
|
145
|
+
default:
|
|
146
|
+
throw new Error(`evaluate_gpu_compare_function: unsupported compare function '${compare}' (expected one of "never", "less", "equal", "less-equal", "greater", "not-equal", "greater-equal", "always")`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -36,4 +36,20 @@
|
|
|
36
36
|
* `texture.dimensionality` (1, 2 or 3 entries)
|
|
37
37
|
*/
|
|
38
38
|
export function cpu_texture_sample(output: Float32Array | number[], sampler: import("../../descriptor/texture/SamplerDescriptor.js").SamplerDescriptor, texture: import("./CPUBitmapData.js").CPUBitmapData, texel_coord: Float32Array | number[]): void;
|
|
39
|
+
/**
|
|
40
|
+
* Wrap an integer texel index back into `[0, size)` using the address
|
|
41
|
+
* mode. Shared by both nearest and linear filtering — the linear filter
|
|
42
|
+
* passes both the floor and floor+1 indices through this so wrapping at
|
|
43
|
+
* the edge is consistent.
|
|
44
|
+
*
|
|
45
|
+
* Exported because {@link cpu_texture_gather} needs the *same* address
|
|
46
|
+
* arithmetic: a gather's 2x2 footprint is the linear filter's footprint,
|
|
47
|
+
* and a second copy of this switch would be free to drift from it.
|
|
48
|
+
*
|
|
49
|
+
* @param {number} i
|
|
50
|
+
* @param {number} size
|
|
51
|
+
* @param {GPUAddressMode} mode
|
|
52
|
+
* @returns {number}
|
|
53
|
+
*/
|
|
54
|
+
export function wrap_int(i: number, size: number, mode: GPUAddressMode): number;
|
|
39
55
|
//# sourceMappingURL=cpu_texture_sample.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cpu_texture_sample.d.ts","sourceRoot":"","sources":["../../../../../src/shade/wgsl/emulator/cpu_texture_sample.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,2CARW,YAAY,GAAG,MAAM,EAAE,WAGvB,OAAO,+CAA+C,EAAE,iBAAiB,WACzE,OAAO,oBAAoB,EAAE,aAAa,eAC1C,YAAY,GAAG,MAAM,EAAE,QAsGjC"}
|
|
1
|
+
{"version":3,"file":"cpu_texture_sample.d.ts","sourceRoot":"","sources":["../../../../../src/shade/wgsl/emulator/cpu_texture_sample.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,2CARW,YAAY,GAAG,MAAM,EAAE,WAGvB,OAAO,+CAA+C,EAAE,iBAAiB,WACzE,OAAO,oBAAoB,EAAE,aAAa,eAC1C,YAAY,GAAG,MAAM,EAAE,QAsGjC;AAED;;;;;;;;;;;;;;GAcG;AACH,4BALW,MAAM,QACN,MAAM,yBAEJ,MAAM,CAsBlB"}
|