@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.
Files changed (113) hide show
  1. package/dist/dist.dev.js +6555 -2373
  2. package/dist/dist.min.js +2984 -237
  3. package/dist/index.cjs +4356 -268
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +13 -3
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +6 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/preprocessor/preprocessor.d.ts +11 -1
  10. package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
  11. package/dist/lib/preprocessor/preprocessor.js +47 -2
  12. package/dist/lib/preprocessor/preprocessor.js.map +1 -1
  13. package/dist/lib/shader-assembler.d.ts +10 -10
  14. package/dist/lib/shader-assembler.d.ts.map +1 -1
  15. package/dist/lib/shader-assembler.js +36 -20
  16. package/dist/lib/shader-assembler.js.map +1 -1
  17. package/dist/lib/shader-assembly/assemble-shaders.d.ts +28 -7
  18. package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
  19. package/dist/lib/shader-assembly/assemble-shaders.js +133 -15
  20. package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
  21. package/dist/lib/shader-assembly/platform-info.d.ts +2 -0
  22. package/dist/lib/shader-assembly/platform-info.d.ts.map +1 -1
  23. package/dist/lib/shader-assembly/shader-hooks.d.ts +1 -1
  24. package/dist/lib/shader-assembly/shader-hooks.d.ts.map +1 -1
  25. package/dist/lib/shader-assembly/shader-hooks.js +6 -3
  26. package/dist/lib/shader-assembly/shader-hooks.js.map +1 -1
  27. package/dist/lib/shader-assembly/shader-injections.d.ts +4 -1
  28. package/dist/lib/shader-assembly/shader-injections.d.ts.map +1 -1
  29. package/dist/lib/shader-assembly/shader-injections.js +68 -11
  30. package/dist/lib/shader-assembly/shader-injections.js.map +1 -1
  31. package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts +15 -0
  32. package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts.map +1 -0
  33. package/dist/lib/shader-assembly/shader-plugin-varyings.js +412 -0
  34. package/dist/lib/shader-assembly/shader-plugin-varyings.js.map +1 -0
  35. package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.d.ts +12 -0
  36. package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.d.ts.map +1 -0
  37. package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.js +237 -0
  38. package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.js.map +1 -0
  39. package/dist/lib/shader-module/shader-module.d.ts +3 -0
  40. package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
  41. package/dist/lib/shader-module/shader-module.js.map +1 -1
  42. package/dist/lib/shader-module/shader-pass-pipeline.d.ts +14 -0
  43. package/dist/lib/shader-module/shader-pass-pipeline.d.ts.map +1 -0
  44. package/dist/lib/shader-module/shader-pass-pipeline.js +5 -0
  45. package/dist/lib/shader-module/shader-pass-pipeline.js.map +1 -0
  46. package/dist/lib/shader-module/shader-pass.d.ts +21 -4
  47. package/dist/lib/shader-module/shader-pass.d.ts.map +1 -1
  48. package/dist/lib/shader-plugin.d.ts +68 -0
  49. package/dist/lib/shader-plugin.d.ts.map +1 -0
  50. package/dist/lib/shader-plugin.js +98 -0
  51. package/dist/lib/shader-plugin.js.map +1 -0
  52. package/dist/lib/utils/assert.js +1 -1
  53. package/dist/lib/utils/assert.js.map +1 -1
  54. package/dist/modules/color/float-colors.d.ts +111 -5
  55. package/dist/modules/color/float-colors.d.ts.map +1 -1
  56. package/dist/modules/color/float-colors.js +200 -34
  57. package/dist/modules/color/float-colors.js.map +1 -1
  58. package/dist/modules/engine/clip/clip.d.ts +12 -0
  59. package/dist/modules/engine/clip/clip.d.ts.map +1 -0
  60. package/dist/modules/engine/clip/clip.js +129 -0
  61. package/dist/modules/engine/clip/clip.js.map +1 -0
  62. package/dist/modules/engine/filter/filter.d.ts +12 -0
  63. package/dist/modules/engine/filter/filter.d.ts.map +1 -0
  64. package/dist/modules/engine/filter/filter.js +88 -0
  65. package/dist/modules/engine/filter/filter.js.map +1 -0
  66. package/dist/modules/geospatial/dggs/dggs-wgsl.d.ts +3 -0
  67. package/dist/modules/geospatial/dggs/dggs-wgsl.d.ts.map +1 -0
  68. package/dist/modules/geospatial/dggs/dggs-wgsl.js +1892 -0
  69. package/dist/modules/geospatial/dggs/dggs-wgsl.js.map +1 -0
  70. package/dist/modules/geospatial/dggs/dggs.d.ts +6 -0
  71. package/dist/modules/geospatial/dggs/dggs.d.ts.map +1 -0
  72. package/dist/modules/geospatial/dggs/dggs.js +10 -0
  73. package/dist/modules/geospatial/dggs/dggs.js.map +1 -0
  74. package/dist/modules/lighting/water-material/water-material.d.ts +28 -0
  75. package/dist/modules/lighting/water-material/water-material.d.ts.map +1 -0
  76. package/dist/modules/lighting/water-material/water-material.js +179 -0
  77. package/dist/modules/lighting/water-material/water-material.js.map +1 -0
  78. package/dist/modules/lighting/water-material/water-shaders-glsl.d.ts +3 -0
  79. package/dist/modules/lighting/water-material/water-shaders-glsl.d.ts.map +1 -0
  80. package/dist/modules/lighting/water-material/water-shaders-glsl.js +232 -0
  81. package/dist/modules/lighting/water-material/water-shaders-glsl.js.map +1 -0
  82. package/dist/modules/lighting/water-material/water-shaders-wgsl.d.ts +2 -0
  83. package/dist/modules/lighting/water-material/water-shaders-wgsl.d.ts.map +1 -0
  84. package/dist/modules/lighting/water-material/water-shaders-wgsl.js +230 -0
  85. package/dist/modules/lighting/water-material/water-shaders-wgsl.js.map +1 -0
  86. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -1
  87. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -1
  88. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +268 -0
  89. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -1
  90. package/package.json +2 -2
  91. package/src/index.ts +50 -3
  92. package/src/lib/preprocessor/preprocessor.ts +68 -3
  93. package/src/lib/shader-assembler.ts +49 -20
  94. package/src/lib/shader-assembly/assemble-shaders.ts +242 -30
  95. package/src/lib/shader-assembly/platform-info.ts +2 -0
  96. package/src/lib/shader-assembly/shader-hooks.ts +7 -3
  97. package/src/lib/shader-assembly/shader-injections.ts +96 -11
  98. package/src/lib/shader-assembly/shader-plugin-varyings.ts +524 -0
  99. package/src/lib/shader-assembly/shader-plugin-vertex-inputs.ts +279 -0
  100. package/src/lib/shader-module/shader-module.ts +3 -0
  101. package/src/lib/shader-module/shader-pass-pipeline.ts +19 -0
  102. package/src/lib/shader-module/shader-pass.ts +29 -4
  103. package/src/lib/shader-plugin.ts +214 -0
  104. package/src/lib/utils/assert.ts +1 -1
  105. package/src/modules/color/float-colors.ts +272 -37
  106. package/src/modules/engine/clip/clip.ts +149 -0
  107. package/src/modules/engine/filter/filter.ts +107 -0
  108. package/src/modules/geospatial/dggs/dggs-wgsl.ts +1892 -0
  109. package/src/modules/geospatial/dggs/dggs.ts +12 -0
  110. package/src/modules/lighting/water-material/water-material.ts +234 -0
  111. package/src/modules/lighting/water-material/water-shaders-glsl.ts +233 -0
  112. package/src/modules/lighting/water-material/water-shaders-wgsl.ts +230 -0
  113. package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +268 -0
@@ -0,0 +1,12 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import type {ShaderModule} from '../../../lib/shader-module/shader-module';
6
+ import {dggsWGSL} from './dggs-wgsl';
7
+
8
+ /** WGSL helpers for 64-bit DGGS cell IDs encoded as two u32 words. */
9
+ export const dggs = {
10
+ name: 'dggs',
11
+ source: dggsWGSL
12
+ } as const satisfies ShaderModule<{}, {}>;
@@ -0,0 +1,234 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import type {NumberArray2, NumberArray3, Vector2, Vector3} from '@math.gl/core';
6
+ import {ShaderModule} from '../../../lib/shader-module/shader-module';
7
+ import {lighting} from '../lights/lighting';
8
+ import {WATER_FS, WATER_VS} from './water-shaders-glsl';
9
+ import {WATER_WGSL} from './water-shaders-wgsl';
10
+
11
+ export type WaterMaterialUniforms = {
12
+ time?: number;
13
+ baseColor?: Readonly<Vector3 | NumberArray3>;
14
+ opacity?: number;
15
+ fresnelColor?: Readonly<Vector3 | NumberArray3>;
16
+ fresnelPower?: number;
17
+ specularIntensity?: number;
18
+ normalStrength?: number;
19
+ mappingMode?: number;
20
+ coordinateScale?: Readonly<Vector2 | NumberArray2>;
21
+ coordinateOffset?: Readonly<Vector2 | NumberArray2>;
22
+ waveADirection?: Readonly<Vector2 | NumberArray2>;
23
+ waveASpeed?: number;
24
+ waveAFrequency?: number;
25
+ waveAAmplitude?: number;
26
+ waveBDirection?: Readonly<Vector2 | NumberArray2>;
27
+ waveBSpeed?: number;
28
+ waveBFrequency?: number;
29
+ waveBAmplitude?: number;
30
+ };
31
+
32
+ export type WaterMaterialProps = Omit<WaterMaterialUniforms, 'mappingMode'> & {
33
+ mapping?: 'uv' | 'world' | 'object';
34
+ };
35
+
36
+ const DEFAULT_WATER_MATERIAL_UNIFORMS: Required<WaterMaterialUniforms> = {
37
+ time: 0,
38
+ baseColor: [0.04, 0.18, 0.31],
39
+ opacity: 0.82,
40
+ fresnelColor: [0.86, 0.95, 1],
41
+ fresnelPower: 5,
42
+ specularIntensity: 1.4,
43
+ normalStrength: 0.35,
44
+ mappingMode: 0,
45
+ coordinateScale: [1, 1],
46
+ coordinateOffset: [0, 0],
47
+ waveADirection: [0.9805806756909201, 0.19611613513818402],
48
+ waveASpeed: 0.6,
49
+ waveAFrequency: 4,
50
+ waveAAmplitude: 0.08,
51
+ waveBDirection: [0.09950371902099893, 0.9950371902099893],
52
+ waveBSpeed: -0.45,
53
+ waveBFrequency: 7,
54
+ waveBAmplitude: 0.04
55
+ };
56
+
57
+ /** Animated water material with procedural waves and Fresnel/specular shading. */
58
+ export const waterMaterial: ShaderModule<WaterMaterialProps, WaterMaterialUniforms> = {
59
+ name: 'waterMaterial',
60
+ firstBindingSlot: 0,
61
+ bindingLayout: [{name: 'waterMaterial', group: 3}],
62
+ dependencies: [lighting],
63
+ source: WATER_WGSL,
64
+ vs: WATER_VS,
65
+ fs: WATER_FS,
66
+ defines: {
67
+ LIGHTING_FRAGMENT: true
68
+ },
69
+ uniformTypes: {
70
+ time: 'f32',
71
+ baseColor: 'vec3<f32>',
72
+ opacity: 'f32',
73
+ fresnelColor: 'vec3<f32>',
74
+ fresnelPower: 'f32',
75
+ specularIntensity: 'f32',
76
+ normalStrength: 'f32',
77
+ mappingMode: 'i32',
78
+ coordinateScale: 'vec2<f32>',
79
+ coordinateOffset: 'vec2<f32>',
80
+ waveADirection: 'vec2<f32>',
81
+ waveASpeed: 'f32',
82
+ waveAFrequency: 'f32',
83
+ waveAAmplitude: 'f32',
84
+ waveBDirection: 'vec2<f32>',
85
+ waveBSpeed: 'f32',
86
+ waveBFrequency: 'f32',
87
+ waveBAmplitude: 'f32'
88
+ },
89
+ defaultUniforms: DEFAULT_WATER_MATERIAL_UNIFORMS,
90
+ getUniforms(
91
+ props?: WaterMaterialProps,
92
+ previousUniforms: Partial<WaterMaterialUniforms> = DEFAULT_WATER_MATERIAL_UNIFORMS
93
+ ) {
94
+ const {mapping, ...uniformProps} = props || {};
95
+ const uniforms = mergeWaterMaterialUniforms(previousUniforms);
96
+
97
+ if (uniformProps.time !== undefined) {
98
+ uniforms.time = uniformProps.time;
99
+ }
100
+ if (uniformProps.opacity !== undefined) {
101
+ uniforms.opacity = uniformProps.opacity;
102
+ }
103
+ if (uniformProps.fresnelPower !== undefined) {
104
+ uniforms.fresnelPower = uniformProps.fresnelPower;
105
+ }
106
+ if (uniformProps.specularIntensity !== undefined) {
107
+ uniforms.specularIntensity = uniformProps.specularIntensity;
108
+ }
109
+ if (uniformProps.normalStrength !== undefined) {
110
+ uniforms.normalStrength = uniformProps.normalStrength;
111
+ }
112
+ if (uniformProps.coordinateScale !== undefined) {
113
+ uniforms.coordinateScale = [
114
+ Number(uniformProps.coordinateScale[0]),
115
+ Number(uniformProps.coordinateScale[1])
116
+ ];
117
+ }
118
+ if (uniformProps.coordinateOffset !== undefined) {
119
+ uniforms.coordinateOffset = [
120
+ Number(uniformProps.coordinateOffset[0]),
121
+ Number(uniformProps.coordinateOffset[1])
122
+ ];
123
+ }
124
+ if (uniformProps.waveASpeed !== undefined) {
125
+ uniforms.waveASpeed = uniformProps.waveASpeed;
126
+ }
127
+ if (uniformProps.waveAFrequency !== undefined) {
128
+ uniforms.waveAFrequency = uniformProps.waveAFrequency;
129
+ }
130
+ if (uniformProps.waveAAmplitude !== undefined) {
131
+ uniforms.waveAAmplitude = uniformProps.waveAAmplitude;
132
+ }
133
+ if (uniformProps.waveBSpeed !== undefined) {
134
+ uniforms.waveBSpeed = uniformProps.waveBSpeed;
135
+ }
136
+ if (uniformProps.waveBFrequency !== undefined) {
137
+ uniforms.waveBFrequency = uniformProps.waveBFrequency;
138
+ }
139
+ if (uniformProps.waveBAmplitude !== undefined) {
140
+ uniforms.waveBAmplitude = uniformProps.waveBAmplitude;
141
+ }
142
+
143
+ if (uniformProps.baseColor) {
144
+ uniforms.baseColor = normalizeColor3(uniformProps.baseColor);
145
+ }
146
+ if (uniformProps.fresnelColor) {
147
+ uniforms.fresnelColor = normalizeColor3(uniformProps.fresnelColor);
148
+ }
149
+ if (uniformProps.waveADirection) {
150
+ uniforms.waveADirection = normalizeDirection2(uniformProps.waveADirection);
151
+ }
152
+ if (uniformProps.waveBDirection) {
153
+ uniforms.waveBDirection = normalizeDirection2(uniformProps.waveBDirection);
154
+ }
155
+
156
+ if (mapping !== undefined) {
157
+ uniforms.mappingMode = mapping === 'world' ? 1 : mapping === 'object' ? 2 : 0;
158
+ }
159
+
160
+ return uniforms;
161
+ }
162
+ };
163
+
164
+ function mergeWaterMaterialUniforms(
165
+ previousUniforms: Partial<WaterMaterialUniforms>
166
+ ): Required<WaterMaterialUniforms> {
167
+ return {
168
+ time: previousUniforms.time ?? DEFAULT_WATER_MATERIAL_UNIFORMS.time,
169
+ baseColor: previousUniforms.baseColor
170
+ ? normalizeColor3(previousUniforms.baseColor)
171
+ : DEFAULT_WATER_MATERIAL_UNIFORMS.baseColor,
172
+ opacity: previousUniforms.opacity ?? DEFAULT_WATER_MATERIAL_UNIFORMS.opacity,
173
+ fresnelColor: previousUniforms.fresnelColor
174
+ ? normalizeColor3(previousUniforms.fresnelColor)
175
+ : DEFAULT_WATER_MATERIAL_UNIFORMS.fresnelColor,
176
+ fresnelPower: previousUniforms.fresnelPower ?? DEFAULT_WATER_MATERIAL_UNIFORMS.fresnelPower,
177
+ specularIntensity:
178
+ previousUniforms.specularIntensity ?? DEFAULT_WATER_MATERIAL_UNIFORMS.specularIntensity,
179
+ normalStrength:
180
+ previousUniforms.normalStrength ?? DEFAULT_WATER_MATERIAL_UNIFORMS.normalStrength,
181
+ mappingMode: previousUniforms.mappingMode ?? DEFAULT_WATER_MATERIAL_UNIFORMS.mappingMode,
182
+ coordinateScale: previousUniforms.coordinateScale
183
+ ? [Number(previousUniforms.coordinateScale[0]), Number(previousUniforms.coordinateScale[1])]
184
+ : DEFAULT_WATER_MATERIAL_UNIFORMS.coordinateScale,
185
+ coordinateOffset: previousUniforms.coordinateOffset
186
+ ? [Number(previousUniforms.coordinateOffset[0]), Number(previousUniforms.coordinateOffset[1])]
187
+ : DEFAULT_WATER_MATERIAL_UNIFORMS.coordinateOffset,
188
+ waveADirection: previousUniforms.waveADirection
189
+ ? normalizeDirection2(previousUniforms.waveADirection)
190
+ : DEFAULT_WATER_MATERIAL_UNIFORMS.waveADirection,
191
+ waveASpeed: previousUniforms.waveASpeed ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveASpeed,
192
+ waveAFrequency:
193
+ previousUniforms.waveAFrequency ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveAFrequency,
194
+ waveAAmplitude:
195
+ previousUniforms.waveAAmplitude ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveAAmplitude,
196
+ waveBDirection: previousUniforms.waveBDirection
197
+ ? normalizeDirection2(previousUniforms.waveBDirection)
198
+ : DEFAULT_WATER_MATERIAL_UNIFORMS.waveBDirection,
199
+ waveBSpeed: previousUniforms.waveBSpeed ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBSpeed,
200
+ waveBFrequency:
201
+ previousUniforms.waveBFrequency ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBFrequency,
202
+ waveBAmplitude:
203
+ previousUniforms.waveBAmplitude ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBAmplitude
204
+ };
205
+ }
206
+
207
+ function normalizeColor3(color: Readonly<Vector3 | NumberArray3>): [number, number, number] {
208
+ const normalizedColor = [Number(color[0]), Number(color[1]), Number(color[2])] as [
209
+ number,
210
+ number,
211
+ number
212
+ ];
213
+ const maxChannel = Math.max(...normalizedColor.map(channel => Math.abs(channel)));
214
+
215
+ if (maxChannel > 1) {
216
+ normalizedColor[0] /= 255;
217
+ normalizedColor[1] /= 255;
218
+ normalizedColor[2] /= 255;
219
+ }
220
+
221
+ return normalizedColor;
222
+ }
223
+
224
+ function normalizeDirection2(direction: Readonly<Vector2 | NumberArray2>): [number, number] {
225
+ const x = Number(direction[0]);
226
+ const y = Number(direction[1]);
227
+ const length = Math.hypot(x, y);
228
+
229
+ if (length === 0) {
230
+ return [1, 0];
231
+ }
232
+
233
+ return [x / length, y / length];
234
+ }
@@ -0,0 +1,233 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ export const WATER_VS = /* glsl */ `\
6
+ layout(std140) uniform waterMaterialUniforms {
7
+ uniform float time;
8
+ uniform vec3 baseColor;
9
+ uniform float opacity;
10
+ uniform vec3 fresnelColor;
11
+ uniform float fresnelPower;
12
+ uniform float specularIntensity;
13
+ uniform float normalStrength;
14
+ uniform int mappingMode;
15
+ uniform vec2 coordinateScale;
16
+ uniform vec2 coordinateOffset;
17
+ uniform vec2 waveADirection;
18
+ uniform float waveASpeed;
19
+ uniform float waveAFrequency;
20
+ uniform float waveAAmplitude;
21
+ uniform vec2 waveBDirection;
22
+ uniform float waveBSpeed;
23
+ uniform float waveBFrequency;
24
+ uniform float waveBAmplitude;
25
+ } waterMaterial;
26
+ `;
27
+
28
+ export const WATER_FS = /* glsl */ `\
29
+ layout(std140) uniform waterMaterialUniforms {
30
+ uniform float time;
31
+ uniform vec3 baseColor;
32
+ uniform float opacity;
33
+ uniform vec3 fresnelColor;
34
+ uniform float fresnelPower;
35
+ uniform float specularIntensity;
36
+ uniform float normalStrength;
37
+ uniform int mappingMode;
38
+ uniform vec2 coordinateScale;
39
+ uniform vec2 coordinateOffset;
40
+ uniform vec2 waveADirection;
41
+ uniform float waveASpeed;
42
+ uniform float waveAFrequency;
43
+ uniform float waveAAmplitude;
44
+ uniform vec2 waveBDirection;
45
+ uniform float waveBSpeed;
46
+ uniform float waveBFrequency;
47
+ uniform float waveBAmplitude;
48
+ } waterMaterial;
49
+
50
+ vec2 water_getDirection(vec2 direction) {
51
+ float directionLength = length(direction);
52
+ return directionLength > 0.0 ? direction / directionLength : vec2(1.0, 0.0);
53
+ }
54
+
55
+ vec2 water_getCoordinates(vec3 position_worldspace, vec3 position_objectspace, vec2 uv) {
56
+ vec2 baseCoordinates = uv;
57
+ if (waterMaterial.mappingMode == 1) {
58
+ baseCoordinates = position_worldspace.xz;
59
+ } else if (waterMaterial.mappingMode == 2) {
60
+ vec3 globeDirection = normalize(position_objectspace);
61
+ float longitude = atan(globeDirection.x, globeDirection.z);
62
+ float latitude = asin(clamp(globeDirection.y, -1.0, 1.0));
63
+ baseCoordinates = vec2(longitude, latitude);
64
+ }
65
+ return baseCoordinates * waterMaterial.coordinateScale + waterMaterial.coordinateOffset;
66
+ }
67
+
68
+ vec2 water_getWaveGradient(
69
+ vec2 coordinates,
70
+ vec2 direction,
71
+ float speed,
72
+ float frequency,
73
+ float amplitude
74
+ ) {
75
+ vec2 normalizedDirection = water_getDirection(direction);
76
+ float phase = dot(coordinates * frequency, normalizedDirection) + waterMaterial.time * speed;
77
+ return cos(phase) * normalizedDirection * frequency * amplitude;
78
+ }
79
+
80
+ vec3 water_getTangent(vec3 normal_worldspace) {
81
+ vec3 referenceAxis = abs(normal_worldspace.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
82
+ return normalize(cross(referenceAxis, normal_worldspace));
83
+ }
84
+
85
+ vec3 water_getNormal(
86
+ vec3 position_worldspace,
87
+ vec3 position_objectspace,
88
+ vec3 normal_worldspace,
89
+ vec2 uv
90
+ ) {
91
+ vec2 coordinates = water_getCoordinates(position_worldspace, position_objectspace, uv);
92
+ vec2 gradient =
93
+ water_getWaveGradient(
94
+ coordinates,
95
+ waterMaterial.waveADirection,
96
+ waterMaterial.waveASpeed,
97
+ waterMaterial.waveAFrequency,
98
+ waterMaterial.waveAAmplitude
99
+ ) +
100
+ water_getWaveGradient(
101
+ coordinates,
102
+ waterMaterial.waveBDirection,
103
+ waterMaterial.waveBSpeed,
104
+ waterMaterial.waveBFrequency,
105
+ waterMaterial.waveBAmplitude
106
+ );
107
+
108
+ vec3 tangent = water_getTangent(normal_worldspace);
109
+ vec3 bitangent = normalize(cross(normal_worldspace, tangent));
110
+ vec3 perturbation =
111
+ waterMaterial.normalStrength * (gradient.x * tangent + gradient.y * bitangent);
112
+
113
+ return normalize(normal_worldspace + perturbation);
114
+ }
115
+
116
+ vec3 water_getSpecularContribution(
117
+ vec3 light_direction,
118
+ vec3 view_direction,
119
+ vec3 normal_worldspace,
120
+ vec3 light_color,
121
+ float fresnel
122
+ ) {
123
+ vec3 halfway_direction = normalize(light_direction + view_direction);
124
+ float specular =
125
+ pow(max(dot(normal_worldspace, halfway_direction), 0.0), 72.0) *
126
+ waterMaterial.specularIntensity *
127
+ (0.25 + 0.75 * fresnel);
128
+
129
+ return waterMaterial.fresnelColor * light_color * specular;
130
+ }
131
+
132
+ vec4 water_getColorMapped(
133
+ vec3 cameraPosition,
134
+ vec3 position_worldspace,
135
+ vec3 position_objectspace,
136
+ vec3 normal_worldspace,
137
+ vec2 uv
138
+ ) {
139
+ vec3 waterNormal = water_getNormal(
140
+ position_worldspace,
141
+ position_objectspace,
142
+ normalize(normal_worldspace),
143
+ uv
144
+ );
145
+ vec3 viewDirection = normalize(cameraPosition - position_worldspace);
146
+ float fresnel =
147
+ pow(
148
+ 1.0 - max(dot(viewDirection, waterNormal), 0.0),
149
+ max(waterMaterial.fresnelPower, 0.0001)
150
+ );
151
+ vec3 surfaceColor = mix(
152
+ waterMaterial.baseColor,
153
+ waterMaterial.fresnelColor,
154
+ clamp(fresnel * 0.6, 0.0, 1.0)
155
+ );
156
+
157
+ if (lighting.enabled == 0) {
158
+ return vec4(surfaceColor, waterMaterial.opacity);
159
+ }
160
+
161
+ vec3 lightColor = surfaceColor * (0.15 + 0.85 * lighting.ambientColor);
162
+
163
+ for (int i = 0; i < lighting.pointLightCount; i++) {
164
+ PointLight pointLight = lighting_getPointLight(i);
165
+ vec3 lightPosition = pointLight.position;
166
+ vec3 lightDirection = normalize(lightPosition - position_worldspace);
167
+ float attenuation =
168
+ getPointLightAttenuation(pointLight, distance(lightPosition, position_worldspace));
169
+ vec3 incidentLight = pointLight.color / attenuation;
170
+ float diffuse = max(dot(waterNormal, lightDirection), 0.0);
171
+
172
+ lightColor += surfaceColor * incidentLight * diffuse;
173
+ lightColor += water_getSpecularContribution(
174
+ lightDirection,
175
+ viewDirection,
176
+ waterNormal,
177
+ incidentLight,
178
+ fresnel
179
+ );
180
+ }
181
+
182
+ for (int i = 0; i < lighting.spotLightCount; i++) {
183
+ SpotLight spotLight = lighting_getSpotLight(i);
184
+ vec3 lightPosition = spotLight.position;
185
+ vec3 lightDirection = normalize(lightPosition - position_worldspace);
186
+ float attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
187
+ vec3 incidentLight = spotLight.color / attenuation;
188
+ float diffuse = max(dot(waterNormal, lightDirection), 0.0);
189
+
190
+ lightColor += surfaceColor * incidentLight * diffuse;
191
+ lightColor += water_getSpecularContribution(
192
+ lightDirection,
193
+ viewDirection,
194
+ waterNormal,
195
+ incidentLight,
196
+ fresnel
197
+ );
198
+ }
199
+
200
+ for (int i = 0; i < lighting.directionalLightCount; i++) {
201
+ DirectionalLight directionalLight = lighting_getDirectionalLight(i);
202
+ vec3 lightDirection = normalize(-directionalLight.direction);
203
+ float diffuse = max(dot(waterNormal, lightDirection), 0.0);
204
+
205
+ lightColor += surfaceColor * directionalLight.color * diffuse;
206
+ lightColor += water_getSpecularContribution(
207
+ lightDirection,
208
+ viewDirection,
209
+ waterNormal,
210
+ directionalLight.color,
211
+ fresnel
212
+ );
213
+ }
214
+
215
+ lightColor = mix(lightColor, waterMaterial.fresnelColor, clamp(fresnel, 0.0, 1.0) * 0.35);
216
+ return vec4(lightColor, waterMaterial.opacity);
217
+ }
218
+
219
+ vec4 water_getColor(
220
+ vec3 cameraPosition,
221
+ vec3 position_worldspace,
222
+ vec3 normal_worldspace,
223
+ vec2 uv
224
+ ) {
225
+ return water_getColorMapped(
226
+ cameraPosition,
227
+ position_worldspace,
228
+ position_worldspace,
229
+ normal_worldspace,
230
+ uv
231
+ );
232
+ }
233
+ `;
@@ -0,0 +1,230 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ export const WATER_WGSL = /* wgsl */ `\
6
+ struct waterMaterialUniforms {
7
+ time: f32,
8
+ baseColor: vec3<f32>,
9
+ opacity: f32,
10
+ fresnelColor: vec3<f32>,
11
+ fresnelPower: f32,
12
+ specularIntensity: f32,
13
+ normalStrength: f32,
14
+ mappingMode: i32,
15
+ coordinateScale: vec2<f32>,
16
+ coordinateOffset: vec2<f32>,
17
+ waveADirection: vec2<f32>,
18
+ waveASpeed: f32,
19
+ waveAFrequency: f32,
20
+ waveAAmplitude: f32,
21
+ waveBDirection: vec2<f32>,
22
+ waveBSpeed: f32,
23
+ waveBFrequency: f32,
24
+ waveBAmplitude: f32,
25
+ };
26
+
27
+ @group(3) @binding(auto) var<uniform> waterMaterial : waterMaterialUniforms;
28
+
29
+ fn water_getDirection(direction: vec2<f32>) -> vec2<f32> {
30
+ let directionLength = length(direction);
31
+ if (directionLength > 0.0) {
32
+ return direction / directionLength;
33
+ }
34
+
35
+ return vec2<f32>(1.0, 0.0);
36
+ }
37
+
38
+ fn water_getCoordinates(
39
+ position_worldspace: vec3<f32>,
40
+ position_objectspace: vec3<f32>,
41
+ uv: vec2<f32>
42
+ ) -> vec2<f32> {
43
+ var baseCoordinates = uv;
44
+ if (waterMaterial.mappingMode == 1) {
45
+ baseCoordinates = position_worldspace.xz;
46
+ } else if (waterMaterial.mappingMode == 2) {
47
+ let globeDirection = normalize(position_objectspace);
48
+ let longitude = atan2(globeDirection.x, globeDirection.z);
49
+ let latitude = asin(clamp(globeDirection.y, -1.0, 1.0));
50
+ baseCoordinates = vec2<f32>(longitude, latitude);
51
+ }
52
+
53
+ return baseCoordinates * waterMaterial.coordinateScale + waterMaterial.coordinateOffset;
54
+ }
55
+
56
+ fn water_getWaveGradient(
57
+ coordinates: vec2<f32>,
58
+ direction: vec2<f32>,
59
+ speed: f32,
60
+ frequency: f32,
61
+ amplitude: f32
62
+ ) -> vec2<f32> {
63
+ let normalizedDirection = water_getDirection(direction);
64
+ let phase = dot(coordinates * frequency, normalizedDirection) + waterMaterial.time * speed;
65
+ return cos(phase) * normalizedDirection * frequency * amplitude;
66
+ }
67
+
68
+ fn water_getTangent(normal_worldspace: vec3<f32>) -> vec3<f32> {
69
+ var referenceAxis = vec3<f32>(0.0, 0.0, 1.0);
70
+ if (abs(normal_worldspace.z) >= 0.999) {
71
+ referenceAxis = vec3<f32>(0.0, 1.0, 0.0);
72
+ }
73
+
74
+ return normalize(cross(referenceAxis, normal_worldspace));
75
+ }
76
+
77
+ fn water_getNormal(
78
+ position_worldspace: vec3<f32>,
79
+ position_objectspace: vec3<f32>,
80
+ normal_worldspace: vec3<f32>,
81
+ uv: vec2<f32>
82
+ ) -> vec3<f32> {
83
+ let coordinates = water_getCoordinates(position_worldspace, position_objectspace, uv);
84
+ let gradient =
85
+ water_getWaveGradient(
86
+ coordinates,
87
+ waterMaterial.waveADirection,
88
+ waterMaterial.waveASpeed,
89
+ waterMaterial.waveAFrequency,
90
+ waterMaterial.waveAAmplitude
91
+ ) +
92
+ water_getWaveGradient(
93
+ coordinates,
94
+ waterMaterial.waveBDirection,
95
+ waterMaterial.waveBSpeed,
96
+ waterMaterial.waveBFrequency,
97
+ waterMaterial.waveBAmplitude
98
+ );
99
+ let tangent = water_getTangent(normal_worldspace);
100
+ let bitangent = normalize(cross(normal_worldspace, tangent));
101
+ let perturbation =
102
+ waterMaterial.normalStrength * (gradient.x * tangent + gradient.y * bitangent);
103
+
104
+ return normalize(normal_worldspace + perturbation);
105
+ }
106
+
107
+ fn water_getSpecularContribution(
108
+ light_direction: vec3<f32>,
109
+ view_direction: vec3<f32>,
110
+ normal_worldspace: vec3<f32>,
111
+ light_color: vec3<f32>,
112
+ fresnel: f32
113
+ ) -> vec3<f32> {
114
+ let halfwayDirection = normalize(light_direction + view_direction);
115
+ let specular =
116
+ pow(max(dot(normal_worldspace, halfwayDirection), 0.0), 72.0) *
117
+ waterMaterial.specularIntensity *
118
+ (0.25 + 0.75 * fresnel);
119
+
120
+ return waterMaterial.fresnelColor * light_color * specular;
121
+ }
122
+
123
+ fn water_getColorMapped(
124
+ cameraPosition: vec3<f32>,
125
+ position_worldspace: vec3<f32>,
126
+ position_objectspace: vec3<f32>,
127
+ normal_worldspace: vec3<f32>,
128
+ uv: vec2<f32>
129
+ ) -> vec4<f32> {
130
+ let waterNormal = water_getNormal(
131
+ position_worldspace,
132
+ position_objectspace,
133
+ normalize(normal_worldspace),
134
+ uv
135
+ );
136
+ let viewDirection = normalize(cameraPosition - position_worldspace);
137
+ let fresnel =
138
+ pow(
139
+ 1.0 - max(dot(viewDirection, waterNormal), 0.0),
140
+ max(waterMaterial.fresnelPower, 0.0001)
141
+ );
142
+ let surfaceColor = mix(
143
+ waterMaterial.baseColor,
144
+ waterMaterial.fresnelColor,
145
+ clamp(fresnel * 0.6, 0.0, 1.0)
146
+ );
147
+
148
+ if (lighting.enabled == 0) {
149
+ return vec4<f32>(surfaceColor, waterMaterial.opacity);
150
+ }
151
+
152
+ var lightColor = surfaceColor * (0.15 + 0.85 * lighting.ambientColor);
153
+
154
+ for (var i: i32 = 0; i < lighting.pointLightCount; i++) {
155
+ let pointLight = lighting_getPointLight(i);
156
+ let lightPosition = pointLight.position;
157
+ let lightDirection = normalize(lightPosition - position_worldspace);
158
+ let attenuation = getPointLightAttenuation(
159
+ pointLight,
160
+ distance(lightPosition, position_worldspace)
161
+ );
162
+ let incidentLight = pointLight.color / attenuation;
163
+ let diffuse = max(dot(waterNormal, lightDirection), 0.0);
164
+
165
+ lightColor += surfaceColor * incidentLight * diffuse;
166
+ lightColor += water_getSpecularContribution(
167
+ lightDirection,
168
+ viewDirection,
169
+ waterNormal,
170
+ incidentLight,
171
+ fresnel
172
+ );
173
+ }
174
+
175
+ for (var i: i32 = 0; i < lighting.spotLightCount; i++) {
176
+ let spotLight = lighting_getSpotLight(i);
177
+ let lightPosition = spotLight.position;
178
+ let lightDirection = normalize(lightPosition - position_worldspace);
179
+ let attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
180
+ let incidentLight = spotLight.color / attenuation;
181
+ let diffuse = max(dot(waterNormal, lightDirection), 0.0);
182
+
183
+ lightColor += surfaceColor * incidentLight * diffuse;
184
+ lightColor += water_getSpecularContribution(
185
+ lightDirection,
186
+ viewDirection,
187
+ waterNormal,
188
+ incidentLight,
189
+ fresnel
190
+ );
191
+ }
192
+
193
+ for (var i: i32 = 0; i < lighting.directionalLightCount; i++) {
194
+ let directionalLight = lighting_getDirectionalLight(i);
195
+ let lightDirection = normalize(-directionalLight.direction);
196
+ let diffuse = max(dot(waterNormal, lightDirection), 0.0);
197
+
198
+ lightColor += surfaceColor * directionalLight.color * diffuse;
199
+ lightColor += water_getSpecularContribution(
200
+ lightDirection,
201
+ viewDirection,
202
+ waterNormal,
203
+ directionalLight.color,
204
+ fresnel
205
+ );
206
+ }
207
+
208
+ lightColor = mix(
209
+ lightColor,
210
+ waterMaterial.fresnelColor,
211
+ clamp(fresnel, 0.0, 1.0) * 0.35
212
+ );
213
+ return vec4<f32>(lightColor, waterMaterial.opacity);
214
+ }
215
+
216
+ fn water_getColor(
217
+ cameraPosition: vec3<f32>,
218
+ position_worldspace: vec3<f32>,
219
+ normal_worldspace: vec3<f32>,
220
+ uv: vec2<f32>
221
+ ) -> vec4<f32> {
222
+ return water_getColorMapped(
223
+ cameraPosition,
224
+ position_worldspace,
225
+ position_worldspace,
226
+ normal_worldspace,
227
+ uv
228
+ );
229
+ }
230
+ `;