vireuikit 0.1.0 → 0.2.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.
@@ -109,8 +109,18 @@ var MEDIUM_DEFAULTS = {
109
109
  condensateColor: [0.94, 0.95, 0.97],
110
110
  channelColors: neutralSpecies(BASE_COLOR),
111
111
  baseColor: BASE_COLOR,
112
- baseWeight: 0.9
112
+ baseWeight: 0.9,
113
+ depthFarScale: 1.6,
114
+ depthFarOffsetFrac: [0.47, 0.53],
115
+ depthFarBlurRadius: 5,
116
+ depthFarWeight: 0.5,
117
+ gravityVaporDrift: 0.6,
118
+ gravityBottomBoost: 2,
119
+ gravityBottomBoostStart: 0.75
113
120
  };
121
+ function depthFarOffsetPx(offsetFrac, gridWidth, gridHeight) {
122
+ return [offsetFrac[0] * gridWidth, offsetFrac[1] * gridHeight];
123
+ }
114
124
 
115
125
  // src/medium/noise.ts
116
126
  var VG_VALUE_NOISE = `
@@ -295,11 +305,16 @@ var MEDIUM_ADVECT_VELOCITY_SETTLE = `
295
305
  ${MEDIUM_ADVECT_VELOCITY}
296
306
  vel.y += u_settleSpeed;
297
307
  `;
308
+ var MEDIUM_ADVECT_VELOCITY_VAPOR = `
309
+ ${MEDIUM_ADVECT_VELOCITY}
310
+ vel.y += u_vaporDrift;
311
+ `;
298
312
  var MEDIUM_VAPOR_FORWARD_SHADER = `
299
313
  ${MEDIUM_ADVECT_UNIFORMS}
314
+ uniform float u_vaporDrift;
300
315
 
301
316
  half4 main(float2 xy) {
302
- ${MEDIUM_ADVECT_VELOCITY}
317
+ ${MEDIUM_ADVECT_VELOCITY_VAPOR}
303
318
  float2 src = xy - vel * u_dt;
304
319
  return u_dye.eval(float2(src.x, u_dyeSize.y - src.y));
305
320
  }
@@ -335,9 +350,10 @@ var MEDIUM_MACCORMACK_CORRECT = `
335
350
  var MEDIUM_VAPOR_CORRECT_SHADER = `
336
351
  ${MEDIUM_ADVECT_UNIFORMS}
337
352
  uniform shader u_forward;
353
+ uniform float u_vaporDrift;
338
354
 
339
355
  half4 main(float2 xy) {
340
- ${MEDIUM_ADVECT_VELOCITY}
356
+ ${MEDIUM_ADVECT_VELOCITY_VAPOR}
341
357
  ${MEDIUM_MACCORMACK_CORRECT}
342
358
  return limited;
343
359
  }
@@ -457,17 +473,52 @@ uniform float3 u_labCondensate;
457
473
  uniform float u_baseWeight;
458
474
  uniform float u_condensateTint;
459
475
  uniform float u_condensateGain;
476
+ uniform float u_farScale;
477
+ uniform float2 u_farOffset;
478
+ uniform float u_farBlurRadius;
479
+ uniform float u_farWeight;
480
+ uniform float u_gravityBoost;
481
+ uniform float u_gravityBoostStart;
460
482
 
461
483
  ${VG_OKLAB_TO_SRGB}
462
484
 
463
485
  half4 main(float2 xy) {
464
- float2 src = xy * u_dyeScale;
465
- half4 vapor = u_vapor.eval(src);
466
- half4 condensate = u_condensate.eval(src);
467
- half4 track = u_track.eval(src);
468
- float w0 = float(vapor.r) + float(track.r);
469
- float w1 = float(vapor.g) + float(track.g);
470
- float w2 = float(vapor.b) + float(track.b);
486
+ float2 baseSrc = xy * u_dyeScale;
487
+
488
+ // Near plane \u2014 sampled exactly as before the depth work; the calibrated look lives here.
489
+ half4 vapor = u_vapor.eval(baseSrc);
490
+ half4 condensate = u_condensate.eval(baseSrc);
491
+ half4 track = u_track.eval(baseSrc);
492
+
493
+ // Far plane \u2014 the identical field, scaled and offset (see the file header). A 4-tap box blur
494
+ // (no separate center sample, the cheapest isotropic blur available) supplies aerial perspective's
495
+ // blur and, as a side effect of averaging, its lower contrast too.
496
+ float2 farSrc = baseSrc * u_farScale + u_farOffset;
497
+ float2 blurX = float2(u_farBlurRadius, 0.0);
498
+ float2 blurY = float2(0.0, u_farBlurRadius);
499
+ half4 vaporFar = (u_vapor.eval(farSrc + blurX) + u_vapor.eval(farSrc - blurX) +
500
+ u_vapor.eval(farSrc + blurY) + u_vapor.eval(farSrc - blurY)) * half4(0.25);
501
+ half4 condensateFar = (u_condensate.eval(farSrc + blurX) + u_condensate.eval(farSrc - blurX) +
502
+ u_condensate.eval(farSrc + blurY) + u_condensate.eval(farSrc - blurY)) * half4(0.25);
503
+
504
+ // Gravity's "denser layer at the bottom of the chamber" \u2014 a compositing-only boost (see
505
+ // MEDIUM_DEFAULTS.gravityBottomBoost): it scales how density already in the conserved buffers is
506
+ // DISPLAYED, never the buffers themselves, so it can't threaten water conservation. Shared by
507
+ // both planes: the chamber's floor is denser everywhere along its depth, not just up close.
508
+ //
509
+ // Verified with a headless render, not assumed: ramping this with xy.y directly lit up the TOP
510
+ // of the frame, not the bottom (contentTexture's own orientation contract flips y once more
511
+ // between this pass and the final scene \u2014 see the file header) \u2014 hence the 1.0 - below.
512
+ float bottomFrac = 1.0 - xy.y / u_resolution.y;
513
+ float bottomT = smoothstep(u_gravityBoostStart, 1.0, bottomFrac);
514
+ float bottomBoost = 1.0 + u_gravityBoost * bottomT;
515
+
516
+ float gasR = (float(vapor.r) + float(vaporFar.r) * u_farWeight) * bottomBoost;
517
+ float gasG = (float(vapor.g) + float(vaporFar.g) * u_farWeight) * bottomBoost;
518
+ float gasB = (float(vapor.b) + float(vaporFar.b) * u_farWeight) * bottomBoost;
519
+ float w0 = gasR + float(track.r);
520
+ float w1 = gasG + float(track.g);
521
+ float w2 = gasB + float(track.b);
471
522
  float wBg = u_baseWeight;
472
523
 
473
524
  // A faint condensate hint from the LOCAL vapor, not its own color (droplets scatter light
@@ -475,7 +526,8 @@ half4 main(float2 xy) {
475
526
  float vaporLocal = max(w0 + w1 + w2, 1e-4);
476
527
  float3 vaporHue = (u_lab0 * w0 + u_lab1 * w1 + u_lab2 * w2) / vaporLocal;
477
528
  float3 condensateLab = mix(u_labCondensate, vaporHue, u_condensateTint);
478
- float wCondensate = float(condensate.r) * u_condensateGain;
529
+ float wCondensate =
530
+ (float(condensate.r) + float(condensateFar.r) * u_farWeight) * u_condensateGain * bottomBoost;
479
531
 
480
532
  float total = max(w0 + w1 + w2 + wBg + wCondensate, 1e-4);
481
533
  float3 mixLab =
@@ -701,6 +753,7 @@ function createMediumRuntime(gl, vertexSource) {
701
753
  web.setUniform(gl, loc("u_curlFreq"), p.curlFreq);
702
754
  web.setUniform(gl, loc("u_advectSpeed"), p.advectSpeed);
703
755
  web.setUniform(gl, loc("u_turbulence"), p.turbulence);
756
+ web.setUniform(gl, loc("u_vaporDrift"), p.gravityVaporDrift);
704
757
  }
705
758
  let phase = 0;
706
759
  function wrapPhase(value) {
@@ -853,6 +906,12 @@ function createMediumRuntime(gl, vertexSource) {
853
906
  web.setUniform(gl, compositeLoc("u_baseWeight"), p.baseWeight);
854
907
  web.setUniform(gl, compositeLoc("u_condensateTint"), p.condensateTint);
855
908
  web.setUniform(gl, compositeLoc("u_condensateGain"), p.condensateGain);
909
+ web.setUniform(gl, compositeLoc("u_farScale"), p.depthFarScale);
910
+ web.setUniform(gl, compositeLoc("u_farOffset"), depthFarOffsetPx(p.depthFarOffsetFrac, gridW, gridH));
911
+ web.setUniform(gl, compositeLoc("u_farBlurRadius"), p.depthFarBlurRadius);
912
+ web.setUniform(gl, compositeLoc("u_farWeight"), p.depthFarWeight);
913
+ web.setUniform(gl, compositeLoc("u_gravityBoost"), p.gravityBottomBoost);
914
+ web.setUniform(gl, compositeLoc("u_gravityBoostStart"), p.gravityBottomBoostStart);
856
915
  web.drawFullscreenTriangle(gl);
857
916
  }
858
917
  function readTarget(target) {