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:
@@ -1,8 +1,11 @@
|
||||
#version 450 core
|
||||
#include "common.glsl"
|
||||
|
||||
// Per-instance attributes; must match BillboardInstance (Billboard.h).
|
||||
layout(location = 0) in vec4 iPosSway; // pivot xyz, sway
|
||||
layout(location = 1) in vec4 iSizeFlipTint; // size xy, flip, tint
|
||||
layout(location = 2) in vec4 iRect; // uv sub-rect (minU, minV, maxU, maxV)
|
||||
layout(location = 3) in vec4 iAnchorFx; // anchor v (< 0 = uOpaque.y), turn, alpha, flash
|
||||
|
||||
uniform vec4 uOpaque; // opaque pixel bounds in uv (minX, minY, maxX, maxY)
|
||||
uniform int uPass; // 0 = color, 1 = shadow
|
||||
@@ -13,22 +16,34 @@ out VS {
|
||||
vec3 pivot;
|
||||
vec2 local; // (horizontal offset, height above pivot) in world units
|
||||
float tint;
|
||||
flat vec2 fx; // alpha, flash
|
||||
} o;
|
||||
|
||||
void main() {
|
||||
vec2 corner = vec2(float(gl_VertexID & 1), float(gl_VertexID >> 1));
|
||||
vec2 size = iSizeFlipTint.xy;
|
||||
vec3 pivot = iPosSway.xyz;
|
||||
vec4 rect = iRect;
|
||||
float rectH = max(rect.w - rect.y, 1e-6);
|
||||
float anchor = iAnchorFx.x < 0.0 ? uOpaque.y : iAnchorFx.x;
|
||||
float anchorLocal = (anchor - rect.y) / rectH;
|
||||
float lx = (corner.x - 0.5) * size.x;
|
||||
float ly = (corner.y - uOpaque.y) * size.y; // lowest opaque row sits on the pivot
|
||||
float ly = (corner.y - anchorLocal) * size.y; // the feet row sits on the pivot
|
||||
|
||||
// Shadow cards face the sun so silhouettes are never edge-on to the light.
|
||||
vec3 right = uPass == 1 ? uShadowRight.xyz : uBillboardRight.xyz;
|
||||
// Shadow cards face the sun so silhouettes are never edge-on to the light;
|
||||
// `turn` yaws color cards away from camera-facing (paper turn).
|
||||
vec3 right = uBillboardRight.xyz;
|
||||
if (iAnchorFx.y != 0.0) {
|
||||
float ct = cos(iAnchorFx.y), st = sin(iAnchorFx.y);
|
||||
right = vec3(right.x * ct - right.z * st, 0.0, right.x * st + right.z * ct);
|
||||
}
|
||||
if (uPass == 1) right = uShadowRight.xyz;
|
||||
vec3 wp = pivot + right * lx + vec3(0.0, ly, 0.0);
|
||||
|
||||
float sway = iPosSway.w;
|
||||
if (sway > 0.0) {
|
||||
float visibleHeight = max(size.y * (uOpaque.w - uOpaque.y), 1e-3);
|
||||
// Feet to the top of the rect (or of the opaque pixels, if lower).
|
||||
float visibleHeight = max(size.y * (min(uOpaque.w, rect.w) - anchor) / rectH, 1e-3);
|
||||
float k = clamp(ly / visibleHeight, 0.0, 1.0);
|
||||
k *= k;
|
||||
float ph = dot(pivot.xz, vec2(0.37, 0.61));
|
||||
@@ -46,13 +61,14 @@ void main() {
|
||||
wp.y -= push * k * sway * 0.3 * visibleHeight;
|
||||
}
|
||||
|
||||
vec2 uv = corner;
|
||||
if (iSizeFlipTint.z > 0.5) uv.x = 1.0 - uv.x;
|
||||
o.uv = uv;
|
||||
vec2 c = corner;
|
||||
if (iSizeFlipTint.z > 0.5) c.x = 1.0 - c.x; // mirror inside the sub-rect
|
||||
o.uv = mix(rect.xy, rect.zw, c);
|
||||
o.worldPos = wp;
|
||||
o.pivot = pivot;
|
||||
o.local = vec2(lx, ly);
|
||||
o.tint = iSizeFlipTint.w;
|
||||
o.fx = iAnchorFx.zw;
|
||||
gl_Position = uViewProj * vec4(wp, 1.0);
|
||||
gl_ClipDistance[0] = dot(vec4(wp, 1.0), uClipPlane);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user