Loading...
Searching...
No Matches
PBRMesh.hpp
1#pragma once
2#include "TransformHelper.hpp"
3
4#include <ossia/dataflow/geometry_port.hpp>
5
6#include <Gfx/Graph/GpuResourceRegistry.hpp>
7
8#include <Threedim/TinyObj.hpp>
9#include <halp/controls.hpp>
10#include <halp/geometry.hpp>
11#include <halp/meta.hpp>
12#include <halp/texture.hpp>
13
14#include <cstdint>
15#include <memory>
16#include <vector>
17
18class QRhiResourceUpdateBatch;
19
20namespace score::gfx
21{
22class RenderList;
23struct Edge;
24}
25
26namespace Threedim
27{
28
29// Wraps a GPU-resident geometry (the output of a compute-shader framework
30// node — `halp::dynamic_gpu_geometry`) as a one-node scene_spec with a
31// PBR material attached. The bridge between "CSF produces a geometry"
32// and "scene-graph pipeline consumes scene_spec".
33//
34// Typical wiring:
35// CSFNode(mesh_out) → PBRMesh(mesh_in, texture_in) → ScenePreprocessor
36//
37// The node emits a single scene_node at the root holding:
38// - a scene_transform built from the TRS controls
39// - the transform of the input geometry, applied before the TRS controls
40// - a mesh_component wrapping the GPU geometry into one mesh_primitive
41// - a direct material_component_ptr, also published into the scene's
42// material list: one material_component carrying the factor controls
43// plus any wired-in runtime textures
44//
45// The input geometry's auxiliary buffers and textures are published on the
46// scene as named injections, so a raster after the Scene Preprocessor binds
47// them by name as it would on the geometry itself. The ones a Scene
48// Preprocessor publishes for its own scene (per_draws, scene_materials, ...)
49// are left out: fed another preprocessor's output, they would replace the
50// next preprocessor's.
51//
52// Texture inputs route through the Dynamic Texture pathway in
53// ScenePreprocessor: non-null handles become `*Dyn<slot>` auxiliary-texture
54// bindings that classic_pbr_full samples directly, no CPU upload, no
55// array-layer copy. Unwired inputs fall through to the scalar factors.
57{
58public:
59 halp_meta(name, "PBR Mesh")
60 halp_meta(category, "Visuals/3D/Scene")
61 halp_meta(c_name, "pbr_mesh")
62 halp_meta(description, "Wrap GPU geometry in a 3D scene with a transform and configurable PBR material.")
63 halp_meta(authors, "ossia team")
64 halp_meta(
65 manual_url, "https://ossia.io/score-docs/processes/pbr-mesh.html")
66 halp_meta(uuid, "d7a2f5c9-3e8b-4b1d-a6f2-5c8e9d1f3b7a")
67
68 struct ins
69 {
70 struct
71 {
72 halp_meta(name, "Mesh");
73 halp::dynamic_gpu_geometry mesh;
74 float transform[16]{};
75 bool dirty_mesh = false;
76 bool dirty_transform = false;
77 } geometry_in;
78
79 // Texture slots. Non-null handle → emitted as a dynamic texture
80 // on the material; null → shader falls back to the scalar factor.
81 halp::gpu_texture_input<"Base Color Tex"> base_color_tex;
82 halp::gpu_texture_input<"Metal Rough Tex"> metal_rough_tex;
83 halp::gpu_texture_input<"Normal Tex"> normal_tex;
84 halp::gpu_texture_input<"Emissive Tex"> emissive_tex;
85
86 // PBR factors — used as-is by the material (no per-factor toggle:
87 // defaults here match glTF defaults, so "untouched" controls produce
88 // a reasonable neutral material).
89 halp::color_chooser<"Color"> base_color;
90 halp::hslider_f32<"Metallic", halp::range{0., 1., 0.}> metallic;
91 halp::hslider_f32<"Roughness", halp::range{0., 1., 0.5}> roughness;
92 // Emissive colour (alpha unused) times strength; strength goes above 1
93 // for HDR emission.
94 halp::color_chooser<"Emissive", halp::color_init{.init = {0., 0., 0., 1.}}>
95 emissive;
96 halp::hslider_f32<"Emissive strength", halp::range{0., 100., 1.}> em_strength;
97
98 // Root-node placement. Same TRS controls as Transform3D / Instancer
99 // so the node stands alone without a separate transform upstream.
100 PositionControl position;
101 RotationControl rotation;
102 ScaleControl scale;
103 } inputs;
104
105 struct outs
106 {
107 struct
108 {
109 halp_meta(name, "Scene Out");
110 ossia::scene_spec scene;
111 uint8_t dirty{0};
112 } scene_out;
113 } outputs;
114
115 void operator()();
116
117 // Render-thread hooks. init allocates a Material arena slot and seeds
118 // it with default bytes; update packs the factor fields from the
119 // control inputs into a MaterialGPU and uploads to the slot; release
120 // returns the slot. Texture references (textureRefs[]) are left at
121 // tex_ref_none() here — the preprocessor resolves those during its
122 // material-channel upload pass because only it knows the per-channel
123 // dynamic-slot / static-layer assignments for the upstream handles.
124 void init(score::gfx::RenderList& r, QRhiResourceUpdateBatch& res);
125 void update(
126 score::gfx::RenderList& r, QRhiResourceUpdateBatch& res,
128 void release(score::gfx::RenderList& r);
129
130 // Republished stable shared_ptr when nothing changed, so ScenePreprocessor's
131 // identity/fingerprint caches stay warm.
132 std::shared_ptr<const ossia::scene_state> m_wrapped_state;
133 CachedTRS m_cachedTRS{};
134
135 // Identity cache: upstream mesh-buffer handles + vertex/index count +
136 // texture handles + factor values. Dirty if any change.
137 void* m_cached_buf0{};
138 int64_t m_cached_vertices{-1};
139 int64_t m_cached_indices{-1};
140 void* m_cached_tex[4]{};
141 float m_cached_factors[10]{};
142 float m_cached_upstream[16]{};
143 std::vector<void*> m_cached_aux;
144 int64_t m_version_counter{0};
145
146 // Stable ids minted once on first rebuild and reused across every
147 // subsequent rebuild so downstream fingerprint / SER / BVH caches stay
148 // identity-stable.
149 uint64_t m_material_stable_id{};
150 uint64_t m_primitive_stable_id{};
151 uint64_t m_xform_stable_id{};
152 uint64_t m_upstream_xform_stable_id{};
153
154 // Slots: one in the Material arena, one in RawTransform for the
155 // emitted scene_transform. Allocated in init(), written in update(),
156 // freed in release().
158 score::gfx::GpuResourceRegistry::Slot raw_transform_slot;
159
160 // Ossia-facing snapshots. Written once in init() on the render
161 // thread; copied onto the emitted material_component /
162 // scene_transform raw_slot in operator()().
163 ossia::gpu_slot_ref m_material_ref{};
164 ossia::gpu_slot_ref m_xform_ref{};
165};
166
167}
Definition PBRMesh.hpp:57
List of nodes to be rendered to an output.
Definition RenderList.hpp:33
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
Definition TransformHelper.hpp:26
Definition PBRMesh.hpp:69
Definition PBRMesh.hpp:106
Definition TinyObj.hpp:98
Definition TinyObj.hpp:103
Definition TinyObj.hpp:107
Definition TinyObj.hpp:27
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:236
Definition GpuResourceRegistry.hpp:84