Loading...
Searching...
No Matches
EnvironmentLoader.hpp
1#pragma once
2#include <halp/controls.hpp>
3#include <halp/meta.hpp>
4
5#include <ossia/dataflow/geometry_port.hpp>
6
7#include <Gfx/Graph/GpuResourceRegistry.hpp>
8
9#include <cstdint>
10#include <memory>
11
12class QRhiResourceUpdateBatch;
13
14namespace score::gfx
15{
16class RenderList;
17struct Edge;
18}
19
20namespace Threedim
21{
22
23// Scene-producing node that defines the environment of a scene:
24// ambient light, exposure, gamma, fog.
25//
26// Pairs with the project-wide scene_spec merge rule: environment is
27// merged field-by-field using the params_set bitmask. This node sets
28// only ambient / exposure-gamma / fog bits — skybox texture and IBL
29// handles are owned by CubemapLoader / CubemapComposer (and a future
30// EnvironmentPrecompute for real IBL) and overlay cleanly via
31// merge_scenes.
32//
33// Downstream pipeline:
34// - `ossia::merge_scenes` overlays this environment onto the merged
35// scene_state — field groups without matching bits pass through
36// from whichever producer set them.
37// - ScenePreprocessor packs scene_environment fields into an Environment
38// Params UBO (auto-bound as aux buffer on Geometry Out).
39// - classic_pbr_ibl shaders read the UBO for ambient / exposure / fog.
41{
42public:
43 halp_meta(name, "Environment")
44 halp_meta(c_name, "environment_loader")
45 halp_meta(category, "Visuals/3D")
46 halp_meta(authors, "ossia team")
47 halp_meta(uuid, "d3f5a8c1-8b47-4e91-9c2d-6f1a9b5e3c82")
48
49 struct ins
50 {
51 // Port-driven rebuild: each control's update() callback fires only
52 // on real change, triggering EnvironmentLoader::rebuild().
53 struct : halp::xyz_spinboxes_f32<"Ambient Color", halp::range{0., 1., 0.03}>
54 { void update(EnvironmentLoader& n) { n.rebuild(); } } ambient_color;
55 struct : halp::hslider_f32<"Ambient Intensity", halp::range{0., 8., 1.}>
56 { void update(EnvironmentLoader& n) { n.rebuild(); } } ambient_intensity;
57
58 // Photographic exposure value at ISO 100. Describes the scene's
59 // expected brightness in photometric terms; downstream shaders
60 // compensate so brighter scenes (higher EV100) display darker
61 // without manual rebalancing. Reference values:
62 // EV100 ≈ -3 moonlit night
63 // EV100 ≈ 3 indoor lighting
64 // EV100 ≈ 12 midday outdoor
65 // EV100 ≈ 16 direct sunlight
66 // EV100 = 0 leaves the linear multiplier at 1× (combined with the
67 // default exposure_stops below it), so a scene that never touches
68 // this control renders unchanged.
69 struct : halp::hslider_f32<"Exposure EV100", halp::range{-6., 18., 0.}>
70 { void update(EnvironmentLoader& n) { n.rebuild(); } } ev100;
71
72 // Fine-tune compensation atop EV100, in stops (±EV). Same role as
73 // a photographer's "exposure compensation" dial: ev100 sets the
74 // photographic anchor, exposure_stops biases above/below.
75 struct : halp::hslider_f32<"Exposure (stops)", halp::range{-8., 8., 0.}>
76 { void update(EnvironmentLoader& n) { n.rebuild(); } } exposure_stops;
77 struct : halp::hslider_f32<"Gamma", halp::range{1., 3., 2.2}>
78 { void update(EnvironmentLoader& n) { n.rebuild(); } } gamma;
79
80 struct : halp::toggle<"Fog">
81 { void update(EnvironmentLoader& n) { n.rebuild(); } } fog_enabled;
82 struct : halp::xyz_spinboxes_f32<"Fog Color", halp::range{0., 1., 0.8}>
83 { void update(EnvironmentLoader& n) { n.rebuild(); } } fog_color;
84 struct : halp::hslider_f32<"Fog Start", halp::range{0., 1000., 10.}>
85 { void update(EnvironmentLoader& n) { n.rebuild(); } } fog_start;
86 struct : halp::hslider_f32<"Fog End", halp::range{0., 10000., 100.}>
87 { void update(EnvironmentLoader& n) { n.rebuild(); } } fog_end;
88
89 // Downstream render-target dimensions (width, height). Stamped on
90 // scene_environment::render_target_size + params_render_target_size
91 // bit when both values > 0. Overrides the preprocessor's default
92 // derivation from the RenderList swap chain.
93 struct : halp::xy_spinboxes_i32<"Render target size", halp::range{0, 16384, 0}>
94 { void update(EnvironmentLoader& n) { n.rebuild(); } } render_target_size;
95 } inputs;
96
97 struct outs
98 {
99 struct
100 {
101 halp_meta(name, "Scene");
102 ossia::scene_spec scene;
103 uint8_t dirty{0};
104 } scene_out;
105 } outputs;
106
107 // Rebuild m_state from current inputs. Invoked by each port's
108 // update() callback on real control changes. operator()() just
109 // republishes m_state, so the emitted shared_ptr + version stay
110 // stable when nothing changed — keeps every downstream cache hot.
111 void rebuild();
112 void operator()();
113
114 // Render-thread GPU hooks, invoked by CpuFilterNode. init allocates a
115 // slot in the Env arena once; update rebuilds the EnvParamsUBO bytes
116 // and uploads them into the slot (ScenePreprocessor will later pick
117 // these up directly instead of repacking the CPU struct — producer
118 // half only for now); release returns the slot.
119 void init(score::gfx::RenderList& r, QRhiResourceUpdateBatch& res);
120 void update(
121 score::gfx::RenderList& r, QRhiResourceUpdateBatch& res,
123 void release(score::gfx::RenderList& r);
124
125 // Invariant identity for the shared scene_environment struct we emit —
126 // holding one stable scene_state across frames lets downstream
127 // `scene.state.get()` comparisons short-circuit the no-op case. We
128 // mutate the state's environment in place on parameter changes.
129 std::shared_ptr<ossia::scene_state> m_state;
130 int64_t m_version{0};
131 uint8_t m_pending_dirty{ossia::scene_port::dirty_environment};
132
133 // Slot in RenderList::registry().buffer(Env). Allocated in init(),
134 // written in update(), freed in release().
136
137 // Ossia-facing snapshot of env_slot, stamped on scene_state::
138 // environment.raw_slot in operator()() so the preprocessor can
139 // resolve our slot via isLive(). Written once in init() on the
140 // render thread, read every tick in operator()() on the execution
141 // thread (trivially-copyable POD, initialised to zero so pre-init
142 // reads look like an invalid ref).
143 ossia::gpu_slot_ref m_env_ref{};
144};
145
146}
Definition EnvironmentLoader.hpp:41
List of nodes to be rendered to an output.
Definition RenderList.hpp:30
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
Definition EnvironmentLoader.hpp:98
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:103
Definition GpuResourceRegistry.hpp:84