@luma.gl/shadertools 9.3.6 → 9.4.0-alpha.1
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/dist/dist.dev.js +6555 -2373
- package/dist/dist.min.js +2984 -237
- package/dist/index.cjs +4356 -268
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +13 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/preprocessor/preprocessor.d.ts +11 -1
- package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
- package/dist/lib/preprocessor/preprocessor.js +47 -2
- package/dist/lib/preprocessor/preprocessor.js.map +1 -1
- package/dist/lib/shader-assembler.d.ts +10 -10
- package/dist/lib/shader-assembler.d.ts.map +1 -1
- package/dist/lib/shader-assembler.js +36 -20
- package/dist/lib/shader-assembler.js.map +1 -1
- package/dist/lib/shader-assembly/assemble-shaders.d.ts +28 -7
- package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
- package/dist/lib/shader-assembly/assemble-shaders.js +133 -15
- package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
- package/dist/lib/shader-assembly/platform-info.d.ts +2 -0
- package/dist/lib/shader-assembly/platform-info.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.d.ts +1 -1
- package/dist/lib/shader-assembly/shader-hooks.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.js +6 -3
- package/dist/lib/shader-assembly/shader-hooks.js.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.d.ts +4 -1
- package/dist/lib/shader-assembly/shader-injections.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.js +68 -11
- package/dist/lib/shader-assembly/shader-injections.js.map +1 -1
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts +15 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.js +412 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.js.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.d.ts +12 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.d.ts.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.js +237 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.js.map +1 -0
- package/dist/lib/shader-module/shader-module.d.ts +3 -0
- package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
- package/dist/lib/shader-module/shader-module.js.map +1 -1
- package/dist/lib/shader-module/shader-pass-pipeline.d.ts +14 -0
- package/dist/lib/shader-module/shader-pass-pipeline.d.ts.map +1 -0
- package/dist/lib/shader-module/shader-pass-pipeline.js +5 -0
- package/dist/lib/shader-module/shader-pass-pipeline.js.map +1 -0
- package/dist/lib/shader-module/shader-pass.d.ts +21 -4
- package/dist/lib/shader-module/shader-pass.d.ts.map +1 -1
- package/dist/lib/shader-plugin.d.ts +68 -0
- package/dist/lib/shader-plugin.d.ts.map +1 -0
- package/dist/lib/shader-plugin.js +98 -0
- package/dist/lib/shader-plugin.js.map +1 -0
- package/dist/lib/utils/assert.js +1 -1
- package/dist/lib/utils/assert.js.map +1 -1
- package/dist/modules/color/float-colors.d.ts +111 -5
- package/dist/modules/color/float-colors.d.ts.map +1 -1
- package/dist/modules/color/float-colors.js +200 -34
- package/dist/modules/color/float-colors.js.map +1 -1
- package/dist/modules/engine/clip/clip.d.ts +12 -0
- package/dist/modules/engine/clip/clip.d.ts.map +1 -0
- package/dist/modules/engine/clip/clip.js +129 -0
- package/dist/modules/engine/clip/clip.js.map +1 -0
- package/dist/modules/engine/filter/filter.d.ts +12 -0
- package/dist/modules/engine/filter/filter.d.ts.map +1 -0
- package/dist/modules/engine/filter/filter.js +88 -0
- package/dist/modules/engine/filter/filter.js.map +1 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.d.ts +3 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.d.ts.map +1 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.js +1892 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.js.map +1 -0
- package/dist/modules/geospatial/dggs/dggs.d.ts +6 -0
- package/dist/modules/geospatial/dggs/dggs.d.ts.map +1 -0
- package/dist/modules/geospatial/dggs/dggs.js +10 -0
- package/dist/modules/geospatial/dggs/dggs.js.map +1 -0
- package/dist/modules/lighting/water-material/water-material.d.ts +28 -0
- package/dist/modules/lighting/water-material/water-material.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-material.js +179 -0
- package/dist/modules/lighting/water-material/water-material.js.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.d.ts +3 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.js +232 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.js.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.d.ts +2 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.js +230 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.js.map +1 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -1
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -1
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +268 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +50 -3
- package/src/lib/preprocessor/preprocessor.ts +68 -3
- package/src/lib/shader-assembler.ts +49 -20
- package/src/lib/shader-assembly/assemble-shaders.ts +242 -30
- package/src/lib/shader-assembly/platform-info.ts +2 -0
- package/src/lib/shader-assembly/shader-hooks.ts +7 -3
- package/src/lib/shader-assembly/shader-injections.ts +96 -11
- package/src/lib/shader-assembly/shader-plugin-varyings.ts +524 -0
- package/src/lib/shader-assembly/shader-plugin-vertex-inputs.ts +279 -0
- package/src/lib/shader-module/shader-module.ts +3 -0
- package/src/lib/shader-module/shader-pass-pipeline.ts +19 -0
- package/src/lib/shader-module/shader-pass.ts +29 -4
- package/src/lib/shader-plugin.ts +214 -0
- package/src/lib/utils/assert.ts +1 -1
- package/src/modules/color/float-colors.ts +272 -37
- package/src/modules/engine/clip/clip.ts +149 -0
- package/src/modules/engine/filter/filter.ts +107 -0
- package/src/modules/geospatial/dggs/dggs-wgsl.ts +1892 -0
- package/src/modules/geospatial/dggs/dggs.ts +12 -0
- package/src/modules/lighting/water-material/water-material.ts +234 -0
- package/src/modules/lighting/water-material/water-shaders-glsl.ts +233 -0
- package/src/modules/lighting/water-material/water-shaders-wgsl.ts +230 -0
- package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +268 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dggs-wgsl.js","sourceRoot":"","sources":["../../../../src/modules/geospatial/dggs/dggs-wgsl.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AAEpC,0EAA0E;AAC1E,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA81DlC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** WGSL helpers for 64-bit DGGS cell IDs encoded as two u32 words. */
|
|
2
|
+
export declare const dggs: {
|
|
3
|
+
readonly name: "dggs";
|
|
4
|
+
readonly source: "const DGGS_H3_CELL_MODE: u32 = 1u;\nconst DGGS_H3_MAX_RESOLUTION: u32 = 15u;\nconst DGGS_H3_MAX_BASE_CELL: u32 = 121u;\nconst DGGS_H3_UNUSED_DIGIT: u32 = 7u;\nconst DGGS_H3_RES0_U_GNOMONIC: f32 = 0.381966011250105;\nconst DGGS_H3_RSQRT7: f32 = 0.3779644730092272;\nconst DGGS_H3_ONETHIRD: f32 = 0.3333333333333333;\nconst DGGS_H3_AP7_ROT_RADS: f32 = 0.3334731722518321;\nconst DGGS_H3_SQRT3_2: f32 = 0.8660254037844386;\nconst DGGS_S2_MAX_LEVEL: u32 = 30u;\nconst DGGS_GEOHASH_MAX_LENGTH: u32 = 12u;\nconst DGGS_GEOHASH_LENGTH_BIT_OFFSET: u32 = 60u;\nconst DGGS_QUADKEY_MAX_LENGTH: u32 = 29u;\nconst DGGS_QUADKEY_LENGTH_BIT_OFFSET: u32 = 58u;\nconst DGGS_A5_FIRST_HILBERT_RESOLUTION: u32 = 2u;\nconst DGGS_A5_MAX_RESOLUTION: u32 = 30u;\nconst DGGS_A5_HILBERT_START_BIT: u32 = 58u;\nconst DGGS_PI: f32 = 3.141592653589793;\nconst DGGS_TWO_PI: f32 = 6.283185307179586;\nconst DGGS_TWO_PI_OVER_5: f32 = 1.2566370614359172;\nconst DGGS_PI_OVER_5: f32 = 0.6283185307179586;\nconst DGGS_PI_OVER_2: f32 = 1.5707963267948966;\nconst DGGS_A5_DISTANCE_TO_EDGE: f32 = 0.6180339887498949;\nconst DGGS_A5_REFLECTED_TRIANGLE_SCALE: f32 = 3.23606797749979;\nconst DGGS_A5_LONGITUDE_OFFSET: f32 = 93.0;\nconst DGGS_RADIANS_TO_DEGREES: f32 = 57.29577951308232;\nconst DGGS_DEGREES_TO_RADIANS: f32 = 0.017453292519943295;\nconst DGGS_U64_HIGH_WORD_FLOAT_SCALE: f32 = 4294967296.0;\n\n// DGGS 64-bit helper functions use canonical word order vec2u(high, low).\n// Arrow BigInt64/BigUint64 buffers are read as little-endian vec2u(low, high),\n// so storage-buffer reads should pass through dggs_u64_from_little_endian_words().\nfn dggs_u64_make(high: u32, low: u32) -> vec2u {\n return vec2u(high, low);\n}\n\nfn dggs_u64_from_little_endian_words(words: vec2u) -> vec2u {\n return words.yx;\n}\n\nfn dggs_u64_to_little_endian_words(value: vec2u) -> vec2u {\n return value.yx;\n}\n\nfn dggs_u64_high(value: vec2u) -> u32 {\n return value.x;\n}\n\nfn dggs_u64_low(value: vec2u) -> u32 {\n return value.y;\n}\n\nfn dggs_u64_is_zero(value: vec2u) -> bool {\n return value.x == 0u && value.y == 0u;\n}\n\nfn dggs_u64_equal(a: vec2u, b: vec2u) -> bool {\n return a.x == b.x && a.y == b.y;\n}\n\nfn dggs_u64_compare(a: vec2u, b: vec2u) -> i32 {\n if (a.x != b.x) {\n return select(-1, 1, a.x > b.x);\n }\n if (a.y != b.y) {\n return select(-1, 1, a.y > b.y);\n }\n return 0;\n}\n\nfn dggs_u64_less(a: vec2u, b: vec2u) -> bool {\n return dggs_u64_compare(a, b) < 0;\n}\n\nfn dggs_u64_add(a: vec2u, b: vec2u) -> vec2u {\n let low = a.y + b.y;\n let carry = select(0u, 1u, low < a.y);\n return vec2u(a.x + b.x + carry, low);\n}\n\nfn dggs_u64_subtract(a: vec2u, b: vec2u) -> vec2u {\n let borrow = select(0u, 1u, a.y < b.y);\n return vec2u(a.x - b.x - borrow, a.y - b.y);\n}\n\nfn dggs_u64_to_f32(value: vec2u) -> f32 {\n return f32(value.x) * DGGS_U64_HIGH_WORD_FLOAT_SCALE + f32(value.y);\n}\n\nfn dggs_i64_from_little_endian_words(words: vec2u) -> vec2u {\n return dggs_u64_from_little_endian_words(words);\n}\n\nfn dggs_i64_to_little_endian_words(value: vec2u) -> vec2u {\n return dggs_u64_to_little_endian_words(value);\n}\n\nfn dggs_i64_is_negative(value: vec2u) -> bool {\n return (value.x & 0x80000000u) != 0u;\n}\n\nfn dggs_i64_negate(value: vec2u) -> vec2u {\n return dggs_u64_add(vec2u(~value.x, ~value.y), vec2u(0u, 1u));\n}\n\nfn dggs_i64_compare(a: vec2u, b: vec2u) -> i32 {\n let highA = bitcast<i32>(a.x);\n let highB = bitcast<i32>(b.x);\n if (highA != highB) {\n return select(-1, 1, highA > highB);\n }\n if (a.y != b.y) {\n return select(-1, 1, a.y > b.y);\n }\n return 0;\n}\n\nfn dggs_i64_less(a: vec2u, b: vec2u) -> bool {\n return dggs_i64_compare(a, b) < 0;\n}\n\nfn dggs_i64_subtract(a: vec2u, b: vec2u) -> vec2u {\n return dggs_u64_subtract(a, b);\n}\n\nfn dggs_i64_to_f32(value: vec2u) -> f32 {\n if (dggs_i64_is_negative(value)) {\n return -dggs_u64_to_f32(dggs_i64_negate(value));\n }\n return dggs_u64_to_f32(value);\n}\n\nfn dggs_u32_mask_low(bitCount: u32) -> u32 {\n if (bitCount == 0u) {\n return 0u;\n }\n if (bitCount >= 32u) {\n return 0xffffffffu;\n }\n return (1u << bitCount) - 1u;\n}\n\nfn dggs_u64_shift_left(value: vec2u, shift: u32) -> vec2u {\n if (shift == 0u) {\n return value;\n }\n if (shift < 32u) {\n return vec2u((value.x << shift) | (value.y >> (32u - shift)), value.y << shift);\n }\n if (shift == 32u) {\n return vec2u(value.y, 0u);\n }\n if (shift < 64u) {\n return vec2u(value.y << (shift - 32u), 0u);\n }\n return vec2u(0u);\n}\n\nfn dggs_u64_shift_right(value: vec2u, shift: u32) -> vec2u {\n if (shift == 0u) {\n return value;\n }\n if (shift < 32u) {\n return vec2u(value.x >> shift, (value.y >> shift) | (value.x << (32u - shift)));\n }\n if (shift == 32u) {\n return vec2u(0u, value.x);\n }\n if (shift < 64u) {\n return vec2u(0u, value.x >> (shift - 32u));\n }\n return vec2u(0u);\n}\n\nfn dggs_u64_extract_bits(value: vec2u, bitOffset: u32, bitCount: u32) -> u32 {\n if (bitCount == 0u || bitOffset >= 64u) {\n return 0u;\n }\n let shifted = dggs_u64_shift_right(value, bitOffset);\n return shifted.y & dggs_u32_mask_low(bitCount);\n}\n\nfn dggs_u64_set_bits(value: vec2u, bitOffset: u32, bitCount: u32, bits: u32) -> vec2u {\n if (bitCount == 0u || bitOffset >= 64u) {\n return value;\n }\n let bitMask = dggs_u32_mask_low(bitCount);\n let fieldMask = dggs_u64_shift_left(vec2u(0u, bitMask), bitOffset);\n let fieldBits = dggs_u64_shift_left(vec2u(0u, bits & bitMask), bitOffset);\n return (value & vec2u(~fieldMask.x, ~fieldMask.y)) | fieldBits;\n}\n\nfn dggs_u64_count_trailing_zeros(value: vec2u) -> u32 {\n if (value.y != 0u) {\n return countTrailingZeros(value.y);\n }\n if (value.x != 0u) {\n return 32u + countTrailingZeros(value.x);\n }\n return 64u;\n}\n\nstruct DggsA5Cell {\n origin : u32,\n segment : u32,\n resolution : u32,\n valid : u32,\n quintantShift : u32,\n hilbertResolution : u32,\n};\n\nstruct DggsA5Anchor {\n q : u32,\n offset : vec2i,\n flips : vec2i,\n orientation : u32,\n quintant : u32,\n};\n\nstruct DggsA5FaceTriangle {\n a : vec2f,\n b : vec2f,\n c : vec2f,\n};\n\nstruct DggsA5SphericalTriangle {\n a : vec3f,\n b : vec3f,\n c : vec3f,\n};\n\nstruct DggsH3FaceIJK {\n face : u32,\n coord : vec3i,\n valid : u32,\n};\n\nstruct DggsH3BoundaryVertex {\n face : u32,\n coord : vec3i,\n resolution : u32,\n valid : u32,\n};\n\nfn dggs_boundary_point_to_fp64_split(point : vec2f) -> vec4f {\n return vec4f(point.x, point.y, 0.0, 0.0);\n}\n\nfn dggs_a5_positive_mod_i32(value : i32, modulus : i32) -> i32 {\n return ((value % modulus) + modulus) % modulus;\n}\n\nfn dggs_a5_has_bit(index : vec2u, bitOffset : u32) -> bool {\n return dggs_u64_extract_bits(index, bitOffset, 1u) != 0u;\n}\n\nfn dggs_a5_get_resolution(index : vec2u) -> u32 {\n if (dggs_u64_is_zero(index)) {\n return 0u;\n }\n if (\n dggs_a5_has_bit(index, 0u) ||\n dggs_u64_extract_bits(index, 0u, 3u) == 4u ||\n dggs_u64_extract_bits(index, 0u, 5u) == 16u\n ) {\n return DGGS_A5_MAX_RESOLUTION;\n }\n\n var resolution = DGGS_A5_MAX_RESOLUTION - 1u;\n var shifted = dggs_u64_shift_right(index, 1u);\n if (dggs_u64_is_zero(shifted)) {\n return 0u;\n }\n\n var remaining = shifted.y;\n if (remaining == 0u) {\n shifted = dggs_u64_shift_right(shifted, 32u);\n resolution -= 16u;\n remaining = shifted.y;\n }\n if ((remaining & 0xffffu) == 0u) {\n remaining >>= 16u;\n resolution -= 8u;\n }\n if (resolution >= 6u && (remaining & 0xffu) == 0u) {\n remaining >>= 8u;\n resolution -= 4u;\n }\n if (resolution >= 4u && (remaining & 0xfu) == 0u) {\n remaining >>= 4u;\n resolution -= 2u;\n }\n loop {\n if ((remaining & 1u) != 0u) {\n break;\n }\n if (resolution == 0u) {\n break;\n }\n resolution -= 1u;\n remaining >>= select(2u, 1u, resolution < DGGS_A5_FIRST_HILBERT_RESOLUTION);\n }\n return resolution;\n}\n\nfn dggs_a5_get_origin_first_quintant(origin : u32) -> u32 {\n let values = array<u32, 12>(\n 4u, 2u, 3u, 0u, 2u, 4u, 2u, 2u, 3u, 0u, 3u, 0u\n );\n return values[min(origin, 11u)];\n}\n\nfn dggs_a5_get_origin_step(origin : u32) -> i32 {\n let values = array<i32, 12>(\n -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1\n );\n return values[min(origin, 11u)];\n}\n\nfn dggs_a5_get_origin_orientation(origin : u32, faceRelativeQuintant : u32) -> u32 {\n // Orientation codes: uv=0, vu=1, uw=2, wu=3, vw=4, wv=5.\n let values = array<u32, 60>(\n 1u, 2u, 4u, 4u, 4u,\n 1u, 0u, 5u, 3u, 2u,\n 3u, 0u, 5u, 3u, 2u,\n 3u, 0u, 5u, 3u, 2u,\n 3u, 2u, 4u, 1u, 2u,\n 1u, 0u, 5u, 3u, 2u,\n 3u, 2u, 4u, 1u, 2u,\n 3u, 2u, 4u, 1u, 2u,\n 3u, 0u, 5u, 3u, 2u,\n 1u, 0u, 5u, 3u, 2u,\n 1u, 0u, 5u, 3u, 2u,\n 3u, 2u, 4u, 1u, 2u\n );\n return values[min(origin, 11u) * 5u + min(faceRelativeQuintant, 4u)];\n}\n\nfn dggs_a5_get_origin_angle(origin : u32) -> f32 {\n if (origin == 0u || origin == 9u) {\n return 0.0;\n }\n return DGGS_PI_OVER_5;\n}\n\nfn dggs_a5_get_origin_quaternion(origin : u32) -> vec4f {\n let values = array<vec4f, 12>(\n vec4f(0.0, 0.0, 0.0, 1.0),\n vec4f(0.0, 0.525731112119, 0.0, 0.850650808352),\n vec4f(-0.5, 0.688190960236, 0.0, 0.525731112119),\n vec4f(-0.809016994375, -0.262865556060, 0.0, 0.525731112119),\n vec4f(-0.5, 0.162459848116, 0.0, 0.850650808352),\n vec4f(-0.309016994375, -0.425325404176, 0.0, 0.850650808352),\n vec4f(0.309016994375, -0.425325404176, 0.0, 0.850650808352),\n vec4f(0.809016994375, -0.262865556060, 0.0, 0.525731112119),\n vec4f(0.0, -0.850650808352, 0.0, 0.525731112119),\n vec4f(0.0, -1.0, 0.0, 0.0),\n vec4f(0.5, 0.688190960236, 0.0, 0.525731112119),\n vec4f(0.5, 0.162459848116, 0.0, 0.850650808352)\n );\n return values[min(origin, 11u)];\n}\n\nfn dggs_a5_quaternion_rotate(point : vec3f, quaternion : vec4f) -> vec3f {\n let q = quaternion.xyz;\n let t = 2.0 * cross(q, point);\n return point + quaternion.w * t + cross(q, t);\n}\n\nfn dggs_a5_deserialize(index : vec2u) -> DggsA5Cell {\n if (dggs_u64_is_zero(index)) {\n return DggsA5Cell(0u, 0u, 0u, 0u, DGGS_A5_HILBERT_START_BIT, 0u);\n }\n\n let resolution = dggs_a5_get_resolution(index);\n var quintantShift = DGGS_A5_HILBERT_START_BIT;\n var quintantOffset = 0u;\n if (resolution == DGGS_A5_MAX_RESOLUTION) {\n var markerBits = 5u;\n if (dggs_a5_has_bit(index, 0u)) {\n markerBits = 1u;\n } else if (dggs_a5_has_bit(index, 2u)) {\n markerBits = 3u;\n }\n quintantShift = DGGS_A5_HILBERT_START_BIT + markerBits;\n quintantOffset = select(select(40u, 32u, markerBits == 3u), 0u, markerBits == 1u);\n }\n\n let topBits = dggs_u64_shift_right(index, quintantShift).y + quintantOffset;\n if (resolution == 0u) {\n if (topBits >= 12u) {\n return DggsA5Cell(0u, 0u, resolution, 0u, quintantShift, 0u);\n }\n return DggsA5Cell(topBits, 0u, resolution, 1u, quintantShift, 0u);\n }\n\n let origin = topBits / 5u;\n if (origin >= 12u) {\n return DggsA5Cell(0u, 0u, resolution, 0u, quintantShift, 0u);\n }\n let segment = (topBits + dggs_a5_get_origin_first_quintant(origin)) % 5u;\n let hilbertResolution = select(0u, resolution - 1u, resolution >= 2u);\n return DggsA5Cell(origin, segment, resolution, 1u, quintantShift, hilbertResolution);\n}\n\nfn dggs_a5_segment_to_anchor_info(cell : DggsA5Cell) -> DggsA5Anchor {\n let firstQuintant = dggs_a5_get_origin_first_quintant(cell.origin);\n let faceRelativeQuintant = (cell.segment + 5u - firstQuintant) % 5u;\n let orientation = dggs_a5_get_origin_orientation(cell.origin, faceRelativeQuintant);\n let step = dggs_a5_get_origin_step(cell.origin);\n let quintant = u32(dggs_a5_positive_mod_i32(\n i32(firstQuintant) + step * i32(faceRelativeQuintant),\n 5\n ));\n return DggsA5Anchor(0u, vec2i(0), vec2i(1), orientation, quintant);\n}\n\nfn dggs_a5_is_reverse_orientation(orientation : u32) -> bool {\n return orientation == 1u || orientation == 3u || orientation == 4u;\n}\n\nfn dggs_a5_is_invert_j_orientation(orientation : u32) -> bool {\n return orientation == 5u || orientation == 4u;\n}\n\nfn dggs_a5_is_flip_ij_orientation(orientation : u32) -> bool {\n return orientation == 3u || orientation == 2u;\n}\n\nfn dggs_a5_pattern_value(index : u32, flipIj : bool) -> u32 {\n let pattern = array<u32, 8>(0u, 1u, 3u, 4u, 5u, 6u, 7u, 2u);\n let flippedPattern = array<u32, 8>(0u, 1u, 2u, 7u, 3u, 4u, 5u, 6u);\n return select(pattern[min(index, 7u)], flippedPattern[min(index, 7u)], flipIj);\n}\n\nfn dggs_a5_quaternary_to_flips(digit : u32) -> vec2i {\n if (digit == 1u) {\n return vec2i(1, -1);\n }\n if (digit == 3u) {\n return vec2i(-1, 1);\n }\n return vec2i(1, 1);\n}\n\nfn dggs_a5_quaternary_to_kj(digit : u32, flips : vec2i) -> vec2i {\n var p = vec2i(0);\n var q = vec2i(0);\n if (flips.x == 1 && flips.y == 1) {\n p = vec2i(1, 0);\n q = vec2i(0, 1);\n } else if (flips.x == -1 && flips.y == 1) {\n p = vec2i(0, -1);\n q = vec2i(-1, 0);\n } else if (flips.x == 1 && flips.y == -1) {\n p = vec2i(0, 1);\n q = vec2i(1, 0);\n } else {\n p = vec2i(-1, 0);\n q = vec2i(0, -1);\n }\n\n if (digit == 1u) {\n return p;\n }\n if (digit == 2u) {\n return p + q;\n }\n if (digit == 3u) {\n return q + 2 * p;\n }\n return vec2i(0);\n}\n\nfn dggs_a5_kj_to_ij(kj : vec2i) -> vec2i {\n return vec2i(kj.x - kj.y, kj.y);\n}\n\nfn dggs_a5_shift_digits(\n digits : ptr<function, array<u32, 29>>,\n digitIndex : u32,\n flips : vec2i,\n invertJ : bool,\n flipIj : bool\n) {\n if (digitIndex == 0u) {\n return;\n }\n let parentK = (*digits)[digitIndex];\n let childK = (*digits)[digitIndex - 1u];\n let flipSum = flips.x + flips.y;\n var needsShift = true;\n var first = true;\n if (invertJ != (flipSum == 0)) {\n needsShift = parentK == 1u || parentK == 2u;\n first = parentK == 1u;\n } else {\n needsShift = parentK < 2u;\n first = parentK == 0u;\n }\n if (!needsShift) {\n return;\n }\n let source = select(childK + 4u, childK, first);\n let destination = dggs_a5_pattern_value(source, flipIj);\n (*digits)[digitIndex - 1u] = destination % 4u;\n (*digits)[digitIndex] = u32(dggs_a5_positive_mod_i32(\n i32(parentK) + 4 + i32(destination / 4u) - i32(source / 4u),\n 4\n ));\n}\n\nfn dggs_a5_make_anchor(index : vec2u, cell : DggsA5Cell, anchorInfo : DggsA5Anchor) -> DggsA5Anchor {\n if (cell.hilbertResolution == 0u) {\n return anchorInfo;\n }\n\n let reverse = dggs_a5_is_reverse_orientation(anchorInfo.orientation);\n let invertJ = dggs_a5_is_invert_j_orientation(anchorInfo.orientation);\n let flipIj = dggs_a5_is_flip_ij_orientation(anchorInfo.orientation);\n let hilbertBits = 2u * cell.hilbertResolution;\n let sBitOffset = cell.quintantShift - hilbertBits;\n var digits : array<u32, 29>;\n var digitIndex = 0u;\n loop {\n if (digitIndex >= cell.hilbertResolution) {\n break;\n }\n var digit = dggs_u64_extract_bits(index, sBitOffset + 2u * digitIndex, 2u);\n if (reverse) {\n digit = 3u - digit;\n }\n digits[digitIndex] = digit;\n digitIndex += 1u;\n }\n\n var flips = vec2i(1, 1);\n digitIndex = cell.hilbertResolution;\n loop {\n if (digitIndex == 0u) {\n break;\n }\n digitIndex -= 1u;\n dggs_a5_shift_digits(&digits, digitIndex, flips, invertJ, flipIj);\n flips *= dggs_a5_quaternary_to_flips(digits[digitIndex]);\n }\n\n flips = vec2i(1, 1);\n var offset = vec2i(0);\n digitIndex = cell.hilbertResolution;\n loop {\n if (digitIndex == 0u) {\n break;\n }\n digitIndex -= 1u;\n offset *= 2;\n offset += dggs_a5_quaternary_to_kj(digits[digitIndex], flips);\n flips *= dggs_a5_quaternary_to_flips(digits[digitIndex]);\n }\n\n var anchorOffset = dggs_a5_kj_to_ij(offset);\n if (flipIj) {\n let originalOffset = anchorOffset;\n anchorOffset = originalOffset.yx;\n if (flips.x == -1) {\n anchorOffset += vec2i(-1, 1);\n }\n if (flips.y == -1) {\n anchorOffset -= vec2i(-1, 1);\n }\n }\n if (invertJ) {\n let i = anchorOffset.x;\n let j = i32(1u << cell.hilbertResolution) - (i + anchorOffset.y);\n flips.x = -flips.x;\n anchorOffset.y = j;\n }\n\n return DggsA5Anchor(\n digits[0],\n anchorOffset,\n flips,\n anchorInfo.orientation,\n anchorInfo.quintant\n );\n}\n\nfn dggs_a5_rotate_face_point(point : vec2f, quintant : u32) -> vec2f {\n let angle = f32(quintant) * DGGS_TWO_PI_OVER_5;\n let cosine = cos(angle);\n let sine = sin(angle);\n return vec2f(point.x * cosine - point.y * sine, point.x * sine + point.y * cosine);\n}\n\nfn dggs_a5_get_base_pentagon_vertex(vertexIndex : u32) -> vec2f {\n let vertices = array<vec2f, 5>(\n vec2f(0.0, 0.0),\n vec2f(0.199381847431, 0.375413822391),\n vec2f(0.618033988750, 0.449027976580),\n vec2f(0.817415836181, 0.073614154188),\n vec2f(0.418652141319, -0.073614154188)\n );\n return vertices[min(vertexIndex, 4u)];\n}\n\nfn dggs_a5_get_base_triangle_vertex(vertexIndex : u32) -> vec2f {\n let vertices = array<vec2f, 3>(\n vec2f(0.0, 0.0),\n vec2f(0.618033988750, 0.449027976580),\n vec2f(0.618033988750, -0.449027976580)\n );\n return vertices[min(vertexIndex, 2u)];\n}\n\nfn dggs_a5_get_face_vertex(vertexIndex : u32) -> vec2f {\n return dggs_a5_rotate_face_point(dggs_a5_get_base_triangle_vertex(1u), 4u - min(vertexIndex, 4u));\n}\n\nfn dggs_a5_get_triangle_vertex(quintant : u32, vertexIndex : u32) -> vec2f {\n return dggs_a5_rotate_face_point(dggs_a5_get_base_triangle_vertex(vertexIndex), quintant);\n}\n\nfn dggs_a5_get_pentagon_vertex(\n anchor : DggsA5Anchor,\n hilbertResolution : u32,\n vertexIndex : u32\n) -> vec2f {\n let flipSum = anchor.flips.x + anchor.flips.y;\n let reflectsY = ((flipSum == -2 || flipSum == 2) && anchor.q > 1u) ||\n (flipSum == 0 && (anchor.q == 0u || anchor.q == 3u));\n let sourceIndex = select(vertexIndex, 4u - vertexIndex, reflectsY);\n var point = dggs_a5_get_base_pentagon_vertex(sourceIndex);\n\n if (anchor.flips.x == 1 && anchor.flips.y == -1) {\n point = -point;\n }\n if (reflectsY) {\n point.y = -point.y;\n }\n if (anchor.flips.x == -1 && anchor.flips.y == -1) {\n point = -point;\n } else if (anchor.flips.x == -1) {\n point += vec2f(-0.618033988750, 0.449027976580);\n } else if (anchor.flips.y == -1) {\n point += vec2f(0.618033988750, -0.449027976580);\n }\n\n let translation = vec2f(\n f32(anchor.offset.x) * 0.618033988750 + f32(anchor.offset.y) * 0.618033988750,\n f32(anchor.offset.x) * 0.449027976580 + f32(anchor.offset.y) * -0.449027976580\n );\n point = (point + translation) / f32(1u << hilbertResolution);\n return dggs_a5_rotate_face_point(point, anchor.quintant);\n}\n\nfn dggs_a5_get_shape_vertex_count(cell : DggsA5Cell) -> u32 {\n return select(5u, 3u, cell.resolution == 1u);\n}\n\nfn dggs_a5_get_reversed_shape_index(vertexIndex : u32, shapeVertexCount : u32) -> u32 {\n if (vertexIndex == 0u || vertexIndex >= shapeVertexCount) {\n return 0u;\n }\n return shapeVertexCount - vertexIndex;\n}\n\nfn dggs_a5_get_cell_shape_face_point(index : vec2u, cell : DggsA5Cell, shapeIndex : u32) -> vec2f {\n let anchorInfo = dggs_a5_segment_to_anchor_info(cell);\n if (cell.resolution == 0u) {\n return dggs_a5_get_face_vertex(shapeIndex);\n }\n if (cell.resolution == 1u) {\n return dggs_a5_get_triangle_vertex(anchorInfo.quintant, shapeIndex);\n }\n let anchor = dggs_a5_make_anchor(index, cell, anchorInfo);\n return dggs_a5_get_pentagon_vertex(anchor, cell.hilbertResolution, shapeIndex);\n}\n\nfn dggs_a5_get_cell_center_face_point(index : vec2u, cell : DggsA5Cell) -> vec2f {\n let shapeVertexCount = dggs_a5_get_shape_vertex_count(cell);\n var center = vec2f(0.0);\n var vertexIndex = 0u;\n loop {\n if (vertexIndex >= shapeVertexCount) {\n break;\n }\n center += dggs_a5_get_cell_shape_face_point(index, cell, vertexIndex);\n vertexIndex += 1u;\n }\n return center / f32(shapeVertexCount);\n}\n\nfn dggs_a5_to_polar(point : vec2f) -> vec2f {\n return vec2f(length(point), atan2(point.y, point.x));\n}\n\nfn dggs_a5_to_cartesian(thetaPhi : vec2f) -> vec3f {\n let sinPhi = sin(thetaPhi.y);\n return vec3f(sinPhi * cos(thetaPhi.x), sinPhi * sin(thetaPhi.x), cos(thetaPhi.y));\n}\n\nfn dggs_a5_normalize_vec3(point : vec3f) -> vec3f {\n let magnitude = length(point);\n if (magnitude < 1.0e-12) {\n return vec3f(0.0, 0.0, 1.0);\n }\n return point / magnitude;\n}\n\nfn dggs_a5_get_face_triangle_index(polar : vec2f) -> u32 {\n return u32(dggs_a5_positive_mod_i32(i32(floor(polar.y / DGGS_PI_OVER_5)), 10));\n}\n\nfn dggs_a5_normalize_gamma(gamma : f32) -> f32 {\n let segment = gamma / DGGS_TWO_PI_OVER_5;\n return (segment - round(segment)) * DGGS_TWO_PI_OVER_5;\n}\n\nfn dggs_a5_should_reflect(polar : vec2f) -> bool {\n return polar.x * cos(dggs_a5_normalize_gamma(polar.y)) > DGGS_A5_DISTANCE_TO_EDGE;\n}\n\nfn dggs_a5_get_base_face_triangle(faceTriangleIndex : u32) -> DggsA5FaceTriangle {\n let quintant = ((faceTriangleIndex + 1u) / 2u) % 5u;\n let center = dggs_a5_get_triangle_vertex(quintant, 0u);\n let corner1 = dggs_a5_get_triangle_vertex(quintant, 1u);\n let corner2 = dggs_a5_get_triangle_vertex(quintant, 2u);\n let edgeMidpoint = (corner1 + corner2) * 0.5;\n if ((faceTriangleIndex & 1u) == 0u) {\n return DggsA5FaceTriangle(center, edgeMidpoint, corner1);\n }\n return DggsA5FaceTriangle(center, corner2, edgeMidpoint);\n}\n\nfn dggs_a5_get_face_triangle_vertex(triangle : DggsA5FaceTriangle, vertexIndex : u32) -> vec2f {\n if (vertexIndex == 0u) {\n return triangle.a;\n }\n if (vertexIndex == 1u) {\n return triangle.b;\n }\n return triangle.c;\n}\n\nfn dggs_a5_get_reflected_face_triangle(\n faceTriangleIndex : u32,\n squashed : bool\n) -> DggsA5FaceTriangle {\n let baseTriangle = dggs_a5_get_base_face_triangle(faceTriangleIndex);\n let even = (faceTriangleIndex & 1u) == 0u;\n let midpoint = select(baseTriangle.c, baseTriangle.b, even);\n let scale = select(2.0, DGGS_A5_REFLECTED_TRIANGLE_SCALE, squashed);\n let reflectedA = -baseTriangle.a + midpoint * scale;\n return DggsA5FaceTriangle(reflectedA, baseTriangle.c, baseTriangle.b);\n}\n\nfn dggs_a5_get_face_triangle(\n faceTriangleIndex : u32,\n reflected : bool,\n squashed : bool\n) -> DggsA5FaceTriangle {\n if (reflected) {\n return dggs_a5_get_reflected_face_triangle(faceTriangleIndex, squashed);\n }\n return dggs_a5_get_base_face_triangle(faceTriangleIndex);\n}\n\nfn dggs_a5_face_triangle_to_spherical_triangle(\n faceTriangleIndex : u32,\n origin : u32,\n reflected : bool\n) -> DggsA5SphericalTriangle {\n let faceTriangle = dggs_a5_get_face_triangle(faceTriangleIndex, reflected, true);\n let originAngle = dggs_a5_get_origin_angle(origin);\n let quaternion = dggs_a5_get_origin_quaternion(origin);\n\n let polarA = dggs_a5_to_polar(faceTriangle.a);\n let polarB = dggs_a5_to_polar(faceTriangle.b);\n let polarC = dggs_a5_to_polar(faceTriangle.c);\n let sphericalA = dggs_a5_quaternion_rotate(\n dggs_a5_to_cartesian(vec2f(polarA.y + originAngle, atan(polarA.x))),\n quaternion\n );\n let sphericalB = dggs_a5_quaternion_rotate(\n dggs_a5_to_cartesian(vec2f(polarB.y + originAngle, atan(polarB.x))),\n quaternion\n );\n let sphericalC = dggs_a5_quaternion_rotate(\n dggs_a5_to_cartesian(vec2f(polarC.y + originAngle, atan(polarC.x))),\n quaternion\n );\n return DggsA5SphericalTriangle(\n dggs_a5_normalize_vec3(sphericalA),\n dggs_a5_normalize_vec3(sphericalB),\n dggs_a5_normalize_vec3(sphericalC)\n );\n}\n\nfn dggs_a5_face_to_barycentric(point : vec2f, triangle : DggsA5FaceTriangle) -> vec3f {\n let d31 = triangle.a - triangle.c;\n let d23 = triangle.c - triangle.b;\n let d3p = point - triangle.c;\n let determinant = d23.x * d31.y - d23.y * d31.x;\n if (abs(determinant) < 1.0e-12) {\n return vec3f(1.0, 0.0, 0.0);\n }\n let b0 = (d23.x * d3p.y - d23.y * d3p.x) / determinant;\n let b1 = (d31.x * d3p.y - d31.y * d3p.x) / determinant;\n return vec3f(b0, b1, 1.0 - (b0 + b1));\n}\n\nfn dggs_a5_triangle_area(a : vec3f, b : vec3f, c : vec3f) -> f32 {\n let midA = dggs_a5_normalize_vec3((b + c) * 0.5);\n let midB = dggs_a5_normalize_vec3((c + a) * 0.5);\n let midC = dggs_a5_normalize_vec3((a + b) * 0.5);\n let tripleProduct = dot(midA, cross(midB, midC));\n let clamped = clamp(tripleProduct, -1.0, 1.0);\n if (abs(clamped) < 1.0e-8) {\n return 2.0 * clamped;\n }\n return asin(clamped) * 2.0;\n}\n\nfn dggs_a5_spherical_triangle_area(triangle : DggsA5SphericalTriangle) -> f32 {\n return dggs_a5_triangle_area(triangle.a, triangle.b, triangle.c);\n}\n\nfn dggs_a5_vector_difference(a : vec3f, b : vec3f) -> f32 {\n let midpoint = dggs_a5_normalize_vec3((a + b) * 0.5);\n let crossProduct = cross(a, midpoint);\n let distance = length(crossProduct);\n if (distance < 1.0e-8) {\n return 0.5 * length(a - b);\n }\n return distance;\n}\n\nfn dggs_a5_slerp(a : vec3f, b : vec3f, t : f32) -> vec3f {\n let cosineGamma = clamp(dot(a, b), -1.0, 1.0);\n let gamma = acos(cosineGamma);\n if (gamma < 1.0e-8) {\n return dggs_a5_normalize_vec3(mix(a, b, t));\n }\n let sinGamma = sin(gamma);\n if (abs(sinGamma) < 1.0e-8) {\n return dggs_a5_normalize_vec3(mix(a, b, t));\n }\n let weightA = sin((1.0 - t) * gamma) / sinGamma;\n let weightB = sin(t * gamma) / sinGamma;\n return dggs_a5_normalize_vec3(weightA * a + weightB * b);\n}\n\nfn dggs_a5_safe_acos(value : f32) -> f32 {\n if (value < 1.0e-3) {\n return 2.0 * value + value * value * value / 3.0;\n }\n return acos(clamp(1.0 - 2.0 * value * value, -1.0, 1.0));\n}\n\nfn dggs_a5_polyhedral_inverse_edge(a : vec3f, b : vec3f, edgeHeight : f32) -> vec3f {\n let difference = dggs_a5_vector_difference(a, b);\n let denominator = max(dggs_a5_safe_acos(difference), 1.0e-8);\n let interpolation = dggs_a5_safe_acos(clamp(edgeHeight, 0.0, 1.0) * difference) / denominator;\n return dggs_a5_slerp(a, b, clamp(interpolation, 0.0, 1.0));\n}\n\nfn dggs_a5_polyhedral_inverse(\n facePoint : vec2f,\n faceTriangle : DggsA5FaceTriangle,\n sphericalTriangle : DggsA5SphericalTriangle\n) -> vec3f {\n let barycentric = dggs_a5_face_to_barycentric(facePoint, faceTriangle);\n if (barycentric.x > 0.9999999) {\n return sphericalTriangle.a;\n }\n if (barycentric.y > 0.9999999) {\n return sphericalTriangle.b;\n }\n if (barycentric.z > 0.9999999) {\n return sphericalTriangle.c;\n }\n if (abs(barycentric.z) < 1.0e-6) {\n return dggs_a5_polyhedral_inverse_edge(\n sphericalTriangle.a,\n sphericalTriangle.b,\n 1.0 - barycentric.x\n );\n }\n if (abs(barycentric.y) < 1.0e-6) {\n return dggs_a5_polyhedral_inverse_edge(\n sphericalTriangle.a,\n sphericalTriangle.c,\n 1.0 - barycentric.x\n );\n }\n\n let crossBC = cross(sphericalTriangle.b, sphericalTriangle.c);\n let areaABC = dggs_a5_spherical_triangle_area(sphericalTriangle);\n let h = max(1.0 - barycentric.x, 1.0e-8);\n let areaRatio = barycentric.z / h;\n let alpha = areaRatio * areaABC;\n let sineAlpha = sin(alpha);\n let halfSineAlpha = sin(alpha * 0.5);\n let chordCoefficient = 2.0 * halfSineAlpha * halfSineAlpha;\n let dotAB = dot(sphericalTriangle.a, sphericalTriangle.b);\n let dotBC = dot(sphericalTriangle.b, sphericalTriangle.c);\n let dotCA = dot(sphericalTriangle.c, sphericalTriangle.a);\n let lengthBC = length(crossBC);\n let volume = dot(sphericalTriangle.a, crossBC);\n let f = sineAlpha * volume + chordCoefficient * (dotAB * dotBC - dotCA);\n let g = chordCoefficient * lengthBC * (1.0 + dotAB);\n let edgeAngle = max(acos(clamp(dotBC, -1.0, 1.0)), 1.0e-8);\n let q = 2.0 / edgeAngle * atan2(g, f);\n let pointOnBC = dggs_a5_slerp(sphericalTriangle.b, sphericalTriangle.c, q);\n let k = dggs_a5_vector_difference(sphericalTriangle.a, pointOnBC);\n let denominator = max(dggs_a5_safe_acos(k), 1.0e-8);\n let t = dggs_a5_safe_acos(h * k) / denominator;\n return dggs_a5_slerp(sphericalTriangle.a, pointOnBC, t);\n}\n\nfn dggs_a5_authalic_inverse(phi : f32) -> f32 {\n let sinPhi = sin(phi);\n let cosPhi = cos(phi);\n let coefficientX = 2.0 * (cosPhi - sinPhi) * (cosPhi + sinPhi);\n var u0 = coefficientX * 4.92842354825238055e-17 + 2.19128723067677184e-14;\n var u1 = coefficientX * u0 + 1.02018123778161003e-11;\n u0 = coefficientX * u1 - u0 + 5.08622073997266026e-9;\n u1 = coefficientX * u0 - u1 + 0.00000288319780486075558;\n u0 = coefficientX * u1 - u0 + 0.00223920899635416575;\n return phi + 2.0 * sinPhi * cosPhi * u0;\n}\n\nfn dggs_a5_normalize_longitude(longitude : f32) -> f32 {\n var result = longitude;\n loop {\n if (result < -180.0) {\n result += 360.0;\n } else {\n break;\n }\n }\n loop {\n if (result >= 180.0) {\n result -= 360.0;\n } else {\n break;\n }\n }\n return result;\n}\n\nfn dggs_a5_normalize_longitude_to_center(longitude : f32, centerLongitude : f32) -> f32 {\n var result = longitude;\n loop {\n if (result - centerLongitude > 180.0) {\n result -= 360.0;\n } else {\n break;\n }\n }\n loop {\n if (result - centerLongitude < -180.0) {\n result += 360.0;\n } else {\n break;\n }\n }\n return result;\n}\n\nfn dggs_a5_sphere_to_lnglat(cartesian : vec3f) -> vec2f {\n let point = dggs_a5_normalize_vec3(cartesian);\n let theta = atan2(point.y, point.x);\n let phi = acos(clamp(point.z, -1.0, 1.0));\n let longitude = dggs_a5_normalize_longitude(theta * DGGS_RADIANS_TO_DEGREES - DGGS_A5_LONGITUDE_OFFSET);\n let authalicLatitude = DGGS_PI_OVER_2 - phi;\n let latitude = dggs_a5_authalic_inverse(authalicLatitude) * DGGS_RADIANS_TO_DEGREES;\n return vec2f(longitude, latitude);\n}\n\nfn dggs_a5_face_to_lnglat(facePoint : vec2f, origin : u32) -> vec2f {\n let polar = dggs_a5_to_polar(facePoint);\n let faceTriangleIndex = dggs_a5_get_face_triangle_index(polar);\n let reflected = dggs_a5_should_reflect(polar);\n let faceTriangle = dggs_a5_get_face_triangle(faceTriangleIndex, reflected, false);\n let sphericalTriangle = dggs_a5_face_triangle_to_spherical_triangle(\n faceTriangleIndex,\n origin,\n reflected\n );\n return dggs_a5_sphere_to_lnglat(\n dggs_a5_polyhedral_inverse(facePoint, faceTriangle, sphericalTriangle)\n );\n}\n\nfn dggs_a5_get_boundary_point(index : vec2u, vertexIndex : u32) -> vec2f {\n let cell = dggs_a5_deserialize(index);\n if (cell.valid == 0u || dggs_u64_is_zero(index)) {\n return vec2f(0.0);\n }\n\n let shapeVertexCount = dggs_a5_get_shape_vertex_count(cell);\n let shapeIndex = dggs_a5_get_reversed_shape_index(vertexIndex, shapeVertexCount);\n let facePoint = dggs_a5_get_cell_shape_face_point(index, cell, shapeIndex);\n let centerPoint = dggs_a5_get_cell_center_face_point(index, cell);\n var lngLat = dggs_a5_face_to_lnglat(facePoint, cell.origin);\n let centerLngLat = dggs_a5_face_to_lnglat(centerPoint, cell.origin);\n lngLat.x = dggs_a5_normalize_longitude_to_center(lngLat.x, centerLngLat.x);\n return lngLat;\n}\n\nfn dggs_a5_get_boundary_point_fp64_split(index : vec2u, vertexIndex : u32) -> vec4f {\n return dggs_boundary_point_to_fp64_split(dggs_a5_get_boundary_point(index, vertexIndex));\n}\n\nfn dggs_h3_get_mode(index: vec2u) -> u32 {\n return dggs_u64_extract_bits(index, 59u, 4u);\n}\n\nfn dggs_h3_is_cell_mode(index: vec2u) -> bool {\n return dggs_h3_get_mode(index) == DGGS_H3_CELL_MODE;\n}\n\nfn dggs_h3_get_resolution(index: vec2u) -> u32 {\n return dggs_u64_extract_bits(index, 52u, 4u);\n}\n\nfn dggs_h3_get_base_cell(index: vec2u) -> u32 {\n return dggs_u64_extract_bits(index, 45u, 7u);\n}\n\nfn dggs_h3_digit_bit_offset(resolution: u32) -> u32 {\n return 3u * (DGGS_H3_MAX_RESOLUTION - resolution);\n}\n\nfn dggs_h3_get_digit(index: vec2u, resolution: u32) -> u32 {\n if (resolution == 0u || resolution > DGGS_H3_MAX_RESOLUTION) {\n return DGGS_H3_UNUSED_DIGIT;\n }\n return dggs_u64_extract_bits(index, dggs_h3_digit_bit_offset(resolution), 3u);\n}\n\nfn dggs_h3_is_valid_cell_id(index: vec2u) -> bool {\n let cellResolution = dggs_h3_get_resolution(index);\n if (\n !dggs_h3_is_cell_mode(index) ||\n cellResolution > DGGS_H3_MAX_RESOLUTION ||\n dggs_h3_get_base_cell(index) > DGGS_H3_MAX_BASE_CELL\n ) {\n return false;\n }\n\n var digitResolution = 1u;\n loop {\n if (digitResolution > DGGS_H3_MAX_RESOLUTION) {\n break;\n }\n\n let digit = dggs_h3_get_digit(index, digitResolution);\n if (digitResolution <= cellResolution) {\n if (digit == DGGS_H3_UNUSED_DIGIT) {\n return false;\n }\n } else if (digit != DGGS_H3_UNUSED_DIGIT) {\n return false;\n }\n digitResolution += 1u;\n }\n return true;\n}\n\nfn dggs_h3_get_parent(index: vec2u, parentResolution: u32) -> vec2u {\n let currentResolution = dggs_h3_get_resolution(index);\n let targetResolution = min(parentResolution, currentResolution);\n var parent = dggs_u64_set_bits(index, 52u, 4u, targetResolution);\n var resolution = targetResolution + 1u;\n loop {\n if (resolution > DGGS_H3_MAX_RESOLUTION) {\n break;\n }\n parent = dggs_u64_set_bits(\n parent,\n dggs_h3_digit_bit_offset(resolution),\n 3u,\n DGGS_H3_UNUSED_DIGIT\n );\n resolution += 1u;\n }\n return parent;\n}\n\nfn dggs_h3_positive_angle_rads(angle: f32) -> f32 {\n var result = angle;\n if (result < 0.0) {\n result += DGGS_TWO_PI;\n }\n if (result >= DGGS_TWO_PI) {\n result -= DGGS_TWO_PI;\n }\n return result;\n}\n\nfn dggs_h3_constrain_longitude(longitude: f32) -> f32 {\n var result = longitude;\n loop {\n if (result <= DGGS_PI) {\n break;\n }\n result -= DGGS_TWO_PI;\n }\n loop {\n if (result >= -DGGS_PI) {\n break;\n }\n result += DGGS_TWO_PI;\n }\n return result;\n}\n\nfn dggs_h3_is_resolution_class_iii(resolution: u32) -> bool {\n return (resolution & 1u) != 0u;\n}\n\nfn dggs_h3_is_base_cell_pentagon(baseCell: u32) -> bool {\n return baseCell == 4u ||\n baseCell == 14u ||\n baseCell == 24u ||\n baseCell == 38u ||\n baseCell == 49u ||\n baseCell == 58u ||\n baseCell == 63u ||\n baseCell == 72u ||\n baseCell == 83u ||\n baseCell == 97u ||\n baseCell == 107u ||\n baseCell == 117u;\n}\n\nfn dggs_h3_get_base_cell_home(baseCell: u32) -> DggsH3FaceIJK {\n let values = array<vec4i, 122>(\n vec4i(1, 1, 0, 0),\n vec4i(2, 1, 1, 0),\n vec4i(1, 0, 0, 0),\n vec4i(2, 1, 0, 0),\n vec4i(0, 2, 0, 0),\n vec4i(1, 1, 1, 0),\n vec4i(1, 0, 0, 1),\n vec4i(2, 0, 0, 0),\n vec4i(0, 1, 0, 0),\n vec4i(2, 0, 1, 0),\n vec4i(1, 0, 1, 0),\n vec4i(1, 0, 1, 1),\n vec4i(3, 1, 0, 0),\n vec4i(3, 1, 1, 0),\n vec4i(11, 2, 0, 0),\n vec4i(4, 1, 0, 0),\n vec4i(0, 0, 0, 0),\n vec4i(6, 0, 1, 0),\n vec4i(0, 0, 0, 1),\n vec4i(2, 0, 1, 1),\n vec4i(7, 0, 0, 1),\n vec4i(2, 0, 0, 1),\n vec4i(0, 1, 1, 0),\n vec4i(6, 0, 0, 1),\n vec4i(10, 2, 0, 0),\n vec4i(6, 0, 0, 0),\n vec4i(3, 0, 0, 0),\n vec4i(11, 1, 0, 0),\n vec4i(4, 1, 1, 0),\n vec4i(3, 0, 1, 0),\n vec4i(0, 0, 1, 1),\n vec4i(4, 0, 0, 0),\n vec4i(5, 0, 1, 0),\n vec4i(0, 0, 1, 0),\n vec4i(7, 0, 1, 0),\n vec4i(11, 1, 1, 0),\n vec4i(7, 0, 0, 0),\n vec4i(10, 1, 0, 0),\n vec4i(12, 2, 0, 0),\n vec4i(6, 1, 0, 1),\n vec4i(7, 1, 0, 1),\n vec4i(4, 0, 0, 1),\n vec4i(3, 0, 0, 1),\n vec4i(3, 0, 1, 1),\n vec4i(4, 0, 1, 0),\n vec4i(6, 1, 0, 0),\n vec4i(11, 0, 0, 0),\n vec4i(8, 0, 0, 1),\n vec4i(5, 0, 0, 1),\n vec4i(14, 2, 0, 0),\n vec4i(5, 0, 0, 0),\n vec4i(12, 1, 0, 0),\n vec4i(10, 1, 1, 0),\n vec4i(4, 0, 1, 1),\n vec4i(12, 1, 1, 0),\n vec4i(7, 1, 0, 0),\n vec4i(11, 0, 1, 0),\n vec4i(10, 0, 0, 0),\n vec4i(13, 2, 0, 0),\n vec4i(10, 0, 0, 1),\n vec4i(11, 0, 0, 1),\n vec4i(9, 0, 1, 0),\n vec4i(8, 0, 1, 0),\n vec4i(6, 2, 0, 0),\n vec4i(8, 0, 0, 0),\n vec4i(9, 0, 0, 1),\n vec4i(14, 1, 0, 0),\n vec4i(5, 1, 0, 1),\n vec4i(16, 0, 1, 1),\n vec4i(8, 1, 0, 1),\n vec4i(5, 1, 0, 0),\n vec4i(12, 0, 0, 0),\n vec4i(7, 2, 0, 0),\n vec4i(12, 0, 1, 0),\n vec4i(10, 0, 1, 0),\n vec4i(9, 0, 0, 0),\n vec4i(13, 1, 0, 0),\n vec4i(16, 0, 0, 1),\n vec4i(15, 0, 1, 1),\n vec4i(15, 0, 1, 0),\n vec4i(16, 0, 1, 0),\n vec4i(14, 1, 1, 0),\n vec4i(13, 1, 1, 0),\n vec4i(5, 2, 0, 0),\n vec4i(8, 1, 0, 0),\n vec4i(14, 0, 0, 0),\n vec4i(9, 1, 0, 1),\n vec4i(14, 0, 0, 1),\n vec4i(17, 0, 0, 1),\n vec4i(12, 0, 0, 1),\n vec4i(16, 0, 0, 0),\n vec4i(17, 0, 1, 1),\n vec4i(15, 0, 0, 1),\n vec4i(16, 1, 0, 1),\n vec4i(9, 1, 0, 0),\n vec4i(15, 0, 0, 0),\n vec4i(13, 0, 0, 0),\n vec4i(8, 2, 0, 0),\n vec4i(13, 0, 1, 0),\n vec4i(17, 1, 0, 1),\n vec4i(19, 0, 1, 0),\n vec4i(14, 0, 1, 0),\n vec4i(19, 0, 1, 1),\n vec4i(17, 0, 1, 0),\n vec4i(13, 0, 0, 1),\n vec4i(17, 0, 0, 0),\n vec4i(16, 1, 0, 0),\n vec4i(9, 2, 0, 0),\n vec4i(15, 1, 0, 1),\n vec4i(15, 1, 0, 0),\n vec4i(18, 0, 1, 1),\n vec4i(18, 0, 0, 1),\n vec4i(19, 0, 0, 1),\n vec4i(17, 1, 0, 0),\n vec4i(19, 0, 0, 0),\n vec4i(18, 0, 1, 0),\n vec4i(18, 1, 0, 1),\n vec4i(19, 2, 0, 0),\n vec4i(19, 1, 0, 0),\n vec4i(18, 0, 0, 0),\n vec4i(19, 1, 0, 1),\n vec4i(18, 1, 0, 0)\n );\n let value = values[min(baseCell, DGGS_H3_MAX_BASE_CELL)];\n return DggsH3FaceIJK(\n u32(value.x),\n value.yzw,\n select(1u, 0u, baseCell > DGGS_H3_MAX_BASE_CELL)\n );\n}\n\nfn dggs_h3_get_face_center_geo(face: u32) -> vec2f {\n let values = array<vec2f, 20>(\n vec2f(0.803582649718989942, 1.248397419617396099),\n vec2f(1.307747883455638156, 2.536945009877921159),\n vec2f(1.054751253523952054, -1.347517358900396623),\n vec2f(0.600191595538186799, -0.450603909469755746),\n vec2f(0.491715428198773866, 0.401988202911306943),\n vec2f(0.172745327415618701, 1.678146885280433686),\n vec2f(0.605929321571350690, 2.953923329812411617),\n vec2f(0.427370518328979641, -1.888876200336285401),\n vec2f(-0.079066118549212831, -0.733429513380867741),\n vec2f(-0.230961644455383637, 0.506495587332349035),\n vec2f(0.079066118549212831, 2.408163140208925497),\n vec2f(0.230961644455383637, -2.635097066257444203),\n vec2f(-0.172745327415618701, -1.463445768309359553),\n vec2f(-0.605929321571350690, -0.187669323777381622),\n vec2f(-0.427370518328979641, 1.252716453253507838),\n vec2f(-0.600191595538186799, 2.690988744120037492),\n vec2f(-0.491715428198773866, -2.739604450678486295),\n vec2f(-0.803582649718989942, -1.893195233972397139),\n vec2f(-1.307747883455638156, -0.604647643711872080),\n vec2f(-1.054751253523952054, 1.794075294689396615)\n );\n return values[min(face, 19u)];\n}\n\nfn dggs_h3_get_face_axis_azimuths(face: u32) -> vec3f {\n let values = array<vec3f, 20>(\n vec3f(5.619958268523939882, 3.525563166130744542, 1.431168063737548730),\n vec3f(5.760339081714187279, 3.665943979320991689, 1.571548876927796127),\n vec3f(0.780213654393430055, 4.969003859179821079, 2.874608756786625655),\n vec3f(0.430469363979999913, 4.619259568766391033, 2.524864466373195467),\n vec3f(6.130269123335111400, 4.035874020941915804, 1.941478918548720291),\n vec3f(2.692877706530642877, 0.598482604137447119, 4.787272808923838195),\n vec3f(2.982963003477243874, 0.888567901084048369, 5.077358105870439581),\n vec3f(3.532912002790141181, 1.438516900396945656, 5.627307105183336758),\n vec3f(3.494305004259568154, 1.399909901866372864, 5.588700106652763840),\n vec3f(3.003214169499538391, 0.908819067106342928, 5.097609271892733906),\n vec3f(5.930472956509811562, 3.836077854116615875, 1.741682751723420374),\n vec3f(0.138378484090254847, 4.327168688876645809, 2.232773586483450311),\n vec3f(0.448714947059150361, 4.637505151845541521, 2.543110049452346120),\n vec3f(0.158629650112549365, 4.347419854898940135, 2.253024752505744869),\n vec3f(5.891865957979238535, 3.797470855586042958, 1.703075753192847583),\n vec3f(2.711123289609793325, 0.616728187216597771, 4.805518392002988683),\n vec3f(3.294508837434268316, 1.200113735041072948, 5.388903939827463911),\n vec3f(3.804819692245439833, 1.710424589852244509, 5.899214794638635174),\n vec3f(3.664438879055192436, 1.570043776661997111, 5.758833981448388027),\n vec3f(2.361378999196363184, 0.266983896803167583, 4.455774101589558636)\n );\n return values[min(face, 19u)];\n}\n\nfn dggs_h3_get_max_dim_by_cii_resolution(resolution: u32) -> i32 {\n let values = array<i32, 17>(\n 2, -1, 14, -1, 98, -1, 686, -1, 4802, -1, 33614, -1, 235298, -1, 1647086, -1, 11529602\n );\n return values[min(resolution, 16u)];\n}\n\nfn dggs_h3_get_unit_vector(digit: u32) -> vec3i {\n if (digit == 1u) {\n return vec3i(0, 0, 1);\n }\n if (digit == 2u) {\n return vec3i(0, 1, 0);\n }\n if (digit == 3u) {\n return vec3i(0, 1, 1);\n }\n if (digit == 4u) {\n return vec3i(1, 0, 0);\n }\n if (digit == 5u) {\n return vec3i(1, 0, 1);\n }\n if (digit == 6u) {\n return vec3i(1, 1, 0);\n }\n return vec3i(0);\n}\n\nfn dggs_h3_ijk_normalize(coord: vec3i) -> vec3i {\n var normalized = coord;\n if (normalized.x < 0) {\n normalized.y -= normalized.x;\n normalized.z -= normalized.x;\n normalized.x = 0;\n }\n if (normalized.y < 0) {\n normalized.x -= normalized.y;\n normalized.z -= normalized.y;\n normalized.y = 0;\n }\n if (normalized.z < 0) {\n normalized.x -= normalized.z;\n normalized.y -= normalized.z;\n normalized.z = 0;\n }\n\n let minimumValue = min(normalized.x, min(normalized.y, normalized.z));\n if (minimumValue > 0) {\n normalized -= vec3i(minimumValue);\n }\n return normalized;\n}\n\nfn dggs_h3_neighbor(coord: vec3i, digit: u32) -> vec3i {\n if (digit > 0u && digit < DGGS_H3_UNUSED_DIGIT) {\n return dggs_h3_ijk_normalize(coord + dggs_h3_get_unit_vector(digit));\n }\n return coord;\n}\n\nfn dggs_h3_down_ap3(coord: vec3i) -> vec3i {\n let iVector = vec3i(2, 0, 1) * coord.x;\n let jVector = vec3i(1, 2, 0) * coord.y;\n let kVector = vec3i(0, 1, 2) * coord.z;\n return dggs_h3_ijk_normalize(iVector + jVector + kVector);\n}\n\nfn dggs_h3_down_ap3r(coord: vec3i) -> vec3i {\n let iVector = vec3i(2, 1, 0) * coord.x;\n let jVector = vec3i(0, 2, 1) * coord.y;\n let kVector = vec3i(1, 0, 2) * coord.z;\n return dggs_h3_ijk_normalize(iVector + jVector + kVector);\n}\n\nfn dggs_h3_down_ap7(coord: vec3i) -> vec3i {\n let iVector = vec3i(3, 0, 1) * coord.x;\n let jVector = vec3i(1, 3, 0) * coord.y;\n let kVector = vec3i(0, 1, 3) * coord.z;\n return dggs_h3_ijk_normalize(iVector + jVector + kVector);\n}\n\nfn dggs_h3_down_ap7r(coord: vec3i) -> vec3i {\n let iVector = vec3i(3, 1, 0) * coord.x;\n let jVector = vec3i(0, 3, 1) * coord.y;\n let kVector = vec3i(1, 0, 3) * coord.z;\n return dggs_h3_ijk_normalize(iVector + jVector + kVector);\n}\n\nfn dggs_h3_get_center_face_ijk(index: vec2u) -> DggsH3FaceIJK {\n if (!dggs_h3_is_valid_cell_id(index)) {\n return DggsH3FaceIJK(0u, vec3i(0), 0u);\n }\n\n let baseCell = dggs_h3_get_base_cell(index);\n if (dggs_h3_is_base_cell_pentagon(baseCell)) {\n return DggsH3FaceIJK(0u, vec3i(0), 0u);\n }\n\n var faceIJK = dggs_h3_get_base_cell_home(baseCell);\n let cellResolution = dggs_h3_get_resolution(index);\n var resolution = 1u;\n loop {\n if (resolution > cellResolution) {\n break;\n }\n\n if (dggs_h3_is_resolution_class_iii(resolution)) {\n faceIJK.coord = dggs_h3_down_ap7(faceIJK.coord);\n } else {\n faceIJK.coord = dggs_h3_down_ap7r(faceIJK.coord);\n }\n faceIJK.coord = dggs_h3_neighbor(faceIJK.coord, dggs_h3_get_digit(index, resolution));\n resolution += 1u;\n }\n\n return faceIJK;\n}\n\nfn dggs_h3_get_vertex_offset(resolution: u32, vertexIndex: u32) -> vec3i {\n let pointIndex = vertexIndex % 6u;\n if (dggs_h3_is_resolution_class_iii(resolution)) {\n let vertices = array<vec3i, 6>(\n vec3i(5, 4, 0),\n vec3i(1, 5, 0),\n vec3i(0, 5, 4),\n vec3i(0, 1, 5),\n vec3i(4, 0, 5),\n vec3i(5, 0, 1)\n );\n return vertices[pointIndex];\n }\n\n let vertices = array<vec3i, 6>(\n vec3i(2, 1, 0),\n vec3i(1, 2, 0),\n vec3i(0, 2, 1),\n vec3i(0, 1, 2),\n vec3i(1, 0, 2),\n vec3i(2, 0, 1)\n );\n return vertices[pointIndex];\n}\n\nfn dggs_h3_get_boundary_vertex(index: vec2u, vertexIndex: u32) -> DggsH3BoundaryVertex {\n let center = dggs_h3_get_center_face_ijk(index);\n if (center.valid == 0u) {\n return DggsH3BoundaryVertex(0u, vec3i(0), 0u, 0u);\n }\n\n let cellResolution = dggs_h3_get_resolution(index);\n var adjustedResolution = cellResolution;\n var centerCoord = dggs_h3_down_ap3r(dggs_h3_down_ap3(center.coord));\n if (dggs_h3_is_resolution_class_iii(cellResolution)) {\n centerCoord = dggs_h3_down_ap7r(centerCoord);\n adjustedResolution += 1u;\n }\n\n let vertexCoord = dggs_h3_ijk_normalize(\n centerCoord + dggs_h3_get_vertex_offset(cellResolution, vertexIndex)\n );\n let maximumDimension = dggs_h3_get_max_dim_by_cii_resolution(adjustedResolution) * 3;\n let vertexDimension = vertexCoord.x + vertexCoord.y + vertexCoord.z;\n if (vertexDimension >= maximumDimension) {\n return DggsH3BoundaryVertex(center.face, vertexCoord, adjustedResolution, 0u);\n }\n\n return DggsH3BoundaryVertex(center.face, vertexCoord, adjustedResolution, 1u);\n}\n\nfn dggs_h3_is_single_face_boundary(index: vec2u) -> bool {\n var vertexIndex = 0u;\n loop {\n if (vertexIndex >= 6u) {\n break;\n }\n if (dggs_h3_get_boundary_vertex(index, vertexIndex).valid == 0u) {\n return false;\n }\n vertexIndex += 1u;\n }\n return true;\n}\n\nfn dggs_h3_ijk_to_hex2d(coord: vec3i) -> vec2f {\n let i = f32(coord.x - coord.z);\n let j = f32(coord.y - coord.z);\n return vec2f(i - 0.5 * j, j * DGGS_H3_SQRT3_2);\n}\n\nfn dggs_h3_geo_az_distance_rads(center: vec2f, azimuth: f32, distance: f32) -> vec2f {\n if (distance < 1.0e-7) {\n return center;\n }\n\n let positiveAzimuth = dggs_h3_positive_angle_rads(azimuth);\n let latitude = asin(clamp(\n sin(center.x) * cos(distance) + cos(center.x) * sin(distance) * cos(positiveAzimuth),\n -1.0,\n 1.0\n ));\n var longitude = 0.0;\n if (abs(latitude - DGGS_PI_OVER_2) < 1.0e-7) {\n return vec2f(DGGS_PI_OVER_2, 0.0);\n }\n if (abs(latitude + DGGS_PI_OVER_2) < 1.0e-7) {\n return vec2f(-DGGS_PI_OVER_2, 0.0);\n }\n\n let inverseCosLatitude = 1.0 / max(cos(latitude), 1.0e-8);\n let sinLongitude = clamp(\n sin(positiveAzimuth) * sin(distance) * inverseCosLatitude,\n -1.0,\n 1.0\n );\n let cosLongitude = clamp(\n (cos(distance) - sin(center.x) * sin(latitude)) / max(cos(center.x), 1.0e-8) *\n inverseCosLatitude,\n -1.0,\n 1.0\n );\n longitude = dggs_h3_constrain_longitude(center.y + atan2(sinLongitude, cosLongitude));\n return vec2f(latitude, longitude);\n}\n\nfn dggs_h3_hex2d_to_lnglat(point: vec2f, face: u32, resolution: u32, substrate: bool) -> vec2f {\n var radius = length(point);\n let center = dggs_h3_get_face_center_geo(face);\n if (radius < 1.0e-7) {\n return vec2f(center.y * DGGS_RADIANS_TO_DEGREES, center.x * DGGS_RADIANS_TO_DEGREES);\n }\n\n var theta = atan2(point.y, point.x);\n var resolutionIndex = 0u;\n loop {\n if (resolutionIndex >= resolution) {\n break;\n }\n radius *= DGGS_H3_RSQRT7;\n resolutionIndex += 1u;\n }\n\n if (substrate) {\n radius *= DGGS_H3_ONETHIRD;\n if (dggs_h3_is_resolution_class_iii(resolution)) {\n radius *= DGGS_H3_RSQRT7;\n }\n } else if (dggs_h3_is_resolution_class_iii(resolution)) {\n theta = dggs_h3_positive_angle_rads(theta + DGGS_H3_AP7_ROT_RADS);\n }\n\n radius = atan(radius * DGGS_H3_RES0_U_GNOMONIC);\n theta = dggs_h3_positive_angle_rads(dggs_h3_get_face_axis_azimuths(face).x - theta);\n let latitudeLongitude = dggs_h3_geo_az_distance_rads(center, theta, radius);\n return vec2f(\n latitudeLongitude.y * DGGS_RADIANS_TO_DEGREES,\n latitudeLongitude.x * DGGS_RADIANS_TO_DEGREES\n );\n}\n\nfn dggs_h3_get_boundary_point(index: vec2u, vertexIndex: u32) -> vec2f {\n if (!dggs_h3_is_single_face_boundary(index)) {\n return vec2f(0.0);\n }\n\n let vertex = dggs_h3_get_boundary_vertex(index, vertexIndex % 6u);\n let hexPoint = dggs_h3_ijk_to_hex2d(vertex.coord);\n return dggs_h3_hex2d_to_lnglat(hexPoint, vertex.face, vertex.resolution, true);\n}\n\nfn dggs_h3_get_boundary_point_fp64_split(index: vec2u, vertexIndex: u32) -> vec4f {\n return dggs_boundary_point_to_fp64_split(dggs_h3_get_boundary_point(index, vertexIndex));\n}\n\nfn dggs_s2_get_face(index: vec2u) -> u32 {\n return dggs_u64_extract_bits(index, 61u, 3u);\n}\n\nfn dggs_s2_get_level(index: vec2u) -> u32 {\n let trailingZeros = dggs_u64_count_trailing_zeros(index);\n if (trailingZeros > 60u) {\n return 0u;\n }\n return DGGS_S2_MAX_LEVEL - trailingZeros / 2u;\n}\n\nfn dggs_s2_is_valid_cell_id(index: vec2u) -> bool {\n let trailingZeros = dggs_u64_count_trailing_zeros(index);\n return !dggs_u64_is_zero(index) &&\n dggs_s2_get_face(index) <= 5u &&\n trailingZeros <= 60u &&\n trailingZeros % 2u == 0u;\n}\n\nfn dggs_s2_get_child_position(index: vec2u, level: u32) -> u32 {\n if (level == 0u || level > DGGS_S2_MAX_LEVEL) {\n return 0u;\n }\n return dggs_u64_extract_bits(index, 2u * (DGGS_S2_MAX_LEVEL - level) + 1u, 2u);\n}\n\n// Packed geohash keys store the geohash length in bits 60..63 and right-align\n// the base32 character codes in the lower 60 bits, first character first.\nfn dggs_geohash_get_length(index: vec2u) -> u32 {\n return min(\n dggs_u64_extract_bits(index, DGGS_GEOHASH_LENGTH_BIT_OFFSET, 4u),\n DGGS_GEOHASH_MAX_LENGTH\n );\n}\n\nfn dggs_geohash_get_character(index: vec2u, characterIndex: u32) -> u32 {\n let length = dggs_geohash_get_length(index);\n if (characterIndex >= length) {\n return 0u;\n }\n return dggs_u64_extract_bits(index, 5u * (length - characterIndex - 1u), 5u);\n}\n\n// Returns vec4(west, south, east, north) in longitude/latitude degrees.\nfn dggs_geohash_get_bounds(index: vec2u) -> vec4f {\n let length = dggs_geohash_get_length(index);\n var west = -180.0;\n var east = 180.0;\n var south = -90.0;\n var north = 90.0;\n var isLongitude = true;\n var characterIndex = 0u;\n loop {\n if (characterIndex >= length) {\n break;\n }\n\n let character = dggs_geohash_get_character(index, characterIndex);\n var bitIndex = 0u;\n loop {\n if (bitIndex >= 5u) {\n break;\n }\n\n let bit = (character >> (4u - bitIndex)) & 1u;\n if (isLongitude) {\n let midpoint = (west + east) * 0.5;\n if (bit == 0u) {\n east = midpoint;\n } else {\n west = midpoint;\n }\n } else {\n let midpoint = (south + north) * 0.5;\n if (bit == 0u) {\n north = midpoint;\n } else {\n south = midpoint;\n }\n }\n isLongitude = !isLongitude;\n bitIndex += 1u;\n }\n characterIndex += 1u;\n }\n\n return vec4f(west, south, east, north);\n}\n\nfn dggs_bounds_get_boundary_point(bounds: vec4f, vertexIndex: u32) -> vec2f {\n let pointIndex = vertexIndex % 4u;\n if (pointIndex == 0u) {\n return vec2f(bounds.x, bounds.w);\n }\n if (pointIndex == 1u) {\n return vec2f(bounds.z, bounds.w);\n }\n if (pointIndex == 2u) {\n return vec2f(bounds.z, bounds.y);\n }\n return vec2f(bounds.x, bounds.y);\n}\n\nfn dggs_geohash_get_boundary_point(index: vec2u, vertexIndex: u32) -> vec2f {\n return dggs_bounds_get_boundary_point(dggs_geohash_get_bounds(index), vertexIndex);\n}\n\nfn dggs_geohash_get_boundary_point_fp64_split(index: vec2u, vertexIndex: u32) -> vec4f {\n return dggs_boundary_point_to_fp64_split(dggs_geohash_get_boundary_point(index, vertexIndex));\n}\n\n// Packed quadkey keys store the quadkey length in bits 58..63 and right-align\n// the base4 digits in the lower 58 bits, first digit first.\nfn dggs_quadkey_get_length(index: vec2u) -> u32 {\n return min(\n dggs_u64_extract_bits(index, DGGS_QUADKEY_LENGTH_BIT_OFFSET, 6u),\n DGGS_QUADKEY_MAX_LENGTH\n );\n}\n\nfn dggs_quadkey_get_digit(index: vec2u, digitIndex: u32) -> u32 {\n let length = dggs_quadkey_get_length(index);\n if (digitIndex >= length) {\n return 0u;\n }\n return dggs_u64_extract_bits(index, 2u * (length - digitIndex - 1u), 2u);\n}\n\nfn dggs_quadkey_get_tile(index: vec2u) -> vec3u {\n let length = dggs_quadkey_get_length(index);\n var tileX = 0u;\n var tileY = 0u;\n var digitIndex = 0u;\n loop {\n if (digitIndex >= length) {\n break;\n }\n\n let digit = dggs_quadkey_get_digit(index, digitIndex);\n let mask = 1u << (length - digitIndex - 1u);\n if ((digit & 1u) != 0u) {\n tileX |= mask;\n }\n if ((digit & 2u) != 0u) {\n tileY |= mask;\n }\n digitIndex += 1u;\n }\n return vec3u(tileX, tileY, length);\n}\n\nfn dggs_web_mercator_tile_y_to_latitude(tileY: f32, tileScale: f32) -> f32 {\n let mercatorY = DGGS_PI * (1.0 - 2.0 * tileY / tileScale);\n return (2.0 * atan(exp(mercatorY)) - DGGS_PI * 0.5) * DGGS_RADIANS_TO_DEGREES;\n}\n\n// Returns vec4(west, south, east, north) in longitude/latitude degrees.\nfn dggs_quadkey_get_bounds(index: vec2u) -> vec4f {\n let tile = dggs_quadkey_get_tile(index);\n let tileScale = f32(1u << tile.z);\n let west = f32(tile.x) / tileScale * 360.0 - 180.0;\n let east = f32(tile.x + 1u) / tileScale * 360.0 - 180.0;\n let north = dggs_web_mercator_tile_y_to_latitude(f32(tile.y), tileScale);\n let south = dggs_web_mercator_tile_y_to_latitude(f32(tile.y + 1u), tileScale);\n return vec4f(west, south, east, north);\n}\n\nfn dggs_quadkey_get_boundary_point(index: vec2u, vertexIndex: u32) -> vec2f {\n return dggs_bounds_get_boundary_point(dggs_quadkey_get_bounds(index), vertexIndex);\n}\n\nfn dggs_quadkey_get_boundary_point_fp64_split(index: vec2u, vertexIndex: u32) -> vec4f {\n return dggs_boundary_point_to_fp64_split(dggs_quadkey_get_boundary_point(index, vertexIndex));\n}\n\nfn dggs_s2_digit_to_xy(digit: u32) -> vec2u {\n if (digit == 1u) {\n return vec2u(0u, 1u);\n }\n if (digit == 2u) {\n return vec2u(1u, 1u);\n }\n if (digit == 3u) {\n return vec2u(1u, 0u);\n }\n return vec2u(0u, 0u);\n}\n\nfn dggs_s2_rotate_and_flip_quadrant(size: u32, point: vec2u, digitXY: vec2u) -> vec2u {\n var result = point;\n if (digitXY.y == 0u) {\n if (digitXY.x == 1u) {\n result = vec2u(size - 1u - result.x, size - 1u - result.y);\n }\n result = result.yx;\n }\n return result;\n}\n\nfn dggs_s2_get_ij(index: vec2u) -> vec2u {\n let level = dggs_s2_get_level(index);\n var point = vec2u(0u);\n var hilbertLevel = 1u;\n loop {\n if (hilbertLevel > level) {\n break;\n }\n let digitLevel = level - hilbertLevel + 1u;\n let digitXY = dggs_s2_digit_to_xy(dggs_s2_get_child_position(index, digitLevel));\n let size = 1u << (hilbertLevel - 1u);\n point = dggs_s2_rotate_and_flip_quadrant(size, point, digitXY);\n point += size * digitXY;\n hilbertLevel += 1u;\n }\n if ((dggs_s2_get_face(index) & 1u) != 0u) {\n point = point.yx;\n }\n return point;\n}\n\nfn dggs_s2_single_st_to_uv(st: f32) -> f32 {\n if (st >= 0.5) {\n return (4.0 * st * st - 1.0) / 3.0;\n }\n return (1.0 - 4.0 * (1.0 - st) * (1.0 - st)) / 3.0;\n}\n\nfn dggs_s2_ij_to_st(ij: vec2u, level: u32, offset: vec2f) -> vec2f {\n let maxSize = f32(1u << level);\n return (vec2f(f32(ij.x), f32(ij.y)) + offset) / maxSize;\n}\n\nfn dggs_s2_st_to_uv(st: vec2f) -> vec2f {\n return vec2f(dggs_s2_single_st_to_uv(st.x), dggs_s2_single_st_to_uv(st.y));\n}\n\nfn dggs_s2_face_uv_to_xyz(face: u32, uv: vec2f) -> vec3f {\n if (face == 0u) {\n return vec3f(1.0, uv.x, uv.y);\n }\n if (face == 1u) {\n return vec3f(-uv.x, 1.0, uv.y);\n }\n if (face == 2u) {\n return vec3f(-uv.x, -uv.y, 1.0);\n }\n if (face == 3u) {\n return vec3f(-1.0, -uv.y, -uv.x);\n }\n if (face == 4u) {\n return vec3f(uv.y, -1.0, -uv.x);\n }\n return vec3f(uv.y, uv.x, -1.0);\n}\n\nfn dggs_s2_xyz_to_lnglat(xyz: vec3f) -> vec2f {\n let latitude = atan2(xyz.z, length(xyz.xy)) * DGGS_RADIANS_TO_DEGREES;\n let longitude = atan2(xyz.y, xyz.x) * DGGS_RADIANS_TO_DEGREES;\n return vec2f(longitude, latitude);\n}\n\nfn dggs_s2_get_boundary_offset(vertexIndex: u32) -> vec2f {\n let pointIndex = vertexIndex % 4u;\n if (pointIndex == 1u) {\n return vec2f(0.0, 1.0);\n }\n if (pointIndex == 2u) {\n return vec2f(1.0, 1.0);\n }\n if (pointIndex == 3u) {\n return vec2f(1.0, 0.0);\n }\n return vec2f(0.0, 0.0);\n}\n\nfn dggs_s2_get_boundary_point(index: vec2u, vertexIndex: u32) -> vec2f {\n let level = dggs_s2_get_level(index);\n let ij = dggs_s2_get_ij(index);\n let st = dggs_s2_ij_to_st(ij, level, dggs_s2_get_boundary_offset(vertexIndex));\n let uv = dggs_s2_st_to_uv(st);\n let xyz = dggs_s2_face_uv_to_xyz(dggs_s2_get_face(index), uv);\n return dggs_s2_xyz_to_lnglat(xyz);\n}\n\nfn dggs_s2_get_boundary_point_fp64_split(index: vec2u, vertexIndex: u32) -> vec4f {\n return dggs_boundary_point_to_fp64_split(dggs_s2_get_boundary_point(index, vertexIndex));\n}\n";
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=dggs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dggs.d.ts","sourceRoot":"","sources":["../../../../src/modules/geospatial/dggs/dggs.ts"],"names":[],"mappings":"AAOA,sEAAsE;AACtE,eAAO,MAAM,IAAI;;;CAGwB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
import { dggsWGSL } from "./dggs-wgsl.js";
|
|
5
|
+
/** WGSL helpers for 64-bit DGGS cell IDs encoded as two u32 words. */
|
|
6
|
+
export const dggs = {
|
|
7
|
+
name: 'dggs',
|
|
8
|
+
source: dggsWGSL
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=dggs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dggs.js","sourceRoot":"","sources":["../../../../src/modules/geospatial/dggs/dggs.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AAGpC,OAAO,EAAC,QAAQ,EAAC,uBAAoB;AAErC,sEAAsE;AACtE,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;CACuB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { NumberArray2, NumberArray3, Vector2, Vector3 } from '@math.gl/core';
|
|
2
|
+
import { ShaderModule } from "../../../lib/shader-module/shader-module.js";
|
|
3
|
+
export type WaterMaterialUniforms = {
|
|
4
|
+
time?: number;
|
|
5
|
+
baseColor?: Readonly<Vector3 | NumberArray3>;
|
|
6
|
+
opacity?: number;
|
|
7
|
+
fresnelColor?: Readonly<Vector3 | NumberArray3>;
|
|
8
|
+
fresnelPower?: number;
|
|
9
|
+
specularIntensity?: number;
|
|
10
|
+
normalStrength?: number;
|
|
11
|
+
mappingMode?: number;
|
|
12
|
+
coordinateScale?: Readonly<Vector2 | NumberArray2>;
|
|
13
|
+
coordinateOffset?: Readonly<Vector2 | NumberArray2>;
|
|
14
|
+
waveADirection?: Readonly<Vector2 | NumberArray2>;
|
|
15
|
+
waveASpeed?: number;
|
|
16
|
+
waveAFrequency?: number;
|
|
17
|
+
waveAAmplitude?: number;
|
|
18
|
+
waveBDirection?: Readonly<Vector2 | NumberArray2>;
|
|
19
|
+
waveBSpeed?: number;
|
|
20
|
+
waveBFrequency?: number;
|
|
21
|
+
waveBAmplitude?: number;
|
|
22
|
+
};
|
|
23
|
+
export type WaterMaterialProps = Omit<WaterMaterialUniforms, 'mappingMode'> & {
|
|
24
|
+
mapping?: 'uv' | 'world' | 'object';
|
|
25
|
+
};
|
|
26
|
+
/** Animated water material with procedural waves and Fresnel/specular shading. */
|
|
27
|
+
export declare const waterMaterial: ShaderModule<WaterMaterialProps, WaterMaterialUniforms>;
|
|
28
|
+
//# sourceMappingURL=water-material.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"water-material.d.ts","sourceRoot":"","sources":["../../../../src/modules/lighting/water-material/water-material.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAC,MAAM,eAAe,CAAC;AAChF,OAAO,EAAC,YAAY,EAAC,oDAAiD;AAKtE,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC;IACnD,gBAAgB,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,qBAAqB,EAAE,aAAa,CAAC,GAAG;IAC5E,OAAO,CAAC,EAAE,IAAI,GAAG,OAAO,GAAG,QAAQ,CAAC;CACrC,CAAC;AAuBF,kFAAkF;AAClF,eAAO,MAAM,aAAa,EAAE,YAAY,CAAC,kBAAkB,EAAE,qBAAqB,CAwGjF,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
import { lighting } from "../lights/lighting.js";
|
|
5
|
+
import { WATER_FS, WATER_VS } from "./water-shaders-glsl.js";
|
|
6
|
+
import { WATER_WGSL } from "./water-shaders-wgsl.js";
|
|
7
|
+
const DEFAULT_WATER_MATERIAL_UNIFORMS = {
|
|
8
|
+
time: 0,
|
|
9
|
+
baseColor: [0.04, 0.18, 0.31],
|
|
10
|
+
opacity: 0.82,
|
|
11
|
+
fresnelColor: [0.86, 0.95, 1],
|
|
12
|
+
fresnelPower: 5,
|
|
13
|
+
specularIntensity: 1.4,
|
|
14
|
+
normalStrength: 0.35,
|
|
15
|
+
mappingMode: 0,
|
|
16
|
+
coordinateScale: [1, 1],
|
|
17
|
+
coordinateOffset: [0, 0],
|
|
18
|
+
waveADirection: [0.9805806756909201, 0.19611613513818402],
|
|
19
|
+
waveASpeed: 0.6,
|
|
20
|
+
waveAFrequency: 4,
|
|
21
|
+
waveAAmplitude: 0.08,
|
|
22
|
+
waveBDirection: [0.09950371902099893, 0.9950371902099893],
|
|
23
|
+
waveBSpeed: -0.45,
|
|
24
|
+
waveBFrequency: 7,
|
|
25
|
+
waveBAmplitude: 0.04
|
|
26
|
+
};
|
|
27
|
+
/** Animated water material with procedural waves and Fresnel/specular shading. */
|
|
28
|
+
export const waterMaterial = {
|
|
29
|
+
name: 'waterMaterial',
|
|
30
|
+
firstBindingSlot: 0,
|
|
31
|
+
bindingLayout: [{ name: 'waterMaterial', group: 3 }],
|
|
32
|
+
dependencies: [lighting],
|
|
33
|
+
source: WATER_WGSL,
|
|
34
|
+
vs: WATER_VS,
|
|
35
|
+
fs: WATER_FS,
|
|
36
|
+
defines: {
|
|
37
|
+
LIGHTING_FRAGMENT: true
|
|
38
|
+
},
|
|
39
|
+
uniformTypes: {
|
|
40
|
+
time: 'f32',
|
|
41
|
+
baseColor: 'vec3<f32>',
|
|
42
|
+
opacity: 'f32',
|
|
43
|
+
fresnelColor: 'vec3<f32>',
|
|
44
|
+
fresnelPower: 'f32',
|
|
45
|
+
specularIntensity: 'f32',
|
|
46
|
+
normalStrength: 'f32',
|
|
47
|
+
mappingMode: 'i32',
|
|
48
|
+
coordinateScale: 'vec2<f32>',
|
|
49
|
+
coordinateOffset: 'vec2<f32>',
|
|
50
|
+
waveADirection: 'vec2<f32>',
|
|
51
|
+
waveASpeed: 'f32',
|
|
52
|
+
waveAFrequency: 'f32',
|
|
53
|
+
waveAAmplitude: 'f32',
|
|
54
|
+
waveBDirection: 'vec2<f32>',
|
|
55
|
+
waveBSpeed: 'f32',
|
|
56
|
+
waveBFrequency: 'f32',
|
|
57
|
+
waveBAmplitude: 'f32'
|
|
58
|
+
},
|
|
59
|
+
defaultUniforms: DEFAULT_WATER_MATERIAL_UNIFORMS,
|
|
60
|
+
getUniforms(props, previousUniforms = DEFAULT_WATER_MATERIAL_UNIFORMS) {
|
|
61
|
+
const { mapping, ...uniformProps } = props || {};
|
|
62
|
+
const uniforms = mergeWaterMaterialUniforms(previousUniforms);
|
|
63
|
+
if (uniformProps.time !== undefined) {
|
|
64
|
+
uniforms.time = uniformProps.time;
|
|
65
|
+
}
|
|
66
|
+
if (uniformProps.opacity !== undefined) {
|
|
67
|
+
uniforms.opacity = uniformProps.opacity;
|
|
68
|
+
}
|
|
69
|
+
if (uniformProps.fresnelPower !== undefined) {
|
|
70
|
+
uniforms.fresnelPower = uniformProps.fresnelPower;
|
|
71
|
+
}
|
|
72
|
+
if (uniformProps.specularIntensity !== undefined) {
|
|
73
|
+
uniforms.specularIntensity = uniformProps.specularIntensity;
|
|
74
|
+
}
|
|
75
|
+
if (uniformProps.normalStrength !== undefined) {
|
|
76
|
+
uniforms.normalStrength = uniformProps.normalStrength;
|
|
77
|
+
}
|
|
78
|
+
if (uniformProps.coordinateScale !== undefined) {
|
|
79
|
+
uniforms.coordinateScale = [
|
|
80
|
+
Number(uniformProps.coordinateScale[0]),
|
|
81
|
+
Number(uniformProps.coordinateScale[1])
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
if (uniformProps.coordinateOffset !== undefined) {
|
|
85
|
+
uniforms.coordinateOffset = [
|
|
86
|
+
Number(uniformProps.coordinateOffset[0]),
|
|
87
|
+
Number(uniformProps.coordinateOffset[1])
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
if (uniformProps.waveASpeed !== undefined) {
|
|
91
|
+
uniforms.waveASpeed = uniformProps.waveASpeed;
|
|
92
|
+
}
|
|
93
|
+
if (uniformProps.waveAFrequency !== undefined) {
|
|
94
|
+
uniforms.waveAFrequency = uniformProps.waveAFrequency;
|
|
95
|
+
}
|
|
96
|
+
if (uniformProps.waveAAmplitude !== undefined) {
|
|
97
|
+
uniforms.waveAAmplitude = uniformProps.waveAAmplitude;
|
|
98
|
+
}
|
|
99
|
+
if (uniformProps.waveBSpeed !== undefined) {
|
|
100
|
+
uniforms.waveBSpeed = uniformProps.waveBSpeed;
|
|
101
|
+
}
|
|
102
|
+
if (uniformProps.waveBFrequency !== undefined) {
|
|
103
|
+
uniforms.waveBFrequency = uniformProps.waveBFrequency;
|
|
104
|
+
}
|
|
105
|
+
if (uniformProps.waveBAmplitude !== undefined) {
|
|
106
|
+
uniforms.waveBAmplitude = uniformProps.waveBAmplitude;
|
|
107
|
+
}
|
|
108
|
+
if (uniformProps.baseColor) {
|
|
109
|
+
uniforms.baseColor = normalizeColor3(uniformProps.baseColor);
|
|
110
|
+
}
|
|
111
|
+
if (uniformProps.fresnelColor) {
|
|
112
|
+
uniforms.fresnelColor = normalizeColor3(uniformProps.fresnelColor);
|
|
113
|
+
}
|
|
114
|
+
if (uniformProps.waveADirection) {
|
|
115
|
+
uniforms.waveADirection = normalizeDirection2(uniformProps.waveADirection);
|
|
116
|
+
}
|
|
117
|
+
if (uniformProps.waveBDirection) {
|
|
118
|
+
uniforms.waveBDirection = normalizeDirection2(uniformProps.waveBDirection);
|
|
119
|
+
}
|
|
120
|
+
if (mapping !== undefined) {
|
|
121
|
+
uniforms.mappingMode = mapping === 'world' ? 1 : mapping === 'object' ? 2 : 0;
|
|
122
|
+
}
|
|
123
|
+
return uniforms;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
function mergeWaterMaterialUniforms(previousUniforms) {
|
|
127
|
+
return {
|
|
128
|
+
time: previousUniforms.time ?? DEFAULT_WATER_MATERIAL_UNIFORMS.time,
|
|
129
|
+
baseColor: previousUniforms.baseColor
|
|
130
|
+
? normalizeColor3(previousUniforms.baseColor)
|
|
131
|
+
: DEFAULT_WATER_MATERIAL_UNIFORMS.baseColor,
|
|
132
|
+
opacity: previousUniforms.opacity ?? DEFAULT_WATER_MATERIAL_UNIFORMS.opacity,
|
|
133
|
+
fresnelColor: previousUniforms.fresnelColor
|
|
134
|
+
? normalizeColor3(previousUniforms.fresnelColor)
|
|
135
|
+
: DEFAULT_WATER_MATERIAL_UNIFORMS.fresnelColor,
|
|
136
|
+
fresnelPower: previousUniforms.fresnelPower ?? DEFAULT_WATER_MATERIAL_UNIFORMS.fresnelPower,
|
|
137
|
+
specularIntensity: previousUniforms.specularIntensity ?? DEFAULT_WATER_MATERIAL_UNIFORMS.specularIntensity,
|
|
138
|
+
normalStrength: previousUniforms.normalStrength ?? DEFAULT_WATER_MATERIAL_UNIFORMS.normalStrength,
|
|
139
|
+
mappingMode: previousUniforms.mappingMode ?? DEFAULT_WATER_MATERIAL_UNIFORMS.mappingMode,
|
|
140
|
+
coordinateScale: previousUniforms.coordinateScale
|
|
141
|
+
? [Number(previousUniforms.coordinateScale[0]), Number(previousUniforms.coordinateScale[1])]
|
|
142
|
+
: DEFAULT_WATER_MATERIAL_UNIFORMS.coordinateScale,
|
|
143
|
+
coordinateOffset: previousUniforms.coordinateOffset
|
|
144
|
+
? [Number(previousUniforms.coordinateOffset[0]), Number(previousUniforms.coordinateOffset[1])]
|
|
145
|
+
: DEFAULT_WATER_MATERIAL_UNIFORMS.coordinateOffset,
|
|
146
|
+
waveADirection: previousUniforms.waveADirection
|
|
147
|
+
? normalizeDirection2(previousUniforms.waveADirection)
|
|
148
|
+
: DEFAULT_WATER_MATERIAL_UNIFORMS.waveADirection,
|
|
149
|
+
waveASpeed: previousUniforms.waveASpeed ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveASpeed,
|
|
150
|
+
waveAFrequency: previousUniforms.waveAFrequency ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveAFrequency,
|
|
151
|
+
waveAAmplitude: previousUniforms.waveAAmplitude ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveAAmplitude,
|
|
152
|
+
waveBDirection: previousUniforms.waveBDirection
|
|
153
|
+
? normalizeDirection2(previousUniforms.waveBDirection)
|
|
154
|
+
: DEFAULT_WATER_MATERIAL_UNIFORMS.waveBDirection,
|
|
155
|
+
waveBSpeed: previousUniforms.waveBSpeed ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBSpeed,
|
|
156
|
+
waveBFrequency: previousUniforms.waveBFrequency ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBFrequency,
|
|
157
|
+
waveBAmplitude: previousUniforms.waveBAmplitude ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBAmplitude
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function normalizeColor3(color) {
|
|
161
|
+
const normalizedColor = [Number(color[0]), Number(color[1]), Number(color[2])];
|
|
162
|
+
const maxChannel = Math.max(...normalizedColor.map(channel => Math.abs(channel)));
|
|
163
|
+
if (maxChannel > 1) {
|
|
164
|
+
normalizedColor[0] /= 255;
|
|
165
|
+
normalizedColor[1] /= 255;
|
|
166
|
+
normalizedColor[2] /= 255;
|
|
167
|
+
}
|
|
168
|
+
return normalizedColor;
|
|
169
|
+
}
|
|
170
|
+
function normalizeDirection2(direction) {
|
|
171
|
+
const x = Number(direction[0]);
|
|
172
|
+
const y = Number(direction[1]);
|
|
173
|
+
const length = Math.hypot(x, y);
|
|
174
|
+
if (length === 0) {
|
|
175
|
+
return [1, 0];
|
|
176
|
+
}
|
|
177
|
+
return [x / length, y / length];
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=water-material.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"water-material.js","sourceRoot":"","sources":["../../../../src/modules/lighting/water-material/water-material.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const WATER_VS = "layout(std140) uniform waterMaterialUniforms {\n uniform float time;\n uniform vec3 baseColor;\n uniform float opacity;\n uniform vec3 fresnelColor;\n uniform float fresnelPower;\n uniform float specularIntensity;\n uniform float normalStrength;\n uniform int mappingMode;\n uniform vec2 coordinateScale;\n uniform vec2 coordinateOffset;\n uniform vec2 waveADirection;\n uniform float waveASpeed;\n uniform float waveAFrequency;\n uniform float waveAAmplitude;\n uniform vec2 waveBDirection;\n uniform float waveBSpeed;\n uniform float waveBFrequency;\n uniform float waveBAmplitude;\n} waterMaterial;\n";
|
|
2
|
+
export declare const WATER_FS = "layout(std140) uniform waterMaterialUniforms {\n uniform float time;\n uniform vec3 baseColor;\n uniform float opacity;\n uniform vec3 fresnelColor;\n uniform float fresnelPower;\n uniform float specularIntensity;\n uniform float normalStrength;\n uniform int mappingMode;\n uniform vec2 coordinateScale;\n uniform vec2 coordinateOffset;\n uniform vec2 waveADirection;\n uniform float waveASpeed;\n uniform float waveAFrequency;\n uniform float waveAAmplitude;\n uniform vec2 waveBDirection;\n uniform float waveBSpeed;\n uniform float waveBFrequency;\n uniform float waveBAmplitude;\n} waterMaterial;\n\nvec2 water_getDirection(vec2 direction) {\n float directionLength = length(direction);\n return directionLength > 0.0 ? direction / directionLength : vec2(1.0, 0.0);\n}\n\nvec2 water_getCoordinates(vec3 position_worldspace, vec3 position_objectspace, vec2 uv) {\n vec2 baseCoordinates = uv;\n if (waterMaterial.mappingMode == 1) {\n baseCoordinates = position_worldspace.xz;\n } else if (waterMaterial.mappingMode == 2) {\n vec3 globeDirection = normalize(position_objectspace);\n float longitude = atan(globeDirection.x, globeDirection.z);\n float latitude = asin(clamp(globeDirection.y, -1.0, 1.0));\n baseCoordinates = vec2(longitude, latitude);\n }\n return baseCoordinates * waterMaterial.coordinateScale + waterMaterial.coordinateOffset;\n}\n\nvec2 water_getWaveGradient(\n vec2 coordinates,\n vec2 direction,\n float speed,\n float frequency,\n float amplitude\n) {\n vec2 normalizedDirection = water_getDirection(direction);\n float phase = dot(coordinates * frequency, normalizedDirection) + waterMaterial.time * speed;\n return cos(phase) * normalizedDirection * frequency * amplitude;\n}\n\nvec3 water_getTangent(vec3 normal_worldspace) {\n vec3 referenceAxis = abs(normal_worldspace.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);\n return normalize(cross(referenceAxis, normal_worldspace));\n}\n\nvec3 water_getNormal(\n vec3 position_worldspace,\n vec3 position_objectspace,\n vec3 normal_worldspace,\n vec2 uv\n) {\n vec2 coordinates = water_getCoordinates(position_worldspace, position_objectspace, uv);\n vec2 gradient =\n water_getWaveGradient(\n coordinates,\n waterMaterial.waveADirection,\n waterMaterial.waveASpeed,\n waterMaterial.waveAFrequency,\n waterMaterial.waveAAmplitude\n ) +\n water_getWaveGradient(\n coordinates,\n waterMaterial.waveBDirection,\n waterMaterial.waveBSpeed,\n waterMaterial.waveBFrequency,\n waterMaterial.waveBAmplitude\n );\n\n vec3 tangent = water_getTangent(normal_worldspace);\n vec3 bitangent = normalize(cross(normal_worldspace, tangent));\n vec3 perturbation =\n waterMaterial.normalStrength * (gradient.x * tangent + gradient.y * bitangent);\n\n return normalize(normal_worldspace + perturbation);\n}\n\nvec3 water_getSpecularContribution(\n vec3 light_direction,\n vec3 view_direction,\n vec3 normal_worldspace,\n vec3 light_color,\n float fresnel\n) {\n vec3 halfway_direction = normalize(light_direction + view_direction);\n float specular =\n pow(max(dot(normal_worldspace, halfway_direction), 0.0), 72.0) *\n waterMaterial.specularIntensity *\n (0.25 + 0.75 * fresnel);\n\n return waterMaterial.fresnelColor * light_color * specular;\n}\n\nvec4 water_getColorMapped(\n vec3 cameraPosition,\n vec3 position_worldspace,\n vec3 position_objectspace,\n vec3 normal_worldspace,\n vec2 uv\n) {\n vec3 waterNormal = water_getNormal(\n position_worldspace,\n position_objectspace,\n normalize(normal_worldspace),\n uv\n );\n vec3 viewDirection = normalize(cameraPosition - position_worldspace);\n float fresnel =\n pow(\n 1.0 - max(dot(viewDirection, waterNormal), 0.0),\n max(waterMaterial.fresnelPower, 0.0001)\n );\n vec3 surfaceColor = mix(\n waterMaterial.baseColor,\n waterMaterial.fresnelColor,\n clamp(fresnel * 0.6, 0.0, 1.0)\n );\n\n if (lighting.enabled == 0) {\n return vec4(surfaceColor, waterMaterial.opacity);\n }\n\n vec3 lightColor = surfaceColor * (0.15 + 0.85 * lighting.ambientColor);\n\n for (int i = 0; i < lighting.pointLightCount; i++) {\n PointLight pointLight = lighting_getPointLight(i);\n vec3 lightPosition = pointLight.position;\n vec3 lightDirection = normalize(lightPosition - position_worldspace);\n float attenuation =\n getPointLightAttenuation(pointLight, distance(lightPosition, position_worldspace));\n vec3 incidentLight = pointLight.color / attenuation;\n float diffuse = max(dot(waterNormal, lightDirection), 0.0);\n\n lightColor += surfaceColor * incidentLight * diffuse;\n lightColor += water_getSpecularContribution(\n lightDirection,\n viewDirection,\n waterNormal,\n incidentLight,\n fresnel\n );\n }\n\n for (int i = 0; i < lighting.spotLightCount; i++) {\n SpotLight spotLight = lighting_getSpotLight(i);\n vec3 lightPosition = spotLight.position;\n vec3 lightDirection = normalize(lightPosition - position_worldspace);\n float attenuation = getSpotLightAttenuation(spotLight, position_worldspace);\n vec3 incidentLight = spotLight.color / attenuation;\n float diffuse = max(dot(waterNormal, lightDirection), 0.0);\n\n lightColor += surfaceColor * incidentLight * diffuse;\n lightColor += water_getSpecularContribution(\n lightDirection,\n viewDirection,\n waterNormal,\n incidentLight,\n fresnel\n );\n }\n\n for (int i = 0; i < lighting.directionalLightCount; i++) {\n DirectionalLight directionalLight = lighting_getDirectionalLight(i);\n vec3 lightDirection = normalize(-directionalLight.direction);\n float diffuse = max(dot(waterNormal, lightDirection), 0.0);\n\n lightColor += surfaceColor * directionalLight.color * diffuse;\n lightColor += water_getSpecularContribution(\n lightDirection,\n viewDirection,\n waterNormal,\n directionalLight.color,\n fresnel\n );\n }\n\n lightColor = mix(lightColor, waterMaterial.fresnelColor, clamp(fresnel, 0.0, 1.0) * 0.35);\n return vec4(lightColor, waterMaterial.opacity);\n}\n\nvec4 water_getColor(\n vec3 cameraPosition,\n vec3 position_worldspace,\n vec3 normal_worldspace,\n vec2 uv\n) {\n return water_getColorMapped(\n cameraPosition,\n position_worldspace,\n position_worldspace,\n normal_worldspace,\n uv\n );\n}\n";
|
|
3
|
+
//# sourceMappingURL=water-shaders-glsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"water-shaders-glsl.d.ts","sourceRoot":"","sources":["../../../../src/modules/lighting/water-material/water-shaders-glsl.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,QAAQ,knBAqBpB,CAAC;AAEF,eAAO,MAAM,QAAQ,m0MA6MpB,CAAC"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
export const WATER_VS = /* glsl */ `\
|
|
5
|
+
layout(std140) uniform waterMaterialUniforms {
|
|
6
|
+
uniform float time;
|
|
7
|
+
uniform vec3 baseColor;
|
|
8
|
+
uniform float opacity;
|
|
9
|
+
uniform vec3 fresnelColor;
|
|
10
|
+
uniform float fresnelPower;
|
|
11
|
+
uniform float specularIntensity;
|
|
12
|
+
uniform float normalStrength;
|
|
13
|
+
uniform int mappingMode;
|
|
14
|
+
uniform vec2 coordinateScale;
|
|
15
|
+
uniform vec2 coordinateOffset;
|
|
16
|
+
uniform vec2 waveADirection;
|
|
17
|
+
uniform float waveASpeed;
|
|
18
|
+
uniform float waveAFrequency;
|
|
19
|
+
uniform float waveAAmplitude;
|
|
20
|
+
uniform vec2 waveBDirection;
|
|
21
|
+
uniform float waveBSpeed;
|
|
22
|
+
uniform float waveBFrequency;
|
|
23
|
+
uniform float waveBAmplitude;
|
|
24
|
+
} waterMaterial;
|
|
25
|
+
`;
|
|
26
|
+
export const WATER_FS = /* glsl */ `\
|
|
27
|
+
layout(std140) uniform waterMaterialUniforms {
|
|
28
|
+
uniform float time;
|
|
29
|
+
uniform vec3 baseColor;
|
|
30
|
+
uniform float opacity;
|
|
31
|
+
uniform vec3 fresnelColor;
|
|
32
|
+
uniform float fresnelPower;
|
|
33
|
+
uniform float specularIntensity;
|
|
34
|
+
uniform float normalStrength;
|
|
35
|
+
uniform int mappingMode;
|
|
36
|
+
uniform vec2 coordinateScale;
|
|
37
|
+
uniform vec2 coordinateOffset;
|
|
38
|
+
uniform vec2 waveADirection;
|
|
39
|
+
uniform float waveASpeed;
|
|
40
|
+
uniform float waveAFrequency;
|
|
41
|
+
uniform float waveAAmplitude;
|
|
42
|
+
uniform vec2 waveBDirection;
|
|
43
|
+
uniform float waveBSpeed;
|
|
44
|
+
uniform float waveBFrequency;
|
|
45
|
+
uniform float waveBAmplitude;
|
|
46
|
+
} waterMaterial;
|
|
47
|
+
|
|
48
|
+
vec2 water_getDirection(vec2 direction) {
|
|
49
|
+
float directionLength = length(direction);
|
|
50
|
+
return directionLength > 0.0 ? direction / directionLength : vec2(1.0, 0.0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
vec2 water_getCoordinates(vec3 position_worldspace, vec3 position_objectspace, vec2 uv) {
|
|
54
|
+
vec2 baseCoordinates = uv;
|
|
55
|
+
if (waterMaterial.mappingMode == 1) {
|
|
56
|
+
baseCoordinates = position_worldspace.xz;
|
|
57
|
+
} else if (waterMaterial.mappingMode == 2) {
|
|
58
|
+
vec3 globeDirection = normalize(position_objectspace);
|
|
59
|
+
float longitude = atan(globeDirection.x, globeDirection.z);
|
|
60
|
+
float latitude = asin(clamp(globeDirection.y, -1.0, 1.0));
|
|
61
|
+
baseCoordinates = vec2(longitude, latitude);
|
|
62
|
+
}
|
|
63
|
+
return baseCoordinates * waterMaterial.coordinateScale + waterMaterial.coordinateOffset;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
vec2 water_getWaveGradient(
|
|
67
|
+
vec2 coordinates,
|
|
68
|
+
vec2 direction,
|
|
69
|
+
float speed,
|
|
70
|
+
float frequency,
|
|
71
|
+
float amplitude
|
|
72
|
+
) {
|
|
73
|
+
vec2 normalizedDirection = water_getDirection(direction);
|
|
74
|
+
float phase = dot(coordinates * frequency, normalizedDirection) + waterMaterial.time * speed;
|
|
75
|
+
return cos(phase) * normalizedDirection * frequency * amplitude;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
vec3 water_getTangent(vec3 normal_worldspace) {
|
|
79
|
+
vec3 referenceAxis = abs(normal_worldspace.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
|
|
80
|
+
return normalize(cross(referenceAxis, normal_worldspace));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
vec3 water_getNormal(
|
|
84
|
+
vec3 position_worldspace,
|
|
85
|
+
vec3 position_objectspace,
|
|
86
|
+
vec3 normal_worldspace,
|
|
87
|
+
vec2 uv
|
|
88
|
+
) {
|
|
89
|
+
vec2 coordinates = water_getCoordinates(position_worldspace, position_objectspace, uv);
|
|
90
|
+
vec2 gradient =
|
|
91
|
+
water_getWaveGradient(
|
|
92
|
+
coordinates,
|
|
93
|
+
waterMaterial.waveADirection,
|
|
94
|
+
waterMaterial.waveASpeed,
|
|
95
|
+
waterMaterial.waveAFrequency,
|
|
96
|
+
waterMaterial.waveAAmplitude
|
|
97
|
+
) +
|
|
98
|
+
water_getWaveGradient(
|
|
99
|
+
coordinates,
|
|
100
|
+
waterMaterial.waveBDirection,
|
|
101
|
+
waterMaterial.waveBSpeed,
|
|
102
|
+
waterMaterial.waveBFrequency,
|
|
103
|
+
waterMaterial.waveBAmplitude
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
vec3 tangent = water_getTangent(normal_worldspace);
|
|
107
|
+
vec3 bitangent = normalize(cross(normal_worldspace, tangent));
|
|
108
|
+
vec3 perturbation =
|
|
109
|
+
waterMaterial.normalStrength * (gradient.x * tangent + gradient.y * bitangent);
|
|
110
|
+
|
|
111
|
+
return normalize(normal_worldspace + perturbation);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
vec3 water_getSpecularContribution(
|
|
115
|
+
vec3 light_direction,
|
|
116
|
+
vec3 view_direction,
|
|
117
|
+
vec3 normal_worldspace,
|
|
118
|
+
vec3 light_color,
|
|
119
|
+
float fresnel
|
|
120
|
+
) {
|
|
121
|
+
vec3 halfway_direction = normalize(light_direction + view_direction);
|
|
122
|
+
float specular =
|
|
123
|
+
pow(max(dot(normal_worldspace, halfway_direction), 0.0), 72.0) *
|
|
124
|
+
waterMaterial.specularIntensity *
|
|
125
|
+
(0.25 + 0.75 * fresnel);
|
|
126
|
+
|
|
127
|
+
return waterMaterial.fresnelColor * light_color * specular;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
vec4 water_getColorMapped(
|
|
131
|
+
vec3 cameraPosition,
|
|
132
|
+
vec3 position_worldspace,
|
|
133
|
+
vec3 position_objectspace,
|
|
134
|
+
vec3 normal_worldspace,
|
|
135
|
+
vec2 uv
|
|
136
|
+
) {
|
|
137
|
+
vec3 waterNormal = water_getNormal(
|
|
138
|
+
position_worldspace,
|
|
139
|
+
position_objectspace,
|
|
140
|
+
normalize(normal_worldspace),
|
|
141
|
+
uv
|
|
142
|
+
);
|
|
143
|
+
vec3 viewDirection = normalize(cameraPosition - position_worldspace);
|
|
144
|
+
float fresnel =
|
|
145
|
+
pow(
|
|
146
|
+
1.0 - max(dot(viewDirection, waterNormal), 0.0),
|
|
147
|
+
max(waterMaterial.fresnelPower, 0.0001)
|
|
148
|
+
);
|
|
149
|
+
vec3 surfaceColor = mix(
|
|
150
|
+
waterMaterial.baseColor,
|
|
151
|
+
waterMaterial.fresnelColor,
|
|
152
|
+
clamp(fresnel * 0.6, 0.0, 1.0)
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
if (lighting.enabled == 0) {
|
|
156
|
+
return vec4(surfaceColor, waterMaterial.opacity);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
vec3 lightColor = surfaceColor * (0.15 + 0.85 * lighting.ambientColor);
|
|
160
|
+
|
|
161
|
+
for (int i = 0; i < lighting.pointLightCount; i++) {
|
|
162
|
+
PointLight pointLight = lighting_getPointLight(i);
|
|
163
|
+
vec3 lightPosition = pointLight.position;
|
|
164
|
+
vec3 lightDirection = normalize(lightPosition - position_worldspace);
|
|
165
|
+
float attenuation =
|
|
166
|
+
getPointLightAttenuation(pointLight, distance(lightPosition, position_worldspace));
|
|
167
|
+
vec3 incidentLight = pointLight.color / attenuation;
|
|
168
|
+
float diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
169
|
+
|
|
170
|
+
lightColor += surfaceColor * incidentLight * diffuse;
|
|
171
|
+
lightColor += water_getSpecularContribution(
|
|
172
|
+
lightDirection,
|
|
173
|
+
viewDirection,
|
|
174
|
+
waterNormal,
|
|
175
|
+
incidentLight,
|
|
176
|
+
fresnel
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
for (int i = 0; i < lighting.spotLightCount; i++) {
|
|
181
|
+
SpotLight spotLight = lighting_getSpotLight(i);
|
|
182
|
+
vec3 lightPosition = spotLight.position;
|
|
183
|
+
vec3 lightDirection = normalize(lightPosition - position_worldspace);
|
|
184
|
+
float attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
|
|
185
|
+
vec3 incidentLight = spotLight.color / attenuation;
|
|
186
|
+
float diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
187
|
+
|
|
188
|
+
lightColor += surfaceColor * incidentLight * diffuse;
|
|
189
|
+
lightColor += water_getSpecularContribution(
|
|
190
|
+
lightDirection,
|
|
191
|
+
viewDirection,
|
|
192
|
+
waterNormal,
|
|
193
|
+
incidentLight,
|
|
194
|
+
fresnel
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for (int i = 0; i < lighting.directionalLightCount; i++) {
|
|
199
|
+
DirectionalLight directionalLight = lighting_getDirectionalLight(i);
|
|
200
|
+
vec3 lightDirection = normalize(-directionalLight.direction);
|
|
201
|
+
float diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
202
|
+
|
|
203
|
+
lightColor += surfaceColor * directionalLight.color * diffuse;
|
|
204
|
+
lightColor += water_getSpecularContribution(
|
|
205
|
+
lightDirection,
|
|
206
|
+
viewDirection,
|
|
207
|
+
waterNormal,
|
|
208
|
+
directionalLight.color,
|
|
209
|
+
fresnel
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
lightColor = mix(lightColor, waterMaterial.fresnelColor, clamp(fresnel, 0.0, 1.0) * 0.35);
|
|
214
|
+
return vec4(lightColor, waterMaterial.opacity);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
vec4 water_getColor(
|
|
218
|
+
vec3 cameraPosition,
|
|
219
|
+
vec3 position_worldspace,
|
|
220
|
+
vec3 normal_worldspace,
|
|
221
|
+
vec2 uv
|
|
222
|
+
) {
|
|
223
|
+
return water_getColorMapped(
|
|
224
|
+
cameraPosition,
|
|
225
|
+
position_worldspace,
|
|
226
|
+
position_worldspace,
|
|
227
|
+
normal_worldspace,
|
|
228
|
+
uv
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
`;
|
|
232
|
+
//# sourceMappingURL=water-shaders-glsl.js.map
|