acdream/src/AcDream.App/Rendering
Erik 4678b3ee6b fix(sky): apply per-Surface Translucency + Luminosity for retail-faithful weather
Two independent brightness bugs were compounding to make rain ~6.7×
too bright at the cylinder rim, and clouds full-bright instead of
time-of-day-tinted:

**Fix 1 — Surface.Translucency was never plumbed to the shader.**

Retail's D3DPolyRender::SetSurface at 0x59c767: when the Surface's
Translucent (0x10) bit is set, its translucency float drives per-vertex
alpha (curr_alpha = ftol(0.5 × 255) = 127). ACViewer
(TextureCache.cs:142) and WorldBuilder (ObjectMeshManager.cs:1115) both
encode the same as `opacity = (1 - x)`. acdream read only Surface.Type
and Surface.Luminosity in GfxObjMesh.Build() — Surface.Translucency
(the float) was never read, never stored, never reached the shader.
For the rain Surface 0x080000C5 (Translucency=0.5) this meant rain
streaks were at full alpha=1.0 instead of 0.5 — 2× brighter than retail
under the (SrcAlpha, One) blend.

Plumbed end-to-end:
  GfxObjSubMesh.SurfTranslucency (init float, default 0)
  GfxObjMesh.Build() reads surface.Translucency next to .Luminosity
  SubMeshGpu.SurfTranslucency carries it to draw time
  SkyRenderer.RenderPass writes uniform `uSurfTranslucency`
  sky.frag final alpha: a = sampled.a × (1 - uTransparency) ×
                            (1 - uSurfTranslucency)

Bonus reach: cloud surface 0x08000023 has Translucency=0.25 → clouds
also dimmed by 25%, more retail-faithful overall.

**Fix 2 — Emissive default was 1.0 instead of the surface's actual Luminosity.**

The sky shader's `effEmissive = (luminosity > 0) ? luminosity : sub.SurfLuminosity`
fallback never fired because the local `luminosity` defaulted to 1f (always
> 0). Every sky mesh got effEmissive=1.0, saturating vTint to white before
the alpha blend. The comment claimed the fallback was active; the code
disagreed.

Empirical sky-surface LUMINOUS audit (RainMeshProbe a6e7108) found that
NO Dereth sky surface carries the SurfaceType.Luminous flag (0x40) —
the previous code comment that did was wrong. The differentiator is
purely the Surface.Luminosity FLOAT:
  dome/sun/moon: Lum=1.0 → vTint saturates → texture passthrough
  stars/clouds:  Lum=0.0 → vTint = ambient + sun·N·L → time-of-day tint
  rain:          Lum=0.1484 → faint emissive baseline + lit additions

Refactored:
  replaceLuminosity = NaN sentinel for "no replace override"
  rep.Luminosity > 0  → set replaceLuminosity to override value
  rep.MaxBright  > 0  → cap replaceLuminosity at MaxBright
  effEmissive = NaN ? sub.SurfLuminosity : replaceLuminosity

Dead uniform `uLuminosity` removed from sky.frag and SkyRenderer SetFloat
call — the redundant multiply was already commented-out earlier this
year (would have double-dimmed clouds), and the uniform value was unused
in the fragment.

Visual verification (Holtburg, live ACE, Rainy DG forced and natural
LCG-picked): rain rim is no longer visible; cloud direction matches
retail when the same DayGroup is active; sky lighting transitions through
day cycle with appropriate time-of-day tint on stars/clouds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:04:55 +02:00
..
Shaders fix(sky): apply per-Surface Translucency + Luminosity for retail-faithful weather 2026-04-27 12:04:55 +02:00
Sky fix(sky): apply per-Surface Translucency + Luminosity for retail-faithful weather 2026-04-27 12:04:55 +02:00
BitmapFont.cs feat(ui): debug overlay + refined input controls 2026-04-17 18:45:38 +02:00
CameraController.cs feat(app): Phase B.2 — CameraController chase mode 2026-04-12 14:29:47 +02:00
CellVisibility.cs feat(render): portal-based EnvCell visibility (Step 4) 2026-04-13 22:20:52 +02:00
ChaseCamera.cs fix(camera): pin chase-camera Z to last-grounded while airborne 2026-04-26 18:23:02 +02:00
DebugLineRenderer.cs feat(ui): debug overlay + refined input controls 2026-04-17 18:45:38 +02:00
FlyCamera.cs feat(app): slow default fly speed and add Shift-boost 2026-04-11 19:19:12 +02:00
FrustumCuller.cs feat(app): Phase A.2 — FrustumCuller + FrustumPlanes (Gribb-Hartmann) 2026-04-12 08:49:17 +02:00
GameWindow.cs feat(sky): split SkyRenderer into pre-/post-scene passes + retail -120m weather Z offset 2026-04-27 08:49:42 +02:00
ICamera.cs feat(app): extract ICamera interface from OrbitCamera 2026-04-10 20:24:29 +02:00
InstancedMeshRenderer.cs feat(render): Phase G.1/G.2 — SceneLighting UBO + sky renderer + shader integration 2026-04-19 10:39:48 +02:00
OrbitCamera.cs feat(app): extract ICamera interface from OrbitCamera 2026-04-10 20:24:29 +02:00
ParticleRenderer.cs feat(render): Phase G.1 — billboard particle renderer for weather + spells 2026-04-19 10:42:05 +02:00
SceneLightingUboBinding.cs feat(render): Phase G.1/G.2 — SceneLighting UBO + sky renderer + shader integration 2026-04-19 10:39:48 +02:00
Shader.cs feat(ui): debug overlay + refined input controls 2026-04-17 18:45:38 +02:00
StaticMeshRenderer.cs fix(app): multi-point Z sampling + never-cull player landblock 2026-04-12 21:29:54 +02:00
TerrainAtlas.cs feat(core+app): per-cell terrain texture blending (Phase 3c.4) 2026-04-11 14:02:15 +02:00
TerrainChunkRenderer.cs feat(render): Phase G.1/G.2 — SceneLighting UBO + sky renderer + shader integration 2026-04-19 10:39:48 +02:00
TerrainRenderer.cs perf(terrain): single shared VAO/VBO/EBO for all landblocks 2026-04-13 21:30:43 +02:00
TextRenderer.cs feat(ui): debug overlay + refined input controls 2026-04-17 18:45:38 +02:00
TextureCache.cs sky(phase-8): retail-faithful night sky + README refresh 2026-04-24 20:34:36 +02:00