Skip to content

Commit 2ab6165

Browse files
committed
Inspect DirLights in editor
- Put dir lights in `Lights`, inspect whole struct. - Fix `Buffer` views not using data size (instead whole size of buffer). - Fix RGB inspection: discard intensity when editing colour. - Allow adding / removing lights (at least one must remain).
1 parent d9e0159 commit 2ab6165

File tree

9 files changed

+92
-32
lines changed

9 files changed

+92
-32
lines changed

lib/engine/include/facade/engine/editor/inspector.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace facade {
1010
struct Mesh;
11+
struct Lights;
1112
class Scene;
1213

1314
namespace editor {
@@ -36,6 +37,7 @@ class Inspector {
3637
bool inspect(char const* label, Rgb& out_rgb) const;
3738
bool inspect(Transform& out_transform, Bool& out_unified_scaling) const;
3839
bool inspect(std::span<Transform> out_instances, Bool unfied_scaling) const;
40+
bool inspect(Lights& out_lights) const;
3941

4042
private:
4143
bool do_inspect(Transform& out_transform, Bool& out_unified_scaling, Bool scaling_toggle) const;
@@ -47,13 +49,13 @@ class SceneInspector : public Inspector {
4749

4850
SceneInspector(NotClosed<Window> target, Scene& scene);
4951

50-
bool inspect(TreeNode const& node, UnlitMaterial& out_material) const;
51-
bool inspect(TreeNode const& node, LitMaterial& out_material) const;
52+
bool inspect(NotClosed<TreeNode>, UnlitMaterial& out_material) const;
53+
bool inspect(NotClosed<TreeNode> node, LitMaterial& out_material) const;
5254
bool inspect(Id<Material> material_id) const;
53-
bool inspect(Id<Node> node_id, Bool& out_unified_scaling) const;
54-
5555
bool inspect(Id<Mesh> mesh) const;
5656

57+
bool inspect(Id<Node> node_id, Bool& out_unified_scaling) const;
58+
5759
private:
5860
Scene& m_scene;
5961
};

lib/engine/src/editor/inspector.cpp

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,11 @@ bool Inspector::inspect_rgb(char const* label, glm::vec3& out_rgb) const {
8383
bool Inspector::inspect(char const* label, Rgb& out_rgb) const {
8484
auto ret = Modified{};
8585
if (auto tn = TreeNode{label}) {
86-
auto vec3 = out_rgb.to_vec3();
87-
if (inspect_rgb("RGB", vec3)) { ret.value = true; }
86+
auto vec3 = Rgb{.channels = out_rgb.channels, .intensity = 1.0f}.to_vec3();
87+
if (inspect_rgb("RGB", vec3)) {
88+
out_rgb = Rgb::make(vec3, out_rgb.intensity);
89+
ret.value = true;
90+
}
8891
ret(ImGui::DragFloat("Intensity", &out_rgb.intensity, 0.05f, 0.1f, 1000.0f));
8992
}
9093
return ret.value;
@@ -106,6 +109,42 @@ bool Inspector::inspect(std::span<Transform> out_instances, Bool unified_scaling
106109
return ret.value;
107110
}
108111

112+
bool Inspector::inspect(Lights& out_lights) const {
113+
if (out_lights.dir_lights.empty()) { return false; }
114+
auto ret = Modified{};
115+
auto to_remove = std::optional<std::size_t>{};
116+
bool allow_removal = out_lights.dir_lights.size() > 1;
117+
auto inspect_dir_light = [&](DirLight& out_light, std::size_t index) {
118+
auto tn = TreeNode{FixedString{"[{}]", index}.c_str()};
119+
if (allow_removal) {
120+
ImGui::SameLine(ImGui::GetWindowContentRegionWidth() - 10.0f);
121+
static constexpr auto colour_v = ImVec4{0.8f, 0.0f, 0.1f, 1.0f};
122+
ImGui::PushStyleColor(ImGuiCol_Button, colour_v);
123+
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colour_v);
124+
ImGui::PushStyleColor(ImGuiCol_ButtonActive, colour_v);
125+
if (ImGui::SmallButton("x")) { to_remove = index; }
126+
ImGui::PopStyleColor(3);
127+
}
128+
if (tn) {
129+
ret(inspect("Direction", out_light.direction));
130+
ret(inspect("Albedo", out_light.rgb));
131+
}
132+
};
133+
if (ImGui::CollapsingHeader("DirLights")) {
134+
for (auto [light, index] : enumerate(out_lights.dir_lights.span())) { inspect_dir_light(light, index); }
135+
}
136+
if (to_remove) {
137+
auto replace = decltype(out_lights.dir_lights){};
138+
for (auto const [light, index] : enumerate(out_lights.dir_lights.span())) {
139+
if (index == *to_remove) { continue; }
140+
replace.insert(light);
141+
}
142+
out_lights.dir_lights = std::move(replace);
143+
}
144+
if (out_lights.dir_lights.size() < Lights::max_lights_v && ImGui::Button("[+]")) { out_lights.dir_lights.insert(DirLight{}); }
145+
return ret.value;
146+
}
147+
109148
bool Inspector::do_inspect(Transform& out_transform, Bool& out_unified_scaling, Bool scaling_toggle) const {
110149
auto ret = Modified{};
111150
auto vec3 = out_transform.position();
@@ -127,15 +166,13 @@ bool Inspector::do_inspect(Transform& out_transform, Bool& out_unified_scaling,
127166

128167
SceneInspector::SceneInspector(NotClosed<Window> target, Scene& scene) : Inspector(target), m_scene(scene) {}
129168

130-
bool SceneInspector::inspect([[maybe_unused]] TreeNode const& node, UnlitMaterial& out_material) const {
131-
assert(node.is_open());
169+
bool SceneInspector::inspect(NotClosed<TreeNode>, UnlitMaterial& out_material) const {
132170
auto ret = Modified{};
133171
ret(inspect("Tint", out_material.tint, 0.01f, 0.0f, 1.0f));
134172
return ret.value;
135173
}
136174

137-
bool SceneInspector::inspect([[maybe_unused]] TreeNode const& node, LitMaterial& out_material) const {
138-
assert(node.is_open());
175+
bool SceneInspector::inspect(NotClosed<TreeNode>, LitMaterial& out_material) const {
139176
auto ret = Modified{};
140177
ret(ImGui::SliderFloat("Metallic", &out_material.metallic, 0.0f, 1.0f));
141178
ret(ImGui::SliderFloat("Roughness", &out_material.roughness, 0.0f, 1.0f));
@@ -168,29 +205,28 @@ bool SceneInspector::inspect(Id<Material> material_id) const {
168205
return false;
169206
}
170207

171-
bool SceneInspector::inspect(Id<Node> node_id, Bool& out_unified_scaling) const {
172-
auto ret = Modified{};
173-
auto* node = m_scene.find(node_id);
174-
if (!node) { return false; }
175-
ret(inspect(node->transform, out_unified_scaling));
176-
ret(inspect(node->instances, out_unified_scaling));
177-
if (auto const* mesh_id = node->find<Id<Mesh>>()) { ret(inspect(*mesh_id)); }
178-
return ret.value;
179-
}
180-
181208
bool SceneInspector::inspect(Id<Mesh> mesh_id) const {
182209
auto ret = Modified{};
183210
auto* mesh = m_scene.find(mesh_id);
184211
if (!mesh) { return ret.value; }
185212
if (ImGui::CollapsingHeader(FixedString{"Mesh ({})###Mesh", mesh_id}.c_str())) {
186-
for (std::size_t i = 0; i < mesh->primitives.size(); ++i) {
187-
if (auto tn = TreeNode{FixedString{"Primitive [{}]", i}.c_str()}) {
188-
auto const& primitive = mesh->primitives[i];
213+
for (auto [primitive, index] : enumerate(mesh->primitives)) {
214+
if (auto tn = TreeNode{FixedString{"Primitive [{}]", index}.c_str()}) {
189215
TreeNode::leaf(FixedString{"Static Mesh ({})", primitive.static_mesh}.c_str());
190216
if (primitive.material) { ret(inspect(*primitive.material)); }
191217
}
192218
}
193219
}
194220
return ret.value;
195221
}
222+
223+
bool SceneInspector::inspect(Id<Node> node_id, Bool& out_unified_scaling) const {
224+
auto ret = Modified{};
225+
auto* node = m_scene.find(node_id);
226+
if (!node) { return false; }
227+
ret(inspect(node->transform, out_unified_scaling));
228+
ret(inspect(node->instances, out_unified_scaling));
229+
if (auto const* mesh_id = node->find<Id<Mesh>>()) { ret(inspect(*mesh_id)); }
230+
return ret.value;
231+
}
196232
} // namespace facade::editor

lib/engine/src/scene_renderer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void SceneRenderer::write_view(glm::vec2 const extent) {
6565
};
6666
m_view_proj.write(&vp, sizeof(vp));
6767
auto dir_lights = FlexArray<DirLightSSBO, 4>{};
68-
for (auto const& light : m_scene->dir_lights.span()) { dir_lights.insert(DirLightSSBO::make(light)); }
68+
for (auto const& light : m_scene->lights.dir_lights.span()) { dir_lights.insert(DirLightSSBO::make(light)); }
6969
m_dir_lights.write(dir_lights.span().data(), dir_lights.span().size_bytes());
7070
}
7171

lib/scene/include/facade/scene/lights.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#pragma once
2+
#include <facade/util/flex_array.hpp>
23
#include <facade/util/nvec3.hpp>
34
#include <facade/util/rgb.hpp>
45

@@ -10,10 +11,16 @@ struct DirLight {
1011
///
1112
/// \brief Direction.
1213
///
13-
nvec3 direction{front_v};
14+
nvec3 direction{-front_v};
1415
///
1516
/// \brief Colour and intensity.
1617
///
1718
Rgb rgb{};
1819
};
20+
21+
struct Lights {
22+
static constexpr std::size_t max_lights_v{4};
23+
24+
FlexArray<DirLight, max_lights_v> dir_lights{};
25+
};
1926
} // namespace facade

lib/scene/include/facade/scene/scene.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,9 @@ class Scene {
244244
Resources resources() const { return m_storage.resources(); }
245245

246246
///
247-
/// \brief All the directional lights in the scene.
247+
/// \brief All the lights in the scene.
248248
///
249-
FlexArray<DirLight, 4> dir_lights{};
249+
Lights lights{};
250250

251251
private:
252252
struct TreeBuilder;

lib/util/include/facade/util/flex_array.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,25 @@ class FlexArray {
4040

4141
///
4242
/// \brief Obtain a mutable view into the array.
43+
/// \returns Mutable view into the array
4344
///
4445
constexpr std::span<Type> span() { return {m_t.data(), m_size}; }
4546
///
4647
/// \brief Obtain an immutable view into the array.
48+
/// \returns Immutable view into the array
4749
///
4850
constexpr std::span<Type const> span() const { return {m_t.data(), m_size}; }
4951

5052
///
5153
/// \brief Obtain the number of elements stored.
54+
/// \returns Number of elements stored
5255
///
5356
constexpr std::size_t size() const { return m_size; }
57+
///
58+
/// \brief Check if the array size is 0.
59+
/// \returns true if size is 0
60+
///
61+
constexpr bool empty() const { return m_size == 0; }
5462

5563
private:
5664
std::array<Type, Capacity> m_t{};

lib/vk/include/facade/vk/buffer.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class Buffer {
3333
Gfx m_gfx{};
3434
mutable Rotator<Defer<UniqueBuffer>> m_buffers{};
3535
std::vector<std::byte> m_data{};
36-
std::size_t m_size{};
3736
Type m_type{};
3837
};
3938
} // namespace facade

lib/vk/src/buffer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ void Buffer::refresh() const {
3535

3636
BufferView Buffer::view() const {
3737
refresh();
38-
return {m_buffers.get().get().get().buffer, m_size};
38+
return {m_buffers.get().get().get().buffer, m_data.size()};
3939
}
4040

4141
DescriptorBuffer Buffer::descriptor_buffer() const {
4242
refresh();
43-
return {m_buffers.get().get().get().buffer, m_buffers.get().get().get().size, to_descriptor_type(m_type)};
43+
return {m_buffers.get().get().get().buffer, m_data.size(), to_descriptor_type(m_type)};
4444
}
4545
} // namespace facade

src/main.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ struct MainMenu {
116116
struct {
117117
bool stats{};
118118
bool tree{};
119+
bool lights{};
119120
bool log{};
120121
bool imgui_demo{};
121122
} windows{};
@@ -174,6 +175,11 @@ struct MainMenu {
174175
if (auto window = editor::Window{"Scene", &windows.tree}) { editor::SceneTree{scene}.render(window, data.inspectee); }
175176
}
176177

178+
void lights(Scene& scene) {
179+
ImGui::SetNextWindowSize({400.0f, 400.0f}, ImGuiCond_Once);
180+
if (auto window = editor::Window{"Lights", &windows.lights}) { editor::Inspector{window}.inspect(scene.lights); }
181+
}
182+
177183
void log() {
178184
ImGui::SetNextWindowSize({600.0f, 200.0f}, ImGuiCond_Once);
179185
if (auto window = editor::Window{"Log", &windows.log}) { data.log.render(window); }
@@ -187,6 +193,7 @@ struct MainMenu {
187193
}
188194
if (auto window = editor::Menu{main, "Window"}) {
189195
if (ImGui::MenuItem("Tree")) { windows.tree = true; }
196+
if (ImGui::MenuItem("Lights")) { windows.lights = true; }
190197
if (ImGui::MenuItem("Stats")) { windows.stats = true; }
191198
if (ImGui::MenuItem("Log")) { windows.log = true; }
192199
if constexpr (debug_v) {
@@ -198,6 +205,7 @@ struct MainMenu {
198205
}
199206

200207
if (windows.tree) { tree(engine.scene()); }
208+
if (windows.lights) { lights(engine.scene()); }
201209
if (data.inspectee) { inspector(engine.scene()); }
202210
if (windows.stats) { stats(engine, dt); }
203211
if (windows.log) { log(); }
@@ -234,12 +242,13 @@ void run() {
234242
auto material_id = Id<Material>{};
235243
auto node_id = Id<Node>{};
236244
auto post_scene_load = [&](Scene& scene) {
245+
scene.lights.dir_lights.insert(DirLight{.direction = glm::normalize(glm::vec3{-1.0f, -1.0f, -1.0f}), .rgb = {.intensity = 5.0f}});
237246
scene.camera().transform.set_position({0.0f, 0.0f, 5.0f});
238247

239248
auto material = std::make_unique<LitMaterial>();
240249
material->albedo = {1.0f, 0.0f, 0.0f};
241250
material_id = scene.add(std::move(material));
242-
auto static_mesh_id = scene.add(make_cubed_sphere(1.0f, 32));
251+
auto static_mesh_id = scene.add(make_manipulator(0.125f, 1.0f, 16));
243252
auto mesh_id = scene.add(Mesh{.primitives = {Mesh::Primitive{static_mesh_id, material_id}}});
244253

245254
auto node = Node{};
@@ -259,7 +268,6 @@ void run() {
259268
engine->add_shader(shaders::unlit());
260269

261270
auto& scene = engine->scene();
262-
scene.dir_lights.insert(DirLight{.direction = glm::normalize(glm::vec3{-1.0f, -1.0f, -1.0f}), .rgb = {.intensity = 5.0f}});
263271
scene.load_gltf(dj::Json::parse(test_json_v), DummyDataProvider{});
264272
post_scene_load(engine->scene());
265273
engine->show(true);

0 commit comments

Comments
 (0)