Files
Vibe-HD-2D/engine/include/hd2d/Renderer.h
Gabrieal Jimmy 83a1f16806 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)
2026-10-02 15:05:23 -05:00

111 lines
3.9 KiB
C++

#pragma once
#include "hd2d/Camera.h"
#include "hd2d/RenderTarget.h"
#include "hd2d/Scene.h"
#include "hd2d/Shader.h"
#include <glm/glm.hpp>
#include <memory>
#include <string>
namespace hd2d {
// All tunable look parameters of the HD-2D pipeline.
struct RenderSettings {
// Shadows
int shadowMapSize = 4096;
float shadowExtent = 34.0f; // half-size of the sun's ortho frustum, world units
float shadowSoftness = 1.5f; // PCF radius in texels
// Dappled canopy light ("cookie" projected along the sun direction)
float cookieStrength = 0.55f;
float cookieScale = 0.13f;
float cookieSpeed = 0.05f;
float cookieCoverage = 0.48f; // fraction of light blocked
// God ray beams: the same implied canopy, sparser, applied inside the fog
float shaftStrength = 0.9f; // 1 = sun scatters only inside beams
float shaftCoverage = 0.62f; // higher = fewer, narrower beams
float shaftScale = 0.45f; // beam pattern frequency (larger = thinner beams)
// Volumetric fog + god rays
bool volumetrics = true;
glm::vec3 fogColor{0.30f, 0.36f, 0.45f}; // ambient fog in-scatter tint
float fogDensity = 0.008f;
float fogHeightFalloff = 0.15f;
float fogBaseHeight = 0.0f;
float fogNoise = 0.6f;
float fogAnisotropy = 0.62f; // Henyey-Greenstein g (forward scattering)
float godRayIntensity = 4.5f;
float fogMaxDistance = 90.0f;
int fogSteps = 56;
// Wind for foliage
glm::vec2 windDirection{0.8f, 0.35f};
float windStrength = 0.06f;
float windGustSpeed = 1.2f;
// Depth of field (tilt-shift miniature look)
bool dof = true;
float focusRange = 6.0f; // fully sharp half-width around the focus distance
float focusTransition = 12.0f; // distance over which blur ramps up
float dofMaxRadius = 9.0f; // max blur radius in half-res pixels
float tiltShift = 0.35f; // extra blur toward screen top/bottom
// Bloom
bool bloom = true;
float bloomStrength = 0.075f;
float bloomRadius = 1.0f;
// Color grading
float exposure = 1.0f;
float contrast = 1.08f;
float saturation = 1.12f;
glm::vec3 lift{0.012f, 0.010f, 0.025f}; // added to shadows
glm::vec3 gain{1.04f, 1.00f, 0.93f}; // multiplied into highlights
float vignette = 0.42f;
float chromaticAberration = 0.0015f;
float grain = 0.025f;
bool reflections = true;
bool occluderFade = true; // dither away 3D scenery between the camera and the player
// Screen-space ambient occlusion (contact darkening everywhere; the baked
// GroundOcclusion handles the large soft shade under trees)
bool ssao = true;
bool groundOcclusion = true; // use Scene::groundOcclusion (baked contact AO)
float ssaoRadius = 0.7f; // world units
float ssaoIntensity = 1.6f;
int maxRainDrops = 18000; // streaks drawn at Scene::rain = 1
};
class Renderer {
public:
Renderer();
~Renderer();
bool init(const std::string& shaderDir, int width, int height);
void resize(int width, int height);
bool reloadShaders();
void render(const Scene& scene, const Camera& camera, float time);
// Framebuffer the final tonemap pass writes to (0 = the window's
// backbuffer). render() leaves it bound with a full-size viewport, so UI
// drawn afterwards (DebugUI, ImGui) lands in it too. It must be at least
// the size given to init()/resize() and use a non-sRGB RGBA8 color
// attachment like the default framebuffer (the tonemap shader
// gamma-encodes itself); OffscreenTarget in Screenshot.h does this.
void setOutputFramebuffer(GLuint fbo) { outputFbo_ = fbo; }
GLuint outputFramebuffer() const { return outputFbo_; }
RenderSettings settings;
float gpuFrameMs() const { return gpuMs_; }
private:
struct Impl;
std::unique_ptr<Impl> impl_;
float gpuMs_ = 0.0f;
GLuint outputFbo_ = 0;
};
} // namespace hd2d