M1 Lite Shader v8
===================

A lightweight Vanilla+ shader pack for Minecraft Java (Iris, OptiFine
shader format), purpose-built for a 2020 MacBook Pro / Apple M1
integrated GPU with 8 GB unified memory. Target: 60+ FPS at low GPU
and memory usage.

Install
-------
1. Open Minecraft with Iris installed.
2. Options > Video Settings > Shaderpacks > Open Shader Pack Folder.
3. Copy M1LiteShader.zip (do NOT unzip it) into that folder.
4. Select "M1 Lite Shader" in the list and click Done.

What's new in v2
-----------------
- Hemisphere ambient lighting with a minimum brightness floor, so
  caves and night are no longer near-pure-black -- replaces the old
  flat "ambient = skylight" model.
- Reworked water: depth-based color absorption (shallow water reads
  light, open/deep water reads dark teal), a soft shoreline fade,
  3-octave animated wave normals, Fresnel reflection and a proper
  Blinn-Phong sun specular highlight.
- Shadows upgraded to a rotated 8-tap Poisson filter (stable -- the
  rotation is keyed to world position, not screen position, so it
  doesn't shimmer as the camera moves) with slope-scaled and
  distance-scaled bias to cut down on acne.
- A cheap analytic atmospheric sky (Rayleigh/Mie-style scattering,
  horizon haze, high-altitude darkening, sunrise/sunset glow) that
  blends with vanilla's own sky/stars/sun/moon rather than replacing
  them.
- Height-aware fog: valleys and low ground read foggier than
  mountain tops, for a bit of atmospheric perspective.
- Bloom is a 5-tap blur on top of the mip chain instead of a single
  fetch, with its threshold tuned for the default clamped 0-1 buffer
  (an earlier build tried an RGBA16F override for HDR bloom headroom;
  that token isn't a real GLSL identifier and broke shader loading on
  this Iris build, so it's been reverted -- see "Fixed since v2" below).
- A reactive auto-exposure pass so looking at the sun/sky no longer
  blows out the screen.
- Cloud lighting: a sun-aligned "silver lining" glow plus warm
  sunset / cool moonlit tinting.
- Warmer, more detailed torch light (bright warm core fading to deep
  orange at the edge) plus a very subtle ambient flicker.
- Underwater: distance-aware blue fog and a subtle animated caustic
  light pattern while your head is submerged.
- Grass, flowers, crops, saplings and leaves now sway/flutter in the
  wind, with matching displacement in the shadow pass so foliage
  shadows move with the foliage.
- A proper cinematic grade: lift/gamma/gain, ACES tonemapping, split
  toning (cool shadows, warm highlights), then saturation/warmth/
  contrast.

Fixed since v2
--------------
- composite.fsh declared `const int colortex0Format = RGBA16F;` to
  get an HDR buffer for cleaner bloom. RGBA16F is not an actual GLSL
  identifier, and this Iris build did not substitute it with a real
  value, so the shader failed to compile with "undeclared identifier
  'RGBA16F'" and the whole pack refused to load. That line has been
  removed; colortex0 now uses its default format, and the bloom
  threshold/intensity were retuned to look right on a plain clamped
  0-1 buffer instead.
- Rotation caused the whole scene's brightness to breathe/flicker.
  Root cause: the hemisphere-ambient term read `normal.y` directly,
  but `normal` is in eye space (it rotates with the camera), so a
  perfectly static surface's ambient brightness changed continuously
  as you looked around. Fixed by using `dot(normal, normalize(upPosition))`
  everywhere instead, which is rotation-invariant. Water's Fresnel/
  specular had a related bug (mixing an eye-space normal with a
  world-oriented view vector); it now reconstructs its view direction
  in eye space to match. Auto exposure also sampled a directionally
  localized patch of the screen instead of a true frame average; it
  now reads a fully-collapsed mip so it no longer swings with aim.
- Sky and lighting flicker at sunset/sunrise, and sunset lasting
  forever instead of reaching real night. Root cause: terrain, water,
  clouds and the sky each computed their own, different formula for
  "how far into sunset/night are we", several of them derived from
  `shadowLightPosition`, which hard-switches (a real ~180-degree
  direction jump) from the sun to the moon the instant the sun dips
  below the horizon. On top of that, the ambient/sky-color formulas
  had no real "night" state at all -- they could only ever get
  warmer at low sun angles, never properly dark. Fixed by adding one
  shared, stable day/night calculation (lib/common.glsl:
  getSunElevation/getDayFactor/getHorizonFactor), driven only by the
  always-continuous sunPosition/upPosition, and using it identically
  in every shader. Night is now genuinely dark (a real cool-toned
  night sky and dim moonlight, gated so cave and Nether brightness
  are mathematically untouched), and twilight fades out into it
  instead of lingering.
- Sun and moon were invisible. Root cause: the sky's atmospheric
  gradient in composite.fsh uniformly darkened every sky pixel,
  including the sun/moon disk itself, blending it into the procedural
  sky instead of sitting distinctly on top of it. composite.fsh now
  detects genuinely bright pixels (the disk) and leaves them
  undarkened; gbuffers_skytextured gives the vanilla sun/moon quad a
  small brightness boost so it reliably clears that check and the
  bloom threshold. The existing mie-scattering glow and bloom pass
  (both unchanged) now give it a soft, bloom-compatible halo for free.
- Daytime-only sky flicker. Root cause: the sun/moon-disk preservation
  check above (from the previous fix) guessed "is this the sun/moon"
  purely from pixel brightness. The sky's mie-scattering term has a
  wide, gentle falloff that spreads extra brightness across a large
  angular region around the sun -- and when the sun is high in the
  sky, that region overlaps most of the visible sky, so ordinary
  daytime sky brightness legitimately sat at or near the same
  threshold meant to single out the actual disk, causing pixels to
  dither between "darken" and "preserve" as that brightness hovered
  on the boundary. At night the sky sits well under the threshold
  everywhere; at dawn/dusk the same falloff is concentrated in a
  narrow band near the horizon instead of spread across the sky, so
  far less of the frame was ever near the line. Fixed by replacing
  the brightness guess with the precise geometric quantity already
  computed for the mie term itself (the view/sun angular alignment,
  cosTheta) -- the disk sits at cosTheta extremely close to 1;
  ordinary sky, however bright, never gets that close. No thresholds
  were softened or hidden; the test itself was replaced with a
  correct one.
- Remaining daytime flicker after the above fix: the reactive auto
  exposure in final.fsh. It sampled the whole screen's average
  brightness fresh every single frame and applied it immediately, with
  no temporal smoothing. That sample was a genuine whole-frame average
  (not biased toward any direction), but the average legitimately
  changes as the camera moves -- different mixes of sky, terrain and
  shadow enter frame continuously -- and applying it unsmoothed turned
  that ordinary, continuous change into a global brightness multiply
  reapplied to the entire image every frame. It looked like the sky
  flickering, but the sky itself was never the cause; this was a
  final-image-wide multiply sitting on top of it. Replaced with a
  fixed exposure of 1.0, which can't react to anything and therefore
  can't flicker. It's a single named constant in final.fsh if the
  overall image ever needs to read a touch brighter or darker.

v8 -- Nether Update
--------------------
Only the Nether changed. Every file this update touches lives either
in the new shaders/world-1/ folder (Iris/OptiFine's dimension-override
mechanism -- files there replace the root versions in the Nether only,
Nether dimension ID -1) or is a single additive line in
block.properties. The root gbuffers_terrain.vsh/fsh that the Overworld
uses are completely untouched, byte-for-byte -- not "probably fine",
provably unused by the Overworld at all, since Iris simply never looks
in world-1/ outside the Nether.

world-1/gbuffers_terrain.vsh + .fsh: a copy of the root terrain shader
(so every existing feature -- shadows, wind sway, wind-driven-rain
support, day/night, cave atmosphere, height fog, rain haze -- keeps
working exactly as before) plus:
- Lava glow: block.properties now tags lava with its own ID (10003),
  the same mc_Entity mechanism already used for water/plants/leaves.
  Lava gets a mild, texture-preserving warm push (+6% red, -8% blue,
  not a raw brightness multiply) so the animated texture's own detail
  and contrast survive and nothing clips to white. The existing bloom
  pass (unchanged) already picks up lava's natural brightness for the
  soft glow; caveWarmthBoost (unchanged, reused as-is) already gives
  nearby blocks a luminance-neutral warm tint that naturally fades
  with blockLight-based distance from the source.
- Heat atmosphere: a new, local (not in common.glsl) luminance-
  preserving hue shift keyed to worldPos.y -- the same camera-relative
  height already used two lines below for height fog -- warmer toward
  lower relative elevation, cooling off looking upward. One subtract,
  one multiply, one saturate; no new uniforms, no raymarching, no
  distortion, no loops.
- Biome atmosphere: reuses fogColor, which the game already computes
  per-biome and already blends smoothly across biome borders, as the
  source hue for a subtle, luminance-preserving atmospheric tint --
  no new biome-detection system, no hard borders possible since
  there's nothing hard-edged driving it.
- Brightness: ambient (not the final blended colour) is boosted 18%,
  landing in the requested 15-20% range. Boosting ambient specifically
  rather than the final pixel keeps already-bright, direct-lit/lava
  areas from clipping toward white, while meaningfully lifting the
  darker, shadow- and cave-dominated areas the brightness request was
  actually about. Shadow PCF/bias sampling itself is completely
  untouched.

v7.1 -- Storm Lighting + Cloud Fix + Rain Polish
--------------------------------------------------
Only 6 files touched this pass: lib/common.glsl, gbuffers_terrain.fsh,
gbuffers_water.fsh, gbuffers_clouds.fsh, gbuffers_weather.vsh,
gbuffers_weather.fsh. Nothing else changed.

Cloud rendering bug, found and fixed: gbuffers_clouds.fsh declared
`uniform float thunderStrength;` last update to drive a separate storm
tint. That was the one new, unverified uniform introduced in exactly
the file that stopped rendering -- every other uniform touched last
update (rainStrength) already had a proven track record elsewhere in
this pack. Rather than guess at the precise failure mode, the
dependency has been removed entirely: storm intensity is now derived
from rainStrength itself (`smoothstep(0.5, 1.0, rainStrength)`),
engaging only in the heaviest rain, with no second uniform at all.
Vanilla cloud geometry, movement, and transparency were never touched
in the first place -- only the fragment shader's colour/alpha logic
was affected.

Storm lighting (terrain.fsh, water.fsh): direct sunlight now drops to
12% of normal at full rainStrength (an 88% reduction, in the
requested 85-90% range) instead of the previous 25%, so the cloudy
sky becomes the dominant light source as requested. Shadow contrast
is softened by blending the existing shadow value toward 1.0 during
rain (the PCF/bias sampling itself is untouched). Ambient light now
nets slightly darker in heavy rain/storms: the existing light-rain
brightening is kept (so a drizzle still reads as a soft, slightly
brighter overcast, unchanged from before), but a new storm-specific
darkening term dominates once rainStrength crosses into "heavy," for
a net ~10% dimmer ambient at full storm. All of it rides the same
smooth rainStrength value the game already provides, so the
transition is continuous with no snapping.

Rain particles (weather.vsh/fsh): falling rain now has a shared,
cheap wind-gust sway (two sine waves) plus a tiny per-quad hash-based
angle jitter, so streaks lean with the wind and don't all move in
perfect lockstep -- both scale up with rainStrength so light rain
stays calm. Streaks are 15% brighter, and the distance fade is now a
steeper curve that fully fades out by 60% of render distance instead
of a flat linear fade all the way to the far plane, reading as denser
near the player and fading out well before the horizon. All vertex-
side, no new textures or per-pixel cost.

Rain haze (common.glsl): strength increased from 0.6 to 0.82, a
uniform +37% at every distance (verified numerically) -- an earlier
version of this fix also reshaped the distance falloff, but combined
with the strength increase that compounded to roughly +114% instead
of the requested 30-40%, so the falloff curve was left exactly as
it was and only the strength constant changed.

v7 -- Weather Update + Cave Upgrade
------------------------------------
Every system on the "do not touch" list for this update (sky colour
calculations, day/night cycle, exposure, fog outside of weather,
shadows, water waves/Fresnel/reflection, bloom, tonemapping, and every
performance choice) is byte-for-byte unchanged. Everything below is
implemented as new, additive layers on top of the existing, untouched
formulas -- each one is an exact no-op at its baseline condition
(clear weather, or open sky / deep cave), not just "tuned to be
subtle." Only lib/common.glsl, gbuffers_terrain.fsh, gbuffers_water.fsh
and gbuffers_clouds.fsh were touched.

Dynamic weather (terrain.fsh, water.fsh, common.glsl):
- Rain haze: a new applyRainHaze() function, entirely separate from
  the existing fog functions, blended on top of the already-fogged
  colour. Starts at 50 blocks, strengthens with distance, uses a
  fixed desaturated grey-blue (never white), and is mathematically
  color = color unchanged whenever rainStrength is 0 -- clear weather
  is never hazy.
- Rain lighting: direct sunlight is multiplied by an extra 0.75 at
  full rain (exact 1.0/no-op at rainStrength 0), and the sky-exposed
  portion of ambient gets up to +15% brightness at full rain, masked
  by actual sky exposure so indoor/torch-lit ambient is untouched.
  Softens contrast toward an overcast look without touching shadow
  strength itself.
- Both ride on rainStrength, which the game already ramps smoothly
  from 0 to 1 over the transition period, so darkening/haze naturally
  build in gradually rather than snapping on.

Weather clouds (clouds.fsh):
- Clear weather is now brighter and more opaque than before (a
  deliberate, requested change, not a side effect): a 1.15x tint and
  0.90 base alpha, versus the old flat 0.85.
- Rain and thunderstorms (using the engine's separate thunderStrength)
  progressively darken, thicken (higher alpha) and flatten (narrower
  brightness-variation range) the clouds, with a distinct, slightly
  denser, blue-grey-tinted storm state on top of rain. The existing
  day/night tint and sun-glow rim are untouched in their own right --
  the weather tint multiplies on top of them, and the glow itself
  dims during rain since the sun would realistically be obscured.

Cave atmosphere (terrain.fsh, water.fsh, common.glsl):
- Two new colour-only functions, both luminance-neutral by
  construction: caveEntranceScatter (a subtle blue shift that peaks
  specifically in the transition zone between full sky exposure and
  none, i.e. a cave mouth, and is exactly zero both out in the open
  and deep underground) and caveWarmthBoost (a slightly warmer,
  slightly wider-reaching tint around torches/lava, evoking soft
  bounce without adding or removing any brightness). Both renormalize
  to the input's own luminance before blending, so cave brightness is
  provably identical to before -- only hue shifts.
- Both can be turned off entirely via the new Cave Atmosphere option
  if you'd rather have plain vanilla cave colour.

Clouds
------
Clouds got a small, deliberately lightweight polish pass: a cheap
4-tap value-noise (two octaves, no textures, no loops beyond the
fixed taps) breaks up the previously flat, uniform box-shading into
soft, subtly varying density -- not volumetric, just gentle depth and
texture. Cloud lighting now uses the same shared day/night calculation
as the rest of the pack, with a silver-lining rim that goes warm-gold
at sunset and a dim, cool, subtle glow at night, fading back to the
original daytime look exactly at full day. Sky colors, fog, and
everything outside the two cloud shader files are untouched.

What it deliberately leaves out (for performance and stability)
------------------------------------------------------------------
No SSR, no ray/path tracing, no volumetric lighting/fog or light
shafts, no motion blur, no depth of field, no heavy multi-pass bloom.
Auto exposure is intentionally a single-frame reactive approximation
rather than a multi-frame temporally-smoothed one: true temporal
smoothing needs a persistent render target and multi-render-target
output (DRAWBUFFERS), which is exactly the kind of feature most likely
to hit edge-case driver bugs on Apple's OpenGL implementation. This
version gets most of the practical benefit (the sun/sky no longer
blows out the screen) with zero added risk on the hardware this pack
targets.

The whole pipeline is still just: gbuffers (forward-shaded, including
shadow sampling) -> one small shadow pass -> composite -> final.

In-game options (Options > Video Settings > Shader Options)
-------------------------------------------------------------
Lighting:      Soft Shadows, Minimum Ambient Light
Environment:   Plant & Leaf Sway, Height Fog Strength, Underwater Caustics, Cave Atmosphere
Weather:       Rain Haze Strength
Post-Processing: Sunlight Warmth, Bloom Strength, Vignette Strength

Two profiles: "Balanced" and "Potato (Max FPS)" (disables soft
shadows, plant sway, underwater caustics and cave atmosphere for
extra FPS).

Tuning further for FPS
-----------------------
- Switch to the "Potato" profile.
- Lower Minecraft's own render distance / simulation distance -- the
  shadow pass distance (96 blocks) already scales with it.
- Lower Minecraft's resolution/GUI scale if needed.
