@certe/atmos-renderer 0.1.0

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 (204) hide show
  1. package/LICENCE +674 -0
  2. package/README.md +166 -0
  3. package/dist/bloom-pass.d.ts +29 -0
  4. package/dist/bloom-pass.d.ts.map +1 -0
  5. package/dist/bloom-pass.js +173 -0
  6. package/dist/bloom-pass.js.map +1 -0
  7. package/dist/bloom-shader.d.ts +9 -0
  8. package/dist/bloom-shader.d.ts.map +1 -0
  9. package/dist/bloom-shader.js +69 -0
  10. package/dist/bloom-shader.js.map +1 -0
  11. package/dist/bounds.d.ts +10 -0
  12. package/dist/bounds.d.ts.map +1 -0
  13. package/dist/bounds.js +37 -0
  14. package/dist/bounds.js.map +1 -0
  15. package/dist/camera.d.ts +31 -0
  16. package/dist/camera.d.ts.map +1 -0
  17. package/dist/camera.js +53 -0
  18. package/dist/camera.js.map +1 -0
  19. package/dist/depth-prepass.d.ts +24 -0
  20. package/dist/depth-prepass.d.ts.map +1 -0
  21. package/dist/depth-prepass.js +107 -0
  22. package/dist/depth-prepass.js.map +1 -0
  23. package/dist/directional-light.d.ts +23 -0
  24. package/dist/directional-light.d.ts.map +1 -0
  25. package/dist/directional-light.js +36 -0
  26. package/dist/directional-light.js.map +1 -0
  27. package/dist/frustum.d.ts +15 -0
  28. package/dist/frustum.d.ts.map +1 -0
  29. package/dist/frustum.js +51 -0
  30. package/dist/frustum.js.map +1 -0
  31. package/dist/fullscreen-quad.d.ts +8 -0
  32. package/dist/fullscreen-quad.d.ts.map +1 -0
  33. package/dist/fullscreen-quad.js +30 -0
  34. package/dist/fullscreen-quad.js.map +1 -0
  35. package/dist/geometry.d.ts +28 -0
  36. package/dist/geometry.d.ts.map +1 -0
  37. package/dist/geometry.js +245 -0
  38. package/dist/geometry.js.map +1 -0
  39. package/dist/grid-renderer.d.ts +10 -0
  40. package/dist/grid-renderer.d.ts.map +1 -0
  41. package/dist/grid-renderer.js +77 -0
  42. package/dist/grid-renderer.js.map +1 -0
  43. package/dist/grid-shader.d.ts +3 -0
  44. package/dist/grid-shader.d.ts.map +1 -0
  45. package/dist/grid-shader.js +89 -0
  46. package/dist/grid-shader.js.map +1 -0
  47. package/dist/index.d.ts +64 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +45 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/light.d.ts +59 -0
  52. package/dist/light.d.ts.map +1 -0
  53. package/dist/light.js +184 -0
  54. package/dist/light.js.map +1 -0
  55. package/dist/material-asset.d.ts +19 -0
  56. package/dist/material-asset.d.ts.map +1 -0
  57. package/dist/material-asset.js +30 -0
  58. package/dist/material-asset.js.map +1 -0
  59. package/dist/material.d.ts +50 -0
  60. package/dist/material.d.ts.map +1 -0
  61. package/dist/material.js +48 -0
  62. package/dist/material.js.map +1 -0
  63. package/dist/mesh-renderer.d.ts +43 -0
  64. package/dist/mesh-renderer.d.ts.map +1 -0
  65. package/dist/mesh-renderer.js +162 -0
  66. package/dist/mesh-renderer.js.map +1 -0
  67. package/dist/mesh.d.ts +16 -0
  68. package/dist/mesh.d.ts.map +1 -0
  69. package/dist/mesh.js +33 -0
  70. package/dist/mesh.js.map +1 -0
  71. package/dist/mipmap-generator.d.ts +7 -0
  72. package/dist/mipmap-generator.d.ts.map +1 -0
  73. package/dist/mipmap-generator.js +96 -0
  74. package/dist/mipmap-generator.js.map +1 -0
  75. package/dist/pbr-wgsl.d.ts +12 -0
  76. package/dist/pbr-wgsl.d.ts.map +1 -0
  77. package/dist/pbr-wgsl.js +159 -0
  78. package/dist/pbr-wgsl.js.map +1 -0
  79. package/dist/pipeline.d.ts +13 -0
  80. package/dist/pipeline.d.ts.map +1 -0
  81. package/dist/pipeline.js +77 -0
  82. package/dist/pipeline.js.map +1 -0
  83. package/dist/point-light.d.ts +16 -0
  84. package/dist/point-light.d.ts.map +1 -0
  85. package/dist/point-light.js +22 -0
  86. package/dist/point-light.js.map +1 -0
  87. package/dist/point-shadow-pass.d.ts +24 -0
  88. package/dist/point-shadow-pass.d.ts.map +1 -0
  89. package/dist/point-shadow-pass.js +192 -0
  90. package/dist/point-shadow-pass.js.map +1 -0
  91. package/dist/point-shadow-shader.d.ts +12 -0
  92. package/dist/point-shadow-shader.d.ts.map +1 -0
  93. package/dist/point-shadow-shader.js +52 -0
  94. package/dist/point-shadow-shader.js.map +1 -0
  95. package/dist/register-builtins.d.ts +2 -0
  96. package/dist/register-builtins.d.ts.map +1 -0
  97. package/dist/register-builtins.js +98 -0
  98. package/dist/register-builtins.js.map +1 -0
  99. package/dist/render-system.d.ts +99 -0
  100. package/dist/render-system.d.ts.map +1 -0
  101. package/dist/render-system.js +476 -0
  102. package/dist/render-system.js.map +1 -0
  103. package/dist/scene-depth.d.ts +36 -0
  104. package/dist/scene-depth.d.ts.map +1 -0
  105. package/dist/scene-depth.js +183 -0
  106. package/dist/scene-depth.js.map +1 -0
  107. package/dist/shader.d.ts +3 -0
  108. package/dist/shader.d.ts.map +1 -0
  109. package/dist/shader.js +144 -0
  110. package/dist/shader.js.map +1 -0
  111. package/dist/shadow-fragment-wgsl.d.ts +13 -0
  112. package/dist/shadow-fragment-wgsl.d.ts.map +1 -0
  113. package/dist/shadow-fragment-wgsl.js +205 -0
  114. package/dist/shadow-fragment-wgsl.js.map +1 -0
  115. package/dist/shadow-manager.d.ts +46 -0
  116. package/dist/shadow-manager.d.ts.map +1 -0
  117. package/dist/shadow-manager.js +259 -0
  118. package/dist/shadow-manager.js.map +1 -0
  119. package/dist/shadow-pass.d.ts +31 -0
  120. package/dist/shadow-pass.d.ts.map +1 -0
  121. package/dist/shadow-pass.js +135 -0
  122. package/dist/shadow-pass.js.map +1 -0
  123. package/dist/shadow-shader.d.ts +10 -0
  124. package/dist/shadow-shader.d.ts.map +1 -0
  125. package/dist/shadow-shader.js +24 -0
  126. package/dist/shadow-shader.js.map +1 -0
  127. package/dist/shadow-uniforms.d.ts +38 -0
  128. package/dist/shadow-uniforms.d.ts.map +1 -0
  129. package/dist/shadow-uniforms.js +97 -0
  130. package/dist/shadow-uniforms.js.map +1 -0
  131. package/dist/skinned-geometry.d.ts +14 -0
  132. package/dist/skinned-geometry.d.ts.map +1 -0
  133. package/dist/skinned-geometry.js +23 -0
  134. package/dist/skinned-geometry.js.map +1 -0
  135. package/dist/skinned-mesh-renderer.d.ts +54 -0
  136. package/dist/skinned-mesh-renderer.d.ts.map +1 -0
  137. package/dist/skinned-mesh-renderer.js +177 -0
  138. package/dist/skinned-mesh-renderer.js.map +1 -0
  139. package/dist/skinned-pipeline.d.ts +16 -0
  140. package/dist/skinned-pipeline.d.ts.map +1 -0
  141. package/dist/skinned-pipeline.js +112 -0
  142. package/dist/skinned-pipeline.js.map +1 -0
  143. package/dist/skinned-shader.d.ts +7 -0
  144. package/dist/skinned-shader.d.ts.map +1 -0
  145. package/dist/skinned-shader.js +52 -0
  146. package/dist/skinned-shader.js.map +1 -0
  147. package/dist/skinned-shadow-shader.d.ts +6 -0
  148. package/dist/skinned-shadow-shader.d.ts.map +1 -0
  149. package/dist/skinned-shadow-shader.js +31 -0
  150. package/dist/skinned-shadow-shader.js.map +1 -0
  151. package/dist/spot-light.d.ts +24 -0
  152. package/dist/spot-light.d.ts.map +1 -0
  153. package/dist/spot-light.js +41 -0
  154. package/dist/spot-light.js.map +1 -0
  155. package/dist/spot-shadow-pass.d.ts +36 -0
  156. package/dist/spot-shadow-pass.d.ts.map +1 -0
  157. package/dist/spot-shadow-pass.js +144 -0
  158. package/dist/spot-shadow-pass.js.map +1 -0
  159. package/dist/ssao-pass.d.ts +37 -0
  160. package/dist/ssao-pass.d.ts.map +1 -0
  161. package/dist/ssao-pass.js +208 -0
  162. package/dist/ssao-pass.js.map +1 -0
  163. package/dist/ssao-shader.d.ts +9 -0
  164. package/dist/ssao-shader.d.ts.map +1 -0
  165. package/dist/ssao-shader.js +120 -0
  166. package/dist/ssao-shader.js.map +1 -0
  167. package/dist/terrain-mesh-renderer.d.ts +39 -0
  168. package/dist/terrain-mesh-renderer.d.ts.map +1 -0
  169. package/dist/terrain-mesh-renderer.js +131 -0
  170. package/dist/terrain-mesh-renderer.js.map +1 -0
  171. package/dist/terrain-pipeline.d.ts +17 -0
  172. package/dist/terrain-pipeline.d.ts.map +1 -0
  173. package/dist/terrain-pipeline.js +70 -0
  174. package/dist/terrain-pipeline.js.map +1 -0
  175. package/dist/terrain-shader.d.ts +10 -0
  176. package/dist/terrain-shader.d.ts.map +1 -0
  177. package/dist/terrain-shader.js +154 -0
  178. package/dist/terrain-shader.js.map +1 -0
  179. package/dist/texture.d.ts +20 -0
  180. package/dist/texture.d.ts.map +1 -0
  181. package/dist/texture.js +87 -0
  182. package/dist/texture.js.map +1 -0
  183. package/dist/tonemap-pass.d.ts +22 -0
  184. package/dist/tonemap-pass.d.ts.map +1 -0
  185. package/dist/tonemap-pass.js +125 -0
  186. package/dist/tonemap-pass.js.map +1 -0
  187. package/dist/unlit-pipeline.d.ts +12 -0
  188. package/dist/unlit-pipeline.d.ts.map +1 -0
  189. package/dist/unlit-pipeline.js +59 -0
  190. package/dist/unlit-pipeline.js.map +1 -0
  191. package/dist/unlit-shader.d.ts +3 -0
  192. package/dist/unlit-shader.d.ts.map +1 -0
  193. package/dist/unlit-shader.js +33 -0
  194. package/dist/unlit-shader.js.map +1 -0
  195. package/dist/webgpu-device.d.ts +13 -0
  196. package/dist/webgpu-device.d.ts.map +1 -0
  197. package/dist/webgpu-device.js +70 -0
  198. package/dist/webgpu-device.js.map +1 -0
  199. package/dist/wireframe-pipeline.d.ts +7 -0
  200. package/dist/wireframe-pipeline.d.ts.map +1 -0
  201. package/dist/wireframe-pipeline.js +72 -0
  202. package/dist/wireframe-pipeline.js.map +1 -0
  203. package/package.json +28 -0
  204. package/src/index.ts +87 -0
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Shared PBR WGSL functions and light loop code.
3
+ * Concatenated into both shader.ts (standard PBR) and terrain-shader.ts (splat PBR).
4
+ */
5
+ /** PBR helper functions: GGX distribution, geometry, Fresnel, computePBR, computeTBN */
6
+ export const PBR_FUNCTIONS_WGSL = /* wgsl */ `
7
+ // GGX/Trowbridge-Reitz normal distribution
8
+ fn distributionGGX(N: vec3<f32>, H: vec3<f32>, roughness: f32) -> f32 {
9
+ let a = roughness * roughness;
10
+ let a2 = a * a;
11
+ let NdotH = max(dot(N, H), 0.0);
12
+ let NdotH2 = NdotH * NdotH;
13
+ let denom = NdotH2 * (a2 - 1.0) + 1.0;
14
+ return a2 / (PI * denom * denom);
15
+ }
16
+
17
+ // Schlick-GGX geometry function
18
+ fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 {
19
+ let r = roughness + 1.0;
20
+ let k = (r * r) / 8.0;
21
+ return NdotV / (NdotV * (1.0 - k) + k);
22
+ }
23
+
24
+ // Smith's geometry function
25
+ fn geometrySmith(N: vec3<f32>, V: vec3<f32>, L: vec3<f32>, roughness: f32) -> f32 {
26
+ let NdotV = max(dot(N, V), 0.0);
27
+ let NdotL = max(dot(N, L), 0.0);
28
+ return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness);
29
+ }
30
+
31
+ // Fresnel-Schlick approximation
32
+ fn fresnelSchlick(cosTheta: f32, F0: vec3<f32>) -> vec3<f32> {
33
+ return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
34
+ }
35
+
36
+ // Compute PBR contribution from a single light direction
37
+ fn computePBR(
38
+ N: vec3<f32>, V: vec3<f32>, L: vec3<f32>,
39
+ albedo: vec3<f32>, metallic: f32, roughness: f32,
40
+ F0: vec3<f32>, radiance: vec3<f32>,
41
+ ) -> vec3<f32> {
42
+ let H = normalize(V + L);
43
+ let NDF = distributionGGX(N, H, roughness);
44
+ let G = geometrySmith(N, V, L, roughness);
45
+ let F = fresnelSchlick(max(dot(H, V), 0.0), F0);
46
+
47
+ let numerator = NDF * G * F;
48
+ let denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
49
+ let specular = numerator / denominator;
50
+
51
+ let kS = F;
52
+ let kD = (vec3<f32>(1.0) - kS) * (1.0 - metallic);
53
+ let NdotL = max(dot(N, L), 0.0);
54
+
55
+ return (kD * albedo / PI + specular) * radiance * NdotL;
56
+ }
57
+
58
+ // Compute cotangent-frame TBN from screen-space derivatives
59
+ fn computeTBN(worldPos: vec3<f32>, worldNormal: vec3<f32>, uv: vec2<f32>) -> mat3x3<f32> {
60
+ let dp1 = dpdx(worldPos);
61
+ let dp2 = dpdy(worldPos);
62
+ let duv1 = dpdx(uv);
63
+ let duv2 = dpdy(uv);
64
+ let T = normalize(dp1 * duv2.y - dp2 * duv1.y);
65
+ let B = normalize(dp2 * duv1.x - dp1 * duv2.x);
66
+ let N = normalize(worldNormal);
67
+ return mat3x3(T, B, N);
68
+ }
69
+ `;
70
+ /** Light loop WGSL: iterates dir/point/spot lights with PBR + shadow sampling.
71
+ * Expects: N, V, albedo, metallic, roughness, F0, worldPosition in scope. Writes to Lo. */
72
+ export const LIGHT_LOOP_WGSL = /* wgsl */ `
73
+ // Directional lights
74
+ for (var i = 0u; i < scene.numDirLights; i = i + 1u) {
75
+ let light = scene.dirLights[i];
76
+ let L = normalize(-light.direction.xyz);
77
+ let intensity = light.color.w;
78
+ let radiance = light.color.rgb * intensity;
79
+ var contribution = computePBR(N, V, L, albedo, metallic, roughness, F0, radiance);
80
+ let dirSlot = shadow.dirLightToSlot[i];
81
+ if (dirSlot != 0xFFFFFFFFu) {
82
+ contribution = contribution * sampleDirShadow(dirSlot, worldPosition);
83
+ }
84
+ Lo = Lo + contribution;
85
+ }
86
+
87
+ // Point lights
88
+ for (var i = 0u; i < scene.numPointLights; i = i + 1u) {
89
+ let light = scene.pointLights[i];
90
+ let lightPos = light.position.xyz;
91
+ let range = light.position.w;
92
+ let intensity = light.color.w;
93
+
94
+ let toLight = lightPos - worldPosition;
95
+ let dist = length(toLight);
96
+ let L = toLight / max(dist, 0.0001);
97
+
98
+ // Smooth distance attenuation with range cutoff
99
+ let attenuation = max(1.0 - (dist * dist) / (range * range), 0.0);
100
+ let radiance = light.color.rgb * intensity * attenuation * attenuation;
101
+
102
+ var contribution = computePBR(N, V, L, albedo, metallic, roughness, F0, radiance);
103
+ let pointSlot = shadow.pointLightToSlot[i];
104
+ if (pointSlot != 0xFFFFFFFFu) {
105
+ contribution = contribution * samplePointShadow(pointSlot, worldPosition, N);
106
+ }
107
+ Lo = Lo + contribution;
108
+ }
109
+
110
+ // Spot lights
111
+ for (var i = 0u; i < scene.numSpotLights; i = i + 1u) {
112
+ let light = scene.spotLights[i];
113
+ let lightPos = light.position.xyz;
114
+ let range = light.position.w;
115
+ let spotDir = light.direction.xyz;
116
+ let outerCos = light.direction.w;
117
+ let innerCos = light.extra.x;
118
+ let intensity = light.color.w;
119
+
120
+ let toLight = lightPos - worldPosition;
121
+ let dist = length(toLight);
122
+ let L = toLight / max(dist, 0.0001);
123
+
124
+ // Distance attenuation (same as point light)
125
+ let distAtt = max(1.0 - (dist * dist) / (range * range), 0.0);
126
+
127
+ // Cone attenuation: smoothstep between outer and inner cosines
128
+ let cosAngle = dot(-L, spotDir);
129
+ let coneAtt = smoothstep(outerCos, innerCos, cosAngle);
130
+
131
+ let attenuation = distAtt * distAtt * coneAtt;
132
+ let radiance = light.color.rgb * intensity * attenuation;
133
+
134
+ var contribution = computePBR(N, V, L, albedo, metallic, roughness, F0, radiance);
135
+ let spotSlot = shadow.spotLightToSlot[i];
136
+ if (spotSlot != 0xFFFFFFFFu) {
137
+ contribution = contribution * sampleSpotShadow(spotSlot, worldPosition);
138
+ }
139
+ Lo = Lo + contribution;
140
+ }
141
+ `;
142
+ /** Fog calculation WGSL. Expects: scene, worldPosition, color in scope. Modifies color. */
143
+ export const FOG_WGSL = /* wgsl */ `
144
+ // Distance fog
145
+ if (scene.fogEnabled != 0u) {
146
+ let fogDist = length(scene.cameraPos.xyz - worldPosition);
147
+ var fogFactor: f32;
148
+ if (scene.fogMode == 0u) {
149
+ // Linear
150
+ fogFactor = saturate((scene.fogEnd - fogDist) / (scene.fogEnd - scene.fogStart));
151
+ } else {
152
+ // Exponential²
153
+ let d = scene.fogDensity * fogDist;
154
+ fogFactor = exp(-(d * d));
155
+ }
156
+ color = mix(scene.fogColor.rgb, color, fogFactor);
157
+ }
158
+ `;
159
+ //# sourceMappingURL=pbr-wgsl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pbr-wgsl.js","sourceRoot":"","sources":["../src/pbr-wgsl.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wFAAwF;AACxF,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+D3C,CAAC;AAEF;4FAC4F;AAC5F,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqExC,CAAC;AAEF,2FAA2F;AAC3F,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAA;;;;;;;;;;;;;;;CAejC,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface PipelineResources {
2
+ pipeline: GPURenderPipeline;
3
+ objectBindGroupLayout: GPUBindGroupLayout;
4
+ materialBindGroupLayout: GPUBindGroupLayout;
5
+ shadowBindGroupLayout: GPUBindGroupLayout;
6
+ /** @deprecated Use objectBindGroupLayout instead */
7
+ bindGroupLayout: GPUBindGroupLayout;
8
+ }
9
+ /** HDR format used for the MSAA resolve target */
10
+ export declare const HDR_FORMAT: GPUTextureFormat;
11
+ export declare const MSAA_SAMPLE_COUNT = 4;
12
+ export declare function createRenderPipeline(device: GPUDevice, _format: GPUTextureFormat): PipelineResources;
13
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,qBAAqB,EAAE,kBAAkB,CAAC;IAC1C,uBAAuB,EAAE,kBAAkB,CAAC;IAC5C,qBAAqB,EAAE,kBAAkB,CAAC;IAC1C,oDAAoD;IACpD,eAAe,EAAE,kBAAkB,CAAC;CACrC;AAED,kDAAkD;AAClD,eAAO,MAAM,UAAU,EAAE,gBAAgC,CAAC;AAC1D,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,gBAAgB,GACxB,iBAAiB,CA2EnB"}
@@ -0,0 +1,77 @@
1
+ import { VERTEX_SHADER, FRAGMENT_SHADER } from './shader.js';
2
+ import { VERTEX_STRIDE_BYTES } from './geometry.js';
3
+ import { createShadowBindGroupLayout } from './shadow-uniforms.js';
4
+ /** HDR format used for the MSAA resolve target */
5
+ export const HDR_FORMAT = 'rgba16float';
6
+ export const MSAA_SAMPLE_COUNT = 4;
7
+ export function createRenderPipeline(device, _format) {
8
+ const vertexModule = device.createShaderModule({ code: VERTEX_SHADER });
9
+ const fragmentModule = device.createShaderModule({ code: FRAGMENT_SHADER });
10
+ // Group 0: per-object uniforms (MVP + model + normalMatrix) – vertex stage
11
+ const objectBindGroupLayout = device.createBindGroupLayout({
12
+ entries: [
13
+ {
14
+ binding: 0,
15
+ visibility: GPUShaderStage.VERTEX,
16
+ buffer: { type: 'uniform' },
17
+ },
18
+ ],
19
+ });
20
+ // Group 1: per-material + per-scene uniforms + textures – fragment stage
21
+ const materialBindGroupLayout = device.createBindGroupLayout({
22
+ entries: [
23
+ { binding: 0, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },
24
+ { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },
25
+ { binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: 'float' } },
26
+ { binding: 3, visibility: GPUShaderStage.FRAGMENT, sampler: { type: 'filtering' } },
27
+ { binding: 4, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: 'float' } },
28
+ { binding: 5, visibility: GPUShaderStage.FRAGMENT, sampler: { type: 'filtering' } },
29
+ { binding: 6, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: 'float' } },
30
+ { binding: 7, visibility: GPUShaderStage.FRAGMENT, sampler: { type: 'filtering' } },
31
+ ],
32
+ });
33
+ const shadowBindGroupLayout = createShadowBindGroupLayout(device);
34
+ const pipelineLayout = device.createPipelineLayout({
35
+ bindGroupLayouts: [objectBindGroupLayout, materialBindGroupLayout, shadowBindGroupLayout],
36
+ });
37
+ const pipeline = device.createRenderPipeline({
38
+ layout: pipelineLayout,
39
+ vertex: {
40
+ module: vertexModule,
41
+ entryPoint: 'main',
42
+ buffers: [
43
+ {
44
+ arrayStride: VERTEX_STRIDE_BYTES,
45
+ attributes: [
46
+ { shaderLocation: 0, offset: 0, format: 'float32x3' }, // position
47
+ { shaderLocation: 1, offset: 12, format: 'float32x3' }, // normal
48
+ { shaderLocation: 2, offset: 24, format: 'float32x2' }, // uv
49
+ ],
50
+ },
51
+ ],
52
+ },
53
+ fragment: {
54
+ module: fragmentModule,
55
+ entryPoint: 'main',
56
+ targets: [{ format: HDR_FORMAT }],
57
+ },
58
+ multisample: { count: MSAA_SAMPLE_COUNT },
59
+ primitive: {
60
+ topology: 'triangle-list',
61
+ cullMode: 'back',
62
+ },
63
+ depthStencil: {
64
+ depthWriteEnabled: true,
65
+ depthCompare: 'less',
66
+ format: 'depth24plus',
67
+ },
68
+ });
69
+ return {
70
+ pipeline,
71
+ objectBindGroupLayout,
72
+ materialBindGroupLayout,
73
+ shadowBindGroupLayout,
74
+ bindGroupLayout: objectBindGroupLayout,
75
+ };
76
+ }
77
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Component } from '@certe/atmos-core';
2
+ /**
3
+ * Point light component.
4
+ * Position is derived from the Transform's world position (worldMatrix[12..14]).
5
+ */
6
+ export declare class PointLight extends Component {
7
+ color: Float32Array<ArrayBuffer>;
8
+ intensity: number;
9
+ range: number;
10
+ castShadows: boolean;
11
+ shadowIntensity: number;
12
+ shadowResolution: number;
13
+ /** Extract world position into `out`. */
14
+ getWorldPosition(out: Float32Array): Float32Array;
15
+ }
16
+ //# sourceMappingURL=point-light.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-light.d.ts","sourceRoot":"","sources":["../src/point-light.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C;;;GAGG;AACH,qBAAa,UAAW,SAAQ,SAAS;IACvC,KAAK,4BAA+B;IACpC,SAAS,SAAO;IAChB,KAAK,SAAQ;IACb,WAAW,UAAS;IACpB,eAAe,SAAO;IACtB,gBAAgB,SAAO;IAEvB,yCAAyC;IACzC,gBAAgB,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY;CAOlD"}
@@ -0,0 +1,22 @@
1
+ import { Component } from '@certe/atmos-core';
2
+ /**
3
+ * Point light component.
4
+ * Position is derived from the Transform's world position (worldMatrix[12..14]).
5
+ */
6
+ export class PointLight extends Component {
7
+ color = new Float32Array([1, 1, 1]);
8
+ intensity = 1.0;
9
+ range = 10.0;
10
+ castShadows = false;
11
+ shadowIntensity = 1.0;
12
+ shadowResolution = 512;
13
+ /** Extract world position into `out`. */
14
+ getWorldPosition(out) {
15
+ const m = this.gameObject.transform.worldMatrix;
16
+ out[0] = m[12];
17
+ out[1] = m[13];
18
+ out[2] = m[14];
19
+ return out;
20
+ }
21
+ }
22
+ //# sourceMappingURL=point-light.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-light.js","sourceRoot":"","sources":["../src/point-light.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C;;;GAGG;AACH,MAAM,OAAO,UAAW,SAAQ,SAAS;IACvC,KAAK,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACpC,SAAS,GAAG,GAAG,CAAC;IAChB,KAAK,GAAG,IAAI,CAAC;IACb,WAAW,GAAG,KAAK,CAAC;IACpB,eAAe,GAAG,GAAG,CAAC;IACtB,gBAAgB,GAAG,GAAG,CAAC;IAEvB,yCAAyC;IACzC,gBAAgB,CAAC,GAAiB;QAChC,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC;QAChD,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAE,CAAC;QAChB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAE,CAAC;QAChB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAE,CAAC;QAChB,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
@@ -0,0 +1,24 @@
1
+ import type { Scene } from '@certe/atmos-core';
2
+ export declare class PointShadowPass {
3
+ private readonly _device;
4
+ private readonly _pipeline;
5
+ private readonly _faceBuffers;
6
+ private readonly _faceBindGroups;
7
+ private readonly _depthTexture;
8
+ private readonly _faceViews;
9
+ private readonly _sampler;
10
+ readonly cubeMapView: GPUTextureView;
11
+ readonly resolution: number;
12
+ private readonly _view;
13
+ private readonly _proj;
14
+ private readonly _vp;
15
+ private readonly _eye;
16
+ private readonly _target;
17
+ private readonly _up;
18
+ private readonly _uniformData;
19
+ get shadowSampler(): GPUSampler;
20
+ constructor(device: GPUDevice, objectBindGroupLayout: GPUBindGroupLayout, resolution?: number);
21
+ execute(encoder: GPUCommandEncoder, scene: Scene, lightPos: Float32Array, range: number, extraDraw?: (pass: GPURenderPassEncoder) => void): void;
22
+ destroy(): void;
23
+ }
24
+ //# sourceMappingURL=point-shadow-pass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-shadow-pass.d.ts","sourceRoot":"","sources":["../src/point-shadow-pass.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AA0B/C,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmB;IAChD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAsB;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAa;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAwB;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IACtC,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAG5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA2B;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuB;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsC;IAEnE,IAAI,aAAa,IAAI,UAAU,CAE9B;gBAGC,MAAM,EAAE,SAAS,EACjB,qBAAqB,EAAE,kBAAkB,EACzC,UAAU,SAAqB;IA+FjC,OAAO,CACL,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAC/E,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,GAC/C,IAAI;IAyEP,OAAO,IAAI,IAAI;CAIhB"}
@@ -0,0 +1,192 @@
1
+ import { Mat4, Vec3 } from '@certe/atmos-math';
2
+ import { POINT_SHADOW_SHADER } from './point-shadow-shader.js';
3
+ import { VERTEX_STRIDE_BYTES } from './geometry.js';
4
+ import { MeshRenderer } from './mesh-renderer.js';
5
+ const DEFAULT_RESOLUTION = 512;
6
+ const NUM_FACES = 6;
7
+ /** Per-face buffer: mat4x4(64) + vec4(16) = 80 bytes */
8
+ const FACE_UNIFORM_SIZE = 80;
9
+ /**
10
+ * Cube face camera directions.
11
+ * Each entry: [dirX, dirY, dirZ, upX, upY, upZ]
12
+ */
13
+ const CUBE_FACES = [
14
+ [1, 0, 0, 0, -1, 0], // +X
15
+ [-1, 0, 0, 0, -1, 0], // -X
16
+ [0, 1, 0, 0, 0, 1], // +Y
17
+ [0, -1, 0, 0, 0, -1], // -Y
18
+ [0, 0, 1, 0, -1, 0], // +Z
19
+ [0, 0, -1, 0, -1, 0], // -Z
20
+ ];
21
+ export class PointShadowPass {
22
+ _device;
23
+ _pipeline;
24
+ _faceBuffers = [];
25
+ _faceBindGroups = [];
26
+ _depthTexture;
27
+ _faceViews = [];
28
+ _sampler;
29
+ cubeMapView;
30
+ resolution;
31
+ // Scratch matrices (reused each frame)
32
+ _view = Mat4.create();
33
+ _proj = Mat4.create();
34
+ _vp = Mat4.create();
35
+ _eye = new Float32Array(3);
36
+ _target = new Float32Array(3);
37
+ _up = new Float32Array(3);
38
+ _uniformData = new ArrayBuffer(FACE_UNIFORM_SIZE);
39
+ get shadowSampler() {
40
+ return this._sampler;
41
+ }
42
+ constructor(device, objectBindGroupLayout, resolution = DEFAULT_RESOLUTION) {
43
+ this._device = device;
44
+ this.resolution = resolution;
45
+ // Cube depth texture (6 layers)
46
+ this._depthTexture = device.createTexture({
47
+ size: [resolution, resolution, NUM_FACES],
48
+ format: 'depth32float',
49
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
50
+ });
51
+ // Per-face 2D views for render targets
52
+ for (let i = 0; i < NUM_FACES; i++) {
53
+ this._faceViews.push(this._depthTexture.createView({
54
+ dimension: '2d',
55
+ baseArrayLayer: i,
56
+ arrayLayerCount: 1,
57
+ }));
58
+ }
59
+ // Cube view for shader sampling
60
+ this.cubeMapView = this._depthTexture.createView({ dimension: 'cube' });
61
+ // Comparison sampler
62
+ this._sampler = device.createSampler({ compare: 'less' });
63
+ // Bind group layout for group 1 (lightVP + lightPosAndFar)
64
+ const shadowBGL = device.createBindGroupLayout({
65
+ entries: [
66
+ {
67
+ binding: 0,
68
+ visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
69
+ buffer: { type: 'uniform' },
70
+ },
71
+ ],
72
+ });
73
+ // One uniform buffer + bind group per face (writeBuffer is enqueued before
74
+ // the command buffer executes, so a single buffer would use only the last write)
75
+ for (let i = 0; i < NUM_FACES; i++) {
76
+ const buf = device.createBuffer({
77
+ size: FACE_UNIFORM_SIZE,
78
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
79
+ });
80
+ this._faceBuffers.push(buf);
81
+ this._faceBindGroups.push(device.createBindGroup({
82
+ layout: shadowBGL,
83
+ entries: [{ binding: 0, resource: { buffer: buf } }],
84
+ }));
85
+ }
86
+ // Shadow render pipeline (vertex + fragment for linear depth)
87
+ const shaderModule = device.createShaderModule({ code: POINT_SHADOW_SHADER });
88
+ const pipelineLayout = device.createPipelineLayout({
89
+ bindGroupLayouts: [objectBindGroupLayout, shadowBGL],
90
+ });
91
+ this._pipeline = device.createRenderPipeline({
92
+ layout: pipelineLayout,
93
+ vertex: {
94
+ module: shaderModule,
95
+ entryPoint: 'vs',
96
+ buffers: [
97
+ {
98
+ arrayStride: VERTEX_STRIDE_BYTES,
99
+ attributes: [
100
+ { shaderLocation: 0, offset: 0, format: 'float32x3' },
101
+ ],
102
+ },
103
+ ],
104
+ },
105
+ fragment: {
106
+ module: shaderModule,
107
+ entryPoint: 'fs',
108
+ targets: [],
109
+ },
110
+ primitive: {
111
+ topology: 'triangle-list',
112
+ cullMode: 'front',
113
+ },
114
+ depthStencil: {
115
+ depthWriteEnabled: true,
116
+ depthCompare: 'less',
117
+ format: 'depth32float',
118
+ depthBias: 2,
119
+ depthBiasSlopeScale: 2.0,
120
+ },
121
+ });
122
+ }
123
+ execute(encoder, scene, lightPos, range, extraDraw) {
124
+ const near = 0.1;
125
+ Mat4.perspective(this._proj, Math.PI / 2, 1.0, near, range);
126
+ // Flip Y: lookAt produces right-handed view but WebGPU cube map sampling
127
+ // expects V=0 at top matching tc convention (e.g. face +X: tc=-ry).
128
+ // Without this flip, all 6 faces are vertically inverted.
129
+ this._proj[5] = -this._proj[5];
130
+ const f32 = new Float32Array(this._uniformData);
131
+ const lx = lightPos[0], ly = lightPos[1], lz = lightPos[2];
132
+ // Collect shadow casters within range once (shared across all 6 faces)
133
+ const casters = [];
134
+ for (const obj of scene.getAllObjects()) {
135
+ const mr = obj.getComponent(MeshRenderer);
136
+ if (!mr || !mr.enabled || !mr.castShadow || !mr.mesh || !mr.bindGroup)
137
+ continue;
138
+ const bs = mr.worldBoundingSphere;
139
+ if (bs) {
140
+ const dx = bs.center[0] - lx;
141
+ const dy = bs.center[1] - ly;
142
+ const dz = bs.center[2] - lz;
143
+ if (dx * dx + dy * dy + dz * dz > (range + bs.radius) * (range + bs.radius))
144
+ continue;
145
+ }
146
+ casters.push(mr);
147
+ }
148
+ for (let face = 0; face < NUM_FACES; face++) {
149
+ const dir = CUBE_FACES[face];
150
+ Vec3.copy(this._eye, lightPos);
151
+ this._target[0] = lx + dir[0];
152
+ this._target[1] = ly + dir[1];
153
+ this._target[2] = lz + dir[2];
154
+ this._up[0] = dir[3];
155
+ this._up[1] = dir[4];
156
+ this._up[2] = dir[5];
157
+ Mat4.lookAt(this._view, this._eye, this._target, this._up);
158
+ Mat4.multiply(this._vp, this._proj, this._view);
159
+ f32.set(this._vp, 0);
160
+ f32[16] = lx;
161
+ f32[17] = ly;
162
+ f32[18] = lz;
163
+ f32[19] = range;
164
+ this._device.queue.writeBuffer(this._faceBuffers[face], 0, this._uniformData);
165
+ const pass = encoder.beginRenderPass({
166
+ colorAttachments: [],
167
+ depthStencilAttachment: {
168
+ view: this._faceViews[face],
169
+ depthClearValue: 1.0,
170
+ depthLoadOp: 'clear',
171
+ depthStoreOp: 'store',
172
+ },
173
+ });
174
+ pass.setPipeline(this._pipeline);
175
+ pass.setBindGroup(1, this._faceBindGroups[face]);
176
+ for (const mr of casters) {
177
+ pass.setBindGroup(0, mr.bindGroup);
178
+ pass.setVertexBuffer(0, mr.mesh.vertexBuffer);
179
+ pass.setIndexBuffer(mr.mesh.indexBuffer, mr.mesh.indexFormat);
180
+ pass.drawIndexed(mr.mesh.indexCount);
181
+ }
182
+ extraDraw?.(pass);
183
+ pass.end();
184
+ }
185
+ }
186
+ destroy() {
187
+ this._depthTexture.destroy();
188
+ for (const buf of this._faceBuffers)
189
+ buf.destroy();
190
+ }
191
+ }
192
+ //# sourceMappingURL=point-shadow-pass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-shadow-pass.js","sourceRoot":"","sources":["../src/point-shadow-pass.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Point light shadow shader – renders linear depth into cube map faces.
3
+ *
4
+ * Unlike directional shadows (depth-only), point shadows need a fragment shader
5
+ * to write linear depth (distance / far) via @builtin(frag_depth) for consistent
6
+ * precision across all 6 cube faces.
7
+ *
8
+ * Group 0: object uniforms (reuses existing objectBGL)
9
+ * Group 1: PointLightShadow { lightVP, lightPosAndFar }
10
+ */
11
+ export declare const POINT_SHADOW_SHADER = "\nstruct ObjectUniforms {\n mvp: mat4x4<f32>,\n model: mat4x4<f32>,\n normalMatrix: mat4x4<f32>,\n};\n\nstruct PointLightShadow {\n lightVP: mat4x4<f32>,\n lightPosAndFar: vec4<f32>,\n};\n\n@group(0) @binding(0) var<uniform> object: ObjectUniforms;\n@group(1) @binding(0) var<uniform> shadow: PointLightShadow;\n\nstruct VsOut {\n @builtin(position) clipPos: vec4<f32>,\n @location(0) worldPos: vec3<f32>,\n};\n\n@vertex\nfn vs(@location(0) position: vec3<f32>) -> VsOut {\n let worldPos = (object.model * vec4<f32>(position, 1.0)).xyz;\n var out: VsOut;\n out.clipPos = shadow.lightVP * vec4<f32>(worldPos, 1.0);\n out.worldPos = worldPos;\n return out;\n}\n\nstruct FsOut {\n @builtin(frag_depth) depth: f32,\n};\n\n@fragment\nfn fs(@location(0) worldPos: vec3<f32>) -> FsOut {\n let dist = length(worldPos - shadow.lightPosAndFar.xyz);\n var out: FsOut;\n out.depth = dist / shadow.lightPosAndFar.w;\n return out;\n}\n";
12
+ //# sourceMappingURL=point-shadow-shader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-shadow-shader.d.ts","sourceRoot":"","sources":["../src/point-shadow-shader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,+6BAwC/B,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Point light shadow shader – renders linear depth into cube map faces.
3
+ *
4
+ * Unlike directional shadows (depth-only), point shadows need a fragment shader
5
+ * to write linear depth (distance / far) via @builtin(frag_depth) for consistent
6
+ * precision across all 6 cube faces.
7
+ *
8
+ * Group 0: object uniforms (reuses existing objectBGL)
9
+ * Group 1: PointLightShadow { lightVP, lightPosAndFar }
10
+ */
11
+ export const POINT_SHADOW_SHADER = /* wgsl */ `
12
+ struct ObjectUniforms {
13
+ mvp: mat4x4<f32>,
14
+ model: mat4x4<f32>,
15
+ normalMatrix: mat4x4<f32>,
16
+ };
17
+
18
+ struct PointLightShadow {
19
+ lightVP: mat4x4<f32>,
20
+ lightPosAndFar: vec4<f32>,
21
+ };
22
+
23
+ @group(0) @binding(0) var<uniform> object: ObjectUniforms;
24
+ @group(1) @binding(0) var<uniform> shadow: PointLightShadow;
25
+
26
+ struct VsOut {
27
+ @builtin(position) clipPos: vec4<f32>,
28
+ @location(0) worldPos: vec3<f32>,
29
+ };
30
+
31
+ @vertex
32
+ fn vs(@location(0) position: vec3<f32>) -> VsOut {
33
+ let worldPos = (object.model * vec4<f32>(position, 1.0)).xyz;
34
+ var out: VsOut;
35
+ out.clipPos = shadow.lightVP * vec4<f32>(worldPos, 1.0);
36
+ out.worldPos = worldPos;
37
+ return out;
38
+ }
39
+
40
+ struct FsOut {
41
+ @builtin(frag_depth) depth: f32,
42
+ };
43
+
44
+ @fragment
45
+ fn fs(@location(0) worldPos: vec3<f32>) -> FsOut {
46
+ let dist = length(worldPos - shadow.lightPosAndFar.xyz);
47
+ var out: FsOut;
48
+ out.depth = dist / shadow.lightPosAndFar.w;
49
+ return out;
50
+ }
51
+ `;
52
+ //# sourceMappingURL=point-shadow-shader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-shadow-shader.js","sourceRoot":"","sources":["../src/point-shadow-shader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwC5C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function registerRendererBuiltins(): void;
2
+ //# sourceMappingURL=register-builtins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-builtins.d.ts","sourceRoot":"","sources":["../src/register-builtins.ts"],"names":[],"mappings":"AASA,wBAAgB,wBAAwB,IAAI,IAAI,CA8F/C"}