diff --git a/include/limitless/instances/skeletal_instance.hpp b/include/limitless/instances/skeletal_instance.hpp index 49588fb..2f1a822 100644 --- a/include/limitless/instances/skeletal_instance.hpp +++ b/include/limitless/instances/skeletal_instance.hpp @@ -83,6 +83,7 @@ namespace Limitless { * throws no_such_animation if not found */ SkeletalInstance& play(const std::string& name); + SkeletalInstance& play(uint32_t index); /** * Pauses current animation diff --git a/include/limitless/renderer/renderer_settings.hpp b/include/limitless/renderer/renderer_settings.hpp index a29e91d..f890144 100644 --- a/include/limitless/renderer/renderer_settings.hpp +++ b/include/limitless/renderer/renderer_settings.hpp @@ -42,7 +42,7 @@ namespace Limitless { /** * Cascade shadow maps */ - bool cascade_shadow_maps = false; + bool cascade_shadow_maps = true; glm::uvec2 csm_resolution = {1024 * 4, 1024 * 4 }; uint8_t csm_split_count = 3; // [2; 4] diff --git a/shaders/pipeline/composite.frag b/shaders/pipeline/composite.frag index f9240ce..eaaa66c 100644 --- a/shaders/pipeline/composite.frag +++ b/shaders/pipeline/composite.frag @@ -17,4 +17,7 @@ void main() { color = texture(lightened, uv).rgb + bloom_color; color = toneMapping(color, tone_mapping_exposure); +// +// float gamma = 2.2; +// color = pow(color, vec3(1.0 / gamma)); } \ No newline at end of file diff --git a/shaders/terrain/terrain.glsl b/shaders/terrain/terrain.glsl index fde83e2..7c8400e 100644 --- a/shaders/terrain/terrain.glsl +++ b/shaders/terrain/terrain.glsl @@ -72,7 +72,7 @@ vec3 StochasticTexture(vec2 uv, float index, sampler2DArray s) void calculateTerrain(inout MaterialContext mctx) { vec2 terrain_uv = (getVertexPosition().xz / 25.6) * 256.0; - vec3 variation = MacroContrast(MacroVariation()); +// vec3 variation = MacroContrast(MacroVariation()); vec3 diffuse = StochasticTexture(terrain_uv, getVertexTileCurrent(), _terrain_diffuse_texture); vec3 normal = StochasticTexture(terrain_uv, getVertexTileCurrent(), _terrain_normal_texture); diff --git a/src/limitless/core/context.cpp b/src/limitless/core/context.cpp index 80c166c..c8d2137 100644 --- a/src/limitless/core/context.cpp +++ b/src/limitless/core/context.cpp @@ -57,7 +57,6 @@ void Context::unregisterContext() noexcept { void Limitless::swap(Context& lhs, Context& rhs) noexcept { using std::swap; - /* * we do NOT register nullptr GLFWWindow at Context default constructor (it is private, so GLFWWindow pointer gets nullptr) * so have to check that it is present here @@ -80,6 +79,13 @@ void Limitless::swap(Context& lhs, Context& rhs) noexcept { swap(lhs.window, rhs.window); swap(lhs.monitor, rhs.monitor); swap(lhs.size, rhs.size); + + swap(lhs.framebuffer_callback, rhs.framebuffer_callback); + swap(lhs.mouseclick_callback, rhs.mouseclick_callback); + swap(lhs.mousemove_callback, rhs.mousemove_callback); + swap(lhs.scroll_callback, rhs.scroll_callback); + swap(lhs.char_callback, rhs.char_callback); + swap(lhs.key_callback, rhs.key_callback); } Context::Context(Context&& rhs) noexcept : ContextState(std::move(rhs)) { diff --git a/src/limitless/instances/skeletal_instance.cpp b/src/limitless/instances/skeletal_instance.cpp index b3261ae..a3a1109 100644 --- a/src/limitless/instances/skeletal_instance.cpp +++ b/src/limitless/instances/skeletal_instance.cpp @@ -140,6 +140,17 @@ void SkeletalInstance::update(Context& context, const Camera& camera) { ModelInstance::update(context, camera); } +SkeletalInstance &SkeletalInstance::play(uint32_t index) { + const auto& skeletal = dynamic_cast(*model); + const auto& animations = skeletal.getAnimations(); + + animation = &animations.at(index); + animation_duration = std::chrono::seconds(0); + last_time = std::chrono::time_point(); + + return *this; +} + SkeletalInstance& SkeletalInstance::play(const std::string& name) { const auto& skeletal = dynamic_cast(*model); const auto& animations = skeletal.getAnimations(); @@ -213,5 +224,3 @@ const std::vector& SkeletalInstance::getAllBones() const noexcept { const auto& bones = skeletal.getBones(); return bones; } - - diff --git a/src/limitless/loaders/gltf_model_loader.cpp b/src/limitless/loaders/gltf_model_loader.cpp index 9911396..7ddf475 100644 --- a/src/limitless/loaders/gltf_model_loader.cpp +++ b/src/limitless/loaders/gltf_model_loader.cpp @@ -250,7 +250,8 @@ loadMeshes( const std::string& model_name, size_t mesh_index, const std::vector>& materials, - const cgltf_data& data + const cgltf_data& data, + const ModelLoaderFlags& flags ) { auto base_mesh_name = std::string(mesh.name ? mesh.name : generateMeshName(model_name, mesh_index)); @@ -387,10 +388,12 @@ loadMeshes( + std::to_string(attribute.data->component_type) + " for bone weights"}; } break; - + case cgltf_attribute_type_color: { +// copyFromAccessor(*attribute.data); + break; + } default: - throw ModelLoadError { - "unsupported attribute type " + std::to_string(attribute.type)}; + throw ModelLoadError {"unsupported attribute type " + std::to_string(attribute.type)}; break; } } @@ -419,13 +422,18 @@ loadMeshes( + " and UVs"}; } + vertices.reserve(positions.size()); for (size_t i = 0; i < positions.size(); ++i) { + auto uv = flags.isPresent(Limitless::ModelLoaderOption::FlipUV) ? uvs[i] : glm::vec2(uvs[i].x, 1.0 - uvs[i].y); + vertices.emplace_back(VertexNormalTangent { positions[i], normals[i], glm::vec3 {tangents[i]}, // TODO: handle tangent basis handedness in W. - uvs[i]}); + // gltf 2.0 spec: uv origin in top left corner + // OpenGL uv origin in bottom left + uv}); } if (!skin) { @@ -655,7 +663,8 @@ static std::shared_ptr loadMaterial( const fs::path& base_path, const cgltf_material& material, const std::string& model_name, - size_t material_index + size_t material_index, + const ModelLoaderFlags& flags ) { ms::Material::Builder builder = ms::Material::builder(); const auto material_name = model_name + (material.name @@ -674,13 +683,19 @@ static std::shared_ptr loadMaterial( case cgltf_alpha_mode_blend: builder.blending(ms::Blending::Translucent); break; + case cgltf_alpha_mode_mask: + builder.blending(ms::Blending::Opaque); + //TODO: add to material built-in + builder.custom("alpha_cutoff", material.alpha_cutoff); + builder.fragment("if (mctx.diffuse.a <= alpha_cutoff) discard;"); + break; default: throw ModelLoadError {"alpha mode " + std::to_string(material.alpha_mode) + " not supported"}; } - if (!material.has_pbr_metallic_roughness) { - throw ModelLoadError {"missing PBR metallic roughness"}; - } +// if (!material.has_pbr_metallic_roughness) { +// throw ModelLoadError {"missing PBR metallic roughness"}; +// } auto bytesFromBase64 = [](const char* cstr) -> std::vector { auto decode_base64_char = [](char c) -> uint8_t { @@ -907,13 +922,14 @@ static std::vector> loadMaterials( Assets& assets, const InstanceTypes& instance_types, const fs::path& path, - const cgltf_data& src + const cgltf_data& src, + const ModelLoaderFlags& flags ) { std::vector> materials; for (size_t i = 0; i < src.materials_count; ++i) { materials.emplace_back(loadMaterial( - assets, instance_types, path.parent_path(), src.materials[i], model_name, i + assets, instance_types, path.parent_path(), src.materials[i], model_name, i, flags )); } @@ -958,7 +974,7 @@ static void fixMissingMaterials( } static SkeletalModel* loadSkeletalModel( - Assets& assets, const fs::path& path, const cgltf_data& src, const std::string& model_name + Assets& assets, const fs::path& path, const cgltf_data& src, const std::string& model_name, const ModelLoaderFlags& flags ) { std::vector bones; std::unordered_map bone_indice_map; @@ -1021,7 +1037,7 @@ static SkeletalModel* loadSkeletalModel( auto bone_indices_tree = makeBoneIndiceTrees(root_nodes, bone_map); const InstanceTypes instance_types {InstanceType::Skeletal}; - auto loaded_materials = loadMaterials(model_name, assets, instance_types, path, src); + auto loaded_materials = loadMaterials(model_name, assets, instance_types, path, src, flags); std::vector> meshes; std::vector> mesh_materials; @@ -1031,7 +1047,7 @@ static SkeletalModel* loadSkeletalModel( if (node.mesh) { auto [more_meshes, more_mesh_materials] = loadMeshes( - node, *node.mesh, node.skin, model_name, meshes.size(), loaded_materials, src + node, *node.mesh, node.skin, model_name, meshes.size(), loaded_materials, src, flags ); meshes.insert(meshes.end(), more_meshes.begin(), more_meshes.end()); mesh_materials.insert( @@ -1059,20 +1075,20 @@ static SkeletalModel* loadSkeletalModel( } static Model* loadPlainModel( - Assets& assets, const fs::path& path, const cgltf_data& src, const std::string& model_name + Assets& assets, const fs::path& path, const cgltf_data& src, const std::string& model_name, const ModelLoaderFlags& flags ) { std::vector> meshes; std::vector> mesh_materials; const InstanceTypes instance_types {InstanceType::Model}; - auto loaded_materials = loadMaterials(model_name, assets, instance_types, path, src); + auto loaded_materials = loadMaterials(model_name, assets, instance_types, path, src, flags); for (size_t i = 0; i < src.nodes_count; ++i) { const cgltf_node& node = src.nodes[i]; if (node.mesh) { auto [more_meshes, more_mesh_materials] = loadMeshes( - node, *node.mesh, nullptr, model_name, meshes.size(), loaded_materials, src + node, *node.mesh, nullptr, model_name, meshes.size(), loaded_materials, src, flags ); meshes.insert(meshes.end(), more_meshes.begin(), more_meshes.end()); mesh_materials.insert( @@ -1087,18 +1103,18 @@ static Model* loadPlainModel( } static std::shared_ptr -loadModel(Assets& assets, const fs::path& path, const cgltf_data& src) { +loadModel(Assets& assets, const fs::path& path, const cgltf_data& src, const ModelLoaderFlags& flags) { auto model_name = path.stem().string(); if (src.skins_count > 0) { - return std::shared_ptr(loadSkeletalModel(assets, path, src, model_name)); + return std::shared_ptr(loadSkeletalModel(assets, path, src, model_name, flags)); } else { - return std::shared_ptr(loadPlainModel(assets, path, src, model_name)); + return std::shared_ptr(loadPlainModel(assets, path, src, model_name, flags)); } } std::shared_ptr -GltfModelLoader::loadModel(Assets& assets, const fs::path& path, [[maybe_unused]] const ModelLoaderFlags& flags) { +GltfModelLoader::loadModel(Assets& assets, const fs::path& path, const ModelLoaderFlags& flags) { cgltf_options opts = cgltf_options { cgltf_file_type_invalid, // autodetect 0, // auto json token count @@ -1126,5 +1142,5 @@ GltfModelLoader::loadModel(Assets& assets, const fs::path& path, [[maybe_unused] throw ModelLoadError {"no scene"}; } - return ::loadModel(assets, path, *out_data); + return ::loadModel(assets, path, *out_data, flags); } diff --git a/src/limitless/pipeline/deferred/translucent_pass.cpp b/src/limitless/pipeline/deferred/translucent_pass.cpp index 7f39e8a..ef98ec8 100644 --- a/src/limitless/pipeline/deferred/translucent_pass.cpp +++ b/src/limitless/pipeline/deferred/translucent_pass.cpp @@ -12,6 +12,7 @@ #include #include #include +#include using namespace Limitless; @@ -72,4 +73,6 @@ std::shared_ptr TranslucentPass::getResult() { void TranslucentPass::onFramebufferChange(glm::uvec2 size) { framebuffer.onFramebufferChange(size); + + framebuffer << TextureAttachment{FramebufferAttachment::Depth, pipeline.get().getDepth()}; }