@tinypoly/gpu-renderer 0.2.4 → 0.2.5

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.
@@ -17,6 +17,8 @@ export interface LensEffects {
17
17
  autoExposure: boolean;
18
18
  /** The share of a dark scene's darkness the meter keeps, `0` to `1`. */
19
19
  darkAdaptation: number;
20
+ /** What the image is multiplied by after the lens, the meter's own exposure aside: the rays are limited against it. */
21
+ exposure: number;
20
22
  }
21
23
  /** The lens effects these settings ask for, or `null` when they ask for none and the pass can be skipped. */
22
24
  export declare function lensEffects(settings: GpuRenderSettings): LensEffects | null;
@@ -1 +1 @@
1
- {"version":3,"file":"lensPass.d.ts","sourceRoot":"","sources":["../src/lensPass.ts"],"names":[],"mappings":"AACA,OAAO,EAA6C,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAclG,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,+GAA+G;IAC/G,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC9B,4FAA4F;IAC5F,YAAY,EAAE,OAAO,CAAC;IACtB,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,6GAA6G;AAC7G,wBAAgB,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,WAAW,GAAG,IAAI,CAyB3E;AAED,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yGAAyG;AACzG,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,CAepE;AAOD;;;GAGG;AACH,qBAAa,QAAQ;IAiBP,OAAO,CAAC,QAAQ,CAAC,MAAM;IAhBnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,0GAA0G;IAC1G,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,IAAI,CAAM;gBAEW,MAAM,EAAE,SAAS;IA6B9C,kFAAkF;IAClF,IAAI,MAAM,IAAI,SAAS,GAAG,IAAI,CAE7B;IAED,OAAO,CAAC,MAAM;IAwBd,OAAO,CAAC,OAAO;IAUf;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EACnG,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,SAAS;IAqHlD,OAAO,CAAC,cAAc;IAQtB,OAAO;CAMR"}
1
+ {"version":3,"file":"lensPass.d.ts","sourceRoot":"","sources":["../src/lensPass.ts"],"names":[],"mappings":"AACA,OAAO,EAAgE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAcrH,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,+GAA+G;IAC/G,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC9B,4FAA4F;IAC5F,YAAY,EAAE,OAAO,CAAC;IACtB,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC;IACvB,uHAAuH;IACvH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,6GAA6G;AAC7G,wBAAgB,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,WAAW,GAAG,IAAI,CA0B3E;AAED,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yGAAyG;AACzG,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,CAepE;AAOD;;;GAGG;AACH,qBAAa,QAAQ;IAiBP,OAAO,CAAC,QAAQ,CAAC,MAAM;IAhBnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,0GAA0G;IAC1G,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,IAAI,CAAM;gBAEW,MAAM,EAAE,SAAS;IA6B9C,kFAAkF;IAClF,IAAI,MAAM,IAAI,SAAS,GAAG,IAAI,CAE7B;IAED,OAAO,CAAC,MAAM;IAwBd,OAAO,CAAC,OAAO;IAUf;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EACnG,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,SAAS;IAuHlD,OAAO,CAAC,cAAc;IAQtB,OAAO;CAMR"}
package/dist/lensPass.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createShaderModule } from "./shaderModule.js";
2
- import { NEUTRAL_WHITE_BALANCE, whiteBalanceMatrix } from "./settings.js";
2
+ import { effectiveExposure, NEUTRAL_WHITE_BALANCE, whiteBalanceMatrix } from "./settings.js";
3
3
  import { LENS_WGSL } from "./wgsl/lens.wgsl.js";
4
4
  const UNIFORM_BYTES = 160;
5
5
  const WORKGROUP = 8;
@@ -31,6 +31,7 @@ export function lensEffects(settings) {
31
31
  whiteBalance: neutral ? null : whiteBalanceMatrix(camera.whiteBalance),
32
32
  autoExposure,
33
33
  darkAdaptation: Math.min(1, Math.max(0, Number(camera.darkAdaptation) || 0)),
34
+ exposure: Math.max(effectiveExposure(settings), 0),
34
35
  };
35
36
  }
36
37
  /** Halved levels of the image, the largest first, until one would be too small to be worth filtering. */
@@ -159,6 +160,7 @@ export class LensPass {
159
160
  floats[34] = effects.glareAngle;
160
161
  floats[35] = effects.autoExposure ? 1 : 0;
161
162
  floats[36] = effects.darkAdaptation;
163
+ floats[37] = effects.exposure;
162
164
  for (let row = 0; row < 3; row++)
163
165
  for (let column = 0; column < 3; column++)
164
166
  floats[20 + row * 4 + column] = white[row * 3 + column];
@@ -193,6 +195,10 @@ export class LensPass {
193
195
  integers[9] = level.height;
194
196
  integers[10] = level.offset;
195
197
  };
198
+ // The meter is one workgroup, whatever the size: dispatched as a single tile of the grid it reads. It goes first,
199
+ // since the rays are limited against the exposure it finds.
200
+ if (effects.autoExposure)
201
+ dispatch(this.meter, { width: 1, height: 1 }, () => { });
196
202
  // The rays are gathered from a level of the same pyramid, so either effect builds it.
197
203
  if (effects.bloom > 0 || effects.glare > 0) {
198
204
  levels.forEach((level, k) => dispatch(this.downsample, level, () => {
@@ -226,9 +232,6 @@ export class LensPass {
226
232
  encoder.copyBufferToBuffer(this.down, 0, this.up, 0, levels[0].width * levels[0].height * 16);
227
233
  }
228
234
  }
229
- // The meter is one workgroup, whatever the size: dispatched as a single tile of the grid it reads.
230
- if (effects.autoExposure)
231
- dispatch(this.meter, { width: 1, height: 1 }, () => { });
232
235
  dispatch(this.composite, { width, height }, () => { });
233
236
  return this.graded;
234
237
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lensPass.js","sourceRoot":"","sources":["../src/lensPass.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAA0B,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,MAAM,SAAS,GAAG,CAAC,CAAC;AAEpB,0GAA0G;AAC1G,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,MAAM,UAAU,GAAG,CAAC,CAAC;AAErB,2GAA2G;AAC3G,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAsB/B,6GAA6G;AAC7G,MAAM,UAAU,WAAW,CAAC,QAA2B;IACrD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;IAChD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC,GAAG,gBAAgB,CAAC;IAC5E,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,MAAM,CAAC,YAAY,KAAK,qBAAqB,CAAC;IACvG,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhF,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,KAAK,IAAI,CAAC;IAElD,IAAI,SAAS,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAE/F,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACjD,UAAU;QACV,KAAK,EAAE,OAAO;QACd,oGAAoG;QACpG,IAAI,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;QAC5C,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAChE,UAAU,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG;QACzD,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,YAAY,CAAC;QACtE,YAAY;QACZ,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;KAC7E,CAAC;AACJ,CAAC;AASD,yGAAyG;AACzG,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,MAAc;IACzD,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC;IAEtC,OAAO,MAAM,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;QAClC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAElC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,cAAc;YAAE,MAAM;QAEhE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7C,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,iGAAiG;AACjG,SAAS,WAAW,CAAC,MAAe;IAClC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,QAAQ;IAiBU;IAhBZ,MAAM,CAAqB;IAC3B,UAAU,CAAqB;IAC/B,QAAQ,CAAqB;IAC7B,SAAS,CAAqB;IAC9B,OAAO,CAAqB;IAC5B,KAAK,CAAqB;IAC1B,OAAO,CAAY;IACpC,0GAA0G;IACzF,QAAQ,GAAgB,EAAE,CAAC;IAC3B,MAAM,GAAG,IAAI,WAAW,CAAC,aAAa,CAAC,CAAC;IACjD,IAAI,GAAqB,IAAI,CAAC;IAC9B,EAAE,GAAqB,IAAI,CAAC;IAC5B,MAAM,GAAqB,IAAI,CAAC;IAChC,QAAQ,GAAqB,IAAI,CAAC;IAClC,IAAI,GAAG,EAAE,CAAC;IAElB,YAA6B,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;QAC5C,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,CAAC,IAA0B,EAAqC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9F,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,qBAAqB,CAAC;YACzC,KAAK,EAAE,MAAM;YACb,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;gBAC/E,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE;gBACxF,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE;gBACxF,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE;gBAC9E,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE;gBAC9E,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE;gBAC9E,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE;gBAC9E,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE;aAC/E;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,CAAC,oBAAoB,CAAC,EAAE,gBAAgB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChF,MAAM,QAAQ,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAEnH,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC;IACvG,CAAC;IAED,kFAAkF;IAClF,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEO,MAAM,CAAC,KAAa,EAAE,MAAc,EAAE,MAAe;QAC3D,MAAM,GAAG,GAAG,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;QAEjC,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAE7C,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAEhB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACnE,8FAA8F;QAC9F,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC;QAEzF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1F,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACrF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,EAAE;YACtF,KAAK,EAAE,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC;QAEnC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAEnC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE;YACpG,KAAK,EAAE,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC;IACrC,CAAC;IAEO,OAAO,CAAC,KAAa;QAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;YACrC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC1C,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,QAAQ;aAC7E,CAAC,CAAC,CAAC;QACN,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAA0B,EAAE,YAAuB,EAAE,QAA0B,EAAE,KAAa,EACnG,MAAc,EAAE,OAAoB;QACpC,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAE5C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAEnC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtF,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,IAAI,GAAG,CAAC,CAAC;QAEb,MAAM,QAAQ,GAAG,CAAC,QAA4B,EAAE,MAAyC,EACvF,IAAgB,EAAE,EAAE;YACpB,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;YACpB,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;YACrB,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/B,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;YAC1B,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;YAC3B,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YAC5B,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;YAChC,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;YAC3B,QAAQ,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YAC5B,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/E,QAAQ,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;YAC5B,QAAQ,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;YAC7B,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;YAChC,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;YACpC,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE;gBAAE,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE;oBACzE,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;YAC1D,IAAI,EAAE,CAAC;YAEP,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAEpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAEtD,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAEzD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3B,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;gBAC/C,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,OAAO,EAAE;oBACP,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE;oBACpC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE;oBAClD,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,QAAQ,IAAI,YAAY,EAAE,EAAE;oBAC9D,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAiB,EAAE,EAAE;oBAC5D,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAe,EAAE,EAAE;oBAC1D,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAmB,EAAE,EAAE;oBAC9D,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,QAAqB,EAAE,EAAE;oBAChE,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE;iBACnD;aACF,CAAC,CAAC,CAAC;YACJ,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;YACnG,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,CAAC,CAAC;QAEF,MAAM,IAAI,GAAG,CAAC,KAAwD,EAAE,EAAE;YACxE,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;YAC1B,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;YAC3B,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QAC7B,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,CAAC,KAAY,EAAE,EAAE;YAC7B,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;YAC1B,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;YAC3B,QAAQ,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QAC9B,CAAC,CAAC;QAEF,sFAAsF;QACtF,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE;gBACjE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBACZ,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;oBACnC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAClB,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACtB,CAAC;gBAED,KAAK,CAAC,KAAK,CAAC,CAAC;YACf,CAAC,CAAC,CAAC,CAAC;QACN,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YACtB,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE;gBAClC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACb,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YACtB,uGAAuG;YACvG,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE;oBACtC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACpB,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC9C,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC;YAED,iFAAiF;YACjF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAiB,EAAE,CAAC,EAAE,IAAI,CAAC,EAAe,EAAE,CAAC,EAC3E,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,mGAAmG;QACnG,IAAI,OAAO,CAAC,YAAY;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAElF,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAEtD,OAAO,IAAI,CAAC,MAAmB,CAAC;IAClC,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC;QACnB,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACvB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QACrD,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,CAAC;CACF"}
1
+ {"version":3,"file":"lensPass.js","sourceRoot":"","sources":["../src/lensPass.ts"],"names":[],"mappings":"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"}
@@ -13,5 +13,5 @@
13
13
  * texel takes the light of the texels behind it along every ray's direction, fading with the distance, with weights
14
14
  * that again sum to one.
15
15
  */
16
- export declare const LENS_WGSL = "\nstruct Lens {\n resolution: vec2<u32>,\n // Whether the colour comes from the denoiser's output rather than straight from the accumulation.\n denoised: u32,\n // Upsampling only: the level read from sits in the downsampled pyramid (the smallest one) instead of the folded one.\n fromDown: u32,\n sourceSize: vec2<u32>,\n // Where the level read from starts in its pyramid; a size of the full resolution reads the image itself.\n sourceOffset: u32,\n // The first downsample reads the image itself, and averages its taps by luminance against fireflies.\n fromImage: u32,\n targetSize: vec2<u32>,\n targetOffset: u32,\n // Where the largest level of the folded pyramid starts, which the composite reads the halo from.\n haloOffset: u32,\n haloSize: vec2<u32>,\n // How much of the light the halo takes, and how much each level takes from the one below it.\n intensity: f32,\n radius: f32,\n // How far red and blue move apart at the corners, as a share of the distance from the centre.\n aberration: f32,\n // How much of the light the aperture's rays take, how many there are, and how far they reach in streak texels.\n glare: f32,\n rays: u32,\n glareLength: f32,\n // The white balance, a linear sRGB matrix, row by row.\n white0: vec4<f32>,\n white1: vec4<f32>,\n white2: vec4<f32>,\n // The size of the level the rays are gathered at, and the angle of the first ray, in radians.\n streakSize: vec2<u32>,\n glareAngle: f32,\n // Whether the camera meters the image and exposes it to middle grey, which the meter pass works out.\n autoExposure: f32,\n // The share of a dark scene's darkness the meter keeps.\n darkAdaptation: f32,\n};\n\nconst PI: f32 = 3.14159265358979;\n\n/** Taps along each of the aperture's rays. */\nconst STREAK_TAPS: i32 = 24;\n\n@group(0) @binding(0) var<uniform> lens: Lens;\n@group(0) @binding(1) var<storage, read> accumulation: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read> denoised: array<vec4<f32>>;\n@group(0) @binding(3) var<storage, read_write> down: array<vec4<f32>>;\n@group(0) @binding(4) var<storage, read_write> up: array<vec4<f32>>;\n@group(0) @binding(5) var<storage, read_write> graded: array<vec4<f32>>;\n@group(0) @binding(6) var<storage, read_write> streaked: array<vec4<f32>>;\n// What the camera's meter read: the exposure that brings the image's average to middle grey, in x.\n@group(0) @binding(7) var<storage, read_write> metered: array<vec4<f32>>;\n\n/** What a light meter calibrates to: an average scene reflects about eighteen percent. */\nconst MIDDLE_GREY: f32 = 0.18;\nconst METER_GRID: vec2<u32> = vec2<u32>(64u, 36u);\nconst METER_THREADS: u32 = 256u;\n\n/**\n * How far above middle grey the meter lets the bright end of the image land: three stops, where AgX still shows\n * detail, three and a half under where it reaches white.\n */\nconst HIGHLIGHT_CEILING: f32 = 8.0;\n/** The share of the metered points that counts as the bright end: the light through a window, not a lamp's own pixels. */\nconst HIGHLIGHT_SHARE: f32 = 0.03;\n/**\n * The average below which a scene counts as dark: about three stops under middle grey, a room lit by a window on a\n * grey day. Above it the meter exposes fully; below it, only for the stops the dark adaptation lets go.\n */\nconst DIM_AVERAGE: f32 = 0.02;\n/** Half stops of luminance, from 2^-16 to 2^16, which the bright end is found in. */\nconst METER_BINS: u32 = 64u;\n\nvar<workgroup> meterSums: array<vec2<f32>, 256>;\nvar<workgroup> meterHistogram: array<atomic<u32>, 64>;\n\n/**\n * The camera's meter: the image's average luminance over a grid of points, taken as the mean of the logarithms so that\n * a bright window or a patch of sky cannot darken everything else, weighed towards the centre as a camera's\n * centre-weighted metering is. What no path has reached yet, or is black, does not count. One workgroup reads the\n * grid and sums it in shared memory.\n *\n * Then it guards the highlights, as a camera's matrix metering does: the average alone takes a dim attic with a shaft\n * of sun in it to middle grey and burns the shaft out, where a photographer keeps the room dim. The brightest few\n * percent of the points, found in a histogram of half stops, may land no more than {@link HIGHLIGHT_CEILING} times\n * brighter; an even scene, whose bright end is close to its average, is left as the average says.\n */\n@compute @workgroup_size(256, 1, 1)\nfn meter(@builtin(local_invocation_index) thread: u32) {\n var sum = vec2<f32>(0.0);\n let count = METER_GRID.x * METER_GRID.y;\n\n if (thread < METER_BINS) {\n atomicStore(&meterHistogram[thread], 0u);\n }\n\n workgroupBarrier();\n\n for (var k = thread; k < count; k = k + METER_THREADS) {\n let cell = vec2<f32>(f32(k % METER_GRID.x), f32(k / METER_GRID.x)) + 0.5;\n let uv = cell / vec2<f32>(METER_GRID);\n let luminance = dot(imageTexel(i32(uv.x * f32(lens.resolution.x)), i32(uv.y * f32(lens.resolution.y))),\n vec3<f32>(0.2126, 0.7152, 0.0722));\n let away = (uv - 0.5) * 2.0;\n let weight = select(0.0, 1.0 - 0.6 * min(dot(away, away) * 0.5, 1.0), luminance > 0.0);\n\n sum = sum + vec2<f32>(log(max(luminance, 1e-6)) * weight, weight);\n\n if (luminance > 0.0) {\n let bin = u32(clamp((log2(luminance) + 16.0) * 2.0, 0.0, f32(METER_BINS - 1u)));\n\n atomicAdd(&meterHistogram[bin], 1u);\n }\n }\n\n meterSums[thread] = sum;\n workgroupBarrier();\n\n for (var stride = METER_THREADS / 2u; stride > 0u; stride = stride / 2u) {\n if (thread < stride) {\n meterSums[thread] = meterSums[thread] + meterSums[thread + stride];\n }\n\n workgroupBarrier();\n }\n\n if (thread == 0u) {\n let total = meterSums[0];\n let average = select(MIDDLE_GREY, exp(total.x / max(total.y, 1e-6)), total.y > 0.0);\n var exposure = MIDDLE_GREY / average;\n\n // A dark scene keeps a share of its missing stops: a night stays a night instead of turning into dusk.\n if (average < DIM_AVERAGE) {\n exposure = exposure * pow(average / DIM_AVERAGE, lens.darkAdaptation);\n }\n\n // From the top down, the first half stop by which the bright share is reached; its upper edge is that end.\n var points = 0u;\n\n for (var bin = 0u; bin < METER_BINS; bin = bin + 1u) {\n points = points + atomicLoad(&meterHistogram[bin]);\n }\n\n var above = 0u;\n var bright = 0.0;\n\n for (var bin = i32(METER_BINS) - 1; bin >= 0 && points > 0u; bin = bin - 1) {\n above = above + atomicLoad(&meterHistogram[u32(bin)]);\n\n if (f32(above) >= HIGHLIGHT_SHARE * f32(points)) {\n bright = exp2(f32(bin + 1) * 0.5 - 16.0);\n break;\n }\n }\n\n if (bright > 0.0) {\n exposure = min(exposure, HIGHLIGHT_CEILING * MIDDLE_GREY / bright);\n }\n\n metered[0] = vec4<f32>(clamp(exposure, 1e-4, 1e4), average, bright, 0.0);\n }\n}\n\n/** The image's own texel: its mean so far, or nothing where no path has landed yet. */\nfn imageTexel(x: i32, y: i32) -> vec3<f32> {\n let size = vec2<i32>(lens.resolution);\n let index = u32(clamp(y, 0, size.y - 1) * size.x + clamp(x, 0, size.x - 1));\n\n if (lens.denoised != 0u) {\n return denoised[index].rgb;\n }\n\n let stored = accumulation[index];\n\n return select(stored.rgb / stored.w, vec3<f32>(0.0), stored.w <= 0.0);\n}\n\nfn downTexel(offset: u32, size: vec2<u32>, x: i32, y: i32) -> vec3<f32> {\n let s = vec2<i32>(size);\n\n return down[offset + u32(clamp(y, 0, s.y - 1) * s.x + clamp(x, 0, s.x - 1))].rgb;\n}\n\nfn upTexel(offset: u32, size: vec2<u32>, x: i32, y: i32) -> vec3<f32> {\n let s = vec2<i32>(size);\n\n return up[offset + u32(clamp(y, 0, s.y - 1) * s.x + clamp(x, 0, s.x - 1))].rgb;\n}\n\n/** Bilinear weights and the texel below and left of a point given in texels, edges clamped. */\nfn bilinearAt(position: vec2<f32>) -> vec4<f32> {\n let p = position - 0.5;\n let base = floor(p);\n\n return vec4<f32>(base, p - base);\n}\n\nfn imageBilinear(position: vec2<f32>) -> vec3<f32> {\n let b = bilinearAt(position);\n let x = i32(b.x);\n let y = i32(b.y);\n\n return mix(\n mix(imageTexel(x, y), imageTexel(x + 1, y), b.z),\n mix(imageTexel(x, y + 1), imageTexel(x + 1, y + 1), b.z), b.w);\n}\n\nfn downBilinear(offset: u32, size: vec2<u32>, position: vec2<f32>) -> vec3<f32> {\n let b = bilinearAt(position);\n let x = i32(b.x);\n let y = i32(b.y);\n\n return mix(\n mix(downTexel(offset, size, x, y), downTexel(offset, size, x + 1, y), b.z),\n mix(downTexel(offset, size, x, y + 1), downTexel(offset, size, x + 1, y + 1), b.z), b.w);\n}\n\nfn upBilinear(offset: u32, size: vec2<u32>, position: vec2<f32>) -> vec3<f32> {\n let b = bilinearAt(position);\n let x = i32(b.x);\n let y = i32(b.y);\n\n return mix(\n mix(upTexel(offset, size, x, y), upTexel(offset, size, x + 1, y), b.z),\n mix(upTexel(offset, size, x, y + 1), upTexel(offset, size, x + 1, y + 1), b.z), b.w);\n}\n\n/** The level being filtered, read bilinearly at a point given in its own texels. */\nfn sourceAt(position: vec2<f32>) -> vec3<f32> {\n if (lens.fromImage != 0u) {\n return imageBilinear(position);\n }\n\n return downBilinear(lens.sourceOffset, lens.sourceSize, position);\n}\n\nfn luminance(color: vec3<f32>) -> f32 {\n return dot(color, vec3<f32>(0.2126, 0.7152, 0.0722));\n}\n\n/** Karis' average: a group of taps weighed by one over one plus its luminance, so a lone firefly cannot flare. */\nfn karis(sum: vec3<f32>) -> vec4<f32> {\n let weight = 1.0 / (1.0 + luminance(sum));\n\n return vec4<f32>(sum * weight, weight);\n}\n\n/** One level of the pyramid from the one above it: Jimenez's 13 taps, four overlapping boxes and a centre one. */\n@compute @workgroup_size(8, 8, 1)\nfn downsample(@builtin(global_invocation_id) id: vec3<u32>) {\n if (id.x >= lens.targetSize.x || id.y >= lens.targetSize.y) {\n return;\n }\n\n let scale = vec2<f32>(lens.sourceSize) / vec2<f32>(lens.targetSize);\n let centre = (vec2<f32>(id.xy) + 0.5) * scale;\n let a = sourceAt(centre + vec2<f32>(-2.0, -2.0));\n let b = sourceAt(centre + vec2<f32>(0.0, -2.0));\n let c = sourceAt(centre + vec2<f32>(2.0, -2.0));\n let d = sourceAt(centre + vec2<f32>(-2.0, 0.0));\n let e = sourceAt(centre);\n let f = sourceAt(centre + vec2<f32>(2.0, 0.0));\n let g = sourceAt(centre + vec2<f32>(-2.0, 2.0));\n let h = sourceAt(centre + vec2<f32>(0.0, 2.0));\n let i = sourceAt(centre + vec2<f32>(2.0, 2.0));\n let j = sourceAt(centre + vec2<f32>(-1.0, -1.0));\n let k = sourceAt(centre + vec2<f32>(1.0, -1.0));\n let l = sourceAt(centre + vec2<f32>(-1.0, 1.0));\n let m = sourceAt(centre + vec2<f32>(1.0, 1.0));\n var result: vec3<f32>;\n\n if (lens.fromImage != 0u) {\n let groups = karis((j + k + l + m) * 0.25) * 0.5\n + karis((a + b + d + e) * 0.25) * 0.125\n + karis((b + c + e + f) * 0.25) * 0.125\n + karis((d + e + g + h) * 0.25) * 0.125\n + karis((e + f + h + i) * 0.25) * 0.125;\n\n result = groups.rgb / max(groups.w, 1e-6);\n } else {\n result = e * 0.125 + (a + c + g + i) * 0.03125 + (b + d + f + h) * 0.0625 + (j + k + l + m) * 0.125;\n }\n\n down[lens.targetOffset + id.y * lens.targetSize.x + id.x] = vec4<f32>(max(result, vec3<f32>(0.0)), 1.0);\n}\n\n/** A 3 x 3 tent over the smaller level, read at a point given in its texels. */\nfn tent(position: vec2<f32>) -> vec3<f32> {\n var sum = vec3<f32>(0.0);\n\n for (var dy = -1; dy <= 1; dy = dy + 1) {\n for (var dx = -1; dx <= 1; dx = dx + 1) {\n let weight = f32((2 - abs(dx)) * (2 - abs(dy))) / 16.0;\n let at = position + vec2<f32>(f32(dx), f32(dy));\n\n if (lens.fromDown != 0u) {\n sum = sum + downBilinear(lens.sourceOffset, lens.sourceSize, at) * weight;\n } else {\n sum = sum + upBilinear(lens.sourceOffset, lens.sourceSize, at) * weight;\n }\n }\n }\n\n return sum;\n}\n\n/** One level folded back: its own light, mixed by the radius with the wider spread of every level below it. */\n@compute @workgroup_size(8, 8, 1)\nfn upsample(@builtin(global_invocation_id) id: vec3<u32>) {\n if (id.x >= lens.targetSize.x || id.y >= lens.targetSize.y) {\n return;\n }\n\n let scale = vec2<f32>(lens.sourceSize) / vec2<f32>(lens.targetSize);\n let wider = tent((vec2<f32>(id.xy) + 0.5) * scale);\n let index = lens.targetOffset + id.y * lens.targetSize.x + id.x;\n\n up[index] = vec4<f32>(mix(down[index].rgb, wider, lens.radius), 1.0);\n}\n\n/** The aperture's rays at one texel of the streak level: the light behind it along each ray, fading with distance. */\n@compute @workgroup_size(8, 8, 1)\nfn streaks(@builtin(global_invocation_id) id: vec3<u32>) {\n if (id.x >= lens.targetSize.x || id.y >= lens.targetSize.y) {\n return;\n }\n\n let centre = vec2<f32>(id.xy) + 0.5;\n var sum = vec3<f32>(0.0);\n var total = 0.0;\n\n for (var r = 0u; r < lens.rays; r = r + 1u) {\n let angle = lens.glareAngle + f32(r) * 2.0 * PI / f32(lens.rays);\n let along = vec2<f32>(cos(angle), sin(angle));\n\n for (var j = 1; j <= STREAK_TAPS; j = j + 1) {\n let t = f32(j) / f32(STREAK_TAPS);\n let weight = exp(-4.0 * t);\n\n sum = sum + downBilinear(lens.sourceOffset, lens.sourceSize, centre - along * (t * lens.glareLength)) * weight;\n total = total + weight;\n }\n }\n\n streaked[id.y * lens.targetSize.x + id.x] = vec4<f32>(sum / max(total, 1e-6), 1.0);\n}\n\nfn streakTexel(x: i32, y: i32) -> vec3<f32> {\n let s = vec2<i32>(lens.streakSize);\n\n return streaked[u32(clamp(y, 0, s.y - 1) * s.x + clamp(x, 0, s.x - 1))].rgb;\n}\n\nfn streakBilinear(position: vec2<f32>) -> vec3<f32> {\n let b = bilinearAt(position);\n let x = i32(b.x);\n let y = i32(b.y);\n\n return mix(mix(streakTexel(x, y), streakTexel(x + 1, y), b.z), mix(streakTexel(x, y + 1), streakTexel(x + 1, y + 1), b.z), b.w);\n}\n\n/** The image as the lens delivers it: fringed towards the corners, with its halo, balanced for the camera's white. */\n@compute @workgroup_size(8, 8, 1)\nfn composite(@builtin(global_invocation_id) id: vec3<u32>) {\n if (id.x >= lens.resolution.x || id.y >= lens.resolution.y) {\n return;\n }\n\n let size = vec2<f32>(lens.resolution);\n let position = vec2<f32>(id.xy) + 0.5;\n var color = imageTexel(i32(id.x), i32(id.y));\n\n // Lateral chromatic aberration: each colour is magnified a little differently, red outwards and blue inwards,\n // in proportion to the distance from the centre, which is how a lens's dispersion moves them.\n if (lens.aberration > 0.0) {\n let centre = size * 0.5;\n let away = position - centre;\n let red = imageBilinear(centre + away * (1.0 - lens.aberration));\n let blue = imageBilinear(centre + away * (1.0 + lens.aberration));\n\n color = vec3<f32>(red.r, color.g, blue.b);\n }\n\n if (lens.intensity > 0.0) {\n // The largest folded level is already a tent over the levels below it, so one bilinear read of it is smooth.\n let halo = upBilinear(lens.haloOffset, lens.haloSize, position * vec2<f32>(lens.haloSize) / size);\n\n color = mix(color, halo, lens.intensity);\n }\n\n if (lens.glare > 0.0) {\n color = mix(color, streakBilinear(position * vec2<f32>(lens.streakSize) / size), lens.glare);\n }\n\n if (lens.autoExposure > 0.0) {\n color = color * metered[0].x;\n }\n\n let balanced = vec3<f32>(dot(lens.white0.xyz, color), dot(lens.white1.xyz, color), dot(lens.white2.xyz, color));\n\n graded[id.y * lens.resolution.x + id.x] = vec4<f32>(max(balanced, vec3<f32>(0.0)), 1.0);\n}\n";
16
+ export declare const LENS_WGSL = "\nstruct Lens {\n resolution: vec2<u32>,\n // Whether the colour comes from the denoiser's output rather than straight from the accumulation.\n denoised: u32,\n // Upsampling only: the level read from sits in the downsampled pyramid (the smallest one) instead of the folded one.\n fromDown: u32,\n sourceSize: vec2<u32>,\n // Where the level read from starts in its pyramid; a size of the full resolution reads the image itself.\n sourceOffset: u32,\n // The first downsample reads the image itself, and averages its taps by luminance against fireflies.\n fromImage: u32,\n targetSize: vec2<u32>,\n targetOffset: u32,\n // Where the largest level of the folded pyramid starts, which the composite reads the halo from.\n haloOffset: u32,\n haloSize: vec2<u32>,\n // How much of the light the halo takes, and how much each level takes from the one below it.\n intensity: f32,\n radius: f32,\n // How far red and blue move apart at the corners, as a share of the distance from the centre.\n aberration: f32,\n // How much of the light the aperture's rays take, how many there are, and how far they reach in streak texels.\n glare: f32,\n rays: u32,\n glareLength: f32,\n // The white balance, a linear sRGB matrix, row by row.\n white0: vec4<f32>,\n white1: vec4<f32>,\n white2: vec4<f32>,\n // The size of the level the rays are gathered at, and the angle of the first ray, in radians.\n streakSize: vec2<u32>,\n glareAngle: f32,\n // Whether the camera meters the image and exposes it to middle grey, which the meter pass works out.\n autoExposure: f32,\n // The share of a dark scene's darkness the meter keeps.\n darkAdaptation: f32,\n // The exposure applied after the lens, the meter's aside, which the rays are limited against.\n exposure: f32,\n};\n\nconst PI: f32 = 3.14159265358979;\n\n/** Taps along each of the aperture's rays. */\nconst STREAK_TAPS: i32 = 24;\n\n/**\n * The brightest a tap of the rays counts as, in multiples of the exposed white. A lamp is thousands of times white,\n * which would carry its rays across the frame at full length; past this they stay as short as a camera shows them.\n */\nconst GLARE_CEILING: f32 = 4.0;\n\n@group(0) @binding(0) var<uniform> lens: Lens;\n@group(0) @binding(1) var<storage, read> accumulation: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read> denoised: array<vec4<f32>>;\n@group(0) @binding(3) var<storage, read_write> down: array<vec4<f32>>;\n@group(0) @binding(4) var<storage, read_write> up: array<vec4<f32>>;\n@group(0) @binding(5) var<storage, read_write> graded: array<vec4<f32>>;\n@group(0) @binding(6) var<storage, read_write> streaked: array<vec4<f32>>;\n// What the camera's meter read: the exposure that brings the image's average to middle grey, in x.\n@group(0) @binding(7) var<storage, read_write> metered: array<vec4<f32>>;\n\n/** What a light meter calibrates to: an average scene reflects about eighteen percent. */\nconst MIDDLE_GREY: f32 = 0.18;\nconst METER_GRID: vec2<u32> = vec2<u32>(64u, 36u);\nconst METER_THREADS: u32 = 256u;\n\n/**\n * How far above middle grey the meter lets the bright end of the image land: three stops, where AgX still shows\n * detail, three and a half under where it reaches white.\n */\nconst HIGHLIGHT_CEILING: f32 = 8.0;\n/** The share of the metered points that counts as the bright end: the light through a window, not a lamp's own pixels. */\nconst HIGHLIGHT_SHARE: f32 = 0.03;\n/**\n * The average below which a scene counts as dark: about three stops under middle grey, a room lit by a window on a\n * grey day. Above it the meter exposes fully; below it, only for the stops the dark adaptation lets go.\n */\nconst DIM_AVERAGE: f32 = 0.02;\n/** Half stops of luminance, from 2^-16 to 2^16, which the bright end is found in. */\nconst METER_BINS: u32 = 64u;\n\nvar<workgroup> meterSums: array<vec2<f32>, 256>;\nvar<workgroup> meterHistogram: array<atomic<u32>, 64>;\n\n/**\n * The camera's meter: the image's average luminance over a grid of points, taken as the mean of the logarithms so that\n * a bright window or a patch of sky cannot darken everything else, weighed towards the centre as a camera's\n * centre-weighted metering is. What no path has reached yet, or is black, does not count. One workgroup reads the\n * grid and sums it in shared memory.\n *\n * Then it guards the highlights, as a camera's matrix metering does: the average alone takes a dim attic with a shaft\n * of sun in it to middle grey and burns the shaft out, where a photographer keeps the room dim. The brightest few\n * percent of the points, found in a histogram of half stops, may land no more than {@link HIGHLIGHT_CEILING} times\n * brighter; an even scene, whose bright end is close to its average, is left as the average says.\n */\n@compute @workgroup_size(256, 1, 1)\nfn meter(@builtin(local_invocation_index) thread: u32) {\n var sum = vec2<f32>(0.0);\n let count = METER_GRID.x * METER_GRID.y;\n\n if (thread < METER_BINS) {\n atomicStore(&meterHistogram[thread], 0u);\n }\n\n workgroupBarrier();\n\n for (var k = thread; k < count; k = k + METER_THREADS) {\n let cell = vec2<f32>(f32(k % METER_GRID.x), f32(k / METER_GRID.x)) + 0.5;\n let uv = cell / vec2<f32>(METER_GRID);\n let luminance = dot(imageTexel(i32(uv.x * f32(lens.resolution.x)), i32(uv.y * f32(lens.resolution.y))),\n vec3<f32>(0.2126, 0.7152, 0.0722));\n let away = (uv - 0.5) * 2.0;\n let weight = select(0.0, 1.0 - 0.6 * min(dot(away, away) * 0.5, 1.0), luminance > 0.0);\n\n sum = sum + vec2<f32>(log(max(luminance, 1e-6)) * weight, weight);\n\n if (luminance > 0.0) {\n let bin = u32(clamp((log2(luminance) + 16.0) * 2.0, 0.0, f32(METER_BINS - 1u)));\n\n atomicAdd(&meterHistogram[bin], 1u);\n }\n }\n\n meterSums[thread] = sum;\n workgroupBarrier();\n\n for (var stride = METER_THREADS / 2u; stride > 0u; stride = stride / 2u) {\n if (thread < stride) {\n meterSums[thread] = meterSums[thread] + meterSums[thread + stride];\n }\n\n workgroupBarrier();\n }\n\n if (thread == 0u) {\n let total = meterSums[0];\n let average = select(MIDDLE_GREY, exp(total.x / max(total.y, 1e-6)), total.y > 0.0);\n var exposure = MIDDLE_GREY / average;\n\n // A dark scene keeps a share of its missing stops: a night stays a night instead of turning into dusk.\n if (average < DIM_AVERAGE) {\n exposure = exposure * pow(average / DIM_AVERAGE, lens.darkAdaptation);\n }\n\n // From the top down, the first half stop by which the bright share is reached; its upper edge is that end.\n var points = 0u;\n\n for (var bin = 0u; bin < METER_BINS; bin = bin + 1u) {\n points = points + atomicLoad(&meterHistogram[bin]);\n }\n\n var above = 0u;\n var bright = 0.0;\n\n for (var bin = i32(METER_BINS) - 1; bin >= 0 && points > 0u; bin = bin - 1) {\n above = above + atomicLoad(&meterHistogram[u32(bin)]);\n\n if (f32(above) >= HIGHLIGHT_SHARE * f32(points)) {\n bright = exp2(f32(bin + 1) * 0.5 - 16.0);\n break;\n }\n }\n\n if (bright > 0.0) {\n exposure = min(exposure, HIGHLIGHT_CEILING * MIDDLE_GREY / bright);\n }\n\n metered[0] = vec4<f32>(clamp(exposure, 1e-4, 1e4), average, bright, 0.0);\n }\n}\n\n/** The image's own texel: its mean so far, or nothing where no path has landed yet. */\nfn imageTexel(x: i32, y: i32) -> vec3<f32> {\n let size = vec2<i32>(lens.resolution);\n let index = u32(clamp(y, 0, size.y - 1) * size.x + clamp(x, 0, size.x - 1));\n\n if (lens.denoised != 0u) {\n return denoised[index].rgb;\n }\n\n let stored = accumulation[index];\n\n return select(stored.rgb / stored.w, vec3<f32>(0.0), stored.w <= 0.0);\n}\n\nfn downTexel(offset: u32, size: vec2<u32>, x: i32, y: i32) -> vec3<f32> {\n let s = vec2<i32>(size);\n\n return down[offset + u32(clamp(y, 0, s.y - 1) * s.x + clamp(x, 0, s.x - 1))].rgb;\n}\n\nfn upTexel(offset: u32, size: vec2<u32>, x: i32, y: i32) -> vec3<f32> {\n let s = vec2<i32>(size);\n\n return up[offset + u32(clamp(y, 0, s.y - 1) * s.x + clamp(x, 0, s.x - 1))].rgb;\n}\n\n/** Bilinear weights and the texel below and left of a point given in texels, edges clamped. */\nfn bilinearAt(position: vec2<f32>) -> vec4<f32> {\n let p = position - 0.5;\n let base = floor(p);\n\n return vec4<f32>(base, p - base);\n}\n\nfn imageBilinear(position: vec2<f32>) -> vec3<f32> {\n let b = bilinearAt(position);\n let x = i32(b.x);\n let y = i32(b.y);\n\n return mix(\n mix(imageTexel(x, y), imageTexel(x + 1, y), b.z),\n mix(imageTexel(x, y + 1), imageTexel(x + 1, y + 1), b.z), b.w);\n}\n\nfn downBilinear(offset: u32, size: vec2<u32>, position: vec2<f32>) -> vec3<f32> {\n let b = bilinearAt(position);\n let x = i32(b.x);\n let y = i32(b.y);\n\n return mix(\n mix(downTexel(offset, size, x, y), downTexel(offset, size, x + 1, y), b.z),\n mix(downTexel(offset, size, x, y + 1), downTexel(offset, size, x + 1, y + 1), b.z), b.w);\n}\n\nfn upBilinear(offset: u32, size: vec2<u32>, position: vec2<f32>) -> vec3<f32> {\n let b = bilinearAt(position);\n let x = i32(b.x);\n let y = i32(b.y);\n\n return mix(\n mix(upTexel(offset, size, x, y), upTexel(offset, size, x + 1, y), b.z),\n mix(upTexel(offset, size, x, y + 1), upTexel(offset, size, x + 1, y + 1), b.z), b.w);\n}\n\n/** The level being filtered, read bilinearly at a point given in its own texels. */\nfn sourceAt(position: vec2<f32>) -> vec3<f32> {\n if (lens.fromImage != 0u) {\n return imageBilinear(position);\n }\n\n return downBilinear(lens.sourceOffset, lens.sourceSize, position);\n}\n\nfn luminance(color: vec3<f32>) -> f32 {\n return dot(color, vec3<f32>(0.2126, 0.7152, 0.0722));\n}\n\n/** Karis' average: a group of taps weighed by one over one plus its luminance, so a lone firefly cannot flare. */\nfn karis(sum: vec3<f32>) -> vec4<f32> {\n let weight = 1.0 / (1.0 + luminance(sum));\n\n return vec4<f32>(sum * weight, weight);\n}\n\n/** One level of the pyramid from the one above it: Jimenez's 13 taps, four overlapping boxes and a centre one. */\n@compute @workgroup_size(8, 8, 1)\nfn downsample(@builtin(global_invocation_id) id: vec3<u32>) {\n if (id.x >= lens.targetSize.x || id.y >= lens.targetSize.y) {\n return;\n }\n\n let scale = vec2<f32>(lens.sourceSize) / vec2<f32>(lens.targetSize);\n let centre = (vec2<f32>(id.xy) + 0.5) * scale;\n let a = sourceAt(centre + vec2<f32>(-2.0, -2.0));\n let b = sourceAt(centre + vec2<f32>(0.0, -2.0));\n let c = sourceAt(centre + vec2<f32>(2.0, -2.0));\n let d = sourceAt(centre + vec2<f32>(-2.0, 0.0));\n let e = sourceAt(centre);\n let f = sourceAt(centre + vec2<f32>(2.0, 0.0));\n let g = sourceAt(centre + vec2<f32>(-2.0, 2.0));\n let h = sourceAt(centre + vec2<f32>(0.0, 2.0));\n let i = sourceAt(centre + vec2<f32>(2.0, 2.0));\n let j = sourceAt(centre + vec2<f32>(-1.0, -1.0));\n let k = sourceAt(centre + vec2<f32>(1.0, -1.0));\n let l = sourceAt(centre + vec2<f32>(-1.0, 1.0));\n let m = sourceAt(centre + vec2<f32>(1.0, 1.0));\n var result: vec3<f32>;\n\n if (lens.fromImage != 0u) {\n let groups = karis((j + k + l + m) * 0.25) * 0.5\n + karis((a + b + d + e) * 0.25) * 0.125\n + karis((b + c + e + f) * 0.25) * 0.125\n + karis((d + e + g + h) * 0.25) * 0.125\n + karis((e + f + h + i) * 0.25) * 0.125;\n\n result = groups.rgb / max(groups.w, 1e-6);\n } else {\n result = e * 0.125 + (a + c + g + i) * 0.03125 + (b + d + f + h) * 0.0625 + (j + k + l + m) * 0.125;\n }\n\n down[lens.targetOffset + id.y * lens.targetSize.x + id.x] = vec4<f32>(max(result, vec3<f32>(0.0)), 1.0);\n}\n\n/** A 3 x 3 tent over the smaller level, read at a point given in its texels. */\nfn tent(position: vec2<f32>) -> vec3<f32> {\n var sum = vec3<f32>(0.0);\n\n for (var dy = -1; dy <= 1; dy = dy + 1) {\n for (var dx = -1; dx <= 1; dx = dx + 1) {\n let weight = f32((2 - abs(dx)) * (2 - abs(dy))) / 16.0;\n let at = position + vec2<f32>(f32(dx), f32(dy));\n\n if (lens.fromDown != 0u) {\n sum = sum + downBilinear(lens.sourceOffset, lens.sourceSize, at) * weight;\n } else {\n sum = sum + upBilinear(lens.sourceOffset, lens.sourceSize, at) * weight;\n }\n }\n }\n\n return sum;\n}\n\n/** One level folded back: its own light, mixed by the radius with the wider spread of every level below it. */\n@compute @workgroup_size(8, 8, 1)\nfn upsample(@builtin(global_invocation_id) id: vec3<u32>) {\n if (id.x >= lens.targetSize.x || id.y >= lens.targetSize.y) {\n return;\n }\n\n let scale = vec2<f32>(lens.sourceSize) / vec2<f32>(lens.targetSize);\n let wider = tent((vec2<f32>(id.xy) + 0.5) * scale);\n let index = lens.targetOffset + id.y * lens.targetSize.x + id.x;\n\n up[index] = vec4<f32>(mix(down[index].rgb, wider, lens.radius), 1.0);\n}\n\n/** The aperture's rays at one texel of the streak level: the light behind it along each ray, fading with distance. */\n@compute @workgroup_size(8, 8, 1)\nfn streaks(@builtin(global_invocation_id) id: vec3<u32>) {\n if (id.x >= lens.targetSize.x || id.y >= lens.targetSize.y) {\n return;\n }\n\n let centre = vec2<f32>(id.xy) + 0.5;\n // The exposure the image will have: the setting's, and the meter's when it meters.\n let exposure = lens.exposure * select(1.0, metered[0].x, lens.autoExposure > 0.0);\n var sum = vec3<f32>(0.0);\n var total = 0.0;\n\n for (var r = 0u; r < lens.rays; r = r + 1u) {\n let angle = lens.glareAngle + f32(r) * 2.0 * PI / f32(lens.rays);\n let along = vec2<f32>(cos(angle), sin(angle));\n\n for (var j = 1; j <= STREAK_TAPS; j = j + 1) {\n let t = f32(j) / f32(STREAK_TAPS);\n let weight = exp(-6.0 * t);\n\n let light = downBilinear(lens.sourceOffset, lens.sourceSize, centre - along * (t * lens.glareLength));\n\n sum = sum + light * (weight / max(1.0, luminance(light) * exposure / GLARE_CEILING));\n total = total + weight;\n }\n }\n\n streaked[id.y * lens.targetSize.x + id.x] = vec4<f32>(sum / max(total, 1e-6), 1.0);\n}\n\nfn streakTexel(x: i32, y: i32) -> vec3<f32> {\n let s = vec2<i32>(lens.streakSize);\n\n return streaked[u32(clamp(y, 0, s.y - 1) * s.x + clamp(x, 0, s.x - 1))].rgb;\n}\n\nfn streakBilinear(position: vec2<f32>) -> vec3<f32> {\n let b = bilinearAt(position);\n let x = i32(b.x);\n let y = i32(b.y);\n\n return mix(mix(streakTexel(x, y), streakTexel(x + 1, y), b.z), mix(streakTexel(x, y + 1), streakTexel(x + 1, y + 1), b.z), b.w);\n}\n\n/** The image as the lens delivers it: fringed towards the corners, with its halo, balanced for the camera's white. */\n@compute @workgroup_size(8, 8, 1)\nfn composite(@builtin(global_invocation_id) id: vec3<u32>) {\n if (id.x >= lens.resolution.x || id.y >= lens.resolution.y) {\n return;\n }\n\n let size = vec2<f32>(lens.resolution);\n let position = vec2<f32>(id.xy) + 0.5;\n var color = imageTexel(i32(id.x), i32(id.y));\n\n // Lateral chromatic aberration: each colour is magnified a little differently, red outwards and blue inwards,\n // in proportion to the distance from the centre, which is how a lens's dispersion moves them.\n if (lens.aberration > 0.0) {\n let centre = size * 0.5;\n let away = position - centre;\n let red = imageBilinear(centre + away * (1.0 - lens.aberration));\n let blue = imageBilinear(centre + away * (1.0 + lens.aberration));\n\n color = vec3<f32>(red.r, color.g, blue.b);\n }\n\n if (lens.intensity > 0.0) {\n // The largest folded level is already a tent over the levels below it, so one bilinear read of it is smooth.\n let halo = upBilinear(lens.haloOffset, lens.haloSize, position * vec2<f32>(lens.haloSize) / size);\n\n color = mix(color, halo, lens.intensity);\n }\n\n if (lens.glare > 0.0) {\n color = mix(color, streakBilinear(position * vec2<f32>(lens.streakSize) / size), lens.glare);\n }\n\n if (lens.autoExposure > 0.0) {\n color = color * metered[0].x;\n }\n\n let balanced = vec3<f32>(dot(lens.white0.xyz, color), dot(lens.white1.xyz, color), dot(lens.white2.xyz, color));\n\n graded[id.y * lens.resolution.x + id.x] = vec4<f32>(max(balanced, vec3<f32>(0.0)), 1.0);\n}\n";
17
17
  //# sourceMappingURL=lens.wgsl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lens.wgsl.d.ts","sourceRoot":"","sources":["../../src/wgsl/lens.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,mpeAmZrB,CAAC"}
1
+ {"version":3,"file":"lens.wgsl.d.ts","sourceRoot":"","sources":["../../src/wgsl/lens.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,kyfA+ZrB,CAAC"}
@@ -50,6 +50,8 @@ struct Lens {
50
50
  autoExposure: f32,
51
51
  // The share of a dark scene's darkness the meter keeps.
52
52
  darkAdaptation: f32,
53
+ // The exposure applied after the lens, the meter's aside, which the rays are limited against.
54
+ exposure: f32,
53
55
  };
54
56
 
55
57
  const PI: f32 = 3.14159265358979;
@@ -57,6 +59,12 @@ const PI: f32 = 3.14159265358979;
57
59
  /** Taps along each of the aperture's rays. */
58
60
  const STREAK_TAPS: i32 = 24;
59
61
 
62
+ /**
63
+ * The brightest a tap of the rays counts as, in multiples of the exposed white. A lamp is thousands of times white,
64
+ * which would carry its rays across the frame at full length; past this they stay as short as a camera shows them.
65
+ */
66
+ const GLARE_CEILING: f32 = 4.0;
67
+
60
68
  @group(0) @binding(0) var<uniform> lens: Lens;
61
69
  @group(0) @binding(1) var<storage, read> accumulation: array<vec4<f32>>;
62
70
  @group(0) @binding(2) var<storage, read> denoised: array<vec4<f32>>;
@@ -342,6 +350,8 @@ fn streaks(@builtin(global_invocation_id) id: vec3<u32>) {
342
350
  }
343
351
 
344
352
  let centre = vec2<f32>(id.xy) + 0.5;
353
+ // The exposure the image will have: the setting's, and the meter's when it meters.
354
+ let exposure = lens.exposure * select(1.0, metered[0].x, lens.autoExposure > 0.0);
345
355
  var sum = vec3<f32>(0.0);
346
356
  var total = 0.0;
347
357
 
@@ -351,9 +361,11 @@ fn streaks(@builtin(global_invocation_id) id: vec3<u32>) {
351
361
 
352
362
  for (var j = 1; j <= STREAK_TAPS; j = j + 1) {
353
363
  let t = f32(j) / f32(STREAK_TAPS);
354
- let weight = exp(-4.0 * t);
364
+ let weight = exp(-6.0 * t);
365
+
366
+ let light = downBilinear(lens.sourceOffset, lens.sourceSize, centre - along * (t * lens.glareLength));
355
367
 
356
- sum = sum + downBilinear(lens.sourceOffset, lens.sourceSize, centre - along * (t * lens.glareLength)) * weight;
368
+ sum = sum + light * (weight / max(1.0, luminance(light) * exposure / GLARE_CEILING));
357
369
  total = total + weight;
358
370
  }
359
371
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lens.wgsl.js","sourceRoot":"","sources":["../../src/wgsl/lens.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmZnC,CAAC"}
1
+ {"version":3,"file":"lens.wgsl.js","sourceRoot":"","sources":["../../src/wgsl/lens.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+ZnC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinypoly/gpu-renderer",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "WebGPU path tracer for Three.js scenes: BVH traversal, progressive accumulation and tone mapping in WGSL compute shaders.",
5
5
  "keywords": [
6
6
  "three",
package/src/lensPass.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createShaderModule } from "./shaderModule.js";
2
- import { NEUTRAL_WHITE_BALANCE, whiteBalanceMatrix, type GpuRenderSettings } from "./settings.js";
2
+ import { effectiveExposure, NEUTRAL_WHITE_BALANCE, whiteBalanceMatrix, type GpuRenderSettings } from "./settings.js";
3
3
  import { LENS_WGSL } from "./wgsl/lens.wgsl.js";
4
4
 
5
5
  const UNIFORM_BYTES = 160;
@@ -31,6 +31,8 @@ export interface LensEffects {
31
31
  autoExposure: boolean;
32
32
  /** The share of a dark scene's darkness the meter keeps, `0` to `1`. */
33
33
  darkAdaptation: number;
34
+ /** What the image is multiplied by after the lens, the meter's own exposure aside: the rays are limited against it. */
35
+ exposure: number;
34
36
  }
35
37
 
36
38
  /** The lens effects these settings ask for, or `null` when they ask for none and the pass can be skipped. */
@@ -58,6 +60,7 @@ export function lensEffects(settings: GpuRenderSettings): LensEffects | null {
58
60
  whiteBalance: neutral ? null : whiteBalanceMatrix(camera.whiteBalance),
59
61
  autoExposure,
60
62
  darkAdaptation: Math.min(1, Math.max(0, Number(camera.darkAdaptation) || 0)),
63
+ exposure: Math.max(effectiveExposure(settings), 0),
61
64
  };
62
65
  }
63
66
 
@@ -216,6 +219,7 @@ export class LensPass {
216
219
  floats[34] = effects.glareAngle;
217
220
  floats[35] = effects.autoExposure ? 1 : 0;
218
221
  floats[36] = effects.darkAdaptation;
222
+ floats[37] = effects.exposure;
219
223
  for (let row = 0; row < 3; row++) for (let column = 0; column < 3; column++)
220
224
  floats[20 + row * 4 + column] = white[row * 3 + column];
221
225
  fill();
@@ -256,6 +260,10 @@ export class LensPass {
256
260
  integers[10] = level.offset;
257
261
  };
258
262
 
263
+ // The meter is one workgroup, whatever the size: dispatched as a single tile of the grid it reads. It goes first,
264
+ // since the rays are limited against the exposure it finds.
265
+ if (effects.autoExposure) dispatch(this.meter, { width: 1, height: 1 }, () => {});
266
+
259
267
  // The rays are gathered from a level of the same pyramid, so either effect builds it.
260
268
  if (effects.bloom > 0 || effects.glare > 0) {
261
269
  levels.forEach((level, k) => dispatch(this.downsample, level, () => {
@@ -294,9 +302,6 @@ export class LensPass {
294
302
  }
295
303
  }
296
304
 
297
- // The meter is one workgroup, whatever the size: dispatched as a single tile of the grid it reads.
298
- if (effects.autoExposure) dispatch(this.meter, { width: 1, height: 1 }, () => {});
299
-
300
305
  dispatch(this.composite, { width, height }, () => {});
301
306
 
302
307
  return this.graded as GPUBuffer;
@@ -50,6 +50,8 @@ struct Lens {
50
50
  autoExposure: f32,
51
51
  // The share of a dark scene's darkness the meter keeps.
52
52
  darkAdaptation: f32,
53
+ // The exposure applied after the lens, the meter's aside, which the rays are limited against.
54
+ exposure: f32,
53
55
  };
54
56
 
55
57
  const PI: f32 = 3.14159265358979;
@@ -57,6 +59,12 @@ const PI: f32 = 3.14159265358979;
57
59
  /** Taps along each of the aperture's rays. */
58
60
  const STREAK_TAPS: i32 = 24;
59
61
 
62
+ /**
63
+ * The brightest a tap of the rays counts as, in multiples of the exposed white. A lamp is thousands of times white,
64
+ * which would carry its rays across the frame at full length; past this they stay as short as a camera shows them.
65
+ */
66
+ const GLARE_CEILING: f32 = 4.0;
67
+
60
68
  @group(0) @binding(0) var<uniform> lens: Lens;
61
69
  @group(0) @binding(1) var<storage, read> accumulation: array<vec4<f32>>;
62
70
  @group(0) @binding(2) var<storage, read> denoised: array<vec4<f32>>;
@@ -342,6 +350,8 @@ fn streaks(@builtin(global_invocation_id) id: vec3<u32>) {
342
350
  }
343
351
 
344
352
  let centre = vec2<f32>(id.xy) + 0.5;
353
+ // The exposure the image will have: the setting's, and the meter's when it meters.
354
+ let exposure = lens.exposure * select(1.0, metered[0].x, lens.autoExposure > 0.0);
345
355
  var sum = vec3<f32>(0.0);
346
356
  var total = 0.0;
347
357
 
@@ -351,9 +361,11 @@ fn streaks(@builtin(global_invocation_id) id: vec3<u32>) {
351
361
 
352
362
  for (var j = 1; j <= STREAK_TAPS; j = j + 1) {
353
363
  let t = f32(j) / f32(STREAK_TAPS);
354
- let weight = exp(-4.0 * t);
364
+ let weight = exp(-6.0 * t);
365
+
366
+ let light = downBilinear(lens.sourceOffset, lens.sourceSize, centre - along * (t * lens.glareLength));
355
367
 
356
- sum = sum + downBilinear(lens.sourceOffset, lens.sourceSize, centre - along * (t * lens.glareLength)) * weight;
368
+ sum = sum + light * (weight / max(1.0, luminance(light) * exposure / GLARE_CEILING));
357
369
  total = total + weight;
358
370
  }
359
371
  }