- 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)
57 lines
2.2 KiB
C++
57 lines
2.2 KiB
C++
#pragma once
|
|
#include "hd2d/Texture.h"
|
|
|
|
#include <glm/glm.hpp>
|
|
#include <vector>
|
|
|
|
namespace hd2d {
|
|
|
|
// Fixed-cell dynamic atlas on one Texture: images of up to `cellPixels` are
|
|
// packed into a cols x rows grid at runtime (e.g. sprites generated or
|
|
// downloaded while the game runs) so many billboards share a texture. Use
|
|
// with `BillboardBatch::sharedTexture = &atlas.texture()` and per-instance
|
|
// `uv = atlas.uv(slot)`, `anchor = atlas.anchor(slot)`.
|
|
//
|
|
// Every cell keeps its own 1-px transparent border (gutter), so sharp
|
|
// bilinear sampling and the first mip levels never bleed between cells.
|
|
// Images are placed bottom-centered in their cell; images larger than the
|
|
// cell are cropped to it (keeping the bottom rows and the horizontal center).
|
|
class SpriteAtlas {
|
|
public:
|
|
// Allocates a transparent texture of cols x rows cells. Clears all slots.
|
|
bool init(glm::ivec2 cellPixels, int cols, int rows);
|
|
|
|
int add(const Image& img); // first free slot, or -1 when full
|
|
void set(int slot, const Image& img); // replace (or fill) a slot
|
|
void remove(int slot); // clear a slot and free it
|
|
|
|
// BillboardInstance::uv of the whole cell (cellPixels, gutter excluded).
|
|
glm::vec4 uv(int slot) const;
|
|
// BillboardInstance::anchor: v of the lowest opaque (alpha >= 128) row of
|
|
// the image in `slot`; the cell bottom if it has no opaque pixels.
|
|
float anchor(int slot) const;
|
|
glm::ivec2 imageSize(int slot) const; // size placed in the cell (after cropping)
|
|
bool inUse(int slot) const;
|
|
|
|
const Texture& texture() const { return texture_; }
|
|
glm::ivec2 cellPixels() const { return cell_; }
|
|
int capacity() const { return cols_ * rows_; }
|
|
int used() const { return used_; }
|
|
|
|
private:
|
|
struct Slot {
|
|
bool used = false;
|
|
glm::ivec2 size{0};
|
|
int feetRow = 0; // lowest opaque row, in cell pixels from the cell bottom
|
|
};
|
|
glm::ivec2 origin(int slot) const; // GL-orientation pixel of the cell's bottom-left (inside the gutter)
|
|
bool valid(int slot) const { return slot >= 0 && slot < capacity(); }
|
|
|
|
Texture texture_;
|
|
glm::ivec2 cell_{0};
|
|
int cols_ = 0, rows_ = 0, used_ = 0;
|
|
std::vector<Slot> slots_;
|
|
};
|
|
|
|
} // namespace hd2d
|