- 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)
70 lines
3.0 KiB
C++
70 lines
3.0 KiB
C++
#pragma once
|
|
#include "hd2d/GL.h"
|
|
#include "hd2d/Texture.h"
|
|
|
|
#include <glm/glm.hpp>
|
|
#include <vector>
|
|
|
|
namespace hd2d {
|
|
|
|
// One upright pixel-art sprite. `pos` is where the feet (pivot) row touches
|
|
// the ground; sprites face the camera around the Y axis. 64 bytes, read by
|
|
// billboard.vert as four vec4 attributes (keep both in sync).
|
|
//
|
|
// A default-initialised instance draws the whole texture, planted by its
|
|
// lowest opaque row. Set `uv` to draw one frame of a sprite sheet / atlas
|
|
// cell (see Texture::cellUV, SpriteAtlas::uv) and `anchor` to that frame's
|
|
// feet row (Texture::cellAnchor, SpriteAtlas::anchor).
|
|
struct BillboardInstance {
|
|
glm::vec3 pos{0.0f};
|
|
float sway = 0.0f; // wind / player-push response (0 = rigid)
|
|
glm::vec2 size{1.0f}; // world size of the `uv` sub-rect quad
|
|
float flip = 0.0f; // 1 = mirror horizontally (inside the sub-rect)
|
|
float tint = 1.0f; // brightness multiplier (breaks up repetition)
|
|
glm::vec4 uv{0, 0, 1, 1}; // texture sub-rect (minU, minV, maxU, maxV), GL orientation (v = 0 is the image bottom)
|
|
float anchor = -1.0f; // texture-space v of the feet (pivot) row; < 0 = use tex().opaqueBounds().y
|
|
float turn = 0.0f; // extra yaw (radians) away from camera-facing; color pass only, shadow cards stay sun-facing
|
|
float alpha = 1.0f; // 0..1 fade, dithered discard in color and shadow passes (no blending)
|
|
float flash = 0.0f; // 0..1 blend toward bright emissive white (hit / capture flash)
|
|
};
|
|
|
|
// Instanced batch of billboards sharing one texture: its own `texture`, or
|
|
// `sharedTexture` (e.g. a SpriteAtlas page shared by many batches) when set.
|
|
class BillboardBatch {
|
|
public:
|
|
BillboardBatch() = default;
|
|
BillboardBatch(const BillboardBatch&) = delete;
|
|
BillboardBatch& operator=(const BillboardBatch&) = delete;
|
|
~BillboardBatch();
|
|
|
|
bool loadTexture(const std::string& path) { return texture.load(path); }
|
|
void upload(); // call after editing `instances`
|
|
void draw() const;
|
|
|
|
// Texture the renderer binds: `sharedTexture` if set, else `texture`.
|
|
const Texture& tex() const { return sharedTexture ? *sharedTexture : texture; }
|
|
|
|
// World size that keeps the own `texture` at `pixelsPerUnit` texel density.
|
|
glm::vec2 sizeForDensity(float pixelsPerUnit) const {
|
|
return glm::vec2(texture.size()) / pixelsPerUnit;
|
|
}
|
|
// World size of one `cellPixels` sheet frame / atlas cell at `pixelsPerUnit`.
|
|
static glm::vec2 cellSize(glm::ivec2 cellPixels, float pixelsPerUnit) {
|
|
return glm::vec2(cellPixels) / pixelsPerUnit;
|
|
}
|
|
|
|
Texture texture;
|
|
const Texture* sharedTexture = nullptr; // not owned; must outlive the batch's use
|
|
std::vector<BillboardInstance> instances;
|
|
bool castShadows = true;
|
|
bool inReflections = true;
|
|
float emissive = 0.0f; // unlit contribution, for glowing sprites
|
|
|
|
private:
|
|
GLuint vao_ = 0, vbo_ = 0;
|
|
size_t capacity_ = 0;
|
|
GLsizei count_ = 0;
|
|
};
|
|
|
|
} // namespace hd2d
|