Sprite sheets, atlases, game UI, time of day, weather presets, headless captures

- BillboardInstance: per-instance uv sub-rect, feet anchor, turn, dithered alpha, flash;
  BillboardBatch::sharedTexture; Texture createEmpty/update/cellUV/cellAnchor/nearest
- SpriteAtlas: fixed-cell runtime atlas with gutters
- hd2d::ui: Octopath-style panels, fonts (Cinzel, EB Garamond), dialogue box with
  typewriter + portraits + choices, menus, nameplates, toasts, ImGui theme
- DayCycle (dawn/day/dusk/night keyframes, sun + moon arcs), Weather overcast/mist/
  lightning, night-aware presets, stars and moon in the sky
- Hidden-window offscreen captures (Window visible=false, Renderer output FBO,
  OffscreenTarget); --screenshot never opens a window
- Camera::worldToScreen; CMake usable via add_subdirectory (HD2D_BUILD_DEMO,
  HD2D_ENGINE_ASSET_DIR)
This commit is contained in:
Gabrieal Jimmy
2026-10-02 15:05:23 -05:00
parent 16c03afd16
commit 83a1f16806
44 changed files with 2835 additions and 226 deletions

View File

@@ -28,6 +28,7 @@ layout(std140, binding = 0) uniform Frame {
vec4 uWaterParams; // level, caustics intensity, has water, unused
vec4 uGroundAO; // world -> uv: minX, minZ, 1/sizeX, 1/sizeZ (z = 0: disabled)
vec4 uWeather; // rain intensity, surface wetness, rain fall speed, unused
vec4 uSkyParams; // night (stars + moon disc at uSunDir), extra cloud cover, unused, unused
ivec4 uLightCount;
vec4 uLightPos[16]; // xyz, w = radius
vec4 uLightColor[16];
@@ -168,18 +169,30 @@ vec3 wetSurface(vec3 albedo, vec3 n, vec3 V, float vis, out vec3 sheen) {
return albedo * mix(1.0, 0.68, uWeather.y);
}
// Cloud layer opacity toward `dir` (0 at and below the horizon). Rain and
// uSkyParams.y (overcast) thicken it.
float skyClouds(vec3 dir) {
if (dir.y <= 0.0) return 0.0;
float cover = max(uWeather.x, uSkyParams.y);
vec2 cp = dir.xz / (dir.y + 0.12) * 1.3 + uTime * vec2(0.012, 0.004);
return smoothstep(0.5 - 0.45 * cover, 0.85 - 0.3 * cover, fbm2(cp)) * 0.55 * smoothstep(0.0, 0.2, dir.y);
}
vec3 skyColor(vec3 dir) {
float h = dir.y;
vec3 c = mix(uSkyHorizon.rgb, uSkyZenith.rgb, pow(clamp(h, 0.0, 1.0), 0.55));
if (h < 0.0) c = mix(uSkyHorizon.rgb, uSkyGround.rgb, clamp(-h * 3.0, 0.0, 1.0));
float sd = max(dot(dir, uSunDir.xyz), 0.0);
float night = uSkyParams.x;
if (h > 0.0) {
vec2 cp = dir.xz / (h + 0.12) * 1.3 + uTime * vec2(0.012, 0.004);
float cl = smoothstep(0.5 - 0.45 * uWeather.x, 0.85 - 0.3 * uWeather.x, fbm2(cp)); // overcast when raining
c = mix(c, uSunColor.rgb * (0.75 + 0.6 * sd), cl * 0.55 * smoothstep(0.0, 0.2, h));
// Clouds catch the sun by day; at night they are faintly moonlit.
vec3 lit = mix(uSunColor.rgb * (0.75 + 0.6 * sd),
uSkyHorizon.rgb * 1.6 + uSunColor.rgb * uSunDir.w * (0.02 + 0.3 * pow(sd, 8.0)), night);
c = mix(c, lit, skyClouds(dir));
}
c += uSunColor.rgb * (pow(sd, 900.0) * 40.0 + pow(sd, 10.0) * 0.3);
// Sun disc + halo (the moon replaces it at night, overcast hides it).
float sunVis = (1.0 - night) * (1.0 - uSkyParams.y) * clamp(uSunDir.w * 2.0, 0.0, 1.0);
c += uSunColor.rgb * (pow(sd, 900.0) * 40.0 + pow(sd, 10.0) * 0.3) * sunVis;
return c;
}