From 67117e1c85f1a6da9d67257c62c64c70db6b348d Mon Sep 17 00:00:00 2001 From: Karn Kaul Date: Mon, 5 Dec 2022 20:43:35 -0800 Subject: [PATCH 1/3] Refactor MaybeFuture to StoredFuture - Add default light in scene. - Use quaternion for light direction. --- lib/engine/src/editor/reflector.cpp | 9 ++++---- lib/engine/src/engine.cpp | 4 ++-- lib/engine/src/scene_renderer.cpp | 2 +- .../include/facade/scene/gltf_loader.hpp | 6 +++--- lib/scene/include/facade/scene/lights.hpp | 3 ++- lib/scene/include/facade/scene/scene.hpp | 13 ++++++------ lib/scene/src/gltf_loader.cpp | 21 +++++++++---------- lib/scene/src/scene.cpp | 10 ++++++++- lib/util/include/facade/util/rgb.hpp | 8 +++++-- lib/util/include/facade/util/thread_pool.hpp | 17 ++++++++------- src/main.cpp | 1 - 11 files changed, 55 insertions(+), 39 deletions(-) diff --git a/lib/engine/src/editor/reflector.cpp b/lib/engine/src/editor/reflector.cpp index daf6d67..cfddeaa 100644 --- a/lib/engine/src/editor/reflector.cpp +++ b/lib/engine/src/editor/reflector.cpp @@ -65,14 +65,17 @@ bool Reflector::operator()(char const* label, glm::quat& out_quat) const { auto euler = to_degree(glm::eulerAngles(out_quat)); float deg[3] = {euler.x, euler.y, euler.z}; auto const org = euler; + bool ret = false; if (drag_float(label, deg, 0.5f, -180.0f, 180.0f, ImGuiSliderFlags_NoInput)) { euler = {deg[0], deg[1], deg[2]}; if (auto const diff = org.x - euler.x; std::abs(diff) > 0.0f) { out_quat = glm::rotate(out_quat, glm::radians(diff), right_v); } if (auto const diff = org.y - euler.y; std::abs(diff) > 0.0f) { out_quat = glm::rotate(out_quat, glm::radians(diff), up_v); } if (auto const diff = org.z - euler.z; std::abs(diff) > 0.0f) { out_quat = glm::rotate(out_quat, glm::radians(diff), front_v); } - return true; + ret = true; } - return false; + ImGui::SameLine(); + if (ImGui::SmallButton("Reset")) { out_quat = quat_identity_v; } + return ret; } bool Reflector::operator()(char const* label, AsRgb out_rgb) const { @@ -101,8 +104,6 @@ bool Reflector::operator()(Transform& out_transform, Bool& out_unified_scaling, if (ret((*this)("Position", vec3, 0.01f))) { out_transform.set_position(vec3); } auto quat = out_transform.orientation(); if (ret((*this)("Orientation", quat))) { out_transform.set_orientation(quat); } - ImGui::SameLine(); - if (ImGui::SmallButton("Reset")) { out_transform.set_orientation(quat_identity_v); } vec3 = out_transform.scale(); if (out_unified_scaling) { if (ret(ImGui::DragFloat("Scale", &vec3.x, 0.01f))) { out_transform.set_scale({vec3.x, vec3.x, vec3.x}); } diff --git a/lib/engine/src/engine.cpp b/lib/engine/src/engine.cpp index d4f3134..f9c36bb 100644 --- a/lib/engine/src/engine.cpp +++ b/lib/engine/src/engine.cpp @@ -193,13 +193,13 @@ std::optional load_skybox_data(char const* path, AtomicLoadStatus& for (auto [face, image] : zip_ranges(faces_v, images)) { image = load_image(json[face].as_string()); } - if (!std::all_of(std::begin(images), std::end(images), [](MaybeFuture const& i) { return i.active(); })) { + if (!std::all_of(std::begin(images), std::end(images), [](StoredFuture const& i) { return i.active(); })) { // TODO: error return {}; } auto ret = Skybox::Data{}; - for (auto [in, out] : zip_ranges(images, ret.images)) { out = in.get(); } + for (auto [in, out] : zip_ranges(images, ret.images)) { out = std::move(in.get()); } return ret; } diff --git a/lib/engine/src/scene_renderer.cpp b/lib/engine/src/scene_renderer.cpp index c0cc88c..c4fc2cf 100644 --- a/lib/engine/src/scene_renderer.cpp +++ b/lib/engine/src/scene_renderer.cpp @@ -14,7 +14,7 @@ struct DirLightSSBO { static DirLightSSBO make(DirLight const& light) { return { - .direction = light.direction.value(), + .direction = glm::normalize(light.direction * front_v), .diffuse = light.rgb.to_vec4(), }; } diff --git a/lib/scene/include/facade/scene/gltf_loader.hpp b/lib/scene/include/facade/scene/gltf_loader.hpp index 435168e..0e7865c 100644 --- a/lib/scene/include/facade/scene/gltf_loader.hpp +++ b/lib/scene/include/facade/scene/gltf_loader.hpp @@ -21,19 +21,19 @@ struct AtomicLoadStatus { }; template -struct LoadFuture : MaybeFuture { +struct LoadFuture : StoredFuture { LoadFuture() = default; template LoadFuture(ThreadPool& pool, std::atomic& post_increment, F func) - : MaybeFuture(pool, [&post_increment, f = std::move(func)] { + : StoredFuture(pool, [&post_increment, f = std::move(func)] { auto ret = f(); ++post_increment; return ret; }) {} template - LoadFuture(std::atomic& post_increment, F func) : MaybeFuture(std::move(func)) { + LoadFuture(std::atomic& post_increment, F func) : StoredFuture(std::move(func)) { ++post_increment; } }; diff --git a/lib/scene/include/facade/scene/lights.hpp b/lib/scene/include/facade/scene/lights.hpp index a5092a9..69d9744 100644 --- a/lib/scene/include/facade/scene/lights.hpp +++ b/lib/scene/include/facade/scene/lights.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace facade { /// @@ -11,7 +12,7 @@ struct DirLight { /// /// \brief Direction. /// - nvec3 direction{-front_v}; + glm::quat direction{glm::angleAxis(glm::radians(180.0f), up_v)}; /// /// \brief Colour and intensity. /// diff --git a/lib/scene/include/facade/scene/scene.hpp b/lib/scene/include/facade/scene/scene.hpp index aed4325..aee5a2f 100644 --- a/lib/scene/include/facade/scene/scene.hpp +++ b/lib/scene/include/facade/scene/scene.hpp @@ -190,6 +190,12 @@ class Scene { /// Texture make_texture(Image::View image) const; + /// + /// \brief Update animations and corresponding nodes. + /// \param dt Duration to advance simulation by (time since last call to tick) + /// + void tick(float dt); + /// /// \brief Obtain a mutable reference to the scene's resources. /// \returns Mutable reference to SceneResources @@ -211,12 +217,6 @@ class Scene { /// RenderMode render_mode{}; - /// - /// \brief Update animations and corresponding nodes. - /// \param dt Duration to advance simulation by (time since last call to tick) - /// - void tick(float dt); - private: struct TreeBuilder; @@ -241,6 +241,7 @@ class Scene { Node make_camera_node(Id id) const; void add_default_camera(); + void add_default_light(); bool load_tree(Id id); Id add_unchecked(Mesh mesh); diff --git a/lib/scene/src/gltf_loader.cpp b/lib/scene/src/gltf_loader.cpp index 0de5029..7f4f656 100644 --- a/lib/scene/src/gltf_loader.cpp +++ b/lib/scene/src/gltf_loader.cpp @@ -313,10 +313,10 @@ auto make_load_future(ThreadPool* pool, std::atomic& out_done, F fu } template -std::vector from_maybe_futures(std::vector>&& futures) { +std::vector from_stored(std::vector>&& futures) { auto ret = std::vector{}; ret.reserve(futures.size()); - for (auto& future : futures) { ret.push_back(future.get()); } + for (auto& future : futures) { ret.push_back(std::move(future.get())); } return ret; } } // namespace @@ -341,11 +341,11 @@ bool Scene::GltfLoader::operator()(dj::Json const& json, DataProvider const& pro m_status.stage = LoadStage::eUploadingResources; m_scene.m_storage = {}; - auto image_futures = std::vector>{}; - image_futures.reserve(root.images.size()); + auto images = std::vector>{}; + images.reserve(root.images.size()); for (auto& image : root.images) { assert(!image.bytes.empty()); - image_futures.push_back(make_load_future(thread_pool, m_status.done, [i = std::move(image)] { return Image{i.bytes.span(), std::move(i.name)}; })); + images.push_back(make_load_future(thread_pool, m_status.done, [i = std::move(image)] { return Image{i.bytes.span(), std::move(i.name)}; })); } for (auto const& sampler : root.samplers) { m_scene.add(to_sampler_info(sampler)); } @@ -354,19 +354,18 @@ bool Scene::GltfLoader::operator()(dj::Json const& json, DataProvider const& pro return m_scene.m_storage.resources.samplers[*sampler_id].sampler(); }; - auto textures = std::vector>{}; + auto textures = std::vector>{}; textures.reserve(root.textures.size()); - auto const images = from_maybe_futures(std::move(image_futures)); for (auto& texture : root.textures) { textures.push_back(make_load_future(thread_pool, m_status.done, [texture = std::move(texture), &images, &get_sampler, this] { bool const mip_mapped = !texture.linear; auto const colour_space = texture.linear ? ColourSpace::eLinear : ColourSpace::eSrgb; auto const tci = Texture::CreateInfo{.name = std::move(texture.name), .mip_mapped = mip_mapped, .colour_space = colour_space}; - return Texture{m_scene.m_gfx, get_sampler(texture.sampler), images[texture.source], tci}; + return Texture{m_scene.m_gfx, get_sampler(texture.sampler), images[texture.source].get(), tci}; })); } - auto mesh_primitives = std::vector>{}; + auto mesh_primitives = std::vector>{}; auto mesh_layout = to_mesh_layout(root); mesh_primitives.reserve(mesh_layout.primitives.size()); for (auto& data : mesh_layout.data) { @@ -384,8 +383,8 @@ bool Scene::GltfLoader::operator()(dj::Json const& json, DataProvider const& pro m_scene.m_storage.resources.nodes.m_array = to_nodes(root.nodes); - m_scene.replace(from_maybe_futures(std::move(textures))); - m_scene.replace(from_maybe_futures(std::move(mesh_primitives))); + m_scene.replace(from_stored(std::move(textures))); + m_scene.replace(from_stored(std::move(mesh_primitives))); m_status.stage = LoadStage::eBuildingScenes; if (root.cameras.empty()) { diff --git a/lib/scene/src/scene.cpp b/lib/scene/src/scene.cpp index d441c85..d17b692 100644 --- a/lib/scene/src/scene.cpp +++ b/lib/scene/src/scene.cpp @@ -67,7 +67,10 @@ struct Scene::TreeBuilder { } }; -Scene::Scene(Gfx const& gfx) : m_gfx(gfx), m_sampler(gfx) { add_default_camera(); } +Scene::Scene(Gfx const& gfx) : m_gfx(gfx), m_sampler(gfx) { + add_default_camera(); + add_default_light(); +} Id Scene::add(Camera camera) { auto const id = m_storage.resources.cameras.size(); @@ -190,6 +193,11 @@ void Scene::add_default_camera() { m_tree.camera = m_tree.cameras.front(); } +void Scene::add_default_light() { + static auto const dir_light_orn = [] { return glm::angleAxis(glm::radians(180.0f + 45.0f), up_v) * glm::angleAxis(glm::radians(45.0f), right_v); }(); + lights.dir_lights.insert(DirLight{.direction = dir_light_orn, .rgb = {.intensity = 5.0f}}); +} + bool Scene::load_tree(Id id) { assert(id < m_storage.data.trees.size()); m_tree = TreeBuilder{*this}(id); diff --git a/lib/util/include/facade/util/rgb.hpp b/lib/util/include/facade/util/rgb.hpp index 10052e6..f25a744 100644 --- a/lib/util/include/facade/util/rgb.hpp +++ b/lib/util/include/facade/util/rgb.hpp @@ -54,15 +54,19 @@ struct Rgb { }; } + /// + /// \brief Obtain only the normalzed tint (no HDR). + /// + constexpr glm::vec4 to_tint(float alpha) const { return glm::vec4{to_f32(channels.x), to_f32(channels.y), to_f32(channels.z), alpha}; } /// /// \brief Convert instance to 3 channel normalized output. /// \returns 3 normalized floats /// - constexpr glm::vec3 to_vec3() const { return intensity * glm::vec3{to_f32(channels.x), to_f32(channels.y), to_f32(channels.z)}; } + constexpr glm::vec3 to_vec3() const { return to_vec4(1.0f); } /// /// \brief Convert instance to 4 channel normalized output. /// \returns 4 normalized floats /// - constexpr glm::vec4 to_vec4(float alpha = 1.0f) const { return {to_vec3(), alpha}; } + constexpr glm::vec4 to_vec4(float alpha = 1.0f) const { return intensity * to_tint(alpha); } }; } // namespace facade diff --git a/lib/util/include/facade/util/thread_pool.hpp b/lib/util/include/facade/util/thread_pool.hpp index d2c9a4c..1add70c 100644 --- a/lib/util/include/facade/util/thread_pool.hpp +++ b/lib/util/include/facade/util/thread_pool.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace facade { @@ -63,26 +64,28 @@ class ThreadPool { }; template -struct MaybeFuture { - std::future future{}; +struct StoredFuture { + std::shared_future future{}; std::optional t{}; - MaybeFuture() = default; + StoredFuture() = default; template requires(std::same_as, T>) - MaybeFuture(ThreadPool& pool, F func) : future(pool.enqueue([f = std::move(func)] { return f(); })) {} + StoredFuture(ThreadPool& pool, F func) : future(pool.enqueue([f = std::move(func)] { return f(); }).share()) {} template requires(std::same_as, T>) - explicit MaybeFuture(F func) : t(func()) {} + explicit StoredFuture(F func) : t(func()) {} bool active() const { return future.valid() || t.has_value(); } - T get() { + T const& get() const { assert(active()); if (future.valid()) { return future.get(); } - return std::move(*t); + return *t; } + + T& get() { return const_cast(std::as_const(*this).get()); } }; } // namespace facade diff --git a/src/main.cpp b/src/main.cpp index c9206de..05c11dd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,7 +57,6 @@ void run(AppOpts const& opts) { auto node_id = Id{}; auto post_scene_load = [&engine, &node_id]() { auto& scene = engine->scene(); - scene.lights.dir_lights.insert(DirLight{.direction = glm::normalize(glm::vec3{-1.0f, -1.0f, -1.0f}), .rgb = {.intensity = 5.0f}}); scene.camera().transform.set_position({0.0f, 0.0f, 5.0f}); auto material = LitMaterial{}; From aeacb524d3474f103b8f167b08466dc4e9e7ee35 Mon Sep 17 00:00:00 2001 From: Karn Kaul Date: Tue, 6 Dec 2022 21:48:16 -0800 Subject: [PATCH 2/3] Add gradient to default skybox - Cleanup camera adding code. - Remove temp code. - Bump version. --- lib/CMakeLists.txt | 2 +- lib/engine/src/editor/reflector.cpp | 5 +- lib/scene/include/facade/scene/scene.hpp | 1 + lib/scene/src/scene.cpp | 39 ++++++------- lib/vk/src/skybox.cpp | 26 +++++++-- src/bin/skybox_frag.spv.hpp | 70 +++++++++++++----------- src/main.cpp | 41 +------------- src/shaders/skybox.frag | 4 +- 8 files changed, 86 insertions(+), 102 deletions(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index c52be43..f17d412 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_DEBUG_POSTFIX "-d") -set(${target_prefix}_version 0.1.0) +set(${target_prefix}_version 0.2.0) project(${target_prefix}-lib VERSION ${${target_prefix}_version}) diff --git a/lib/engine/src/editor/reflector.cpp b/lib/engine/src/editor/reflector.cpp index cfddeaa..310d230 100644 --- a/lib/engine/src/editor/reflector.cpp +++ b/lib/engine/src/editor/reflector.cpp @@ -74,7 +74,10 @@ bool Reflector::operator()(char const* label, glm::quat& out_quat) const { ret = true; } ImGui::SameLine(); - if (ImGui::SmallButton("Reset")) { out_quat = quat_identity_v; } + if (ImGui::SmallButton("Reset")) { + out_quat = quat_identity_v; + ret = true; + } return ret; } diff --git a/lib/scene/include/facade/scene/scene.hpp b/lib/scene/include/facade/scene/scene.hpp index aee5a2f..a02a61a 100644 --- a/lib/scene/include/facade/scene/scene.hpp +++ b/lib/scene/include/facade/scene/scene.hpp @@ -241,6 +241,7 @@ class Scene { Node make_camera_node(Id id) const; void add_default_camera(); + void add_default_camera(TreeImpl& out, Id id); void add_default_light(); bool load_tree(Id id); Id add_unchecked(Mesh mesh); diff --git a/lib/scene/src/scene.cpp b/lib/scene/src/scene.cpp index d17b692..689540c 100644 --- a/lib/scene/src/scene.cpp +++ b/lib/scene/src/scene.cpp @@ -34,29 +34,20 @@ struct Img1x1 { struct Scene::TreeBuilder { Scene& out_scene; - bool set_camera(TreeImpl& out_tree, Id id, std::span nodes) const { + void add_cameras(TreeImpl& out_tree, Id id, std::span nodes) const { auto& node = nodes[id]; - if (auto cam = node.find()) { - out_tree.camera = id; - return true; - } - for (auto const child : node.children) { - if (set_camera(out_tree, child, nodes)) { return true; } - } - return false; + if (auto cam = node.find()) { out_tree.cameras.push_back(id); } + for (auto const child : node.children) { add_cameras(out_tree, child, nodes); } } void set_camera(TreeImpl& out_tree, std::span nodes) const { - for (auto const& id : out_tree.roots) { - if (set_camera(out_tree, id, nodes)) { return; } + for (auto const& id : out_tree.roots) { add_cameras(out_tree, id, nodes); } + if (!out_tree.cameras.empty()) { + out_tree.camera = out_tree.cameras.front(); + return; } - auto node = Node{.name = "camera"}; - node.attach(0); - auto const id = out_scene.m_storage.resources.nodes.size(); - out_scene.m_storage.resources.nodes.m_array.push_back(std::move(node)); - out_tree.roots.push_back(id); - out_tree.cameras.push_back(id); - out_tree.camera = out_tree.cameras.front(); + assert(!out_scene.m_storage.resources.cameras.empty()); + out_scene.add_default_camera(out_tree, 0); } TreeImpl operator()(Id id) { @@ -186,13 +177,15 @@ Node Scene::make_camera_node(Id id) const { return node; } -void Scene::add_default_camera() { - m_tree.cameras.push_back(m_storage.resources.nodes.size()); - m_tree.roots.push_back(m_storage.resources.nodes.size()); - m_storage.resources.nodes.m_array.push_back(make_camera_node(add(Camera{.name = "default"}))); - m_tree.camera = m_tree.cameras.front(); +void Scene::add_default_camera(TreeImpl& out, Id id) { + auto const node = add(make_camera_node(id)); + out.roots.push_back(node); + out.cameras.push_back(node); + out.camera = out.cameras.front(); } +void Scene::add_default_camera() { add_default_camera(m_tree, add(Camera{.name = "default"})); } + void Scene::add_default_light() { static auto const dir_light_orn = [] { return glm::angleAxis(glm::radians(180.0f + 45.0f), up_v) * glm::angleAxis(glm::radians(45.0f), right_v); }(); lights.dir_lights.insert(DirLight{.direction = dir_light_orn, .rgb = {.intensity = 5.0f}}); diff --git a/lib/vk/src/skybox.cpp b/lib/vk/src/skybox.cpp index e84199d..9056c73 100644 --- a/lib/vk/src/skybox.cpp +++ b/lib/vk/src/skybox.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,18 +6,35 @@ namespace facade { namespace { -std::array make_blank_cubemap_images() { - static constexpr std::byte black_v[] = {0x0_B, 0x0_B, 0x0_B, 0xff_B}; +template +constexpr void set_rgbs(std::span vertices, glm::vec3 rgb, T... indices) { + ((vertices[static_cast(indices)].rgb = rgb), ...); +} + +constexpr glm::vec4 gradient_v[2] = { + {0.9254f, 0.9215f, 0.8942f, 1.0f}, + {0.7254f, 0.7215f, 0.6942f, 1.0f}, +}; + +Geometry make_gradient_cubemap_cube() { + auto ret = make_cube(glm::vec3{1.0f}); + set_rgbs(ret.vertices, Rgb::to_linear(gradient_v[0]), 0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 18, 19); + set_rgbs(ret.vertices, Rgb::to_linear(gradient_v[1]), 2, 3, 6, 7, 10, 11, 14, 15, 20, 21, 22, 23); + return ret; +} + +std::array make_cubemap_images() { + static constexpr std::byte black_v[] = {0xff_B, 0xff_B, 0xff_B, 0xff_B}; static constexpr auto image_v = Image::View{.bytes = black_v, .extent = {1, 1}}; return {image_v, image_v, image_v, image_v, image_v, image_v}; } } // namespace Skybox::Skybox(Gfx const& gfx) - : m_sampler(gfx), m_cube(gfx, make_cube(glm::vec3{1.0f}), {}, "skybox"), m_cubemap(gfx, m_sampler.sampler(), make_blank_cubemap_images(), "skybox"), + : m_sampler(gfx), m_cube(gfx, make_gradient_cubemap_cube(), {}, "skybox"), m_cubemap(gfx, m_sampler.sampler(), make_cubemap_images(), "skybox"), m_gfx(gfx) {} void Skybox::set(std::span images) { m_cubemap = {m_gfx, m_sampler.sampler(), images, "skybox"}; } -void Skybox::reset() { m_cubemap = {m_gfx, m_sampler.sampler(), make_blank_cubemap_images()}; } +void Skybox::reset() { m_cubemap = {m_gfx, m_sampler.sampler(), make_cubemap_images()}; } } // namespace facade diff --git a/src/bin/skybox_frag.spv.hpp b/src/bin/skybox_frag.spv.hpp index 3213811..6100465 100644 --- a/src/bin/skybox_frag.spv.hpp +++ b/src/bin/skybox_frag.spv.hpp @@ -2,48 +2,54 @@ namespace facade { inline constexpr unsigned char skybox_frag_v[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, - 0x74, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x63, 0x75, 0x62, 0x65, 0x6d, - 0x61, 0x70, 0x00, 0x05, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x66, 0x70, 0x6f, 0x73, 0x00, 0x05, 0x00, 0x07, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x76, 0x70, 0x6f, 0x73, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x75, 0x72, 0x65, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x72, 0x67, 0x62, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x1c, 0x00, - 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x75, 0x76, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x6e, 0x6f, + 0x74, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x72, 0x67, + 0x62, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x63, 0x75, 0x62, 0x65, 0x6d, 0x61, 0x70, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x66, 0x70, 0x6f, 0x73, 0x00, 0x05, 0x00, 0x07, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, + 0x76, 0x70, 0x6f, 0x73, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x75, 0x72, 0x65, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x23, 0x00, + 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x75, 0x76, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x24, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x19, - 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, + 0x47, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1b, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, - 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, - 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, - 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, - 0x00, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, - 0x01, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0b, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x3f, 0x19, 0x00, 0x09, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3b, 0x00, + 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3d, 0x00, + 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00, }; } // namespace facade diff --git a/src/main.cpp b/src/main.cpp index 05c11dd..595aedb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,39 +54,17 @@ void run(AppOpts const& opts) { engine_info.desired_msaa = config.config.window.msaa; engine_info.force_thread_count = opts.force_threads; - auto node_id = Id{}; - auto post_scene_load = [&engine, &node_id]() { - auto& scene = engine->scene(); - scene.camera().transform.set_position({0.0f, 0.0f, 5.0f}); - - auto material = LitMaterial{}; - material.albedo = {1.0f, 0.0f, 0.0f}; - auto material_id = scene.add(Material{std::move(material), "custom"}); - auto primitive_id = scene.add(Geometry::Packed::from(make_cubed_sphere(1.0f, 32))); - auto mesh_id = scene.add(Mesh{.primitives = {Mesh::Primitive{.primitive = primitive_id, .material = material_id}}}); - - auto node = Node{}; - node.attach(mesh_id); - node.instances.emplace_back().set_position({1.0f, -5.0f, -20.0f}); - node.instances.emplace_back().set_position({-1.0f, 1.0f, 0.0f}); - node_id = scene.add(std::move(node)); - }; - auto init = [&] { engine.emplace(engine_info); if (config.config.window.position) { glfwSetWindowPos(engine->window(), config.config.window.position->x, config.config.window.position->y); } log_prologue(); engine->add_shaders(vert::default_(), vert::skinned(), frag::unlit(), frag::lit(), frag::skybox()); - - post_scene_load(); engine->show(true); }; init(); - float const drot_z[] = {100.0f, -150.0f}; - auto file_menu = FileMenu{}; auto window_menu = WindowMenu{}; @@ -97,8 +75,8 @@ void run(AppOpts const& opts) { std::string title{}; } loading{}; - auto load_async = [&engine, &file_menu, &loading, &post_scene_load, &config](fs::path const& path) { - if (engine->load_async(path.generic_string(), post_scene_load)) { + auto load_async = [&engine, &file_menu, &loading, &config](fs::path const& path) { + if (engine->load_async(path.generic_string())) { loading.title = fmt::format("Loading {}...", path.filename().generic_string()); file_menu.add_recent(path.generic_string()); config.config.file_menu.recents = {file_menu.recents().begin(), file_menu.recents().end()}; @@ -155,21 +133,6 @@ void run(AppOpts const& opts) { if (auto path = path_sources.update(); !path.empty()) { load_async(std::move(path)); } config.update(*engine); - - // TEMP CODE - if (!ImGui::GetIO().WantTextInput && input.keyboard.pressed(GLFW_KEY_R)) { - logger::info("Reloading..."); - engine.reset(); - init(); - continue; - } - - if (auto* node = engine->scene().resources().nodes.find(node_id); node && node->instances.size() > 1) { - node->instances[0].rotate(glm::radians(drot_z[0]) * dt, {0.0f, 1.0f, 0.0f}); - node->instances[1].rotate(glm::radians(drot_z[1]) * dt, {1.0f, 0.0f, 0.0f}); - } - // TEMP CODE - engine->render(); } } diff --git a/src/shaders/skybox.frag b/src/shaders/skybox.frag index c795ecb..1d6a911 100644 --- a/src/shaders/skybox.frag +++ b/src/shaders/skybox.frag @@ -2,16 +2,16 @@ layout (set = 1, binding = 0) uniform samplerCube cubemap; +layout (location = 0) in vec3 in_rgb; layout (location = 3) in vec3 in_fpos; layout (location = 4) in vec4 in_vpos_exposure; layout (location = 0) out vec4 out_rgba; // unused -layout (location = 0) in vec3 in_rgb; layout (location = 1) in vec2 in_uv; layout (location = 2) in vec3 in_normal; void main() { - out_rgba = texture(cubemap, in_fpos - in_vpos_exposure.xyz); + out_rgba = vec4(in_rgb, 1.0) * texture(cubemap, in_fpos - in_vpos_exposure.xyz); } From 9565cc07b5894b3c7755d1811cfdddc418b62893 Mon Sep 17 00:00:00 2001 From: Karn Kaul Date: Thu, 22 Dec 2022 21:52:36 -0800 Subject: [PATCH 3/3] Update gltf2cpp; misc fixes --- lib/engine/src/scene_renderer.cpp | 4 ++-- lib/ext/src.zip | Bin 4213335 -> 4256258 bytes lib/scene/src/gltf_loader.cpp | 12 ++++++++++-- lib/vk/include/facade/vk/mesh_primitive.hpp | 2 ++ lib/vk/include/facade/vk/pipes.hpp | 3 --- lib/vk/src/geometry.cpp | 1 + 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/engine/src/scene_renderer.cpp b/lib/engine/src/scene_renderer.cpp index c4fc2cf..5a2e702 100644 --- a/lib/engine/src/scene_renderer.cpp +++ b/lib/engine/src/scene_renderer.cpp @@ -147,8 +147,8 @@ void SceneRenderer::render(Renderer& renderer, vk::CommandBuffer cb, Node const& update_view(pipeline); material.write_sets(pipeline, store); - if (mesh_primitive.has_joints()) { - auto& set3 = pipeline.next_set(3); + if (auto const joints_set = mesh_primitive.joints_set()) { + auto& set3 = pipeline.next_set(*joints_set); set3.update(0, make_joint_mats(resources.skins[*node.find()], parent)); pipeline.bind(set3); draw(cb, mesh_primitive, {}); diff --git a/lib/ext/src.zip b/lib/ext/src.zip index a7ac3d3511886f2a3c5ed6a7193a3c61ae283988..43c88fecdd88909af857aeafba4152910e326f59 100644 GIT binary patch delta 57523 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 HoA!SIu{}; + auto loaded_mutex = std::mutex{}; + auto get_bytes = [&](std::string_view uri) { + auto str = std::string{uri}; + auto lock = std::unique_lock{loaded_mutex}; + if (auto it = loaded_bytes.find(str); it != loaded_bytes.end()) { return it->second.span(); } + lock.unlock(); auto ret = provider.load(uri); - return gltf2cpp::ByteArray{std::move(ret.bytes), ret.size}; + lock.lock(); + auto [it, _] = loaded_bytes.insert_or_assign(str, std::move(ret)); + return it->second.span(); }; auto root = parser.parse(get_bytes); diff --git a/lib/vk/include/facade/vk/mesh_primitive.hpp b/lib/vk/include/facade/vk/mesh_primitive.hpp index c0dc375..a7f2e54 100644 --- a/lib/vk/include/facade/vk/mesh_primitive.hpp +++ b/lib/vk/include/facade/vk/mesh_primitive.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace facade { struct MeshJoints { @@ -27,6 +28,7 @@ class MeshPrimitive { Info info() const; VertexLayout const& vertex_layout() const { return m_vlayout; } bool has_joints() const { return m_jwbo.get().get().size > 0; } + std::optional joints_set() const { return m_jwbo.get().get().size > 0 ? std::optional{3} : std::nullopt; } std::uint32_t instance_binding() const { return m_instance_binding; } void draw(vk::CommandBuffer cb, std::uint32_t instances = 1u) const; diff --git a/lib/vk/include/facade/vk/pipes.hpp b/lib/vk/include/facade/vk/pipes.hpp index 3274434..94fbd9c 100644 --- a/lib/vk/include/facade/vk/pipes.hpp +++ b/lib/vk/include/facade/vk/pipes.hpp @@ -10,9 +10,6 @@ #include namespace facade { -struct DrawInstance; -class StaticMesh; - class Pipes { public: using State = Pipeline::State; diff --git a/lib/vk/src/geometry.cpp b/lib/vk/src/geometry.cpp index 599d3aa..c850127 100644 --- a/lib/vk/src/geometry.cpp +++ b/lib/vk/src/geometry.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include