diff --git a/CMakeLists.txt b/CMakeLists.txt index bc2b9c25edaac17a99e238496743d50fdd3aa684..a32145ae5595b340090f99acc54a87be81802d83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,7 +191,25 @@ add_library(lava.resource STATIC ${LIBLAVA_DIR}/resource/texture.hpp ) -target_include_directories(lava.resource PUBLIC +target_link_libraries(lava.resource + lava::base + ) + +set_property(TARGET lava.resource PROPERTY EXPORT_NAME resource) +add_library(lava::resource ALIAS lava.resource) + +message(">> lava::asset") + +add_library(lava.asset STATIC + ${LIBLAVA_DIR}/asset/mesh_loader.cpp + ${LIBLAVA_DIR}/asset/mesh_loader.hpp + ${LIBLAVA_DIR}/asset/scope_image.cpp + ${LIBLAVA_DIR}/asset/scope_image.hpp + ${LIBLAVA_DIR}/asset/texture_loader.cpp + ${LIBLAVA_DIR}/asset/texture_loader.hpp + ) + +target_include_directories(lava.asset PUBLIC $<BUILD_INTERFACE:${LIBLAVA_EXT_DIR}/stb> $<BUILD_INTERFACE:${LIBLAVA_EXT_DIR}/gli> $<BUILD_INTERFACE:${LIBLAVA_EXT_DIR}/tinyobjloader> @@ -209,13 +227,13 @@ add_subdirectory(${LIBLAVA_EXT_DIR}/selene selene EXCLUDE_FROM_ALL) message("<<< selene") -target_link_libraries(lava.resource - lava::base +target_link_libraries(lava.asset lava::file + lava::resource ) -set_property(TARGET lava.resource PROPERTY EXPORT_NAME resource) -add_library(lava::resource ALIAS lava.resource) +set_property(TARGET lava.asset PROPERTY EXPORT_NAME asset) +add_library(lava::asset ALIAS lava.asset) message(">> lava::frame") @@ -251,7 +269,8 @@ add_subdirectory(${LIBLAVA_EXT_DIR}/glfw glfw EXCLUDE_FROM_ALL) message("<<< glfw") target_link_libraries(lava.frame - lava::resource + lava::base + lava::file glfw ${GLFW_LIBRARIES} ) @@ -305,6 +324,7 @@ target_include_directories(lava.app PUBLIC ) target_link_libraries(lava.app + lava::asset lava::block lava::frame ) @@ -336,6 +356,7 @@ install(TARGETS lava.file lava.base lava.resource + lava.asset lava.frame lava.block lava.app diff --git a/DOCS.md b/DOCS.md index 67dc6cffdf6f3a0919d478e7d5e6f447de58a695..9dc7960207a5860063ef4ff3e60fd2c79bde0422 100644 --- a/DOCS.md +++ b/DOCS.md @@ -335,13 +335,17 @@ int main(int argc, char* argv[]) { [](https://github.com/liblava/liblava/tree/master/liblava/app/app.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/app/camera.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/app/forward_shading.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/app/gui.hpp) +#### lava [block](https://github.com/liblava/liblava/tree/master/liblava/block) + +[](https://github.com/liblava/liblava/tree/master/liblava/block/attachment.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/block.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/descriptor.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/pipeline.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/render_pass.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/subpass.hpp) + #### lava [frame](https://github.com/liblava/liblava/tree/master/liblava/frame) [](https://github.com/liblava/liblava/tree/master/liblava/frame/frame.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/frame/input.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/frame/render_target.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/frame/renderer.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/frame/swapchain.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/frame/window.hpp) -#### lava [block](https://github.com/liblava/liblava/tree/master/liblava/block) +#### lava [asset](https://github.com/liblava/liblava/tree/master/liblava/asset) -[](https://github.com/liblava/liblava/tree/master/liblava/block/attachment.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/block.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/descriptor.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/pipeline.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/render_pass.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/block/subpass.hpp) +[](https://github.com/liblava/liblava/tree/master/liblava/asset/mesh_loader.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/asset/scope_image.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/asset/texture_loader.hpp) #### lava [resource](https://github.com/liblava/liblava/tree/master/liblava/resource) diff --git a/README.md b/README.md index e4c11a96e2f147c0958ab8a1a224f71e46632c1b..7805c8b03343fbb26863c1c0c68f34e4272bd692 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ <br /> -##### [Modules](DOCS.md/#modules) +#### [Modules](DOCS.md/#modules) -[](https://github.com/liblava/liblava/tree/master/liblava/core) [](https://github.com/liblava/liblava/tree/master/liblava/util) [](https://github.com/liblava/liblava/tree/master/liblava/file) [](https://github.com/liblava/liblava/tree/master/liblava/base) [](https://github.com/liblava/liblava/tree/master/liblava/resource) [](https://github.com/liblava/liblava/tree/master/liblava/frame) [](https://github.com/liblava/liblava/tree/master/liblava/block) [](https://github.com/liblava/liblava/tree/master/liblava/app) [](https://git.io/liblava-engine) +[](https://github.com/liblava/liblava/tree/master/liblava/core) [](https://github.com/liblava/liblava/tree/master/liblava/util) [](https://github.com/liblava/liblava/tree/master/liblava/file) [](https://github.com/liblava/liblava/tree/master/liblava/base) [](https://github.com/liblava/liblava/tree/master/liblava/resource) [](https://github.com/liblava/liblava/tree/master/liblava/asset) [](https://github.com/liblava/liblava/tree/master/liblava/frame) [](https://github.com/liblava/liblava/tree/master/liblava/block) [](https://github.com/liblava/liblava/tree/master/liblava/app) [](https://git.io/liblava-engine) <br /> diff --git a/liblava/app/app.cpp b/liblava/app/app.cpp index eaad5d5224be66e76400b3a3d6f6a21730a82c24..e81aa23593df5a29489efc3c6a79ea95aec6b93e 100644 --- a/liblava/app/app.cpp +++ b/liblava/app/app.cpp @@ -5,6 +5,7 @@ #include <imgui.h> #include <liblava/app/app.hpp> #include <liblava/app/def.hpp> +#include <liblava/asset/scope_image.hpp> #include <liblava/base/debug_utils.hpp> namespace lava { diff --git a/liblava/asset.hpp b/liblava/asset.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4de8dbe3c86914e021e9fc177a8bad77e80236bb --- /dev/null +++ b/liblava/asset.hpp @@ -0,0 +1,9 @@ +// file : liblava/asset.hpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ +// license : MIT; see accompanying LICENSE file + +#pragma once + +#include <liblava/asset/mesh_loader.hpp> +#include <liblava/asset/scope_image.hpp> +#include <liblava/asset/texture_loader.hpp> diff --git a/liblava/asset/mesh_loader.cpp b/liblava/asset/mesh_loader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aeecfe0c808d2a72bd32310d6acf21d722af9e89 --- /dev/null +++ b/liblava/asset/mesh_loader.cpp @@ -0,0 +1,102 @@ +// file : liblava/asset/mesh_loader.cpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ +// license : MIT; see accompanying LICENSE file + +#include <liblava/asset/mesh_loader.hpp> +#include <liblava/file.hpp> + +#ifndef LIBLAVA_TINYOBJLOADER +# define LIBLAVA_TINYOBJLOADER 1 +#endif + +#if LIBLAVA_TINYOBJLOADER + +# ifdef _WIN32 +# pragma warning(push, 4) +# else +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +# endif + +# define TINYOBJLOADER_IMPLEMENTATION +# include <tiny_obj_loader.h> + +# ifdef _WIN32 +# pragma warning(pop) +# else +# pragma GCC diagnostic pop +# endif + +#endif + +lava::mesh::ptr lava::load_mesh(device_ptr device, name filename) { +#if LIBLAVA_TINYOBJLOADER + if (extension(filename, "OBJ")) { + tinyobj::attrib_t attrib; + std::vector<tinyobj::shape_t> shapes; + std::vector<tinyobj::material_t> materials; + std::string err; + std::string warn; + + string target_file = filename; + + file_remover temp_file_remover; + { + file file(filename); + if (file.opened() && file.get_type() == file_type::fs) { + string temp_file; + temp_file = file_system::get_pref_dir(); + temp_file += get_filename_from(target_file, true); + + scope_data temp_data(file.get_size()); + if (!temp_data.ptr) + return nullptr; + + if (file_error(file.read(temp_data.ptr))) + return nullptr; + + if (!write_file(str(temp_file), temp_data.ptr, temp_data.size)) + return nullptr; + + target_file = temp_file; + + temp_file_remover.filename = target_file; + } + } + + if (tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, str(target_file))) { + auto mesh = make_mesh(); + + for (auto const& shape : shapes) { + for (auto const& index : shape.mesh.indices) { + vertex vertex; + + vertex.position = v3(attrib.vertices[3 * index.vertex_index], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2]); + + vertex.color = v4(1.f); + + if (!attrib.texcoords.empty()) + vertex.uv = v2(attrib.texcoords[2 * index.texcoord_index], 1.f - attrib.texcoords[2 * index.texcoord_index + 1]); + + vertex.normal = attrib.normals.empty() ? v3(0.f) : v3(attrib.normals[3 * index.normal_index], attrib.normals[3 * index.normal_index + 1], attrib.normals[3 * index.normal_index + 2]); + + mesh->get_vertices().push_back(vertex); + mesh->get_indices().push_back(mesh->get_indices_count()); + } + } + + if (mesh->empty()) + return nullptr; + + if (!mesh->create(device)) + return nullptr; + + return mesh; + } + } +#endif + + return nullptr; +} diff --git a/liblava/asset/mesh_loader.hpp b/liblava/asset/mesh_loader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7364ea1724fbb3e9d9dee7a5a25d7168bab1a4fd --- /dev/null +++ b/liblava/asset/mesh_loader.hpp @@ -0,0 +1,13 @@ +// file : liblava/asset/mesh_loader.hpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ +// license : MIT; see accompanying LICENSE file + +#pragma once + +#include <liblava/resource/mesh.hpp> + +namespace lava { + + mesh::ptr load_mesh(device_ptr device, name filename); + +} // namespace lava diff --git a/liblava/asset/scope_image.cpp b/liblava/asset/scope_image.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d491b7f7627f3681b13cc089390f2b2bcf37e51 --- /dev/null +++ b/liblava/asset/scope_image.cpp @@ -0,0 +1,41 @@ +// file : liblava/asset/scope_image.cpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ +// license : MIT; see accompanying LICENSE file + +#include <stb_image.h> +#include <liblava/asset/scope_image.hpp> + +namespace lava { + + scope_image::scope_image(string_ref filename) + : image_file(str(filename)), file_data(image_file.get_size(), false) { + if (image_file.opened()) { + if (!file_data.allocate()) + return; + + if (file_error(image_file.read(file_data.ptr))) + return; + } + + i32 tex_width, tex_height, tex_channels = 0; + + if (image_file.opened()) + data = as_ptr(stbi_load_from_memory((stbi_uc const*) file_data.ptr, to_i32(file_data.size), + &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha)); + else + data = as_ptr(stbi_load(str(filename), &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha)); + + if (!data) + return; + + size = { tex_width, tex_height }; + channels = tex_channels; + ready = true; + } + + scope_image::~scope_image() { + if (data) + stbi_image_free(data); + } + +} // namespace lava diff --git a/liblava/asset/scope_image.hpp b/liblava/asset/scope_image.hpp new file mode 100644 index 0000000000000000000000000000000000000000..178f0117a1b16e723b5048eef3f4d9a22a9ebc54 --- /dev/null +++ b/liblava/asset/scope_image.hpp @@ -0,0 +1,27 @@ +// file : liblava/asset/scope_image.hpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ +// license : MIT; see accompanying LICENSE file + +#pragma once + +#include <liblava/core/math.hpp> +#include <liblava/file/file.hpp> + +namespace lava { + + struct scope_image { + explicit scope_image(string_ref filename); + ~scope_image(); + + bool ready = false; + + data_ptr data = nullptr; + uv2 size = uv2(0, 0); + ui32 channels = 0; + + private: + file image_file; + scope_data file_data; + }; + +} // namespace lava diff --git a/liblava/asset/texture_loader.cpp b/liblava/asset/texture_loader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6bf757fed3d1d7419ea4c3fd7f62782929a7221 --- /dev/null +++ b/liblava/asset/texture_loader.cpp @@ -0,0 +1,240 @@ +// file : liblava/asset/texture_loader.cpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ +// license : MIT; see accompanying LICENSE file + +#include <bitmap_image.hpp> +#include <liblava/asset/texture_loader.hpp> +#include <liblava/file.hpp> +#include <selene/img/pixel/PixelTypeAliases.hpp> +#include <selene/img_ops/ImageConversions.hpp> + +#ifdef _WIN32 +# pragma warning(push, 4) +# pragma warning(disable : 4458) +# pragma warning(disable : 4100) +# pragma warning(disable : 5054) +# pragma warning(disable : 4244) +#else +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wignored-qualifiers" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wtype-limits" +# pragma GCC diagnostic ignored "-Wempty-body" +# pragma GCC diagnostic ignored "-Wunused-result" +#endif + +#include <gli/gli.hpp> + +#ifdef _WIN32 +# pragma warning(pop) +#else +# pragma GCC diagnostic pop +#endif + +#define STB_IMAGE_IMPLEMENTATION +#include <stb_image.h> + +namespace lava { + + texture::ptr create_gli_texture_2d(device_ptr device, file const& file, VkFormat format, scope_data const& temp_data) { + gli::texture2d tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) + : gli::load(file.get_path())); + assert(!tex.empty()); + if (tex.empty()) + return nullptr; + + auto mip_levels = to_ui32(tex.levels()); + + texture::layer layer; + + for (auto m = 0u; m < mip_levels; ++m) { + texture::mip_level level; + level.extent = { tex[m].extent().x, tex[m].extent().y }; + level.size = to_ui32(tex[m].size()); + + layer.levels.push_back(level); + } + + texture::layer::list layers; + layers.push_back(layer); + + auto texture = make_texture(); + + uv2 size = { tex[0].extent().x, tex[0].extent().y }; + if (!texture->create(device, size, format, layers, texture_type::tex_2d)) + return nullptr; + + if (!texture->upload(tex.data(), tex.size())) + return nullptr; + + return texture; + } + + template<typename T> + texture::layer::list create_layer_list(T const& tex, ui32 layer_count) { + texture::layer::list layers; + + auto mip_levels = to_ui32(tex.levels()); + + for (auto i = 0u; i < layer_count; ++i) { + texture::layer layer; + + for (auto m = 0u; m < mip_levels; ++m) { + texture::mip_level level; + level.extent = { tex[i][m].extent().x, tex[i][m].extent().y }; + level.size = to_ui32(tex[i][m].size()); + + layer.levels.push_back(level); + } + + layers.push_back(layer); + } + + return layers; + } + + texture::ptr create_gli_texture_array(device_ptr device, file const& file, VkFormat format, scope_data const& temp_data) { + gli::texture2d_array tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) + : gli::load(file.get_path())); + assert(!tex.empty()); + if (tex.empty()) + return nullptr; + + auto layers = create_layer_list(tex, to_ui32(tex.layers())); + + auto texture = make_texture(); + + uv2 size = { tex[0].extent().x, tex[0].extent().y }; + if (!texture->create(device, size, format, layers, texture_type::array)) + return nullptr; + + if (!texture->upload(tex.data(), tex.size())) + return nullptr; + + return texture; + } + + texture::ptr create_gli_texture_cube_map(device_ptr device, file const& file, VkFormat format, scope_data const& temp_data) { + gli::texture_cube tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) + : gli::load(file.get_path())); + assert(!tex.empty()); + if (tex.empty()) + return nullptr; + + auto layers = create_layer_list(tex, to_ui32(tex.faces())); + + auto texture = make_texture(); + + uv2 size = { tex[0].extent().x, tex[0].extent().y }; + if (!texture->create(device, size, format, layers, texture_type::cube_map)) + return nullptr; + + if (!texture->upload(tex.data(), tex.size())) + return nullptr; + + return texture; + } + + texture::ptr create_stbi_texture(device_ptr device, file const& file, scope_data const& temp_data) { + i32 tex_width = 0, tex_height = 0; + stbi_uc* data = nullptr; + + if (file.opened()) + data = stbi_load_from_memory((stbi_uc const*) temp_data.ptr, to_i32(temp_data.size), + &tex_width, &tex_height, nullptr, STBI_rgb_alpha); + else + data = stbi_load(str(file.get_path()), &tex_width, &tex_height, nullptr, STBI_rgb_alpha); + + if (!data) + return nullptr; + + auto texture = make_texture(); + + uv2 size = { tex_width, tex_height }; + if (!texture->create(device, size, VK_FORMAT_R8G8B8A8_UNORM)) + return nullptr; + + const i32 tex_channels = 4; + auto uploadSize = tex_width * tex_height * tex_channels * sizeof(char); + auto result = texture->upload(data, uploadSize); + + stbi_image_free(data); + + if (!result) + return nullptr; + + return texture; + } + +} // namespace lava + +lava::texture::ptr lava::load_texture(device_ptr device, file_format filename, texture_type type) { + auto supported = (filename.format == VK_FORMAT_R8G8B8A8_UNORM) || (device->get_features().textureCompressionBC && (filename.format == VK_FORMAT_BC3_UNORM_BLOCK)) || (device->get_features().textureCompressionASTC_LDR && (filename.format == VK_FORMAT_ASTC_8x8_UNORM_BLOCK)) || (device->get_features().textureCompressionETC2 && (filename.format == VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK)); + if (!supported) + return nullptr; + + auto use_gli = extension(str(filename.path), { "DDS", "KTX", "KMG" }); + auto use_stbi = false; + + if (!use_gli) + use_stbi = extension(str(filename.path), { "JPG", "PNG", "TGA", "BMP", "PSD", "GIF", "HDR", "PIC" }); + + if (!use_gli && !use_stbi) + return nullptr; + + file file(str(filename.path)); + scope_data temp_data(file.get_size(), false); + + if (file.opened()) { + if (!temp_data.allocate()) + return nullptr; + + if (file_error(file.read(temp_data.ptr))) + return nullptr; + } + + if (use_gli) { + texture::layer::list layers; + + switch (type) { + case texture_type::tex_2d: { + return create_gli_texture_2d(device, file, filename.format, temp_data); + } + + case texture_type::array: { + return create_gli_texture_array(device, file, filename.format, temp_data); + } + + case texture_type::cube_map: { + return create_gli_texture_cube_map(device, file, filename.format, temp_data); + } + } + } else { + return create_stbi_texture(device, file, temp_data); + } + + return nullptr; +} + +lava::texture::ptr lava::create_default_texture(device_ptr device, uv2 size) { + auto result = make_texture(); + + if (!result->create(device, size, VK_FORMAT_R8G8B8A8_UNORM)) + return nullptr; + + bitmap_image image(size.x, size.y); + checkered_pattern(64, 64, 255, 255, 255, image); + + image.bgr_to_rgb(); + + sln::TypedLayout typed_layout((sln::PixelLength) size.x, (sln::PixelLength) size.y, (sln::Stride)(image.width() * image.bytes_per_pixel())); + + sln::ImageView<sln::PixelRGB_8u, sln::ImageModifiability::Mutable> img_rgb((uint8_t*) image.data(), typed_layout); + + sln::Image<sln::PixelRGBA_8u> const img_rgba = sln::convert_image<sln::PixelFormat::RGBA>(img_rgb, std::uint8_t{ 192 }); + + if (!result->upload(img_rgba.data(), img_rgba.total_bytes())) + return nullptr; + + return result; +} diff --git a/liblava/asset/texture_loader.hpp b/liblava/asset/texture_loader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b9e3b575688447e71e55933053173edd7370d5b6 --- /dev/null +++ b/liblava/asset/texture_loader.hpp @@ -0,0 +1,20 @@ +// file : liblava/asset/texture_loader.hpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ +// license : MIT; see accompanying LICENSE file + +#pragma once + +#include <liblava/resource/texture.hpp> + +namespace lava { + + texture::ptr load_texture(device_ptr device, file_format filename, texture_type type = texture_type::tex_2d); + + inline texture::ptr load_texture(device_ptr device, string_ref filename, + VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, texture_type type = texture_type::tex_2d) { + return load_texture(device, { filename, format }, type); + } + + texture::ptr create_default_texture(device_ptr device, uv2 size = { 512, 512 }); + +} // namespace lava diff --git a/liblava/lava.hpp b/liblava/lava.hpp index 779458a57ae0ca0d4481d98846f3a18b7010cb0c..70a86a1111751fc86c90e393aa60becf063bd08d 100644 --- a/liblava/lava.hpp +++ b/liblava/lava.hpp @@ -5,6 +5,7 @@ #pragma once #include <liblava/app.hpp> +#include <liblava/asset.hpp> #include <liblava/base.hpp> #include <liblava/block.hpp> #include <liblava/core.hpp> diff --git a/liblava/resource/buffer.hpp b/liblava/resource/buffer.hpp index e8310b509b6bb6c26ed58d636360c2365e381073..67e58e7015143d08ceb1787b5c8d8adba19aca78 100644 --- a/liblava/resource/buffer.hpp +++ b/liblava/resource/buffer.hpp @@ -5,7 +5,6 @@ #pragma once #include <liblava/base/device.hpp> -#include <liblava/base/memory.hpp> namespace lava { diff --git a/liblava/resource/format.hpp b/liblava/resource/format.hpp index 896f232de3b0ebddbf3cb1f008b5a5a92f46556e..f3e5c517c18e6444847f9c6e04dd317b0860ac20 100644 --- a/liblava/resource/format.hpp +++ b/liblava/resource/format.hpp @@ -5,7 +5,6 @@ #pragma once #include <liblava/base/device.hpp> -#include <liblava/core/data.hpp> namespace lava { diff --git a/liblava/resource/image.hpp b/liblava/resource/image.hpp index 1f16664e8adaaff96a73ea445b57b3e8719f3b06..c606c502662ddb34d1952a2678faf7d7092aace3 100644 --- a/liblava/resource/image.hpp +++ b/liblava/resource/image.hpp @@ -5,9 +5,6 @@ #pragma once #include <liblava/base/device.hpp> -#include <liblava/base/memory.hpp> -#include <liblava/core/id.hpp> -#include <liblava/core/math.hpp> namespace lava { diff --git a/liblava/resource/mesh.cpp b/liblava/resource/mesh.cpp index bb6793aaf855aa67ff8f0f59c45a27f64c633536..b094f53ff5339c0915a48701ab3b697914f7105d 100644 --- a/liblava/resource/mesh.cpp +++ b/liblava/resource/mesh.cpp @@ -2,33 +2,8 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/file.hpp> #include <liblava/resource/mesh.hpp> -#ifndef LIBLAVA_TINYOBJLOADER -# define LIBLAVA_TINYOBJLOADER 1 -#endif - -#if LIBLAVA_TINYOBJLOADER - -# ifdef _WIN32 -# pragma warning(push, 4) -# else -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -# endif - -# define TINYOBJLOADER_IMPLEMENTATION -# include <tiny_obj_loader.h> - -# ifdef _WIN32 -# pragma warning(pop) -# else -# pragma GCC diagnostic pop -# endif - -#endif - namespace lava { void mesh::add_data(mesh_data const& value) { @@ -101,78 +76,6 @@ namespace lava { } // namespace lava -lava::mesh::ptr lava::load_mesh(device_ptr device, name filename) { -#if LIBLAVA_TINYOBJLOADER - if (extension(filename, "OBJ")) { - tinyobj::attrib_t attrib; - std::vector<tinyobj::shape_t> shapes; - std::vector<tinyobj::material_t> materials; - std::string err; - std::string warn; - - string target_file = filename; - - file_remover temp_file_remover; - { - file file(filename); - if (file.opened() && file.get_type() == file_type::fs) { - string temp_file; - temp_file = file_system::get_pref_dir(); - temp_file += get_filename_from(target_file, true); - - scope_data temp_data(file.get_size()); - if (!temp_data.ptr) - return nullptr; - - if (file_error(file.read(temp_data.ptr))) - return nullptr; - - if (!write_file(str(temp_file), temp_data.ptr, temp_data.size)) - return nullptr; - - target_file = temp_file; - - temp_file_remover.filename = target_file; - } - } - - if (tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, str(target_file))) { - auto mesh = make_mesh(); - - for (auto const& shape : shapes) { - for (auto const& index : shape.mesh.indices) { - vertex vertex; - - vertex.position = v3(attrib.vertices[3 * index.vertex_index], - attrib.vertices[3 * index.vertex_index + 1], - attrib.vertices[3 * index.vertex_index + 2]); - - vertex.color = v4(1.f); - - if (!attrib.texcoords.empty()) - vertex.uv = v2(attrib.texcoords[2 * index.texcoord_index], 1.f - attrib.texcoords[2 * index.texcoord_index + 1]); - - vertex.normal = attrib.normals.empty() ? v3(0.f) : v3(attrib.normals[3 * index.normal_index], attrib.normals[3 * index.normal_index + 1], attrib.normals[3 * index.normal_index + 2]); - - mesh->get_vertices().push_back(vertex); - mesh->get_indices().push_back(mesh->get_indices_count()); - } - } - - if (mesh->empty()) - return nullptr; - - if (!mesh->create(device)) - return nullptr; - - return mesh; - } - } -#endif - - return nullptr; -} - lava::mesh::ptr lava::create_mesh(device_ptr device, mesh_type type) { switch (type) { case mesh_type::cube: { diff --git a/liblava/resource/mesh.hpp b/liblava/resource/mesh.hpp index c4b5b5c67b44bc5a7919dbfcfde87df7d3e765c0..a629cf801c92736119b6f8946938dafe9a805615 100644 --- a/liblava/resource/mesh.hpp +++ b/liblava/resource/mesh.hpp @@ -4,8 +4,6 @@ #pragma once -#include <liblava/core/data.hpp> -#include <liblava/core/math.hpp> #include <liblava/resource/buffer.hpp> namespace lava { diff --git a/liblava/resource/texture.cpp b/liblava/resource/texture.cpp index 1cee8f079bc5817bf874af42ddc60f2d50f63389..5191179d2993cdea2942b0cc73f973cebb1b0da5 100644 --- a/liblava/resource/texture.cpp +++ b/liblava/resource/texture.cpp @@ -2,38 +2,8 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <bitmap_image.hpp> -#include <liblava/file/file_utils.hpp> #include <liblava/resource/format.hpp> #include <liblava/resource/texture.hpp> -#include <selene/img/pixel/PixelTypeAliases.hpp> -#include <selene/img/typed/ImageView.hpp> -#include <selene/img_ops/ImageConversions.hpp> - -#ifdef _WIN32 -# pragma warning(push, 4) -# pragma warning(disable : 4458) -# pragma warning(disable : 4100) -# pragma warning(disable : 5054) -#else -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wignored-qualifiers" -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wtype-limits" -# pragma GCC diagnostic ignored "-Wempty-body" -# pragma GCC diagnostic ignored "-Wunused-result" -#endif - -#include <gli/gli.hpp> - -#ifdef _WIN32 -# pragma warning(pop) -#else -# pragma GCC diagnostic pop -#endif - -#define STB_IMAGE_IMPLEMENTATION -#include <stb_image.h> namespace lava { @@ -249,236 +219,4 @@ namespace lava { return true; } - scope_image::scope_image(string_ref filename) - : image_file(str(filename)), file_data(image_file.get_size(), false) { - if (image_file.opened()) { - if (!file_data.allocate()) - return; - - if (file_error(image_file.read(file_data.ptr))) - return; - } - - i32 tex_width, tex_height, tex_channels = 0; - - if (image_file.opened()) - data = as_ptr(stbi_load_from_memory((stbi_uc const*) file_data.ptr, to_i32(file_data.size), - &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha)); - else - data = as_ptr(stbi_load(str(filename), &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha)); - - if (!data) - return; - - size = { tex_width, tex_height }; - channels = tex_channels; - ready = true; - } - - scope_image::~scope_image() { - if (data) - stbi_image_free(data); - } - - texture::ptr create_gli_texture_2d(device_ptr device, file const& file, VkFormat format, scope_data const& temp_data) { - gli::texture2d tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) - : gli::load(file.get_path())); - assert(!tex.empty()); - if (tex.empty()) - return nullptr; - - auto mip_levels = to_ui32(tex.levels()); - - texture::layer layer; - - for (auto m = 0u; m < mip_levels; ++m) { - texture::mip_level level; - level.extent = { tex[m].extent().x, tex[m].extent().y }; - level.size = to_ui32(tex[m].size()); - - layer.levels.push_back(level); - } - - texture::layer::list layers; - layers.push_back(layer); - - auto texture = make_texture(); - - uv2 size = { tex[0].extent().x, tex[0].extent().y }; - if (!texture->create(device, size, format, layers, texture_type::tex_2d)) - return nullptr; - - if (!texture->upload(tex.data(), tex.size())) - return nullptr; - - return texture; - } - - template<typename T> - texture::layer::list create_layer_list(T const& tex, ui32 layer_count) { - texture::layer::list layers; - - auto mip_levels = to_ui32(tex.levels()); - - for (auto i = 0u; i < layer_count; ++i) { - texture::layer layer; - - for (auto m = 0u; m < mip_levels; ++m) { - texture::mip_level level; - level.extent = { tex[i][m].extent().x, tex[i][m].extent().y }; - level.size = to_ui32(tex[i][m].size()); - - layer.levels.push_back(level); - } - - layers.push_back(layer); - } - - return layers; - } - - texture::ptr create_gli_texture_array(device_ptr device, file const& file, VkFormat format, scope_data const& temp_data) { - gli::texture2d_array tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) - : gli::load(file.get_path())); - assert(!tex.empty()); - if (tex.empty()) - return nullptr; - - auto layers = create_layer_list(tex, to_ui32(tex.layers())); - - auto texture = make_texture(); - - uv2 size = { tex[0].extent().x, tex[0].extent().y }; - if (!texture->create(device, size, format, layers, texture_type::array)) - return nullptr; - - if (!texture->upload(tex.data(), tex.size())) - return nullptr; - - return texture; - } - - texture::ptr create_gli_texture_cube_map(device_ptr device, file const& file, VkFormat format, scope_data const& temp_data) { - gli::texture_cube tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) - : gli::load(file.get_path())); - assert(!tex.empty()); - if (tex.empty()) - return nullptr; - - auto layers = create_layer_list(tex, to_ui32(tex.faces())); - - auto texture = make_texture(); - - uv2 size = { tex[0].extent().x, tex[0].extent().y }; - if (!texture->create(device, size, format, layers, texture_type::cube_map)) - return nullptr; - - if (!texture->upload(tex.data(), tex.size())) - return nullptr; - - return texture; - } - - texture::ptr create_stbi_texture(device_ptr device, file const& file, scope_data const& temp_data) { - i32 tex_width = 0, tex_height = 0; - stbi_uc* data = nullptr; - - if (file.opened()) - data = stbi_load_from_memory((stbi_uc const*) temp_data.ptr, to_i32(temp_data.size), - &tex_width, &tex_height, nullptr, STBI_rgb_alpha); - else - data = stbi_load(str(file.get_path()), &tex_width, &tex_height, nullptr, STBI_rgb_alpha); - - if (!data) - return nullptr; - - auto texture = make_texture(); - - uv2 size = { tex_width, tex_height }; - if (!texture->create(device, size, VK_FORMAT_R8G8B8A8_UNORM)) - return nullptr; - - const i32 tex_channels = 4; - auto uploadSize = tex_width * tex_height * tex_channels * sizeof(char); - auto result = texture->upload(data, uploadSize); - - stbi_image_free(data); - - if (!result) - return nullptr; - - return texture; - } - } // namespace lava - -lava::texture::ptr lava::load_texture(device_ptr device, file_format filename, texture_type type) { - auto supported = (filename.format == VK_FORMAT_R8G8B8A8_UNORM) || (device->get_features().textureCompressionBC && (filename.format == VK_FORMAT_BC3_UNORM_BLOCK)) || (device->get_features().textureCompressionASTC_LDR && (filename.format == VK_FORMAT_ASTC_8x8_UNORM_BLOCK)) || (device->get_features().textureCompressionETC2 && (filename.format == VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK)); - if (!supported) - return nullptr; - - auto use_gli = extension(str(filename.path), { "DDS", "KTX", "KMG" }); - auto use_stbi = false; - - if (!use_gli) - use_stbi = extension(str(filename.path), { "JPG", "PNG", "TGA", "BMP", "PSD", "GIF", "HDR", "PIC" }); - - if (!use_gli && !use_stbi) - return nullptr; - - file file(str(filename.path)); - scope_data temp_data(file.get_size(), false); - - if (file.opened()) { - if (!temp_data.allocate()) - return nullptr; - - if (file_error(file.read(temp_data.ptr))) - return nullptr; - } - - if (use_gli) { - texture::layer::list layers; - - switch (type) { - case texture_type::tex_2d: { - return create_gli_texture_2d(device, file, filename.format, temp_data); - } - - case texture_type::array: { - return create_gli_texture_array(device, file, filename.format, temp_data); - } - - case texture_type::cube_map: { - return create_gli_texture_cube_map(device, file, filename.format, temp_data); - } - } - } else { - return create_stbi_texture(device, file, temp_data); - } - - return nullptr; -} - -lava::texture::ptr lava::create_default_texture(device_ptr device, uv2 size) { - auto result = make_texture(); - - if (!result->create(device, size, VK_FORMAT_R8G8B8A8_UNORM)) - return nullptr; - - bitmap_image image(size.x, size.y); - checkered_pattern(64, 64, 255, 255, 255, image); - - image.bgr_to_rgb(); - - sln::TypedLayout typed_layout((sln::PixelLength) size.x, (sln::PixelLength) size.y, (sln::Stride)(image.width() * image.bytes_per_pixel())); - - sln::ImageView<sln::PixelRGB_8u, sln::ImageModifiability::Mutable> img_rgb((uint8_t*) image.data(), typed_layout); - - sln::Image<sln::PixelRGBA_8u> const img_rgba = sln::convert_image<sln::PixelFormat::RGBA>(img_rgb, std::uint8_t{ 192 }); - - if (!result->upload(img_rgba.data(), img_rgba.total_bytes())) - return nullptr; - - return result; -} diff --git a/liblava/resource/texture.hpp b/liblava/resource/texture.hpp index c654a7196f1515de6e2985c1bd7a2da4d6107e2b..6fa58a08d9ae051e01170ce5c03e87f76818e7e2 100644 --- a/liblava/resource/texture.hpp +++ b/liblava/resource/texture.hpp @@ -4,7 +4,6 @@ #pragma once -#include <liblava/file/file.hpp> #include <liblava/resource/buffer.hpp> #include <liblava/resource/image.hpp> @@ -92,15 +91,6 @@ namespace lava { return std::make_shared<texture>(); } - texture::ptr load_texture(device_ptr device, file_format filename, texture_type type = texture_type::tex_2d); - - inline texture::ptr load_texture(device_ptr device, string_ref filename, - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, texture_type type = texture_type::tex_2d) { - return load_texture(device, { filename, format }, type); - } - - texture::ptr create_default_texture(device_ptr device, uv2 size = { 512, 512 }); - struct staging { void add(texture::ptr texture) { todo.push_back(texture); @@ -126,19 +116,4 @@ namespace lava { using texture_registry = id_registry<texture, file_format>; - struct scope_image { - explicit scope_image(string_ref filename); - ~scope_image(); - - bool ready = false; - - data_ptr data = nullptr; - uv2 size = uv2(0, 0); - ui32 channels = 0; - - private: - file image_file; - scope_data file_data; - }; - } // namespace lava