@tinypoly/gpu-renderer 0.0.5 → 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 (110) hide show
  1. package/ARCHITECTURE.md +59 -3
  2. package/README.md +52 -4
  3. package/dist/atmosphere.d.ts +21 -0
  4. package/dist/atmosphere.d.ts.map +1 -0
  5. package/dist/atmosphere.js +72 -0
  6. package/dist/atmosphere.js.map +1 -0
  7. package/dist/denoise.d.ts +11 -1
  8. package/dist/denoise.d.ts.map +1 -1
  9. package/dist/denoise.js +34 -6
  10. package/dist/denoise.js.map +1 -1
  11. package/dist/frameLayout.d.ts.map +1 -1
  12. package/dist/frameLayout.js +15 -0
  13. package/dist/frameLayout.js.map +1 -1
  14. package/dist/geometry.d.ts.map +1 -1
  15. package/dist/geometry.js +6 -3
  16. package/dist/geometry.js.map +1 -1
  17. package/dist/index.d.ts +4 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/lensPass.d.ts +60 -0
  22. package/dist/lensPass.d.ts.map +1 -0
  23. package/dist/lensPass.js +235 -0
  24. package/dist/lensPass.js.map +1 -0
  25. package/dist/lightTree.d.ts +43 -0
  26. package/dist/lightTree.d.ts.map +1 -0
  27. package/dist/lightTree.js +107 -0
  28. package/dist/lightTree.js.map +1 -0
  29. package/dist/lights.d.ts +10 -0
  30. package/dist/lights.d.ts.map +1 -1
  31. package/dist/lights.js +54 -1
  32. package/dist/lights.js.map +1 -1
  33. package/dist/materialLayout.d.ts +24 -0
  34. package/dist/materialLayout.d.ts.map +1 -1
  35. package/dist/materialLayout.js +36 -1
  36. package/dist/materialLayout.js.map +1 -1
  37. package/dist/pathTracePass.d.ts +6 -3
  38. package/dist/pathTracePass.d.ts.map +1 -1
  39. package/dist/pathTracePass.js +16 -10
  40. package/dist/pathTracePass.js.map +1 -1
  41. package/dist/renderer.d.ts +19 -7
  42. package/dist/renderer.d.ts.map +1 -1
  43. package/dist/renderer.js +118 -14
  44. package/dist/renderer.js.map +1 -1
  45. package/dist/sceneUpload.d.ts +5 -0
  46. package/dist/sceneUpload.d.ts.map +1 -1
  47. package/dist/sceneUpload.js +4 -0
  48. package/dist/sceneUpload.js.map +1 -1
  49. package/dist/settings.d.ts +136 -0
  50. package/dist/settings.d.ts.map +1 -0
  51. package/dist/settings.js +100 -0
  52. package/dist/settings.js.map +1 -0
  53. package/dist/subsurface.d.ts +76 -0
  54. package/dist/subsurface.d.ts.map +1 -0
  55. package/dist/subsurface.js +70 -0
  56. package/dist/subsurface.js.map +1 -0
  57. package/dist/volumeContainment.d.ts +17 -0
  58. package/dist/volumeContainment.d.ts.map +1 -0
  59. package/dist/volumeContainment.js +61 -0
  60. package/dist/volumeContainment.js.map +1 -0
  61. package/dist/wgsl/bsdf.wgsl.d.ts +1 -1
  62. package/dist/wgsl/bsdf.wgsl.d.ts.map +1 -1
  63. package/dist/wgsl/bsdf.wgsl.js +35 -3
  64. package/dist/wgsl/bsdf.wgsl.js.map +1 -1
  65. package/dist/wgsl/common.wgsl.d.ts.map +1 -1
  66. package/dist/wgsl/common.wgsl.js +4 -0
  67. package/dist/wgsl/common.wgsl.js.map +1 -1
  68. package/dist/wgsl/lens.wgsl.d.ts +17 -0
  69. package/dist/wgsl/lens.wgsl.d.ts.map +1 -0
  70. package/dist/wgsl/lens.wgsl.js +315 -0
  71. package/dist/wgsl/lens.wgsl.js.map +1 -0
  72. package/dist/wgsl/lights.wgsl.d.ts +1 -1
  73. package/dist/wgsl/lights.wgsl.d.ts.map +1 -1
  74. package/dist/wgsl/lights.wgsl.js +203 -31
  75. package/dist/wgsl/lights.wgsl.js.map +1 -1
  76. package/dist/wgsl/pathTrace.wgsl.d.ts +1 -1
  77. package/dist/wgsl/pathTrace.wgsl.d.ts.map +1 -1
  78. package/dist/wgsl/pathTrace.wgsl.js +396 -25
  79. package/dist/wgsl/pathTrace.wgsl.js.map +1 -1
  80. package/dist/wgsl/sampling.wgsl.d.ts +1 -1
  81. package/dist/wgsl/sampling.wgsl.d.ts.map +1 -1
  82. package/dist/wgsl/sampling.wgsl.js +25 -0
  83. package/dist/wgsl/sampling.wgsl.js.map +1 -1
  84. package/dist/wgsl/surface.wgsl.d.ts +1 -1
  85. package/dist/wgsl/surface.wgsl.d.ts.map +1 -1
  86. package/dist/wgsl/surface.wgsl.js +21 -1
  87. package/dist/wgsl/surface.wgsl.js.map +1 -1
  88. package/package.json +1 -1
  89. package/src/atmosphere.ts +95 -0
  90. package/src/denoise.ts +44 -6
  91. package/src/frameLayout.ts +15 -0
  92. package/src/geometry.ts +6 -2
  93. package/src/index.ts +13 -0
  94. package/src/lensPass.ts +299 -0
  95. package/src/lightTree.ts +172 -0
  96. package/src/lights.ts +71 -1
  97. package/src/materialLayout.ts +52 -1
  98. package/src/pathTracePass.ts +19 -10
  99. package/src/renderer.ts +166 -22
  100. package/src/sceneUpload.ts +9 -0
  101. package/src/settings.ts +234 -0
  102. package/src/subsurface.ts +153 -0
  103. package/src/volumeContainment.ts +81 -0
  104. package/src/wgsl/bsdf.wgsl.ts +35 -3
  105. package/src/wgsl/common.wgsl.ts +4 -0
  106. package/src/wgsl/lens.wgsl.ts +314 -0
  107. package/src/wgsl/lights.wgsl.ts +203 -31
  108. package/src/wgsl/pathTrace.wgsl.ts +396 -25
  109. package/src/wgsl/sampling.wgsl.ts +25 -0
  110. package/src/wgsl/surface.wgsl.ts +21 -1
@@ -18,8 +18,11 @@ import { TEXTURE_WGSL } from "./wgsl/texture.wgsl.js";
18
18
  * declarations. The scene's translated shaders sit between the texture code they call and the surface code that calls
19
19
  * them.
20
20
  */
21
- export function pathTraceSource(programs = null) {
22
- return COMMON_WGSL + RANDOM_WGSL + BVH_WGSL + SAMPLING_WGSL + TEXTURE_WGSL + SHADER_SUPPORT_WGSL
21
+ export function pathTraceSource(programs = null, subsurface = true, volumes = true, bevel = true) {
22
+ // The random walk inside materials and the media inside volumes are compiled in only for a scene that has them: the
23
+ // kernel is bound by its size, and either would cost every other scene a few percent for code that never runs.
24
+ return `const SUBSURFACE_WALK: bool = ${subsurface};\nconst VOLUMES: bool = ${volumes};\nconst BEVEL: bool = ${bevel};\n`
25
+ + COMMON_WGSL + RANDOM_WGSL + BVH_WGSL + SAMPLING_WGSL + TEXTURE_WGSL + SHADER_SUPPORT_WGSL
23
26
  + programsWgsl(programs) + ENVIRONMENT_WGSL + SURFACE_WGSL + BSDF_WGSL + LIGHTS_WGSL + PATH_TRACE_WGSL;
24
27
  }
25
28
  const FRAME_BYTES = FRAME_WORDS * 4;
@@ -30,23 +33,26 @@ export class PathTracePass {
30
33
  uniforms;
31
34
  values = new ArrayBuffer(FRAME_BYTES);
32
35
  bindGroup = null;
33
- programKey = "";
36
+ programKey = "|false|false|false";
34
37
  constructor(device) {
35
38
  this.device = device;
36
- this.pipeline = this.build(null);
39
+ this.pipeline = this.build(null, false, false, false);
37
40
  this.uniforms = device.createBuffer({ size: FRAME_BYTES, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
38
41
  }
39
- /** Recompiles the kernel when the scene's shaders changed; the same set of programs keeps the pipeline it has. */
40
- setPrograms(programs) {
41
- const key = programs?.key ?? "";
42
+ /**
43
+ * Recompiles the kernel when the scene's shaders changed, or whether it has a material that scatters light inside;
44
+ * the same set keeps the pipeline it has.
45
+ */
46
+ setPrograms(programs, subsurface = false, volumes = false, bevel = false) {
47
+ const key = `${programs?.key ?? ""}|${subsurface}|${volumes}|${bevel}`;
42
48
  if (key === this.programKey)
43
49
  return;
44
50
  this.programKey = key;
45
- this.pipeline = this.build(programs);
51
+ this.pipeline = this.build(programs, subsurface, volumes, bevel);
46
52
  this.bindGroup = null;
47
53
  }
48
- build(programs) {
49
- const module = createShaderModule(this.device, "path trace", pathTraceSource(programs));
54
+ build(programs, subsurface, volumes, bevel) {
55
+ const module = createShaderModule(this.device, "path trace", pathTraceSource(programs, subsurface, volumes, bevel));
50
56
  return this.device.createComputePipeline({ layout: "auto", compute: { module, entryPoint: "main" } });
51
57
  }
52
58
  /** Rebinds after the scene or the accumulation buffer was replaced. */
@@ -1 +1 @@
1
- {"version":3,"file":"pathTracePass.js","sourceRoot":"","sources":["../src/pathTracePass.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAuB,MAAM,oBAAoB,CAAC;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAKtD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,WAAkC,IAAI;IACpE,OAAO,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa,GAAG,YAAY,GAAG,mBAAmB;UAC5F,YAAY,CAAC,QAAQ,CAAC,GAAG,gBAAgB,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,eAAe,CAAC;AAC3G,CAAC;AAED,MAAM,WAAW,GAAG,WAAW,GAAG,CAAC,CAAC;AAEpC,MAAM,SAAS,GAAG,CAAC,CAAC;AAEpB,MAAM,OAAO,aAAa;IAOK;IANrB,QAAQ,CAAqB;IACpB,QAAQ,CAAY;IACpB,MAAM,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC;IAC/C,SAAS,GAAwB,IAAI,CAAC;IACtC,UAAU,GAAG,EAAE,CAAC;IAExB,YAA6B,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;QAC5C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtH,CAAC;IAED,kHAAkH;IAClH,WAAW,CAAC,QAA+B;QACzC,MAAM,GAAG,GAAG,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC;QAEhC,IAAI,GAAG,KAAK,IAAI,CAAC,UAAU;YAAE,OAAO;QAEpC,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAEO,KAAK,CAAC,QAA+B;QAC3C,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;QAExF,OAAO,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACxG,CAAC;IAED,uEAAuE;IACvE,WAAW,CAAC,KAAmB,EAAE,YAAuB;QACtD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;YAC3C,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAC3C,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE;gBACnD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE;gBACrD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE;gBACtD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE;gBACnD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE;gBACrD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE;gBACjD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE;gBAClD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE;gBAClD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE;aACrD;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,OAA0B,EAAE,KAAoB;QACrD,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAEhG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,WAAW,CAAC,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAE7D,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,KAAK,CAAC,QAA6B,CAAC;QAEjD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,GAAG,EAAE,CAAC;IACb,CAAC;CACF"}
1
+ {"version":3,"file":"pathTracePass.js","sourceRoot":"","sources":["../src/pathTracePass.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { type BvhWorkerFactory } from "./bvhBuilder.js";
2
+ import { type GpuRenderSettings, type GpuRenderSettingsInput } from "./settings.js";
2
3
  import { type DenoiserSettings } from "./denoise.js";
3
- import { EventEmitter, type Bucket, type RenderCamera, type RenderEnvironment, type RenderImage, type RenderPhase, type RenderPixels, type RenderScene, type RenderSettings, type RenderSettingsInput, type SerializedScene } from "./upstream.js";
4
+ import { EventEmitter, type Bucket, type RenderCamera, type RenderEnvironment, type RenderImage, type RenderPhase, type RenderPixels, type RenderScene, type SerializedScene } from "./upstream.js";
4
5
  export type { RenderCamera, RenderImage, RenderPhase, RenderPixels, RenderScene } from "./upstream.js";
5
6
  /**
6
7
  * The CPU renderer's events, with the same payloads, so a host listens to either renderer the same way. What differs
@@ -42,8 +43,11 @@ export interface GpuRendererOptions {
42
43
  scene?: RenderScene | SerializedScene;
43
44
  /** Defaults to a perspective camera at (5, 5, 5) looking at the origin. */
44
45
  camera?: RenderCamera;
45
- /** Merged over `DEFAULT_RENDER_SETTINGS`, group by group. */
46
- settings?: RenderSettingsInput;
46
+ /**
47
+ * Merged over `DEFAULT_GPU_RENDER_SETTINGS`, group by group: the CPU renderer's settings, and the groups only this
48
+ * renderer reads (`bloom`, `lens`, `camera`, `subsurface`, the roulette under `globalIllumination`).
49
+ */
50
+ settings?: GpuRenderSettingsInput;
47
51
  /** Defaults to `DEFAULT_RENDER_ENVIRONMENT`. */
48
52
  environment?: RenderEnvironment;
49
53
  /** Image size in CSS pixels; the render size also applies `pixelRatio` and `settings.renderScale`. */
@@ -102,11 +106,13 @@ export declare class GpuRenderer extends EventEmitter<GpuRendererEvents> {
102
106
  private planar;
103
107
  private resolve;
104
108
  private denoisePass;
109
+ private lensPass;
105
110
  private denoiserSettings;
106
111
  private finished;
107
112
  private denoised;
108
113
  private denoiseView;
109
114
  private environmentSource;
115
+ private environmentAverage;
110
116
  private environmentImage;
111
117
  private canvas;
112
118
  private context;
@@ -117,7 +123,7 @@ export declare class GpuRenderer extends EventEmitter<GpuRendererEvents> {
117
123
  private bvh;
118
124
  constructor(options: GpuRendererOptions);
119
125
  /** The settings the next frame renders with. */
120
- get settings(): Readonly<RenderSettings>;
126
+ get settings(): Readonly<GpuRenderSettings>;
121
127
  /** How the denoiser filters. */
122
128
  get denoiser(): Readonly<DenoiserSettings>;
123
129
  /**
@@ -153,10 +159,11 @@ export declare class GpuRenderer extends EventEmitter<GpuRendererEvents> {
153
159
  */
154
160
  setCamera(camera: RenderCamera): void;
155
161
  /**
156
- * Merges the given fields into the current settings, group by group. Turning the denoiser on or off also filters the
157
- * finished image again at once, as `setDenoiser` does, since that needs no tracing.
162
+ * Merges the given fields into the current settings, group by group. Turning the denoiser on or off, or changing
163
+ * what is done to the light after it is traced (exposure, tone mapping, vignette, bloom, chromatic aberration, white
164
+ * balance), shows the finished image again at once, as `setDenoiser` does, since none of that needs tracing.
158
165
  */
159
- setSettings(settings: RenderSettingsInput): void;
166
+ setSettings(settings: GpuRenderSettingsInput): void;
160
167
  setEnvironment(environment: RenderEnvironment): void;
161
168
  /** Used by `attachCanvas`; pass `null` to detach. */
162
169
  setOutputCanvas(canvas: HTMLCanvasElement | null): void;
@@ -201,6 +208,11 @@ export declare class GpuRenderer extends EventEmitter<GpuRendererEvents> {
201
208
  private renderCaptures;
202
209
  private configureCanvas;
203
210
  private encodePresent;
211
+ /**
212
+ * The lens and the sensor over the radiance (or the denoiser's output), when the settings ask for any of them: the
213
+ * buffer of graded colour the display transform reads instead, or the input as it was.
214
+ */
215
+ private encodeLens;
204
216
  /** Denoises the accumulation as it stands, for the canvas and for the finished image. */
205
217
  private encodeDenoise;
206
218
  private frameUniforms;
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
package/dist/renderer.js CHANGED
@@ -12,12 +12,17 @@ import { NO_TEXTURE, planTextures, textureEntry, writeTextures } from "./texture
12
12
  import { PathTracePass } from "./pathTracePass.js";
13
13
  import { ImageResolvePass } from "./imageResolve.js";
14
14
  import { PresentPass } from "./presentPass.js";
15
+ import { LensPass, lensEffects } from "./lensPass.js";
16
+ import { DEFAULT_GPU_RENDER_SETTINGS, effectiveExposure, mergeGpuSettings, } from "./settings.js";
17
+ import { bevelOf, bevelRadius, subsurfaceMedium, subsurfaceOf, volumeMedium, volumeOf, } from "./subsurface.js";
18
+ import { containingVolume, NO_MATERIAL, volumeTriangles } from "./volumeContainment.js";
15
19
  import { CONVERGED_ERROR, DEFAULT_DENOISER, DenoisePass, mergeDenoiser, } from "./denoise.js";
16
20
  import { CaptureResolvePass, planarCaptures } from "./planarCapture.js";
17
21
  import { prepareSceneAssets } from "./sceneAssets.js";
18
22
  import { packVolumetricLights, VOLUMETRIC_WORDS } from "./volumetric.js";
19
23
  import { environmentPower, uploadScene } from "./sceneUpload.js";
20
- import { DEFAULT_RENDER_ENVIRONMENT, DEFAULT_RENDER_SETTINGS, EventEmitter, mergeSettings, serializeCamera, serializeScene, srgbToLinear, } from "./upstream.js";
24
+ import { atmosphereExtinction, averageRadiance, brightestSun, gradientAverage } from "./atmosphere.js";
25
+ import { DEFAULT_RENDER_ENVIRONMENT, EventEmitter, serializeCamera, serializeScene, srgbToLinear, } from "./upstream.js";
21
26
  function abortError(message) {
22
27
  return Object.assign(new Error(message), { name: "AbortError" });
23
28
  }
@@ -43,6 +48,8 @@ const SHOW_EVERY_MS = 16;
43
48
  * still stays short enough for the watchdog on its own.
44
49
  */
45
50
  const BANDS_IN_FLIGHT = 2;
51
+ /** Throughput under which Russian roulette may end a path, with the chance of carrying on equal to the throughput. */
52
+ const ROULETTE_THRESHOLD = 0.2;
46
53
  /** How often the canvas takes a freshly denoised image while a frame traces. */
47
54
  const DENOISE_EVERY_MS = 200;
48
55
  /** The most paths per pixel one dispatch takes, while no pixel can stop yet. */
@@ -127,6 +134,7 @@ export class GpuRenderer extends EventEmitter {
127
134
  planar = false;
128
135
  resolve = null;
129
136
  denoisePass = null;
137
+ lensPass = null;
130
138
  denoiserSettings = { ...DEFAULT_DENOISER };
131
139
  // The size of the last frame that finished, which setDenoiser filters again; null while a frame traces.
132
140
  finished = null;
@@ -136,6 +144,8 @@ export class GpuRenderer extends EventEmitter {
136
144
  denoiseView = { pixelScale: 1, orthographic: false };
137
145
  // Reading an environment image is a fetch, so it is started once and awaited by the frame that needs it.
138
146
  environmentSource = "";
147
+ // The surroundings' radiance averaged over the sphere, which the air glows with; null for the gradient.
148
+ environmentAverage = null;
139
149
  environmentImage = Promise.resolve(null);
140
150
  canvas = null;
141
151
  context = null;
@@ -150,7 +160,7 @@ export class GpuRenderer extends EventEmitter {
150
160
  this.width = Math.max(1, Math.floor(options.width));
151
161
  this.height = Math.max(1, Math.floor(options.height));
152
162
  this.pixelRatio = checkedPixelRatio(options.pixelRatio ?? 1);
153
- this.current = mergeSettings(DEFAULT_RENDER_SETTINGS, options.settings);
163
+ this.current = mergeGpuSettings(DEFAULT_GPU_RENDER_SETTINGS, options.settings);
154
164
  this.denoiserSettings = mergeDenoiser(DEFAULT_DENOISER, options.denoiser);
155
165
  this.environment = DEFAULT_RENDER_ENVIRONMENT;
156
166
  this.scheduler = new DispatchScheduler({ maxRows: this.renderHeight, maxSamples: BATCH_PATHS });
@@ -253,13 +263,14 @@ export class GpuRenderer extends EventEmitter {
253
263
  this.camera = camera;
254
264
  }
255
265
  /**
256
- * Merges the given fields into the current settings, group by group. Turning the denoiser on or off also filters the
257
- * finished image again at once, as `setDenoiser` does, since that needs no tracing.
266
+ * Merges the given fields into the current settings, group by group. Turning the denoiser on or off, or changing
267
+ * what is done to the light after it is traced (exposure, tone mapping, vignette, bloom, chromatic aberration, white
268
+ * balance), shows the finished image again at once, as `setDenoiser` does, since none of that needs tracing.
258
269
  */
259
270
  setSettings(settings) {
260
- const denoise = this.current.globalIllumination.denoise;
261
- this.current = mergeSettings(this.current, settings);
262
- if (this.current.globalIllumination.denoise !== denoise)
271
+ const before = developing(this.current);
272
+ this.current = mergeGpuSettings(this.current, settings);
273
+ if (developing(this.current) !== before)
263
274
  this.refilter();
264
275
  }
265
276
  setEnvironment(environment) {
@@ -347,6 +358,8 @@ export class GpuRenderer extends EventEmitter {
347
358
  this.buffers?.destroy();
348
359
  this.accumulator?.destroy();
349
360
  this.denoisePass?.destroy();
361
+ this.lensPass?.destroy();
362
+ this.lensPass = null;
350
363
  this.imageResolve?.dispose();
351
364
  this.imageResolve = null;
352
365
  this.gpu?.device.destroy();
@@ -549,9 +562,14 @@ export class GpuRenderer extends EventEmitter {
549
562
  /** Uploads what changed and makes sure the passes point at the current buffers. */
550
563
  async prepare(gpu, revision, assets, camera, width, height, image) {
551
564
  this.pathTrace ??= new PathTracePass(gpu.device);
552
- this.pathTrace.setPrograms(assets.programs);
565
+ const materials = assets.scene.meshes.flatMap(mesh => mesh.materials);
566
+ this.pathTrace.setPrograms(assets.programs, this.current.subsurface.enabled && materials.some(material => (material.type === "MeshStandardMaterial" || material.type === "MeshPhysicalMaterial")
567
+ && subsurfaceOf(material) !== null),
568
+ // Even turned off, a volume's boundary has to stay invisible, which takes the same code.
569
+ materials.some(material => volumeOf(material) !== null), this.current.bevel.enabled && materials.some(material => bevelOf(material) > 0));
553
570
  // A procedural sky stands in for the renderer's own environment, as it does in the CPU renderer.
554
571
  const environment = assets.sky?.environment ?? image;
572
+ this.environmentAverage = environment ? averageRadiance(environment) : null;
555
573
  const matrices = cameraMatrices(camera, width, height);
556
574
  const view = `${JSON.stringify(camera)}|${width}|${height}`;
557
575
  const moved = (!!this.packed?.cameraDependent || this.planar) && view !== this.packedView;
@@ -642,6 +660,7 @@ export class GpuRenderer extends EventEmitter {
642
660
  skyData,
643
661
  volumetricData,
644
662
  volumetricCount: Math.min(volumetric.length / VOLUMETRIC_WORDS, 8),
663
+ volumes: volumeTriangles(geometry),
645
664
  };
646
665
  }
647
666
  /**
@@ -671,6 +690,10 @@ export class GpuRenderer extends EventEmitter {
671
690
  const uniforms = {
672
691
  ...this.frameUniforms(capture.camera, width, height, assets, target, capture.background),
673
692
  lens: [0, 1, 0, 0],
693
+ lensDistortion: 0,
694
+ // A capture is a texture of the scene, seen again by the camera, which lays the air over it then.
695
+ atmosphereColor: [0, 0, 0, 0],
696
+ cameraVolume: NO_MATERIAL,
674
697
  volumetricCount: 0,
675
698
  clipPlane: capture.clip ?? [0, 0, 0, 0],
676
699
  bandOrigin: [0, 0],
@@ -714,20 +737,31 @@ export class GpuRenderer extends EventEmitter {
714
737
  this.present.setAccumulation(this.accumulator.buffer);
715
738
  }
716
739
  encodePresent(encoder, width, height) {
717
- if (!this.context || !this.present)
740
+ if (!this.context || !this.present || !this.gpu)
718
741
  return;
719
742
  this.present.encode(encoder, this.context.getCurrentTexture().createView(), {
720
743
  width,
721
744
  height,
722
- exposure: this.current.exposure,
745
+ exposure: effectiveExposure(this.current),
723
746
  toneMapping: this.current.toneMapping,
724
747
  vignette: this.current.vignette,
725
748
  grain: this.current.grain,
726
749
  frameIndex: this.frameIndex,
727
750
  transparent: this.current.background.mode === "transparent",
728
- denoised: this.denoised ? this.denoisePass?.output : null,
751
+ denoised: this.encodeLens(this.gpu, encoder, width, height, this.denoised ? this.denoisePass?.output ?? null : null),
729
752
  });
730
753
  }
754
+ /**
755
+ * The lens and the sensor over the radiance (or the denoiser's output), when the settings ask for any of them: the
756
+ * buffer of graded colour the display transform reads instead, or the input as it was.
757
+ */
758
+ encodeLens(gpu, encoder, width, height, denoised) {
759
+ const effects = lensEffects(this.current);
760
+ if (!effects)
761
+ return denoised;
762
+ this.lensPass ??= new LensPass(gpu.device);
763
+ return this.lensPass.encode(encoder, this.accumulator.buffer, denoised, width, height, effects);
764
+ }
731
765
  /** Denoises the accumulation as it stands, for the canvas and for the finished image. */
732
766
  encodeDenoise(gpu, encoder, width, height) {
733
767
  this.denoisePass ??= new DenoisePass(gpu.device);
@@ -750,6 +784,13 @@ export class GpuRenderer extends EventEmitter {
750
784
  ? focalLength / (2 * Math.max(depthOfField.aperture, 1e-3))
751
785
  : 0;
752
786
  const backgroundMode = background.mode === "color" ? 1 : background.mode === "transparent" ? 2 : 0;
787
+ const { atmosphere } = this.current;
788
+ const strength = sky ? sky.intensity : this.environment.intensity ?? 1;
789
+ const airGlow = atmosphere.color
790
+ ? linearColor(atmosphere.color, [0, 0, 0])
791
+ : (this.environmentAverage ?? gradientAverage(linearColor(gradient?.topColor, [1, 1, 1]), linearColor(gradient?.bottomColor, [0, 0, 0]), gradient?.exponent ?? 2)).map(channel => channel * strength);
792
+ const extinction = atmosphereExtinction(atmosphere);
793
+ const sun = brightestSun(assets.scene.lights);
753
794
  return {
754
795
  cameraToWorld: matrices.cameraWorld,
755
796
  worldToCamera: matrices.view,
@@ -776,11 +817,28 @@ export class GpuRenderer extends EventEmitter {
776
817
  resolution: [width, height],
777
818
  cameraKind: matrices.orthographic ? 1 : 0,
778
819
  bounces: Math.max(1, Math.round(this.current.globalIllumination.bounces)),
820
+ rouletteThreshold: this.current.globalIllumination.russianRoulette === false ? 0 : ROULETTE_THRESHOLD,
821
+ rouletteStart: Math.max(0, Math.round(this.current.globalIllumination.rouletteStart ?? 0)),
822
+ lensDistortion: Number.isFinite(this.current.lens.distortion) ? this.current.lens.distortion : 0,
823
+ subsurfaceEnabled: this.current.subsurface.enabled,
824
+ bevelEnabled: this.current.bevel.enabled,
825
+ volumesEnabled: this.current.volumes.enabled,
826
+ cameraVolume: this.current.volumes.enabled
827
+ ? containingVolume(target?.volumes ?? null, matrices.cameraWorld.slice(12, 15))
828
+ : NO_MATERIAL,
829
+ atmosphereColor: [...airGlow, extinction.some(value => value > 0) ? 1 : 0],
830
+ atmosphereExtinction: [...extinction, Math.min(1, Math.max(0, Number(atmosphere.haze) || 0))],
831
+ atmosphereSun: [...sun?.direction ?? [0, 1, 0], 0],
832
+ atmosphereSunColor: [...sun?.irradiance ?? [0, 0, 0], 0],
779
833
  triangleCount: buffers?.triangleCount ?? 0,
780
834
  lightCount: buffers?.lightCount ?? 0,
781
835
  areaLightCount: buffers?.areaLightCount ?? 0,
782
836
  lightCdf: buffers?.lightCdf ?? 0,
783
837
  lightTriangles: buffers?.lightTriangles ?? 0,
838
+ localLightCount: buffers?.localLightCount ?? 0,
839
+ localLightPick: buffers?.localLightPick ?? 0,
840
+ lightTree: this.current.globalIllumination.lightTree === false ? 0 : buffers?.lightTree ?? 0,
841
+ lightLeaves: buffers?.lightLeaves ?? 0,
784
842
  clampIndirect: Math.max(0, this.current.globalIllumination.clamp),
785
843
  // The setting is the angular diameter a light covers, in degrees, as it is for the CPU renderer's shadow blur.
786
844
  shadowSpread: shadows.enabled ? Math.tan(Math.max(0, shadows.softness) * Math.PI / 360) : 0,
@@ -813,11 +871,16 @@ export class GpuRenderer extends EventEmitter {
813
871
  */
814
872
  async readImage(gpu, width, height, denoised) {
815
873
  const accumulator = this.accumulator;
816
- const { exposure, toneMapping, vignette } = this.current;
874
+ const { toneMapping, vignette } = this.current;
875
+ const exposure = effectiveExposure(this.current);
817
876
  const transparent = this.current.background.mode === "transparent";
818
877
  // Resolved on the device, so the page only copies the bytes of the image.
819
878
  this.imageResolve ??= new ImageResolvePass(gpu.device);
820
- const data = await this.imageResolve.read(accumulator.buffer, denoised, width, height, { exposure, toneMapping, vignette, transparent });
879
+ // The lens's effects are encoded on their own, ahead of the resolve, which reads the colour they leave.
880
+ const encoder = gpu.device.createCommandEncoder({ label: "lens" });
881
+ const graded = this.encodeLens(gpu, encoder, width, height, denoised);
882
+ gpu.device.queue.submit([encoder.finish()]);
883
+ const data = await this.imageResolve.read(accumulator.buffer, graded, width, height, { exposure, toneMapping, vignette, transparent });
821
884
  return { width, height, data };
822
885
  }
823
886
  }
@@ -835,6 +898,9 @@ const SERIALIZABLE = new Set([
835
898
  */
836
899
  async function serializeLive(scene) {
837
900
  const renamed = new Map();
901
+ // The snapshot keeps a material's name but not its media, so the name carries a mark to them.
902
+ const named = new Map();
903
+ const media = [];
838
904
  scene.traverse(object => {
839
905
  const value = object.material;
840
906
  for (const material of Array.isArray(value) ? value : value ? [value] : []) {
@@ -843,16 +909,54 @@ async function serializeLive(scene) {
843
909
  renamed.set(material, material.type);
844
910
  material.type = shader.isRawShaderMaterial ? "RawShaderMaterial" : "ShaderMaterial";
845
911
  }
912
+ const data = material.userData?.cpuRenderer;
913
+ if (!named.has(material)
914
+ && (subsurfaceMedium(data?.subsurface) || volumeMedium(data?.volume) || bevelRadius(data?.bevel) > 0)) {
915
+ named.set(material, material.name);
916
+ material.name = `${material.name}${MEDIA_MARK}${media.length}`;
917
+ media.push({ subsurface: data?.subsurface, volume: data?.volume, bevel: data?.bevel });
918
+ }
846
919
  }
847
920
  });
921
+ let snapshot;
848
922
  try {
849
923
  // The path tracer samples only the base level of a texture: the mip chain would be built and thrown away.
850
- return (await serializeScene(scene, { mipmaps: false })).scene;
924
+ snapshot = (await serializeScene(scene, { mipmaps: false })).scene;
851
925
  }
852
926
  finally {
853
927
  for (const [material, type] of renamed)
854
928
  material.type = type;
929
+ for (const [material, name] of named)
930
+ material.name = name;
931
+ }
932
+ // Materials are shared between the meshes that use them, so each one is unmarked once and seen marked no more.
933
+ for (const mesh of snapshot.meshes) {
934
+ for (const material of mesh.materials) {
935
+ const at = material.name.lastIndexOf(MEDIA_MARK);
936
+ if (at < 0)
937
+ continue;
938
+ const medium = media[Number(material.name.slice(at + MEDIA_MARK.length))];
939
+ material.name = material.name.slice(0, at) || material.type;
940
+ if (medium.subsurface !== undefined)
941
+ material.subsurface = medium.subsurface;
942
+ if (medium.volume !== undefined)
943
+ material.volume = medium.volume;
944
+ if (medium.bevel !== undefined)
945
+ material.bevel = medium.bevel;
946
+ }
855
947
  }
948
+ return snapshot;
949
+ }
950
+ /** Ends a material's name while it is serialized, followed by the index of its media. */
951
+ const MEDIA_MARK = "\u0000media:";
952
+ /**
953
+ * Everything that changes the finished image without tracing it again, as one string: the denoiser switch and what
954
+ * happens to the light between the radiance and the screen.
955
+ */
956
+ function developing(settings) {
957
+ const { exposure, toneMapping, vignette, bloom, glare, lens, camera, depthOfField, globalIllumination } = settings;
958
+ return JSON.stringify([globalIllumination.denoise, exposure, toneMapping, vignette, bloom, glare,
959
+ lens.chromaticAberration, camera, camera.physicalExposure ? depthOfField.aperture : 0]);
856
960
  }
857
961
  /**
858
962
  * The summed coefficients of every LightProbe the renderer would draw, times its intensity, as Three's WebGLLights sums