@luma.gl/shadertools 9.2.5 → 9.3.0-alpha.10

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 (174) hide show
  1. package/dist/dist.dev.js +4798 -6439
  2. package/dist/dist.min.js +2047 -311
  3. package/dist/index.cjs +3033 -507
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +12 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +5 -2
  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 +35 -8
  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 +20 -3
  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 +214 -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 +7 -4
  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 +91 -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 +209 -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 +12 -6
  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/assert.d.ts.map +1 -1
  37. package/dist/lib/utils/assert.js +3 -1
  38. package/dist/lib/utils/assert.js.map +1 -1
  39. package/dist/lib/utils/uniform-types.d.ts +11 -7
  40. package/dist/lib/utils/uniform-types.d.ts.map +1 -1
  41. package/dist/modules/engine/picking/picking.d.ts +5 -2
  42. package/dist/modules/engine/picking/picking.d.ts.map +1 -1
  43. package/dist/modules/engine/picking/picking.js +5 -2
  44. package/dist/modules/engine/picking/picking.js.map +1 -1
  45. package/dist/modules/engine/project/project.d.ts +1 -1
  46. package/dist/modules/engine/project/project.js +1 -1
  47. package/dist/modules/engine/skin/skin.d.ts +30 -0
  48. package/dist/modules/engine/skin/skin.d.ts.map +1 -0
  49. package/dist/modules/engine/skin/skin.js +86 -0
  50. package/dist/modules/engine/skin/skin.js.map +1 -0
  51. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts +1 -0
  52. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts.map +1 -1
  53. package/dist/modules/lighting/gouraud-material/gouraud-material.js +3 -0
  54. package/dist/modules/lighting/gouraud-material/gouraud-material.js.map +1 -1
  55. package/dist/modules/lighting/ibl/ibl.d.ts +26 -0
  56. package/dist/modules/lighting/ibl/ibl.d.ts.map +1 -0
  57. package/dist/modules/lighting/ibl/ibl.js +33 -0
  58. package/dist/modules/lighting/ibl/ibl.js.map +1 -0
  59. package/dist/modules/lighting/lambert-material/lambert-material.d.ts +10 -0
  60. package/dist/modules/lighting/lambert-material/lambert-material.d.ts.map +1 -0
  61. package/dist/modules/lighting/lambert-material/lambert-material.js +33 -0
  62. package/dist/modules/lighting/lambert-material/lambert-material.js.map +1 -0
  63. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts +3 -0
  64. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts.map +1 -0
  65. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js +60 -0
  66. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js.map +1 -0
  67. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts +2 -0
  68. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts.map +1 -0
  69. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js +73 -0
  70. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js.map +1 -0
  71. package/dist/modules/lighting/lights/lighting-glsl.d.ts +1 -1
  72. package/dist/modules/lighting/lights/lighting-glsl.d.ts.map +1 -1
  73. package/dist/modules/lighting/lights/lighting-glsl.js +44 -38
  74. package/dist/modules/lighting/lights/lighting-glsl.js.map +1 -1
  75. package/dist/modules/lighting/lights/lighting-wgsl.d.ts +1 -1
  76. package/dist/modules/lighting/lights/lighting-wgsl.d.ts.map +1 -1
  77. package/dist/modules/lighting/lights/lighting-wgsl.js +46 -18
  78. package/dist/modules/lighting/lights/lighting-wgsl.js.map +1 -1
  79. package/dist/modules/lighting/lights/lighting.d.ts +104 -62
  80. package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
  81. package/dist/modules/lighting/lights/lighting.js +107 -68
  82. package/dist/modules/lighting/lights/lighting.js.map +1 -1
  83. package/dist/modules/lighting/no-material/dirlight.d.ts +8 -3
  84. package/dist/modules/lighting/no-material/dirlight.d.ts.map +1 -1
  85. package/dist/modules/lighting/no-material/dirlight.js +4 -2
  86. package/dist/modules/lighting/no-material/dirlight.js.map +1 -1
  87. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts +1 -1
  88. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts.map +1 -1
  89. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js +581 -28
  90. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js.map +1 -1
  91. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts +2 -2
  92. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts.map +1 -1
  93. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js +850 -107
  94. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js.map +1 -1
  95. package/dist/modules/lighting/pbr-material/pbr-material.d.ts +172 -41
  96. package/dist/modules/lighting/pbr-material/pbr-material.d.ts.map +1 -1
  97. package/dist/modules/lighting/pbr-material/pbr-material.js +109 -1
  98. package/dist/modules/lighting/pbr-material/pbr-material.js.map +1 -1
  99. package/dist/modules/lighting/pbr-material/pbr-projection.d.ts.map +1 -1
  100. package/dist/modules/lighting/pbr-material/pbr-projection.js +14 -2
  101. package/dist/modules/lighting/pbr-material/pbr-projection.js.map +1 -1
  102. package/dist/modules/lighting/pbr-material/pbr-scene.d.ts +40 -0
  103. package/dist/modules/lighting/pbr-material/pbr-scene.d.ts.map +1 -0
  104. package/dist/modules/lighting/pbr-material/pbr-scene.js +67 -0
  105. package/dist/modules/lighting/pbr-material/pbr-scene.js.map +1 -0
  106. package/dist/modules/lighting/phong-material/phong-material.d.ts +1 -0
  107. package/dist/modules/lighting/phong-material/phong-material.d.ts.map +1 -1
  108. package/dist/modules/lighting/phong-material/phong-material.js +4 -0
  109. package/dist/modules/lighting/phong-material/phong-material.js.map +1 -1
  110. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts +2 -2
  111. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts.map +1 -1
  112. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js +17 -6
  113. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js.map +1 -1
  114. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts +1 -40
  115. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts.map +1 -1
  116. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js +71 -76
  117. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js.map +1 -1
  118. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts +1 -1
  119. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts.map +1 -1
  120. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js +42 -11
  121. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js.map +1 -1
  122. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -0
  123. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -0
  124. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +212 -0
  125. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -0
  126. package/dist/modules/math/fp64/fp64.d.ts +1 -0
  127. package/dist/modules/math/fp64/fp64.d.ts.map +1 -1
  128. package/dist/modules/math/fp64/fp64.js +8 -2
  129. package/dist/modules/math/fp64/fp64.js.map +1 -1
  130. package/dist/modules/math/random/random.d.ts +1 -1
  131. package/dist/modules/math/random/random.d.ts.map +1 -1
  132. package/dist/modules/math/random/random.js +2 -3
  133. package/dist/modules/math/random/random.js.map +1 -1
  134. package/package.json +4 -5
  135. package/src/index.ts +37 -6
  136. package/src/lib/preprocessor/preprocessor.ts +44 -8
  137. package/src/lib/shader-assembler.ts +25 -3
  138. package/src/lib/shader-assembly/assemble-shaders.ts +384 -12
  139. package/src/lib/shader-assembly/wgsl-binding-debug.ts +216 -0
  140. package/src/lib/shader-generator/glsl/generate-glsl.ts +11 -5
  141. package/src/lib/shader-generator/wgsl/generate-wgsl.ts +6 -0
  142. package/src/lib/shader-module/shader-module-uniform-layout.ts +346 -0
  143. package/src/lib/shader-module/shader-module.ts +17 -7
  144. package/src/lib/utils/assert.ts +3 -1
  145. package/src/lib/utils/uniform-types.ts +24 -9
  146. package/src/modules/engine/picking/picking.ts +5 -2
  147. package/src/modules/engine/project/project.ts +1 -1
  148. package/src/modules/engine/skin/skin.ts +114 -0
  149. package/src/modules/lighting/gouraud-material/gouraud-material.ts +4 -0
  150. package/src/modules/lighting/ibl/ibl.ts +44 -0
  151. package/src/modules/lighting/lambert-material/lambert-material.ts +42 -0
  152. package/src/modules/lighting/lambert-material/lambert-shaders-glsl.ts +61 -0
  153. package/src/modules/lighting/lambert-material/lambert-shaders-wgsl.ts +73 -0
  154. package/src/modules/lighting/lights/lighting-glsl.ts +44 -38
  155. package/src/modules/lighting/lights/lighting-wgsl.ts +46 -18
  156. package/src/modules/lighting/lights/lighting.ts +198 -99
  157. package/src/modules/lighting/no-material/dirlight.ts +4 -2
  158. package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +581 -28
  159. package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +850 -107
  160. package/src/modules/lighting/pbr-material/pbr-material.ts +185 -5
  161. package/src/modules/lighting/pbr-material/pbr-projection.ts +15 -2
  162. package/src/modules/lighting/pbr-material/pbr-scene.ts +91 -0
  163. package/src/modules/lighting/phong-material/phong-material.ts +5 -0
  164. package/src/modules/lighting/phong-material/phong-shaders-glsl.ts +17 -6
  165. package/src/modules/lighting/phong-material/phong-shaders-wgsl.ts +71 -77
  166. package/src/modules/math/fp64/fp64-arithmetic-glsl.ts +42 -11
  167. package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +212 -0
  168. package/src/modules/math/fp64/fp64.ts +9 -3
  169. package/src/modules/math/random/random.ts +2 -3
  170. package/dist/lib/wgsl/get-shader-layout-wgsl.d.ts +0 -8
  171. package/dist/lib/wgsl/get-shader-layout-wgsl.d.ts.map +0 -1
  172. package/dist/lib/wgsl/get-shader-layout-wgsl.js +0 -95
  173. package/dist/lib/wgsl/get-shader-layout-wgsl.js.map +0 -1
  174. package/src/lib/wgsl/get-shader-layout-wgsl.ts +0 -105
@@ -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,70 +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>;
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>;
78
132
  };
79
133
 
80
- /** 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
+ */
81
148
  export const lighting = {
82
149
  props: {} as LightingProps,
83
150
  uniforms: {} as LightingUniforms,
@@ -90,53 +157,16 @@ export const lighting = {
90
157
 
91
158
  uniformTypes: {
92
159
  enabled: 'i32',
93
- lightType: 'i32',
94
-
95
160
  directionalLightCount: 'i32',
96
161
  pointLightCount: 'i32',
97
-
162
+ spotLightCount: 'i32',
98
163
  ambientColor: 'vec3<f32>',
99
-
100
- // TODO define as arrays once we have appropriate uniformTypes
101
- lightColor0: 'vec3<f32>',
102
- lightPosition0: 'vec3<f32>',
103
- // TODO - could combine direction and attenuation
104
- lightDirection0: 'vec3<f32>',
105
- lightAttenuation0: 'vec3<f32>',
106
-
107
- lightColor1: 'vec3<f32>',
108
- lightPosition1: 'vec3<f32>',
109
- lightDirection1: 'vec3<f32>',
110
- lightAttenuation1: 'vec3<f32>',
111
- lightColor2: 'vec3<f32>',
112
- lightPosition2: 'vec3<f32>',
113
- lightDirection2: 'vec3<f32>',
114
- lightAttenuation2: 'vec3<f32>'
164
+ lights: [LIGHT_UNIFORM_TYPE, MAX_LIGHTS]
115
165
  },
116
166
 
117
- defaultUniforms: {
118
- enabled: 1,
119
- lightType: LIGHT_TYPE.POINT,
120
-
121
- directionalLightCount: 0,
122
- pointLightCount: 0,
123
-
124
- ambientColor: [0.1, 0.1, 0.1],
125
- lightColor0: [1, 1, 1],
126
- lightPosition0: [1, 1, 2],
127
- // TODO - could combine direction and attenuation
128
- lightDirection0: [1, 1, 1],
129
- lightAttenuation0: [1, 0, 0],
130
-
131
- lightColor1: [1, 1, 1],
132
- lightPosition1: [1, 1, 2],
133
- lightDirection1: [1, 1, 1],
134
- lightAttenuation1: [1, 0, 0],
135
- lightColor2: [1, 1, 1],
136
- lightPosition2: [1, 1, 2],
137
- lightDirection2: [1, 1, 1],
138
- lightAttenuation2: [1, 0, 0]
139
- },
167
+ defaultUniforms: createDefaultLightingUniforms(),
168
+ bindingLayout: [{name: 'lighting', group: 2}],
169
+ firstBindingSlot: 0,
140
170
  source: lightingUniformsWGSL,
141
171
  vs: lightingUniformsGLSL,
142
172
  fs: lightingUniformsGLSL,
@@ -146,14 +176,14 @@ export const lighting = {
146
176
 
147
177
  function getUniforms(
148
178
  props?: LightingProps,
149
- prevUniforms: Partial<LightingUniforms> = {}
179
+ _prevUniforms: Partial<LightingUniforms> = {}
150
180
  ): LightingUniforms {
151
181
  // Copy props so we can modify
152
182
  props = props ? {...props} : props;
153
183
 
154
184
  // TODO legacy
155
185
  if (!props) {
156
- return {...lighting.defaultUniforms};
186
+ return createDefaultLightingUniforms();
157
187
  }
158
188
  // Support for array of lights. Type of light is detected by type field
159
189
  if (props.lights) {
@@ -161,21 +191,24 @@ function getUniforms(
161
191
  }
162
192
 
163
193
  // Specify lights separately
164
- const {ambientLight, pointLights, directionalLights} = props || {};
194
+ const {ambientLight, pointLights, spotLights, directionalLights} = props || {};
165
195
  const hasLights =
166
196
  ambientLight ||
167
197
  (pointLights && pointLights.length > 0) ||
198
+ (spotLights && spotLights.length > 0) ||
168
199
  (directionalLights && directionalLights.length > 0);
169
200
 
170
201
  // TODO - this may not be the correct decision
171
202
  if (!hasLights) {
172
- return {...lighting.defaultUniforms, enabled: 0};
203
+ return {
204
+ ...createDefaultLightingUniforms(),
205
+ enabled: 0
206
+ };
173
207
  }
174
208
 
175
209
  const uniforms = {
176
- ...lighting.defaultUniforms,
177
- ...prevUniforms,
178
- ...getLightSourceUniforms({ambientLight, pointLights, directionalLights})
210
+ ...createDefaultLightingUniforms(),
211
+ ...getLightSourceUniforms({ambientLight, pointLights, spotLights, directionalLights})
179
212
  };
180
213
 
181
214
  if (props.enabled !== undefined) {
@@ -188,45 +221,77 @@ function getUniforms(
188
221
  function getLightSourceUniforms({
189
222
  ambientLight,
190
223
  pointLights = [],
224
+ spotLights = [],
191
225
  directionalLights = []
192
- }: LightingProps): Partial<LightingUniforms> {
193
- const lightSourceUniforms: Partial<LightingUniforms> = {};
226
+ }: LightingProps): Omit<LightingUniforms, 'enabled'> {
227
+ const lights = createDefaultLightUniforms();
194
228
 
195
- lightSourceUniforms.ambientColor = convertColor(ambientLight);
196
-
197
- let currentLight: 0 | 1 | 2 = 0;
229
+ let currentLight = 0;
230
+ let pointLightCount = 0;
231
+ let spotLightCount = 0;
232
+ let directionalLightCount = 0;
198
233
 
199
234
  for (const pointLight of pointLights) {
200
- lightSourceUniforms.lightType = LIGHT_TYPE.POINT;
235
+ if (currentLight >= MAX_LIGHTS) {
236
+ break;
237
+ }
201
238
 
202
- const i = currentLight as 0 | 1 | 2;
203
- lightSourceUniforms[`lightColor${i}`] = convertColor(pointLight);
204
- lightSourceUniforms[`lightPosition${i}`] = pointLight.position;
205
- 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
+ };
206
245
  currentLight++;
246
+ pointLightCount++;
207
247
  }
208
248
 
209
- for (const directionalLight of directionalLights) {
210
- lightSourceUniforms.lightType = LIGHT_TYPE.DIRECTIONAL;
249
+ for (const spotLight of spotLights) {
250
+ if (currentLight >= MAX_LIGHTS) {
251
+ break;
252
+ }
211
253
 
212
- const i = currentLight as 0 | 1 | 2;
213
- lightSourceUniforms[`lightColor${i}`] = convertColor(directionalLight);
214
- lightSourceUniforms[`lightDirection${i}`] = directionalLight.direction;
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
+ };
215
262
  currentLight++;
263
+ spotLightCount++;
216
264
  }
217
265
 
218
- if (currentLight > MAX_LIGHTS) {
219
- log.warn('MAX_LIGHTS exceeded')();
266
+ for (const directionalLight of directionalLights) {
267
+ if (currentLight >= MAX_LIGHTS) {
268
+ break;
269
+ }
270
+
271
+ lights[currentLight] = {
272
+ ...lights[currentLight],
273
+ color: convertColor(directionalLight),
274
+ direction: directionalLight.direction
275
+ };
276
+ currentLight++;
277
+ directionalLightCount++;
220
278
  }
221
279
 
222
- lightSourceUniforms.directionalLightCount = directionalLights.length;
223
- lightSourceUniforms.pointLightCount = pointLights.length;
280
+ if (pointLights.length + spotLights.length + directionalLights.length > MAX_LIGHTS) {
281
+ log.warn(`MAX_LIGHTS exceeded, truncating to ${MAX_LIGHTS}`)();
282
+ }
224
283
 
225
- return lightSourceUniforms;
284
+ return {
285
+ ambientColor: convertColor(ambientLight),
286
+ directionalLightCount,
287
+ pointLightCount,
288
+ spotLightCount,
289
+ lights
290
+ };
226
291
  }
227
292
 
228
293
  function extractLightTypes(lights: Light[]): LightingProps {
229
- const lightSources: LightingProps = {pointLights: [], directionalLights: []};
294
+ const lightSources: LightingProps = {pointLights: [], spotLights: [], directionalLights: []};
230
295
  for (const light of lights || []) {
231
296
  switch (light.type) {
232
297
  case 'ambient':
@@ -240,6 +305,9 @@ function extractLightTypes(lights: Light[]): LightingProps {
240
305
  case 'point':
241
306
  lightSources.pointLights?.push(light);
242
307
  break;
308
+ case 'spot':
309
+ lightSources.spotLights?.push(light);
310
+ break;
243
311
  default:
244
312
  // eslint-disable-next-line
245
313
  // console.warn(light.type);
@@ -255,3 +323,34 @@ function convertColor(
255
323
  const {color = [0, 0, 0], intensity = 1.0} = colorDef;
256
324
  return color.map(component => (component * intensity) / COLOR_FACTOR) as NumberArray3;
257
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 {
@@ -49,7 +49,7 @@ void dirlight_setNormal(vec3 normal) {
49
49
  `;
50
50
 
51
51
  const FS_GLSL = /* glsl */ `\
52
- uniform dirlightUniforms {
52
+ layout(std140) uniform dirlightUniforms {
53
53
  vec3 lightDirection;
54
54
  } dirlight;
55
55
 
@@ -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,