@luma.gl/shadertools 9.3.0-alpha.6 → 9.3.0-alpha.8

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 (152) hide show
  1. package/dist/dist.dev.js +2550 -330
  2. package/dist/dist.min.js +1803 -283
  3. package/dist/index.cjs +2495 -358
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +9 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
  10. package/dist/lib/preprocessor/preprocessor.js +4 -3
  11. package/dist/lib/preprocessor/preprocessor.js.map +1 -1
  12. package/dist/lib/shader-assembler.d.ts +10 -0
  13. package/dist/lib/shader-assembler.d.ts.map +1 -1
  14. package/dist/lib/shader-assembler.js +12 -2
  15. package/dist/lib/shader-assembler.js.map +1 -1
  16. package/dist/lib/shader-assembly/assemble-shaders.d.ts +23 -2
  17. package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
  18. package/dist/lib/shader-assembly/assemble-shaders.js +211 -11
  19. package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
  20. package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts +37 -0
  21. package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts.map +1 -0
  22. package/dist/lib/shader-assembly/wgsl-binding-debug.js +140 -0
  23. package/dist/lib/shader-assembly/wgsl-binding-debug.js.map +1 -0
  24. package/dist/lib/shader-generator/glsl/generate-glsl.js +3 -0
  25. package/dist/lib/shader-generator/glsl/generate-glsl.js.map +1 -1
  26. package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts.map +1 -1
  27. package/dist/lib/shader-generator/wgsl/generate-wgsl.js +3 -0
  28. package/dist/lib/shader-generator/wgsl/generate-wgsl.js.map +1 -1
  29. package/dist/lib/shader-module/shader-module-uniform-layout.d.ts +22 -0
  30. package/dist/lib/shader-module/shader-module-uniform-layout.d.ts.map +1 -0
  31. package/dist/lib/shader-module/shader-module-uniform-layout.js +112 -0
  32. package/dist/lib/shader-module/shader-module-uniform-layout.js.map +1 -0
  33. package/dist/lib/shader-module/shader-module.d.ts +11 -5
  34. package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
  35. package/dist/lib/shader-module/shader-module.js.map +1 -1
  36. package/dist/lib/utils/uniform-types.d.ts +11 -7
  37. package/dist/lib/utils/uniform-types.d.ts.map +1 -1
  38. package/dist/modules/engine/picking/picking.d.ts +3 -0
  39. package/dist/modules/engine/picking/picking.d.ts.map +1 -1
  40. package/dist/modules/engine/picking/picking.js +3 -0
  41. package/dist/modules/engine/picking/picking.js.map +1 -1
  42. package/dist/modules/engine/skin/skin.d.ts +7 -6
  43. package/dist/modules/engine/skin/skin.d.ts.map +1 -1
  44. package/dist/modules/engine/skin/skin.js +3 -5
  45. package/dist/modules/engine/skin/skin.js.map +1 -1
  46. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts +1 -0
  47. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts.map +1 -1
  48. package/dist/modules/lighting/gouraud-material/gouraud-material.js +3 -0
  49. package/dist/modules/lighting/gouraud-material/gouraud-material.js.map +1 -1
  50. package/dist/modules/lighting/ibl/ibl.d.ts +26 -0
  51. package/dist/modules/lighting/ibl/ibl.d.ts.map +1 -0
  52. package/dist/modules/lighting/ibl/ibl.js +33 -0
  53. package/dist/modules/lighting/ibl/ibl.js.map +1 -0
  54. package/dist/modules/lighting/lambert-material/lambert-material.d.ts +10 -0
  55. package/dist/modules/lighting/lambert-material/lambert-material.d.ts.map +1 -0
  56. package/dist/modules/lighting/lambert-material/lambert-material.js +33 -0
  57. package/dist/modules/lighting/lambert-material/lambert-material.js.map +1 -0
  58. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts +3 -0
  59. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts.map +1 -0
  60. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js +60 -0
  61. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js.map +1 -0
  62. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts +2 -0
  63. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts.map +1 -0
  64. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js +73 -0
  65. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js.map +1 -0
  66. package/dist/modules/lighting/lights/lighting-glsl.d.ts +1 -1
  67. package/dist/modules/lighting/lights/lighting-glsl.d.ts.map +1 -1
  68. package/dist/modules/lighting/lights/lighting-glsl.js +43 -55
  69. package/dist/modules/lighting/lights/lighting-glsl.js.map +1 -1
  70. package/dist/modules/lighting/lights/lighting-wgsl.d.ts +1 -1
  71. package/dist/modules/lighting/lights/lighting-wgsl.d.ts.map +1 -1
  72. package/dist/modules/lighting/lights/lighting-wgsl.js +43 -65
  73. package/dist/modules/lighting/lights/lighting-wgsl.js.map +1 -1
  74. package/dist/modules/lighting/lights/lighting.d.ts +104 -86
  75. package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
  76. package/dist/modules/lighting/lights/lighting.js +96 -83
  77. package/dist/modules/lighting/lights/lighting.js.map +1 -1
  78. package/dist/modules/lighting/no-material/dirlight.d.ts +7 -2
  79. package/dist/modules/lighting/no-material/dirlight.d.ts.map +1 -1
  80. package/dist/modules/lighting/no-material/dirlight.js +3 -1
  81. package/dist/modules/lighting/no-material/dirlight.js.map +1 -1
  82. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts +1 -1
  83. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts.map +1 -1
  84. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js +524 -28
  85. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js.map +1 -1
  86. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts +2 -2
  87. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts.map +1 -1
  88. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js +706 -50
  89. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js.map +1 -1
  90. package/dist/modules/lighting/pbr-material/pbr-material.d.ts +110 -61
  91. package/dist/modules/lighting/pbr-material/pbr-material.d.ts.map +1 -1
  92. package/dist/modules/lighting/pbr-material/pbr-material.js +85 -9
  93. package/dist/modules/lighting/pbr-material/pbr-material.js.map +1 -1
  94. package/dist/modules/lighting/pbr-material/pbr-projection.d.ts.map +1 -1
  95. package/dist/modules/lighting/pbr-material/pbr-projection.js +2 -1
  96. package/dist/modules/lighting/pbr-material/pbr-projection.js.map +1 -1
  97. package/dist/modules/lighting/phong-material/phong-material.d.ts +1 -0
  98. package/dist/modules/lighting/phong-material/phong-material.d.ts.map +1 -1
  99. package/dist/modules/lighting/phong-material/phong-material.js +4 -0
  100. package/dist/modules/lighting/phong-material/phong-material.js.map +1 -1
  101. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts +2 -2
  102. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts.map +1 -1
  103. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js +15 -4
  104. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js.map +1 -1
  105. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts +1 -1
  106. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts.map +1 -1
  107. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js +36 -5
  108. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js.map +1 -1
  109. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts +1 -1
  110. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts.map +1 -1
  111. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js +41 -10
  112. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js.map +1 -1
  113. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -0
  114. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -0
  115. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +212 -0
  116. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -0
  117. package/dist/modules/math/fp64/fp64.d.ts +1 -0
  118. package/dist/modules/math/fp64/fp64.d.ts.map +1 -1
  119. package/dist/modules/math/fp64/fp64.js +8 -2
  120. package/dist/modules/math/fp64/fp64.js.map +1 -1
  121. package/package.json +3 -3
  122. package/src/index.ts +19 -2
  123. package/src/lib/preprocessor/preprocessor.ts +6 -3
  124. package/src/lib/shader-assembler.ts +17 -2
  125. package/src/lib/shader-assembly/assemble-shaders.ts +377 -12
  126. package/src/lib/shader-assembly/wgsl-binding-debug.ts +216 -0
  127. package/src/lib/shader-generator/glsl/generate-glsl.ts +7 -1
  128. package/src/lib/shader-generator/wgsl/generate-wgsl.ts +6 -0
  129. package/src/lib/shader-module/shader-module-uniform-layout.ts +194 -0
  130. package/src/lib/shader-module/shader-module.ts +16 -6
  131. package/src/lib/utils/uniform-types.ts +24 -9
  132. package/src/modules/engine/picking/picking.ts +3 -0
  133. package/src/modules/engine/skin/skin.ts +3 -5
  134. package/src/modules/lighting/gouraud-material/gouraud-material.ts +4 -0
  135. package/src/modules/lighting/ibl/ibl.ts +44 -0
  136. package/src/modules/lighting/lambert-material/lambert-material.ts +42 -0
  137. package/src/modules/lighting/lambert-material/lambert-shaders-glsl.ts +61 -0
  138. package/src/modules/lighting/lambert-material/lambert-shaders-wgsl.ts +73 -0
  139. package/src/modules/lighting/lights/lighting-glsl.ts +43 -55
  140. package/src/modules/lighting/lights/lighting-wgsl.ts +43 -65
  141. package/src/modules/lighting/lights/lighting.ts +186 -123
  142. package/src/modules/lighting/no-material/dirlight.ts +3 -1
  143. package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +524 -28
  144. package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +706 -50
  145. package/src/modules/lighting/pbr-material/pbr-material.ts +111 -18
  146. package/src/modules/lighting/pbr-material/pbr-projection.ts +2 -1
  147. package/src/modules/lighting/phong-material/phong-material.ts +5 -0
  148. package/src/modules/lighting/phong-material/phong-shaders-glsl.ts +15 -4
  149. package/src/modules/lighting/phong-material/phong-shaders-wgsl.ts +36 -5
  150. package/src/modules/math/fp64/fp64-arithmetic-glsl.ts +41 -10
  151. package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +212 -0
  152. package/src/modules/math/fp64/fp64.ts +9 -3
@@ -6,7 +6,7 @@ import {log} from '@luma.gl/core';
6
6
  import {ShaderModule} from '../../../lib/shader-module/shader-module';
7
7
  import {lightingUniformsGLSL} from './lighting-glsl';
8
8
  import {lightingUniformsWGSL} from './lighting-wgsl';
9
- import type {NumberArray3} from '@math.gl/core';
9
+ import type {NumberArray2, NumberArray3} from '@math.gl/core';
10
10
 
11
11
  /** Max number of supported lights (in addition to ambient light */
12
12
  const MAX_LIGHTS = 5;
@@ -14,78 +14,137 @@ const MAX_LIGHTS = 5;
14
14
  /** Whether to divide */
15
15
  const COLOR_FACTOR = 255.0;
16
16
 
17
- /** Shader type field for lights */
18
- // eslint-disable-next-line no-shadow
19
- export enum LIGHT_TYPE {
20
- POINT = 0,
21
- DIRECTIONAL = 1
22
- }
23
-
24
- /** Lighting helper types */
25
-
26
- export type Light = AmbientLight | PointLight | DirectionalLight;
17
+ /** Supported light source descriptions accepted by the lighting shader module. */
18
+ export type Light = AmbientLight | PointLight | SpotLight | DirectionalLight;
27
19
 
20
+ /** Ambient light contribution shared across the entire scene. */
28
21
  export type AmbientLight = {
22
+ /** Discriminator used to identify ambient lights in `lights: Light[]`. */
29
23
  type: 'ambient';
24
+ /** RGB light color in the existing `0..255` convention used by luma.gl materials. */
30
25
  color?: Readonly<NumberArray3>;
26
+ /** Scalar intensity multiplier applied to the light color. */
31
27
  intensity?: number;
32
28
  };
33
29
 
30
+ /** Omnidirectional point light emitted from a world-space position. */
34
31
  export type PointLight = {
32
+ /** Discriminator used to identify point lights in `lights: Light[]`. */
35
33
  type: 'point';
34
+ /** World-space light position. */
36
35
  position: Readonly<NumberArray3>;
36
+ /** RGB light color in the existing `0..255` convention used by luma.gl materials. */
37
37
  color?: Readonly<NumberArray3>;
38
+ /** Scalar intensity multiplier applied to the light color. */
38
39
  intensity?: number;
40
+ /** Constant, linear, and quadratic attenuation coefficients. */
39
41
  attenuation?: Readonly<NumberArray3>;
40
42
  };
41
43
 
44
+ /** Directional light defined only by its incoming world-space direction. */
42
45
  export type DirectionalLight = {
46
+ /** Discriminator used to identify directional lights in `lights: Light[]`. */
43
47
  type: 'directional';
48
+ /** World-space light direction. */
44
49
  direction: Readonly<NumberArray3>;
50
+ /** RGB light color in the existing `0..255` convention used by luma.gl materials. */
45
51
  color?: Readonly<NumberArray3>;
52
+ /** Scalar intensity multiplier applied to the light color. */
46
53
  intensity?: number;
47
54
  };
48
55
 
56
+ /** Cone-shaped light emitted from a position and focused along a direction. */
57
+ export type SpotLight = {
58
+ /** Discriminator used to identify spot lights in `lights: Light[]`. */
59
+ type: 'spot';
60
+ /** World-space light position. */
61
+ position: Readonly<NumberArray3>;
62
+ /** World-space light direction. */
63
+ direction: Readonly<NumberArray3>;
64
+ /** RGB light color in the existing `0..255` convention used by luma.gl materials. */
65
+ color?: Readonly<NumberArray3>;
66
+ /** Scalar intensity multiplier applied to the light color. */
67
+ intensity?: number;
68
+ /** Constant, linear, and quadratic attenuation coefficients. */
69
+ attenuation?: Readonly<NumberArray3>;
70
+ /** Inner spotlight cone angle in radians. */
71
+ innerConeAngle?: number;
72
+ /** Outer spotlight cone angle in radians. */
73
+ outerConeAngle?: number;
74
+ };
75
+
76
+ /** Public JavaScript props accepted by the `lighting` shader module. */
49
77
  export type LightingProps = {
78
+ /** Enables or disables lighting calculations for the module. */
50
79
  enabled?: boolean;
80
+ /** Preferred API for supplying mixed ambient, point, spot, and directional lights. */
51
81
  lights?: Light[];
52
- /** @deprecated */
82
+ /**
83
+ * Legacy ambient-light prop.
84
+ * @deprecated Use `lights` with `{type: 'ambient', ...}` entries instead.
85
+ */
53
86
  ambientLight?: AmbientLight;
54
- /** @deprecated */
87
+ /**
88
+ * Legacy point-light prop.
89
+ * @deprecated Use `lights` with `{type: 'point', ...}` entries instead.
90
+ */
55
91
  pointLights?: PointLight[];
56
- /** @deprecated */
92
+ /**
93
+ * Legacy spot-light prop.
94
+ * @deprecated Use `lights` with `{type: 'spot', ...}` entries instead.
95
+ */
96
+ spotLights?: SpotLight[];
97
+ /**
98
+ * Legacy directional-light prop.
99
+ * @deprecated Use `lights` with `{type: 'directional', ...}` entries instead.
100
+ */
57
101
  directionalLights?: DirectionalLight[];
58
102
  };
59
103
 
104
+ /** Packed per-light data written into the module's fixed-size uniform array. */
105
+ export type LightingLightUniform = {
106
+ /** Light color converted to normalized shader-space RGB. */
107
+ color: Readonly<NumberArray3>;
108
+ /** World-space light position or a default placeholder for non-positional lights. */
109
+ position: Readonly<NumberArray3>;
110
+ /** World-space light direction or a default placeholder for positional lights. */
111
+ direction: Readonly<NumberArray3>;
112
+ /** Constant, linear, and quadratic attenuation coefficients. */
113
+ attenuation: Readonly<NumberArray3>;
114
+ /** Cosines of the inner and outer spotlight cone angles. */
115
+ coneCos: Readonly<NumberArray2>;
116
+ };
117
+
118
+ /** Fully normalized uniform values produced by the `lighting` shader module. */
60
119
  export type LightingUniforms = {
120
+ /** `1` when lighting is enabled, otherwise `0`. */
61
121
  enabled: number;
62
- ambientColor: Readonly<NumberArray3>;
122
+ /** Number of packed directional lights in the `lights` array. */
63
123
  directionalLightCount: number;
124
+ /** Number of packed point lights in the `lights` array. */
64
125
  pointLightCount: number;
65
- lightType: number; // [];
66
- lightColor0: Readonly<NumberArray3>;
67
- lightPosition0: Readonly<NumberArray3>;
68
- lightDirection0: Readonly<NumberArray3>;
69
- lightAttenuation0: Readonly<NumberArray3>;
70
- lightColor1: Readonly<NumberArray3>;
71
- lightPosition1: Readonly<NumberArray3>;
72
- lightDirection1: Readonly<NumberArray3>;
73
- lightAttenuation1: Readonly<NumberArray3>;
74
- lightColor2: Readonly<NumberArray3>;
75
- lightPosition2: Readonly<NumberArray3>;
76
- lightDirection2: Readonly<NumberArray3>;
77
- lightAttenuation2: Readonly<NumberArray3>;
78
- lightColor3: Readonly<NumberArray3>;
79
- lightPosition3: Readonly<NumberArray3>;
80
- lightDirection3: Readonly<NumberArray3>;
81
- lightAttenuation3: Readonly<NumberArray3>;
82
- lightColor4: Readonly<NumberArray3>;
83
- lightPosition4: Readonly<NumberArray3>;
84
- lightDirection4: Readonly<NumberArray3>;
85
- lightAttenuation4: Readonly<NumberArray3>;
126
+ /** Number of packed spot lights in the `lights` array. */
127
+ spotLightCount: number;
128
+ /** Accumulated ambient color converted to normalized shader-space RGB. */
129
+ ambientColor: Readonly<NumberArray3>;
130
+ /** Packed trailing array of non-ambient light structs. */
131
+ lights: ReadonlyArray<LightingLightUniform>;
86
132
  };
87
133
 
88
- /** UBO ready lighting module */
134
+ const LIGHT_UNIFORM_TYPE = {
135
+ color: 'vec3<f32>',
136
+ position: 'vec3<f32>',
137
+ direction: 'vec3<f32>',
138
+ attenuation: 'vec3<f32>',
139
+ coneCos: 'vec2<f32>'
140
+ } as const;
141
+
142
+ /**
143
+ * Portable lighting shader module shared by the Phong, Gouraud, and PBR material modules.
144
+ *
145
+ * The public JavaScript API accepts `lights: Light[]`, while the uniform buffer packs
146
+ * non-ambient lights into a fixed-size trailing array for portability across WebGL2 and WebGPU.
147
+ */
89
148
  export const lighting = {
90
149
  props: {} as LightingProps,
91
150
  uniforms: {} as LightingUniforms,
@@ -98,71 +157,16 @@ export const lighting = {
98
157
 
99
158
  uniformTypes: {
100
159
  enabled: 'i32',
101
- lightType: 'i32',
102
-
103
160
  directionalLightCount: 'i32',
104
161
  pointLightCount: 'i32',
105
-
162
+ spotLightCount: 'i32',
106
163
  ambientColor: 'vec3<f32>',
107
-
108
- // TODO define as arrays once we have appropriate uniformTypes
109
- lightColor0: 'vec3<f32>',
110
- lightPosition0: 'vec3<f32>',
111
- // TODO - could combine direction and attenuation
112
- lightDirection0: 'vec3<f32>',
113
- lightAttenuation0: 'vec3<f32>',
114
-
115
- lightColor1: 'vec3<f32>',
116
- lightPosition1: 'vec3<f32>',
117
- lightDirection1: 'vec3<f32>',
118
- lightAttenuation1: 'vec3<f32>',
119
- lightColor2: 'vec3<f32>',
120
- lightPosition2: 'vec3<f32>',
121
- lightDirection2: 'vec3<f32>',
122
- lightAttenuation2: 'vec3<f32>',
123
-
124
- lightColor3: 'vec3<f32>',
125
- lightPosition3: 'vec3<f32>',
126
- lightDirection3: 'vec3<f32>',
127
- lightAttenuation3: 'vec3<f32>',
128
-
129
- lightColor4: 'vec3<f32>',
130
- lightPosition4: 'vec3<f32>',
131
- lightDirection4: 'vec3<f32>',
132
- lightAttenuation4: 'vec3<f32>'
164
+ lights: [LIGHT_UNIFORM_TYPE, MAX_LIGHTS]
133
165
  },
134
166
 
135
- defaultUniforms: {
136
- enabled: 1,
137
- lightType: LIGHT_TYPE.POINT,
138
-
139
- directionalLightCount: 0,
140
- pointLightCount: 0,
141
-
142
- ambientColor: [0.1, 0.1, 0.1],
143
- lightColor0: [1, 1, 1],
144
- lightPosition0: [1, 1, 2],
145
- // TODO - could combine direction and attenuation
146
- lightDirection0: [1, 1, 1],
147
- lightAttenuation0: [1, 0, 0],
148
-
149
- lightColor1: [1, 1, 1],
150
- lightPosition1: [1, 1, 2],
151
- lightDirection1: [1, 1, 1],
152
- lightAttenuation1: [1, 0, 0],
153
- lightColor2: [1, 1, 1],
154
- lightPosition2: [1, 1, 2],
155
- lightDirection2: [1, 1, 1],
156
- lightAttenuation2: [1, 0, 0],
157
- lightColor3: [1, 1, 1],
158
- lightPosition3: [1, 1, 2],
159
- lightDirection3: [1, 1, 1],
160
- lightAttenuation3: [1, 0, 0],
161
- lightColor4: [1, 1, 1],
162
- lightPosition4: [1, 1, 2],
163
- lightDirection4: [1, 1, 1],
164
- lightAttenuation4: [1, 0, 0]
165
- },
167
+ defaultUniforms: createDefaultLightingUniforms(),
168
+ bindingLayout: [{name: 'lighting', group: 2}],
169
+ firstBindingSlot: 0,
166
170
  source: lightingUniformsWGSL,
167
171
  vs: lightingUniformsGLSL,
168
172
  fs: lightingUniformsGLSL,
@@ -172,14 +176,14 @@ export const lighting = {
172
176
 
173
177
  function getUniforms(
174
178
  props?: LightingProps,
175
- prevUniforms: Partial<LightingUniforms> = {}
179
+ _prevUniforms: Partial<LightingUniforms> = {}
176
180
  ): LightingUniforms {
177
181
  // Copy props so we can modify
178
182
  props = props ? {...props} : props;
179
183
 
180
184
  // TODO legacy
181
185
  if (!props) {
182
- return {...lighting.defaultUniforms};
186
+ return createDefaultLightingUniforms();
183
187
  }
184
188
  // Support for array of lights. Type of light is detected by type field
185
189
  if (props.lights) {
@@ -187,21 +191,24 @@ function getUniforms(
187
191
  }
188
192
 
189
193
  // Specify lights separately
190
- const {ambientLight, pointLights, directionalLights} = props || {};
194
+ const {ambientLight, pointLights, spotLights, directionalLights} = props || {};
191
195
  const hasLights =
192
196
  ambientLight ||
193
197
  (pointLights && pointLights.length > 0) ||
198
+ (spotLights && spotLights.length > 0) ||
194
199
  (directionalLights && directionalLights.length > 0);
195
200
 
196
201
  // TODO - this may not be the correct decision
197
202
  if (!hasLights) {
198
- return {...lighting.defaultUniforms, enabled: 0};
203
+ return {
204
+ ...createDefaultLightingUniforms(),
205
+ enabled: 0
206
+ };
199
207
  }
200
208
 
201
209
  const uniforms = {
202
- ...lighting.defaultUniforms,
203
- ...prevUniforms,
204
- ...getLightSourceUniforms({ambientLight, pointLights, directionalLights})
210
+ ...createDefaultLightingUniforms(),
211
+ ...getLightSourceUniforms({ambientLight, pointLights, spotLights, directionalLights})
205
212
  };
206
213
 
207
214
  if (props.enabled !== undefined) {
@@ -214,55 +221,77 @@ function getUniforms(
214
221
  function getLightSourceUniforms({
215
222
  ambientLight,
216
223
  pointLights = [],
224
+ spotLights = [],
217
225
  directionalLights = []
218
- }: LightingProps): Partial<LightingUniforms> {
219
- const lightSourceUniforms: Partial<LightingUniforms> = {};
220
-
221
- lightSourceUniforms.ambientColor = convertColor(ambientLight);
226
+ }: LightingProps): Omit<LightingUniforms, 'enabled'> {
227
+ const lights = createDefaultLightUniforms();
222
228
 
223
229
  let currentLight = 0;
224
230
  let pointLightCount = 0;
231
+ let spotLightCount = 0;
225
232
  let directionalLightCount = 0;
226
233
 
227
234
  for (const pointLight of pointLights) {
228
235
  if (currentLight >= MAX_LIGHTS) {
229
236
  break;
230
237
  }
231
- lightSourceUniforms.lightType = LIGHT_TYPE.POINT;
232
238
 
233
- const i = currentLight as 0 | 1 | 2 | 3 | 4;
234
- lightSourceUniforms[`lightColor${i}`] = convertColor(pointLight);
235
- lightSourceUniforms[`lightPosition${i}`] = pointLight.position;
236
- lightSourceUniforms[`lightAttenuation${i}`] = pointLight.attenuation || [1, 0, 0];
239
+ lights[currentLight] = {
240
+ ...lights[currentLight],
241
+ color: convertColor(pointLight),
242
+ position: pointLight.position,
243
+ attenuation: pointLight.attenuation || [1, 0, 0]
244
+ };
237
245
  currentLight++;
238
246
  pointLightCount++;
239
247
  }
240
248
 
249
+ for (const spotLight of spotLights) {
250
+ if (currentLight >= MAX_LIGHTS) {
251
+ break;
252
+ }
253
+
254
+ lights[currentLight] = {
255
+ ...lights[currentLight],
256
+ color: convertColor(spotLight),
257
+ position: spotLight.position,
258
+ direction: spotLight.direction,
259
+ attenuation: spotLight.attenuation || [1, 0, 0],
260
+ coneCos: getSpotConeCos(spotLight)
261
+ };
262
+ currentLight++;
263
+ spotLightCount++;
264
+ }
265
+
241
266
  for (const directionalLight of directionalLights) {
242
267
  if (currentLight >= MAX_LIGHTS) {
243
268
  break;
244
269
  }
245
- lightSourceUniforms.lightType = LIGHT_TYPE.DIRECTIONAL;
246
270
 
247
- const i = currentLight as 0 | 1 | 2 | 3 | 4;
248
- lightSourceUniforms[`lightColor${i}`] = convertColor(directionalLight);
249
- lightSourceUniforms[`lightDirection${i}`] = directionalLight.direction;
271
+ lights[currentLight] = {
272
+ ...lights[currentLight],
273
+ color: convertColor(directionalLight),
274
+ direction: directionalLight.direction
275
+ };
250
276
  currentLight++;
251
277
  directionalLightCount++;
252
278
  }
253
279
 
254
- if (pointLights.length + directionalLights.length > MAX_LIGHTS) {
280
+ if (pointLights.length + spotLights.length + directionalLights.length > MAX_LIGHTS) {
255
281
  log.warn(`MAX_LIGHTS exceeded, truncating to ${MAX_LIGHTS}`)();
256
282
  }
257
283
 
258
- lightSourceUniforms.directionalLightCount = directionalLightCount;
259
- lightSourceUniforms.pointLightCount = pointLightCount;
260
-
261
- return lightSourceUniforms;
284
+ return {
285
+ ambientColor: convertColor(ambientLight),
286
+ directionalLightCount,
287
+ pointLightCount,
288
+ spotLightCount,
289
+ lights
290
+ };
262
291
  }
263
292
 
264
293
  function extractLightTypes(lights: Light[]): LightingProps {
265
- const lightSources: LightingProps = {pointLights: [], directionalLights: []};
294
+ const lightSources: LightingProps = {pointLights: [], spotLights: [], directionalLights: []};
266
295
  for (const light of lights || []) {
267
296
  switch (light.type) {
268
297
  case 'ambient':
@@ -276,6 +305,9 @@ function extractLightTypes(lights: Light[]): LightingProps {
276
305
  case 'point':
277
306
  lightSources.pointLights?.push(light);
278
307
  break;
308
+ case 'spot':
309
+ lightSources.spotLights?.push(light);
310
+ break;
279
311
  default:
280
312
  // eslint-disable-next-line
281
313
  // console.warn(light.type);
@@ -291,3 +323,34 @@ function convertColor(
291
323
  const {color = [0, 0, 0], intensity = 1.0} = colorDef;
292
324
  return color.map(component => (component * intensity) / COLOR_FACTOR) as NumberArray3;
293
325
  }
326
+
327
+ function createDefaultLightingUniforms(): LightingUniforms {
328
+ return {
329
+ enabled: 1,
330
+ directionalLightCount: 0,
331
+ pointLightCount: 0,
332
+ spotLightCount: 0,
333
+ ambientColor: [0.1, 0.1, 0.1],
334
+ lights: createDefaultLightUniforms()
335
+ };
336
+ }
337
+
338
+ function createDefaultLightUniforms(): LightingLightUniform[] {
339
+ return Array.from({length: MAX_LIGHTS}, () => createDefaultLightUniform());
340
+ }
341
+
342
+ function createDefaultLightUniform(): LightingLightUniform {
343
+ return {
344
+ color: [1, 1, 1],
345
+ position: [1, 1, 2],
346
+ direction: [1, 1, 1],
347
+ attenuation: [1, 0, 0],
348
+ coneCos: [1, 0]
349
+ };
350
+ }
351
+
352
+ function getSpotConeCos(spotLight: SpotLight): NumberArray2 {
353
+ const innerConeAngle = spotLight.innerConeAngle ?? 0;
354
+ const outerConeAngle = spotLight.outerConeAngle ?? Math.PI / 4;
355
+ return [Math.cos(innerConeAngle), Math.cos(outerConeAngle)];
356
+ }
@@ -23,7 +23,7 @@ struct DirlightInputs {
23
23
  normal: DirlightNormal,
24
24
  };
25
25
 
26
- @binding(1) @group(0) var<uniform> dirlight : dirlightUniforms;
26
+ @group(2) @binding(auto) var<uniform> dirlight : dirlightUniforms;
27
27
 
28
28
  // For vertex
29
29
  fn dirlight_setNormal(normal: vec3<f32>) -> DirlightNormal {
@@ -70,6 +70,8 @@ export const dirlight = {
70
70
  uniforms: {} as DirlightUniforms,
71
71
 
72
72
  name: 'dirlight',
73
+ bindingLayout: [{name: 'dirlight', group: 2}],
74
+ firstBindingSlot: 16,
73
75
  dependencies: [],
74
76
  source: SOURCE_WGSL,
75
77
  vs: VS_GLSL,