From 3449a8ecef06931035ac256cca88aefdf500b4d8 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Wed, 12 Jun 2024 22:44:13 +0300 Subject: [PATCH 01/28] WIP font render --- learnopengl.vcxproj | 2 ++ learnopengl.vcxproj.filters | 6 ++++ scene/scene_text.yml | 52 ++++++++++++++-------------- src/loader/EntityLoader.cpp | 24 +++---------- src/loader/EntityLoader.h | 4 --- src/loader/FontLoader.cpp | 8 +++++ src/loader/FontLoader.h | 4 +++ src/loader/Loaders.cpp | 2 ++ src/loader/Loaders.h | 2 ++ src/loader/SceneLoader.cpp | 32 +++-------------- src/loader/SceneLoader.h | 10 ------ src/loader/TextData.h | 8 +++++ src/loader/TextLoader.cpp | 69 +++++++++++++++++++++++++++++++++++++ src/loader/TextLoader.h | 24 +++++++++++++ 14 files changed, 159 insertions(+), 88 deletions(-) create mode 100644 src/loader/TextLoader.cpp create mode 100644 src/loader/TextLoader.h diff --git a/learnopengl.vcxproj b/learnopengl.vcxproj index f639e55c7..6eac1f5e3 100644 --- a/learnopengl.vcxproj +++ b/learnopengl.vcxproj @@ -212,6 +212,7 @@ + @@ -419,6 +420,7 @@ + diff --git a/learnopengl.vcxproj.filters b/learnopengl.vcxproj.filters index 84176e7c0..9e2249165 100644 --- a/learnopengl.vcxproj.filters +++ b/learnopengl.vcxproj.filters @@ -696,6 +696,9 @@ Source Files + + Source Files + @@ -1733,6 +1736,9 @@ Header Files + + Header Files + diff --git a/scene/scene_text.yml b/scene/scene_text.yml index c29b71dc4..db2364f77 100644 --- a/scene/scene_text.yml +++ b/scene/scene_text.yml @@ -30,20 +30,21 @@ entities: mesh: flags: billboard: true + text: + text: "- fps" + font: + path: fonts/Vera.ttf + size: 36 material: name: fps_text kd: [0.0, 0.8, 0.0, 1.0] xmetal: [1.0, 0.0, 0, 1] alpha: true render_back: true - text: - font: fps_font - text: "- fps" - program: g_font_render - shadow_program: shadow_font_render + program: g_font_render + shadow_program: shadow_font_render pos: [1.0, 0.75, -0.75] scale: 0.01 - xrender_flags: - id: player_camera parent_id: player type: origo @@ -63,6 +64,10 @@ entities: alpha: true xblend: true render_back: true + text: + font: + path: fonts/LuckiestGuy.ttf + size: 72 custom_material: type: text font: hello_font @@ -73,7 +78,11 @@ entities: xeffect: true - id: hello_world type: text - mesh: + text: + font: + path: fonts/LuckiestGuy.ttf + size: 72 + text: ÄÅÖ äåö - Hello world material: name: hello map_pbr: textures\Plastic 01 [4K] @@ -83,11 +92,8 @@ entities: alpha: true xblend: true render_back: true - text: - font: hello_font - text: ÄÅÖ äåö - Hello world - program: g_font_render - shadow_program: shadow_font_render + program: g_font_render + shadow_program: shadow_font_render pos: [0.0, 4.0, -3.0] scale: 0.01 render_flags: @@ -98,17 +104,19 @@ entities: mesh: flags: billboard: true + text: + font: + path: fonts/Lobster-Regular.ttf + size: 36 + text: Look at ME material: name: another_text map_pbr: textures\Leather037_1K tiling: 1 alpha: true render_back: true - text: - font: another_font - text: Look at ME - program: g_font_render - shadow_program: shadow_font_render + program: g_font_render + shadow_program: shadow_font_render pos: [0, 4, -8] scale: 0.01 xrender_flags: @@ -181,13 +189,3 @@ entities: pos: [-5.0, 4.0, -5.0] scale: 0.8 xrender_flags: -fonts: - - name: hello_font - path: fonts/LuckiestGuy.ttf - size: 72 - - name: another_font - path: fonts/Lobster-Regular.ttf - size: 36 - - name: fps_font - path: fonts/Vera.ttf - size: 36 diff --git a/src/loader/EntityLoader.cpp b/src/loader/EntityLoader.cpp index fe0381a02..3b9381aaa 100644 --- a/src/loader/EntityLoader.cpp +++ b/src/loader/EntityLoader.cpp @@ -161,7 +161,7 @@ namespace loader { data.front = readVec3(v); } else if (k == "text") { - loadText(v, data.text); + loaders.m_textLoader.loadText(v, data.text, loaders); } else if (k == "position" || k == "pos") { data.position = readVec3(v); @@ -253,6 +253,9 @@ namespace loader { if (!data.meshes.empty()) { data.type = EntityType::model; } + if (data.text.enabled) { + data.type = EntityType::text; + } } if (data.enabled) { @@ -294,23 +297,4 @@ namespace loader { } } - void EntityLoader::loadText( - const loader::DocNode& node, - TextData& data) const - { - for (const auto& pair : node.getNodes()) { - const std::string& k = pair.getName(); - const loader::DocNode& v = pair.getNode(); - - if (k == "text") { - data.text = readString(v); - } - else if (k == "font") { - data.font = readString(v); - } - else { - reportUnknown("text_entry", k, v); - } - } - } } diff --git a/src/loader/EntityLoader.h b/src/loader/EntityLoader.h index 14e26c62b..371aa64a5 100644 --- a/src/loader/EntityLoader.h +++ b/src/loader/EntityLoader.h @@ -28,9 +28,5 @@ namespace loader { std::vector& clones, bool recurse, Loaders& loaders) const; - - void loadText( - const loader::DocNode& node, - TextData& data) const; }; } diff --git a/src/loader/FontLoader.cpp b/src/loader/FontLoader.cpp index 577b49adc..2ca9a2afb 100644 --- a/src/loader/FontLoader.cpp +++ b/src/loader/FontLoader.cpp @@ -60,6 +60,14 @@ namespace loader { } } + text::font_id FontLoader::resolveFont( + pool::TypeHandle typeHandle, + const TextData& data) const + { + auto* font = findFont(data.font); + return font ? font->id : 0; + } + text::font_id FontLoader::createFont( const FontData& data) const { diff --git a/src/loader/FontLoader.h b/src/loader/FontLoader.h index 2d6f69ff9..e00137458 100644 --- a/src/loader/FontLoader.h +++ b/src/loader/FontLoader.h @@ -27,5 +27,9 @@ namespace loader { text::font_id createFont( const FontData& data) const; + + text::font_id resolveFont( + pool::TypeHandle typeHandle, + const TextData& data) const; }; } diff --git a/src/loader/Loaders.cpp b/src/loader/Loaders.cpp index aa49157b2..8288d7d6b 100644 --- a/src/loader/Loaders.cpp +++ b/src/loader/Loaders.cpp @@ -19,6 +19,7 @@ namespace loader { m_physicsLoader(ctx), m_entityLoader(ctx), m_meshLoader(ctx), + m_textLoader(ctx), m_prefabLoader{ctx} {} @@ -38,6 +39,7 @@ namespace loader { m_physicsLoader.setRegistry(registry); m_entityLoader.setRegistry(registry); m_meshLoader.setRegistry(registry); + m_textLoader.setRegistry(registry); m_prefabLoader.setRegistry(registry); } } diff --git a/src/loader/Loaders.h b/src/loader/Loaders.h index 53f549b29..77135dec6 100644 --- a/src/loader/Loaders.h +++ b/src/loader/Loaders.h @@ -21,6 +21,7 @@ #include "PrefabLoader.h" #include "EntityLoader.h" #include "MeshLoader.h" +#include "TextLoader.h" class Registry; @@ -43,6 +44,7 @@ namespace loader { EntityLoader m_entityLoader; MeshLoader m_meshLoader; + TextLoader m_textLoader; FontLoader m_fontLoader; MaterialLoader m_materialLoader; diff --git a/src/loader/SceneLoader.cpp b/src/loader/SceneLoader.cpp index 5abd089c3..51f830173 100644 --- a/src/loader/SceneLoader.cpp +++ b/src/loader/SceneLoader.cpp @@ -44,7 +44,7 @@ //#include "generator/GridGenerator.h" //#include "generator/AsteroidBeltGenerator.h" -#include "generator/TextGenerator.h" +//#include "generator/TextGenerator.h" //#include "terrain/TerrainGenerator.h" #include "event/Dispatcher.h" @@ -129,8 +129,6 @@ namespace loader { l.m_skyboxLoader.loadSkybox(doc.findNode("skybox"), *m_skybox); - l.m_fontLoader.loadFonts(doc.findNode("fonts"), m_fonts); - l.m_rootLoader.loadRoot(doc.findNode("root"), *m_root); l.m_scriptLoader.loadScriptEngine(doc.findNode("script"), *m_scriptEngineData); @@ -485,14 +483,6 @@ namespace loader { return typeHandle; } - text::font_id SceneLoader::resolveFont( - pool::TypeHandle typeHandle, - const TextData& data) const - { - auto* font = findFont(data.font); - return font ? font->id : 0; - } - void SceneLoader::resolveMaterials( mesh::MeshType* type, mesh::LodMesh& lodMesh, @@ -745,11 +735,10 @@ namespace loader { entityData.particle); if (type->m_entityType == EntityType::text) { - auto fontId = resolveFont(typeHandle, entityData.text); - auto generator = std::make_unique(); - generator->setFontId(fontId); - generator->setText(entityData.text.text); - node->m_generator = std::move(generator); + node->m_generator = m_loaders->m_textLoader.createGenerator( + entityData.text, + type, + *m_loaders); } l.m_scriptLoader.createScript( @@ -1024,15 +1013,4 @@ namespace loader { } } } - - const FontData* SceneLoader::findFont( - std::string_view name) const - { - const auto& it = std::find_if( - m_fonts.cbegin(), - m_fonts.cend(), - [&name](const auto& m) { return m.name == name; }); - return it != m_fonts.end() ? &(*it) : nullptr; - } - } diff --git a/src/loader/SceneLoader.h b/src/loader/SceneLoader.h index fd6221b30..4b338b0a6 100644 --- a/src/loader/SceneLoader.h +++ b/src/loader/SceneLoader.h @@ -31,7 +31,6 @@ namespace mesh { namespace loader { struct RootData; struct SkyboxData; - struct FontData; struct MaterialData; struct ScriptEngineData; struct EntityRoot; @@ -124,10 +123,6 @@ namespace loader { const EntityData& entityData, const glm::uvec3& tile); - text::font_id resolveFont( - pool::TypeHandle typeHandle, - const TextData& data) const; - void resolveMaterials( mesh::MeshType* type, mesh::LodMesh& lodMesh, @@ -202,9 +197,6 @@ namespace loader { int& errorCount, std::map& collectedIds); - const FontData* findFont( - std::string_view name) const; - private: size_t m_pendingCount{ 0 }; std::mutex m_ready_lock{}; @@ -221,8 +213,6 @@ namespace loader { std::vector m_resolvedEntities; - std::vector m_fonts; - std::unique_ptr m_defaultMaterial; std::unique_ptr m_loaders; diff --git a/src/loader/TextData.h b/src/loader/TextData.h index 92bd9795e..de6e85ce3 100644 --- a/src/loader/TextData.h +++ b/src/loader/TextData.h @@ -2,9 +2,17 @@ #include +#include "MaterialData.h" +#include "FontData.h" + namespace loader { struct TextData { + bool enabled{ false }; + std::string text; std::string font; + + MaterialData materialData; + FontData fontData; }; } diff --git a/src/loader/TextLoader.cpp b/src/loader/TextLoader.cpp new file mode 100644 index 000000000..470d3dba8 --- /dev/null +++ b/src/loader/TextLoader.cpp @@ -0,0 +1,69 @@ +#include "TextLoader.h" + +#include "asset/Assets.h" + +#include "loader/document.h" +#include "Loaders.h" + +#include "generator/TextGenerator.h" + + +namespace loader { + TextLoader::TextLoader( + Context ctx) + : BaseLoader(ctx) + { + } + + void TextLoader::loadText( + const loader::DocNode& node, + TextData& data, + Loaders& loaders) const + { + for (const auto& pair : node.getNodes()) { + const std::string& k = pair.getName(); + const loader::DocNode& v = pair.getNode(); + + if (k == "xtext") { + data.text = readString(v); + data.enabled = false; + } + if (k == "text") { + data.text = readString(v); + data.enabled = true; + } + else if (k == "font") { + loaders.m_fontLoader.loadFont(v, data.fontData); + } + else if (k == "material") { + loaders.m_materialLoader.loadMaterial(v, data.materialData); + } + else { + reportUnknown("text_entry", k, v); + } + } + } + + std::unique_ptr TextLoader::createGenerator( + const TextData& data, + mesh::MeshType* type, + Loaders& loaders) + { + if (!data.enabled) return nullptr; + + const auto& assets = Assets::get(); + + auto generator = std::make_unique(); + + auto fontId = resolveFont(typeHandle, entityData.text); + generator->setFontId(fontId); + generator->setText(data.text); + + //generator->m_material = data.materialData.material; + //generator->m_material.loadTextures(); + + //loaders.m_materialLoader.resolveProgram(type, &generator->m_material); + + return generator; + } +} diff --git a/src/loader/TextLoader.h b/src/loader/TextLoader.h new file mode 100644 index 000000000..0b6ab09f8 --- /dev/null +++ b/src/loader/TextLoader.h @@ -0,0 +1,24 @@ +#pragma once + +#include "BaseLoader.h" + +#include "TextData.h" + +namespace loader { + class TextLoader : public BaseLoader + { + public: + TextLoader( + Context ctx); + + void loadText( + const loader::DocNode& node, + TextData& data, + Loaders& loaders) const; + + std::unique_ptr createGenerator( + const TextData& data, + mesh::MeshType* type, + Loaders& loaders); + }; +} From 5c554914d74434d0b632504dd1e625a83f2b1aef Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sat, 15 Jun 2024 00:18:25 +0300 Subject: [PATCH 02/28] FIX font render --- scene/scene_asteroids.yml | 9 +++--- scene/scene_blend.yml | 11 ++++---- scene/scene_full.yml | 9 +++--- scene/scene_particle.yml | 13 ++++----- scene/scene_text.yml | 31 ++++++++++---------- shader/font_render.vs | 1 + shader/g_font_render.fs | 2 +- shader/g_font_render.vs | 3 +- shader/shadow_font_render.vs | 1 + src/generator/TextGenerator.cpp | 4 +++ src/generator/TextGenerator.h | 6 ++++ src/loader/BaseLoader.cpp | 2 ++ src/loader/BaseLoader.h | 2 ++ src/loader/EntityLoader.cpp | 20 ++++++------- src/loader/FontLoader.cpp | 31 ++++---------------- src/loader/FontLoader.h | 9 +----- src/loader/SceneLoader.cpp | 18 +----------- src/loader/TextData.h | 1 - src/loader/TextLoader.cpp | 13 ++++----- src/loader/TextLoader.h | 9 +++++- src/registry/FontRegistry.cpp | 50 +++++++++++++++++++++++---------- src/registry/FontRegistry.h | 8 ++++-- src/render/Batch.cpp | 2 ++ 23 files changed, 127 insertions(+), 128 deletions(-) diff --git a/scene/scene_asteroids.yml b/scene/scene_asteroids.yml index 045aca91b..0e237377a 100644 --- a/scene/scene_asteroids.yml +++ b/scene/scene_asteroids.yml @@ -32,8 +32,11 @@ entities: alpha: true render_back: true text: - font: fps_font text: "- fps" + font: + name: fps_font + path: fonts/Vera.ttf + size: 36 program: g_font_render shadow_program: shadow_font_render pos: [-1.8, 0.95, -2.5] @@ -144,7 +147,3 @@ entities: type: directional diffuse: [0.9, 0.9, 0.7, 1.0] intensity: 50000 -fonts: - - name: fps_font - path: fonts/Vera.ttf - size: 36 diff --git a/scene/scene_blend.yml b/scene/scene_blend.yml index 1b9c5368d..e3c09e7fa 100644 --- a/scene/scene_blend.yml +++ b/scene/scene_blend.yml @@ -108,9 +108,12 @@ entities: alpha: true render_back: true text: - font: hello_font text: Hello world - program: font_render + fonts: + name: hello_font + path: fonts/LuckiestGuy.ttf + size: 72 + program: g_font_render shadow_program: shadow_font_render pos: [-2.5, 0.0, -9.0] scale: 0.01 @@ -129,7 +132,3 @@ entities: type: directional diffuse: [0.7, 0.7, 0.7, 1.0] intensity: 40000 -fonts: - - name: hello_font - path: fonts/LuckiestGuy.ttf - size: 72 diff --git a/scene/scene_full.yml b/scene/scene_full.yml index a0194e16c..553e8b42c 100644 --- a/scene/scene_full.yml +++ b/scene/scene_full.yml @@ -75,8 +75,11 @@ entities: alpha: true render_back: true text: - font: fps_font text: "- fps" + fonts: + name: fps_font + path: fonts/Vera.ttf + size: 36 program: g_font_render shadow_program: shadow_font_render pos: [-1.8, 0.95, -2.5] @@ -1446,7 +1449,3 @@ entities: geom: type: plane rot: [270, 0, 0] -fonts: - - name: fps_font - path: fonts/Vera.ttf - size: 36 diff --git a/scene/scene_particle.yml b/scene/scene_particle.yml index 1d4d3763b..b81f48ddf 100644 --- a/scene/scene_particle.yml +++ b/scene/scene_particle.yml @@ -29,6 +29,8 @@ entities: parent_id: player type: text mesh: + flags: + billboard: true material: - name: fps_text kd: [0.0, 0.8, 0.0, 1.0] @@ -36,14 +38,15 @@ entities: alpha: true render_back: true text: - font: fps_font text: "- fps" + fonts: + name: fps_font + path: fonts/Vera.ttf + size: 36 program: g_font_render shadow_program: shadow_font_render pos: [1.0, 0.75, -0.75] scale: 0.01 - render_flags: - billboard: true - id: player_camera parent_id: player type: origo @@ -220,7 +223,3 @@ entities: type: directional diffuse: [0.7, 0.7, 0.7, 1.0] intensity: 20000 -fonts: - - name: fps_font - path: fonts/Vera.ttf - size: 36 diff --git a/scene/scene_text.yml b/scene/scene_text.yml index db2364f77..4da275460 100644 --- a/scene/scene_text.yml +++ b/scene/scene_text.yml @@ -30,11 +30,6 @@ entities: mesh: flags: billboard: true - text: - text: "- fps" - font: - path: fonts/Vera.ttf - size: 36 material: name: fps_text kd: [0.0, 0.8, 0.0, 1.0] @@ -43,6 +38,11 @@ entities: render_back: true program: g_font_render shadow_program: shadow_font_render + text: + text: "- fps" + font: + path: fonts/Vera.ttf + size: 36 pos: [1.0, 0.75, -0.75] scale: 0.01 - id: player_camera @@ -78,11 +78,7 @@ entities: xeffect: true - id: hello_world type: text - text: - font: - path: fonts/LuckiestGuy.ttf - size: 72 - text: ÄÅÖ äåö - Hello world + mesh: material: name: hello map_pbr: textures\Plastic 01 [4K] @@ -94,6 +90,11 @@ entities: render_back: true program: g_font_render shadow_program: shadow_font_render + text: + font: + path: fonts/LuckiestGuy.ttf + size: 72 + text: ÄÅÖ äåö - Hello world pos: [0.0, 4.0, -3.0] scale: 0.01 render_flags: @@ -104,11 +105,6 @@ entities: mesh: flags: billboard: true - text: - font: - path: fonts/Lobster-Regular.ttf - size: 36 - text: Look at ME material: name: another_text map_pbr: textures\Leather037_1K @@ -117,6 +113,11 @@ entities: render_back: true program: g_font_render shadow_program: shadow_font_render + text: + font: + path: fonts/Lobster-Regular.ttf + size: 36 + text: Look at ME pos: [0, 4, -8] scale: 0.01 xrender_flags: diff --git a/shader/font_render.vs b/shader/font_render.vs index 88f6fe3d9..d420d99d7 100644 --- a/shader/font_render.vs +++ b/shader/font_render.vs @@ -5,6 +5,7 @@ #include ssbo_entities.glsl #include ssbo_instance_indeces.glsl +#include ssbo_mesh_transforms.glsl #include uniform_matrices.glsl diff --git a/shader/g_font_render.fs b/shader/g_font_render.fs index 0f78dd627..30d8975aa 100644 --- a/shader/g_font_render.fs +++ b/shader/g_font_render.fs @@ -31,7 +31,7 @@ in VS_OUT { flat uint shapeIndex; #ifdef USE_TBN - mat4 tbn; + mat3 tbn; #endif #ifdef USE_PARALLAX vec3 viewTangentPos; diff --git a/shader/g_font_render.vs b/shader/g_font_render.vs index 530a0720a..d03bf2078 100644 --- a/shader/g_font_render.vs +++ b/shader/g_font_render.vs @@ -17,6 +17,7 @@ layout (location = ATTR_FONT_ATLAS_TEX) in vec2 a_atlasCoord; #include ssbo_entities.glsl #include ssbo_instance_indeces.glsl +#include ssbo_mesh_transforms.glsl #include ssbo_materials.glsl #include uniform_matrices.glsl @@ -41,7 +42,7 @@ out VS_OUT { flat uint shapeIndex; #ifdef USE_TBN - mat4 tbn; + mat3 tbn; #endif #ifdef USE_PARALLAX vec3 viewTangentPos; diff --git a/shader/shadow_font_render.vs b/shader/shadow_font_render.vs index 6a7ad8f98..3e140900b 100644 --- a/shader/shadow_font_render.vs +++ b/shader/shadow_font_render.vs @@ -5,6 +5,7 @@ #include ssbo_entities.glsl #include ssbo_instance_indeces.glsl +#include ssbo_mesh_transforms.glsl #include uniform_matrices.glsl diff --git a/src/generator/TextGenerator.cpp b/src/generator/TextGenerator.cpp index 751217143..110cd07a7 100644 --- a/src/generator/TextGenerator.cpp +++ b/src/generator/TextGenerator.cpp @@ -33,6 +33,8 @@ TextGenerator::TextGenerator() : m_vboAtlasTex{ "vbo_font", ATTR_FONT_ATLAS_TEX, VBO_FONT_ATLAS_BINDING } {} +TextGenerator::~TextGenerator() = default; + void TextGenerator::prepare( const PrepareContext& ctx, Node& container) @@ -117,6 +119,8 @@ void TextGenerator::updateVAO( m_vao.updateRT(); } + lodMesh->m_vao = m_vao.getVAO(); + lod.m_baseVertex = mesh->getBaseVertex(); lod.m_baseIndex = mesh->getBaseIndex(); lod.m_indexCount = mesh->getIndexCount(); diff --git a/src/generator/TextGenerator.h b/src/generator/TextGenerator.h index eecdbb716..ba983c930 100644 --- a/src/generator/TextGenerator.h +++ b/src/generator/TextGenerator.h @@ -2,6 +2,7 @@ #include +#include "asset/Material.h" #include "asset/AABB.h" #include "NodeGenerator.h" @@ -26,6 +27,8 @@ class TextGenerator final : public NodeGenerator { public: TextGenerator(); + ~TextGenerator(); + virtual void prepare( const PrepareContext& ctx, Node& container) override; @@ -73,6 +76,9 @@ class TextGenerator final : public NodeGenerator { void clear(); +public: + Material m_material; + private: bool m_dirty{ true }; diff --git a/src/loader/BaseLoader.cpp b/src/loader/BaseLoader.cpp index ee4c9aaff..58e4f9ba6 100644 --- a/src/loader/BaseLoader.cpp +++ b/src/loader/BaseLoader.cpp @@ -38,6 +38,8 @@ namespace loader { } + BaseLoader::~BaseLoader() = default; + void BaseLoader::setRegistry(std::shared_ptr registry) { m_registry = registry; diff --git a/src/loader/BaseLoader.h b/src/loader/BaseLoader.h index cab9943d7..16ac3956a 100644 --- a/src/loader/BaseLoader.h +++ b/src/loader/BaseLoader.h @@ -38,6 +38,8 @@ namespace loader BaseLoader( Context ctx); + ~BaseLoader(); + void setRegistry(std::shared_ptr registry); void loadRepeat( diff --git a/src/loader/EntityLoader.cpp b/src/loader/EntityLoader.cpp index 3b9381aaa..754c5ca8e 100644 --- a/src/loader/EntityLoader.cpp +++ b/src/loader/EntityLoader.cpp @@ -120,10 +120,8 @@ namespace loader { data.active = readBool(v); } else if (k == "mesh" || k == "model") { - if (data.type == EntityType::none) { - auto& meshData = data.meshes.emplace_back(); - loaders.m_meshLoader.loadMesh(v, meshData, loaders); - } + auto& meshData = data.meshes.emplace_back(); + loaders.m_meshLoader.loadMesh(v, meshData, loaders); } else if (k == "program") { data.programs[MaterialProgramType::shader] = readString(v); @@ -259,13 +257,13 @@ namespace loader { } if (data.enabled) { - if (!data.meshes.empty()) { - if (data.type != EntityType::model) { - auto msg = fmt::format("INVALID: type is not model - id={}, name={}", data.baseId, data.name); - KI_INFO_OUT(msg); - throw msg; - } - } + //if (!data.meshes.empty()) { + // if (data.type != EntityType::model) { + // auto msg = fmt::format("INVALID: type is not model - id={}, name={}", data.baseId, data.name); + // KI_INFO_OUT(msg); + // throw msg; + // } + //} if (data.type == EntityType::none) { auto msg = fmt::format("INVALID: type missing - id={}, name={}", data.baseId, data.name); diff --git a/src/loader/FontLoader.cpp b/src/loader/FontLoader.cpp index 2ca9a2afb..9fc021fa8 100644 --- a/src/loader/FontLoader.cpp +++ b/src/loader/FontLoader.cpp @@ -52,36 +52,17 @@ namespace loader { } } - void FontLoader::createFonts( - std::vector& fonts) - { - for (auto& data : fonts) { - data.id = createFont(data); - } - } - text::font_id FontLoader::resolveFont( - pool::TypeHandle typeHandle, - const TextData& data) const - { - auto* font = findFont(data.font); - return font ? font->id : 0; - } - - text::font_id FontLoader::createFont( const FontData& data) const { auto& fr = FontRegistry::get(); - auto id = fr.registerFont(data.name); - - auto* font = fr.modifyFont(id); - font->m_fontPath = data.path; - font->m_fontSize = data.size; - font->m_atlasSize = data.atlasSize; - // TODO KI race condition with RT - //font->prepare(); + text::FontAtlas font; + font.m_name = data.name; + font.m_fontPath = data.path; + font.m_fontSize = data.size; + font.m_atlasSize = data.atlasSize; - return id; + return fr.registerFont(std::move(font)); } } diff --git a/src/loader/FontLoader.h b/src/loader/FontLoader.h index e00137458..8f7fac4e1 100644 --- a/src/loader/FontLoader.h +++ b/src/loader/FontLoader.h @@ -22,14 +22,7 @@ namespace loader { const loader::DocNode& node, FontData& data) const; - void createFonts( - std::vector& data); - - text::font_id createFont( - const FontData& data) const; - text::font_id resolveFont( - pool::TypeHandle typeHandle, - const TextData& data) const; + const FontData& data) const; }; } diff --git a/src/loader/SceneLoader.cpp b/src/loader/SceneLoader.cpp index 51f830173..ab8c8e15c 100644 --- a/src/loader/SceneLoader.cpp +++ b/src/loader/SceneLoader.cpp @@ -30,8 +30,6 @@ #include "mesh/QuadMesh.h" #include "mesh/TextMesh.h" -#include "text/TextDraw.h" - #include "component/Light.h" #include "component/Camera.h" @@ -42,11 +40,6 @@ #include "animation/AnimationLoader.h" -//#include "generator/GridGenerator.h" -//#include "generator/AsteroidBeltGenerator.h" -//#include "generator/TextGenerator.h" -//#include "terrain/TerrainGenerator.h" - #include "event/Dispatcher.h" #include "mesh/MeshType.h" @@ -201,8 +194,6 @@ namespace loader { l.m_volumeLoader.attachVolume(root.rootId); l.m_cubeMapLoader.attachCubeMap(root.rootId); - l.m_fontLoader.createFonts(m_fonts); - { std::lock_guard lock(m_ready_lock); @@ -523,13 +514,6 @@ namespace loader { } } - { - bool useParallax = material.hasBoundTex(TextureType::displacement_map) && material.parallaxDepth > 0; - if (!useParallax) { - material.parallaxDepth = 0.f; - } - } - m_loaders->m_materialLoader.resolveMaterial(type, material); } @@ -736,8 +720,8 @@ namespace loader { if (type->m_entityType == EntityType::text) { node->m_generator = m_loaders->m_textLoader.createGenerator( - entityData.text, type, + entityData.text, *m_loaders); } diff --git a/src/loader/TextData.h b/src/loader/TextData.h index de6e85ce3..0fc78e20d 100644 --- a/src/loader/TextData.h +++ b/src/loader/TextData.h @@ -10,7 +10,6 @@ namespace loader { bool enabled{ false }; std::string text; - std::string font; MaterialData materialData; FontData fontData; diff --git a/src/loader/TextLoader.cpp b/src/loader/TextLoader.cpp index 470d3dba8..d1a0878bc 100644 --- a/src/loader/TextLoader.cpp +++ b/src/loader/TextLoader.cpp @@ -28,7 +28,7 @@ namespace loader { data.text = readString(v); data.enabled = false; } - if (k == "text") { + else if (k == "text") { data.text = readString(v); data.enabled = true; } @@ -45,8 +45,8 @@ namespace loader { } std::unique_ptr TextLoader::createGenerator( + const mesh::MeshType* type, const TextData& data, - mesh::MeshType* type, Loaders& loaders) { if (!data.enabled) return nullptr; @@ -55,14 +55,13 @@ namespace loader { auto generator = std::make_unique(); - auto fontId = resolveFont(typeHandle, entityData.text); + auto fontId = loaders.m_fontLoader.resolveFont(data.fontData); generator->setFontId(fontId); generator->setText(data.text); - //generator->m_material = data.materialData.material; - //generator->m_material.loadTextures(); - - //loaders.m_materialLoader.resolveProgram(type, &generator->m_material); + generator->m_material = data.materialData.material; + generator->m_material.loadTextures(); + loaders.m_materialLoader.resolveProgram(type, generator->m_material); return generator; } diff --git a/src/loader/TextLoader.h b/src/loader/TextLoader.h index 0b6ab09f8..0914a70fc 100644 --- a/src/loader/TextLoader.h +++ b/src/loader/TextLoader.h @@ -4,6 +4,13 @@ #include "TextData.h" +#include "generator/NodeGenerator.h" + + +namespace mesh { + class MeshType; +} + namespace loader { class TextLoader : public BaseLoader { @@ -17,8 +24,8 @@ namespace loader { Loaders& loaders) const; std::unique_ptr createGenerator( + const mesh::MeshType* type, const TextData& data, - mesh::MeshType* type, Loaders& loaders); }; } diff --git a/src/registry/FontRegistry.cpp b/src/registry/FontRegistry.cpp index 6b234832f..2f6938e1a 100644 --- a/src/registry/FontRegistry.cpp +++ b/src/registry/FontRegistry.cpp @@ -14,7 +14,10 @@ FontRegistry& FontRegistry::get() noexcept } FontRegistry::FontRegistry() -{} +{ + // NOTE KI reserve 0 for null font + registerFont({}); +} FontRegistry::~FontRegistry() { @@ -35,15 +38,15 @@ void FontRegistry::updateRT(const UpdateContext& ctx) } } -text::FontAtlas* FontRegistry::modifyFont(text::font_id id) -{ - if (id < 1) return nullptr; - - std::shared_lock lock(m_lock); - assert(id > 0 && id <= m_fonts.size()); - - return &m_fonts[id - 1]; -} +//text::FontAtlas* FontRegistry::modifyFont(text::font_id id) +//{ +// if (id < 1) return nullptr; +// +// std::shared_lock lock(m_lock); +// assert(id > 0 && id <= m_fonts.size()); +// +// return &m_fonts[id - 1]; +//} bool FontRegistry::bindFont( text::font_id id) @@ -66,13 +69,30 @@ bool FontRegistry::unbindFont( } text::font_id FontRegistry::registerFont( - const std::string& name) + text::FontAtlas&& src) { std::unique_lock lock(m_lock); - auto& font = m_fonts.emplace_back({}); - font.m_name = name; - font.m_id = static_cast(m_fonts.size()); + text::font_id fontId = findFont(src); + if (!fontId) { + auto& font = m_fonts.emplace_back(std::move(src)); + font.m_id = static_cast(m_fonts.size()); + fontId = font.m_id; + } - return font.m_id; + return fontId; +} + +text::font_id FontRegistry::findFont( + const text::FontAtlas& src) const noexcept +{ + const auto& it = std::find_if( + m_fonts.begin(), m_fonts.end(), + [&src](const auto& font) { + return font.m_fontPath == src.m_fontPath && + font.m_fontSize == src.m_fontSize && + font.m_atlasSize == src.m_atlasSize; + }); + + return it != m_fonts.end() ? it->m_id : 0; } diff --git a/src/registry/FontRegistry.h b/src/registry/FontRegistry.h index 16f354392..c0f4bb09a 100644 --- a/src/registry/FontRegistry.h +++ b/src/registry/FontRegistry.h @@ -30,8 +30,6 @@ class FontRegistry { return &m_fonts[id - 1]; } - text::FontAtlas* modifyFont(text::font_id id); - bool bindFont( text::font_id id); @@ -39,7 +37,11 @@ class FontRegistry { text::font_id id); text::font_id registerFont( - const std::string& name); + text::FontAtlas&& src); + +private: + text::font_id findFont( + const text::FontAtlas& src) const noexcept; private: mutable std::shared_mutex m_lock{}; diff --git a/src/render/Batch.cpp b/src/render/Batch.cpp index fbc18f93d..d911d2fde 100644 --- a/src/render/Batch.cpp +++ b/src/render/Batch.cpp @@ -89,6 +89,7 @@ namespace render { for (const auto& lodMesh : *type->m_lodMeshes) { if (lodMesh.m_level != lodLevel) continue; + if (!lodMesh.m_vao) continue; const auto& drawOptions = lodMesh.m_drawOptions; if (!drawOptions.isKind(kindBits)) continue; @@ -199,6 +200,7 @@ namespace render { for (const auto& lodMesh : *type->m_lodMeshes) { if (lodMesh.m_level != lodLevel) continue; + if (!lodMesh.m_vao) continue; const auto& drawOptions = lodMesh.m_drawOptions; if (!drawOptions.isKind(kindBits)) continue; From 172b02ab5d180a837303cbb911ede44971d898ad Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sat, 15 Jun 2024 22:34:58 +0300 Subject: [PATCH 03/28] FIX move fonts to text package --- learnopengl.vcxproj | 4 +- src/generator/TextGenerator.cpp | 5 +- src/loader/FontLoader.cpp | 6 +- src/registry/FontRegistry.cpp | 98 ------------------------------- src/registry/FontRegistry.h | 50 ---------------- src/registry/Registry.cpp | 5 +- src/text/FontRegistry.cpp | 101 ++++++++++++++++++++++++++++++++ src/text/FontRegistry.h | 52 ++++++++++++++++ src/text/TextDraw.cpp | 4 +- 9 files changed, 163 insertions(+), 162 deletions(-) delete mode 100644 src/registry/FontRegistry.cpp delete mode 100644 src/registry/FontRegistry.h create mode 100644 src/text/FontRegistry.cpp create mode 100644 src/text/FontRegistry.h diff --git a/learnopengl.vcxproj b/learnopengl.vcxproj index 6eac1f5e3..a02d29ef2 100644 --- a/learnopengl.vcxproj +++ b/learnopengl.vcxproj @@ -232,7 +232,7 @@ - + @@ -510,7 +510,7 @@ - + diff --git a/src/generator/TextGenerator.cpp b/src/generator/TextGenerator.cpp index 110cd07a7..6745f33ce 100644 --- a/src/generator/TextGenerator.cpp +++ b/src/generator/TextGenerator.cpp @@ -20,9 +20,8 @@ #include "registry/Registry.h" #include "registry/NodeSnapshotRegistry.h" #include "registry/EntityRegistry.h" -#include "registry/FontRegistry.h" - +#include "text/FontRegistry.h" #include "text/TextDraw.h" #include "text/FontAtlas.h" @@ -149,7 +148,7 @@ void TextGenerator::bindBatch( GLuint64 TextGenerator::getAtlasTextureHandle() const noexcept { - return FontRegistry::get().getFont(m_fontId)->getTextureHandle(); + return text::FontRegistry::get().getFont(m_fontId)->getTextureHandle(); } void TextGenerator::clear() diff --git a/src/loader/FontLoader.cpp b/src/loader/FontLoader.cpp index 9fc021fa8..5c0eda00d 100644 --- a/src/loader/FontLoader.cpp +++ b/src/loader/FontLoader.cpp @@ -3,9 +3,7 @@ #include "util/Util.h" #include "text/FontAtlas.h" - -#include "registry/Registry.h" -#include "registry/FontRegistry.h" +#include "text/FontRegistry.h" #include "loader/document.h" @@ -55,7 +53,7 @@ namespace loader { text::font_id FontLoader::resolveFont( const FontData& data) const { - auto& fr = FontRegistry::get(); + auto& fr = text::FontRegistry::get(); text::FontAtlas font; font.m_name = data.name; diff --git a/src/registry/FontRegistry.cpp b/src/registry/FontRegistry.cpp deleted file mode 100644 index 2f6938e1a..000000000 --- a/src/registry/FontRegistry.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "FontRegistry.h" - -#include "engine/UpdateContext.h" - -#include "kigl/GLState.h" - -namespace { - static FontRegistry s_registry; -} - -FontRegistry& FontRegistry::get() noexcept -{ - return s_registry; -} - -FontRegistry::FontRegistry() -{ - // NOTE KI reserve 0 for null font - registerFont({}); -} - -FontRegistry::~FontRegistry() -{ - m_fonts.clear(); -} - -void FontRegistry::prepareRT() -{ -} - -void FontRegistry::updateRT(const UpdateContext& ctx) -{ - std::shared_lock lock(m_lock); - - for (auto& font : m_fonts) { - font.prepare(); - font.update(); - } -} - -//text::FontAtlas* FontRegistry::modifyFont(text::font_id id) -//{ -// if (id < 1) return nullptr; -// -// std::shared_lock lock(m_lock); -// assert(id > 0 && id <= m_fonts.size()); -// -// return &m_fonts[id - 1]; -//} - -bool FontRegistry::bindFont( - text::font_id id) -{ - auto* font = getFont(id); - //if (font) { - // font->bindTextures(); - //} - return font; -} - -bool FontRegistry::unbindFont( - text::font_id id) -{ - auto* font = getFont(id); - //if (font) { - // font->unbindTextures(); - //} - return font; -} - -text::font_id FontRegistry::registerFont( - text::FontAtlas&& src) -{ - std::unique_lock lock(m_lock); - - text::font_id fontId = findFont(src); - if (!fontId) { - auto& font = m_fonts.emplace_back(std::move(src)); - font.m_id = static_cast(m_fonts.size()); - fontId = font.m_id; - } - - return fontId; -} - -text::font_id FontRegistry::findFont( - const text::FontAtlas& src) const noexcept -{ - const auto& it = std::find_if( - m_fonts.begin(), m_fonts.end(), - [&src](const auto& font) { - return font.m_fontPath == src.m_fontPath && - font.m_fontSize == src.m_fontSize && - font.m_atlasSize == src.m_atlasSize; - }); - - return it != m_fonts.end() ? it->m_id : 0; -} diff --git a/src/registry/FontRegistry.h b/src/registry/FontRegistry.h deleted file mode 100644 index c0f4bb09a..000000000 --- a/src/registry/FontRegistry.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include - -#include "text/FontAtlas.h" - -struct UpdateContext; - -class FontRegistry { -public: - static FontRegistry& get() noexcept; - - FontRegistry(); - FontRegistry& operator=(const FontRegistry&) = delete; - - ~FontRegistry(); - - void prepareRT(); - - void updateRT(const UpdateContext& ctx); - - text::FontAtlas* getFont(text::font_id id) noexcept - { - if (id < 1) return nullptr; - - std::shared_lock lock(m_lock); - assert(id > 0 && id <= m_fonts.size()); - - return &m_fonts[id - 1]; - } - - bool bindFont( - text::font_id id); - - bool unbindFont( - text::font_id id); - - text::font_id registerFont( - text::FontAtlas&& src); - -private: - text::font_id findFont( - const text::FontAtlas& src) const noexcept; - -private: - mutable std::shared_mutex m_lock{}; - - std::vector m_fonts; -}; diff --git a/src/registry/Registry.cpp b/src/registry/Registry.cpp index 0bf33f9cc..13e60b73d 100644 --- a/src/registry/Registry.cpp +++ b/src/registry/Registry.cpp @@ -23,10 +23,9 @@ #include "animation/AnimationSystem.h" #include "terrain/TerrainTileRegistry.h" - #include "mesh/TransformRegistry.h" +#include "text/FontRegistry.h" -#include "registry/FontRegistry.h" #include "registry/MaterialRegistry.h" #include "registry/NodeRegistry.h" #include "registry/ModelRegistry.h" @@ -115,7 +114,7 @@ void Registry::updateWT(const UpdateContext& ctx) void Registry::updateRT(const UpdateContext& ctx) { ASSERT_RT(); - FontRegistry::get().updateRT(ctx); + text::FontRegistry::get().updateRT(ctx); mesh::TransformRegistry::get().updateRT(ctx); MaterialRegistry::get().updateRT(ctx); ModelRegistry::get().updateRT(ctx); diff --git a/src/text/FontRegistry.cpp b/src/text/FontRegistry.cpp new file mode 100644 index 000000000..f79003528 --- /dev/null +++ b/src/text/FontRegistry.cpp @@ -0,0 +1,101 @@ +#include "FontRegistry.h" + +#include "engine/UpdateContext.h" + +#include "kigl/GLState.h" + +namespace { + static text::FontRegistry s_registry; +} + +namespace text { + + FontRegistry& FontRegistry::get() noexcept + { + return s_registry; + } + + FontRegistry::FontRegistry() + { + // NOTE KI reserve 0 for null font + registerFont({}); + } + + FontRegistry::~FontRegistry() + { + m_fonts.clear(); + } + + void FontRegistry::prepareRT() + { + } + + void FontRegistry::updateRT(const UpdateContext& ctx) + { + std::shared_lock lock(m_lock); + + for (auto& font : m_fonts) { + font.prepare(); + font.update(); + } + } + + //text::FontAtlas* FontRegistry::modifyFont(text::font_id id) + //{ + // if (id < 1) return nullptr; + // + // std::shared_lock lock(m_lock); + // assert(id > 0 && id <= m_fonts.size()); + // + // return &m_fonts[id - 1]; + //} + + bool FontRegistry::bindFont( + text::font_id id) + { + auto* font = getFont(id); + //if (font) { + // font->bindTextures(); + //} + return font; + } + + bool FontRegistry::unbindFont( + text::font_id id) + { + auto* font = getFont(id); + //if (font) { + // font->unbindTextures(); + //} + return font; + } + + text::font_id FontRegistry::registerFont( + text::FontAtlas&& src) + { + std::unique_lock lock(m_lock); + + text::font_id fontId = findFont(src); + if (!fontId) { + auto& font = m_fonts.emplace_back(std::move(src)); + font.m_id = static_cast(m_fonts.size()); + fontId = font.m_id; + } + + return fontId; + } + + text::font_id FontRegistry::findFont( + const text::FontAtlas& src) const noexcept + { + const auto& it = std::find_if( + m_fonts.begin(), m_fonts.end(), + [&src](const auto& font) { + return font.m_fontPath == src.m_fontPath && + font.m_fontSize == src.m_fontSize && + font.m_atlasSize == src.m_atlasSize; + }); + + return it != m_fonts.end() ? it->m_id : 0; + } +} diff --git a/src/text/FontRegistry.h b/src/text/FontRegistry.h new file mode 100644 index 000000000..99d9ab83f --- /dev/null +++ b/src/text/FontRegistry.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +#include "text/FontAtlas.h" + +struct UpdateContext; + +namespace text { + class FontRegistry { + public: + static FontRegistry& get() noexcept; + + FontRegistry(); + FontRegistry& operator=(const FontRegistry&) = delete; + + ~FontRegistry(); + + void prepareRT(); + + void updateRT(const UpdateContext& ctx); + + text::FontAtlas* getFont(text::font_id id) noexcept + { + if (id < 1) return nullptr; + + std::shared_lock lock(m_lock); + assert(id > 0 && id <= m_fonts.size()); + + return &m_fonts[id - 1]; + } + + bool bindFont( + text::font_id id); + + bool unbindFont( + text::font_id id); + + text::font_id registerFont( + text::FontAtlas&& src); + + private: + text::font_id findFont( + const text::FontAtlas& src) const noexcept; + + private: + mutable std::shared_mutex m_lock{}; + + std::vector m_fonts; + }; +} diff --git a/src/text/TextDraw.cpp b/src/text/TextDraw.cpp index 5b4c14a2c..6ff1492ed 100644 --- a/src/text/TextDraw.cpp +++ b/src/text/TextDraw.cpp @@ -12,12 +12,12 @@ #include "engine/UpdateContext.h" #include "registry/Registry.h" -#include "registry/FontRegistry.h" #include "mesh/TextMesh.h" #include "mesh/vao/VBO_impl.h" +#include "FontRegistry.h" #include "FontAtlas.h" #include "FontHandle.h" @@ -172,7 +172,7 @@ namespace text glm::vec2& pen, mesh::TextMesh* mesh) { - auto* font = FontRegistry::get().getFont(fontId); + auto* font = text::FontRegistry::get().getFont(fontId); if (!font) return; addText(mesh, font, text, pen); From afe221f40d45fa70981dd7025ef2c6dc68a028ce Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 16:14:37 +0300 Subject: [PATCH 04/28] FIX u_shadowIndex is redundant --- shader/_globals.glsl | 2 +- shader/simple_depth.vs | 2 -- src/asset/ProgramUniforms.cpp | 3 +-- src/asset/ProgramUniforms.h | 1 - src/renderer/ShadowCascade.cpp | 15 +-------------- 5 files changed, 3 insertions(+), 20 deletions(-) diff --git a/shader/_globals.glsl b/shader/_globals.glsl index 3a5ae80fa..d7e01514b 100644 --- a/shader/_globals.glsl +++ b/shader/_globals.glsl @@ -61,7 +61,7 @@ #define UNIFORM_FAR_PLANE 4 #define UNIFORM_DRAW_PARAMETERS_INDEX 6 #define UNIFORM_STENCIL_MODE 7 -#define UNIFORM_SHADOW_MAP_INDEX 8 +// #define UNIFORM_SHADOW_MAP_INDEX 8 #define UNIFORM_EFFECT_BLOOM_ITERATION 9 #define UNIFORM_TONE_HDRI 10 diff --git a/shader/simple_depth.vs b/shader/simple_depth.vs index 6ec574658..13adac1ab 100644 --- a/shader/simple_depth.vs +++ b/shader/simple_depth.vs @@ -17,8 +17,6 @@ layout (location = ATTR_TEX) in vec2 a_texCoord; #include uniform_matrices.glsl #include uniform_data.glsl -layout(location = UNIFORM_SHADOW_MAP_INDEX) uniform uint u_shadowIndex; - #ifdef USE_ALPHA out VS_OUT { vec2 texCoord; diff --git a/src/asset/ProgramUniforms.cpp b/src/asset/ProgramUniforms.cpp index 32b27fa7f..a6bdf4a37 100644 --- a/src/asset/ProgramUniforms.cpp +++ b/src/asset/ProgramUniforms.cpp @@ -1,8 +1,7 @@ #include "ProgramUniforms.h" ProgramUniforms::ProgramUniforms(Program& program) - : u_shadowIndex{ "u_shadowIndex", UNIFORM_SHADOW_MAP_INDEX }, - u_effect{ "u_effect", GL_FRAGMENT_SHADER, SUBROUTINE_EFFECT }, + : u_effect{ "u_effect", GL_FRAGMENT_SHADER, SUBROUTINE_EFFECT }, u_nearPlane{ "u_nearPlane", UNIFORM_NEAR_PLANE }, u_farPlane{ "u_farPlane", UNIFORM_FAR_PLANE }, u_drawParametersIndex{ "u_drawParametersIndex", UNIFORM_DRAW_PARAMETERS_INDEX }, diff --git a/src/asset/ProgramUniforms.h b/src/asset/ProgramUniforms.h index 70f4c967e..dac097836 100644 --- a/src/asset/ProgramUniforms.h +++ b/src/asset/ProgramUniforms.h @@ -17,7 +17,6 @@ class Program; struct ProgramUniforms { ProgramUniforms(Program& program); - uniform::UInt u_shadowIndex; uniform::Subroutine u_effect; uniform::Float u_nearPlane; diff --git a/src/renderer/ShadowCascade.cpp b/src/renderer/ShadowCascade.cpp index 51123a0a4..f75dfdbd1 100644 --- a/src/renderer/ShadowCascade.cpp +++ b/src/renderer/ShadowCascade.cpp @@ -256,24 +256,11 @@ void ShadowCascade::drawNodes( }; { - // TODO KI separate UBO would be better than early program binds - // => these *can* mess drawing - m_solidShadowProgram->bind(); - m_solidShadowProgram->m_uniforms->u_shadowIndex.set(m_index); - - m_alphaShadowProgram->bind(); - m_alphaShadowProgram->m_uniforms->u_shadowIndex.set(m_index); - ctx.m_nodeDraw->drawProgram( ctx, [this](const mesh::LodMesh& lodMesh) { if (lodMesh.m_shadowProgram) return lodMesh.m_shadowProgram; - if (lodMesh.m_drawOptions.m_alpha) { - return m_alphaShadowProgram; - } - else { - return m_solidShadowProgram; - } + return lodMesh.m_drawOptions.m_alpha ? m_alphaShadowProgram : m_solidShadowProgram; }, typeFilter, nodeFilter, From a5f4a349a8f0e06bb409e5a6139091e25749cf50 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 16:45:37 +0300 Subject: [PATCH 05/28] FIX shadow render fixes - no_shadow lost from water - redundant render_back flags --- scene/scene_full.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scene/scene_full.yml b/scene/scene_full.yml index 553e8b42c..8df42843e 100644 --- a/scene/scene_full.yml +++ b/scene/scene_full.yml @@ -491,8 +491,8 @@ entities: - name: wyvern_pbr alias: M_Wyvern map_pbr: wyvern_pbr - alpha: true - render_back: true + xalpha: true + xrender_back: true xwireframe: true animations: - name: fire @@ -578,7 +578,6 @@ entities: xrefraction: 0.05 xrefraction_ratio: [1.0, 1.52] tiling: 6 - render_back: true program: g_tex pos: [-5.0, 25.0, -5.0] scale: 1.0 @@ -601,7 +600,6 @@ entities: kd: [0.160, 0.578, 0.168, 1.0] map_pbr: textures/Plastic 01 [4K] xreflection: 0.4 - render_back: false program: g_tex pos: [5.0, 25.0, -5.0] rotation: [0, 180, 0] @@ -631,7 +629,6 @@ entities: material_modifier: xreflection: 0.1 map_pbr: textures/Plastic 01 [4K] - render_back: false program: g_tex pos: [5.0, 25.0, -15.0] rotation: [0, 180, 0] @@ -832,7 +829,7 @@ entities: program: g_water pos: [0, 9.5, -10] scale: 30 - xrender_flags: + render_flags: no_shadow: true water: true repeat: From 8ba28bbfb86f90a34e3d6c7bd4e8d1bf97be2f39 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 16:45:52 +0300 Subject: [PATCH 06/28] FIX more descriptive debug names for programs --- src/asset/Program.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/asset/Program.cpp b/src/asset/Program.cpp index 5700b4c2f..bf9e131b6 100644 --- a/src/asset/Program.cpp +++ b/src/asset/Program.cpp @@ -259,7 +259,7 @@ int Program::createProgram() { { m_programId = glCreateProgram(); - kigl::setLabel(GL_PROGRAM, m_programId, m_programName); + kigl::setLabel(GL_PROGRAM, m_programId, m_key); for (auto& [type, shaderId] : shaderIds) { if (shaderId == -1) continue; From bcf32c2a04fb498370871ac5f532f90f7785b417 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 16:51:42 +0300 Subject: [PATCH 07/28] FIX simplify force logic of draw options --- src/backend/DrawBuffer.cpp | 8 ++++---- src/backend/DrawRange.h | 3 --- src/render/Batch.cpp | 10 ++++++---- src/render/BatchCommand.cpp | 10 +++++++++- src/render/BatchCommand.h | 6 ++++-- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/backend/DrawBuffer.cpp b/src/backend/DrawBuffer.cpp index bca88eaa7..200cb6c60 100644 --- a/src/backend/DrawBuffer.cpp +++ b/src/backend/DrawBuffer.cpp @@ -221,8 +221,8 @@ namespace backend { sameDraw = curr.m_vao == sendRange.m_vao && curr.m_program == sendRange.m_program && cd.m_renderBack == sd.m_renderBack && - (curr.m_forceWireframe ? true : cd.m_wireframe == sd.m_wireframe) && - (curr.m_forceSolid ? true : cd.m_blend == sd.m_blend) && + cd.m_wireframe == sd.m_wireframe && + cd.m_blend == sd.m_blend && cd.m_mode == sd.m_mode && cd.m_type == sd.m_type && cd.m_tessellation == sd.m_tessellation; @@ -382,7 +382,7 @@ namespace backend { state.setEnabled(GL_CULL_FACE, !drawOptions.m_renderBack); - const bool wireframe = drawOptions.m_wireframe || drawRange.m_forceWireframe; + const bool wireframe = drawOptions.m_wireframe; state.polygonFrontAndBack(wireframe ? GL_LINE : GL_FILL); @@ -390,7 +390,7 @@ namespace backend { glPatchParameteri(GL_PATCH_VERTICES, drawOptions.m_patchVertices); } - const bool blend = !wireframe && !drawRange.m_forceSolid && drawOptions.m_blend; + const bool blend = !wireframe && drawOptions.m_blend; state.setEnabled(GL_BLEND, blend); if (blend) { // NOTE KI no blend mode with OIT blend diff --git a/src/backend/DrawRange.h b/src/backend/DrawRange.h index 363e39596..4e766b6cd 100644 --- a/src/backend/DrawRange.h +++ b/src/backend/DrawRange.h @@ -14,8 +14,5 @@ namespace backend { const kigl::GLVertexArray* m_vao{ nullptr }; const Program* m_program{ nullptr }; DrawOptions m_drawOptions; - - bool m_forceSolid : 1 {false}; - bool m_forceWireframe : 1 {false}; }; } diff --git a/src/render/Batch.cpp b/src/render/Batch.cpp index d911d2fde..c20b877e0 100644 --- a/src/render/Batch.cpp +++ b/src/render/Batch.cpp @@ -104,7 +104,9 @@ namespace render { lodMesh.m_priority, program, lodMesh.m_vao, - drawOptions + drawOptions, + ctx.m_forceSolid, + ctx.m_forceWireframe, }; const auto& it = m_batches.find(key); @@ -215,7 +217,9 @@ namespace render { lodMesh.m_priority, program, lodMesh.m_vao, - drawOptions + drawOptions, + ctx.m_forceSolid, + ctx.m_forceWireframe, }; const auto& it = m_batches.find(key); @@ -376,8 +380,6 @@ namespace render { key.m_vao, key.m_program, key.m_drawOptions, - ctx.m_forceSolid, - ctx.m_forceWireframe }; const auto& drawOptions = key.m_drawOptions; diff --git a/src/render/BatchCommand.cpp b/src/render/BatchCommand.cpp index aa6cc86f6..5e698a054 100644 --- a/src/render/BatchCommand.cpp +++ b/src/render/BatchCommand.cpp @@ -10,12 +10,20 @@ namespace render { int8_t priority, const Program* program, const kigl::GLVertexArray* vao, - const backend::DrawOptions& drawOptions) noexcept + const backend::DrawOptions& drawOptions, + bool forceSolid, + bool forceWireframe) noexcept : m_program(program), m_vao{ vao }, m_priority( -priority ), m_drawOptions{ drawOptions } { + if (forceSolid) { + m_drawOptions.m_blend = false; + } + if (forceWireframe) { + m_drawOptions.m_wireframe = true; + } } //inline bool operator<(const DrawOptions& o) const noexcept { diff --git a/src/render/BatchCommand.h b/src/render/BatchCommand.h index a234d619c..db3b0fedb 100644 --- a/src/render/BatchCommand.h +++ b/src/render/BatchCommand.h @@ -24,14 +24,16 @@ namespace render { int8_t priority, const Program* program, const kigl::GLVertexArray* vao, - const backend::DrawOptions& drawOptions) noexcept; + const backend::DrawOptions& drawOptions, + bool forceSolid, + bool forceWireframe) noexcept; bool operator<(const BatchKey& o) const noexcept; const Program* m_program{ nullptr }; const kigl::GLVertexArray* m_vao{ nullptr }; - const backend::DrawOptions m_drawOptions; + backend::DrawOptions m_drawOptions; const int8_t m_priority; }; From 55c169b2f0ffebe4554ca10eec950f34c74f6fd2 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 17:12:14 +0300 Subject: [PATCH 08/28] FIX 4th shadow cascade is overkill and very expensive - adjust cascade levels to compensate removal of it --- scene/assets.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scene/assets.yml b/scene/assets.yml index 433679204..a175b55c8 100644 --- a/scene/assets.yml +++ b/scene/assets.yml @@ -129,8 +129,10 @@ assets: shadow_polygon_offset_enabled: true shadow_polygon_offset: [2, 0.5] - shadow_planes: [0.1, 25, 75, 150, 500] - shadow_map_sizes: [1024, 1024, 1024, 1024] + xshadow_planes: [0.1, 25, 75, 150, 500] + xshadow_map_sizes: [1024, 1024, 1024, 1024] + shadow_planes: [0.1, 40, 90, 300] + shadow_map_sizes: [2048, 2048, 2048] shadow_render_frame_start: 0 shadow_render_frame_step: 1 shadow_visual: false From a61c96bf443a36c0d19896b0bd500f278c8c24aa Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 17:30:59 +0300 Subject: [PATCH 09/28] FIX terrain priority was lost --- src/loader/EntityData.h | 2 ++ src/loader/EntityLoader.cpp | 3 +++ src/loader/SceneLoader.cpp | 7 +++++-- src/loader/SceneLoader.h | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/loader/EntityData.h b/src/loader/EntityData.h index 2a2e6f1e1..d44591650 100644 --- a/src/loader/EntityData.h +++ b/src/loader/EntityData.h @@ -43,6 +43,8 @@ namespace loader { std::string prefabName; + int8_t priority{ 0 }; + std::vector meshes; std::string geometryType; diff --git a/src/loader/EntityLoader.cpp b/src/loader/EntityLoader.cpp index 754c5ca8e..fcec4ca58 100644 --- a/src/loader/EntityLoader.cpp +++ b/src/loader/EntityLoader.cpp @@ -119,6 +119,9 @@ namespace loader { else if (k == "active") { data.active = readBool(v); } + else if (k == "priority") { + data.priority = readInt(v); + } else if (k == "mesh" || k == "model") { auto& meshData = data.meshes.emplace_back(); loaders.m_meshLoader.loadMesh(v, meshData, loaders); diff --git a/src/loader/SceneLoader.cpp b/src/loader/SceneLoader.cpp index ab8c8e15c..b56bcfa66 100644 --- a/src/loader/SceneLoader.cpp +++ b/src/loader/SceneLoader.cpp @@ -595,7 +595,7 @@ namespace loader { if (meshCount > 0) { const auto& span = std::span{ *type->m_lodMeshes.get() }.subspan(startIndex, meshCount); for (auto& lodMesh : span) { - resolveLod(type, meshData, lodMesh); + resolveLod(type, entityData, meshData, lodMesh); resolveMaterials(type, lodMesh, entityData, meshData); assignMeshFlags(meshData, lodMesh); lodMesh.setupDrawOptions(); @@ -605,17 +605,20 @@ namespace loader { void SceneLoader::resolveLod( mesh::MeshType* type, + const EntityData& entityData, const MeshData& meshData, mesh::LodMesh& lodMesh) { auto* mesh = lodMesh.getMesh(); if (!mesh) return; + lodMesh.m_priority = entityData.priority; + const auto* lod = meshData.findLod(mesh->m_name); if (!lod) return; lodMesh.m_level = lod->level; - lodMesh.m_priority = lod->priority; + lodMesh.m_priority = lod->priority != 0 ? lod->priority : entityData.priority; lodMesh.setDistance(lod->distance); } diff --git a/src/loader/SceneLoader.h b/src/loader/SceneLoader.h index 4b338b0a6..bf29e256d 100644 --- a/src/loader/SceneLoader.h +++ b/src/loader/SceneLoader.h @@ -143,6 +143,7 @@ namespace loader { void resolveLod( mesh::MeshType* type, + const EntityData& entityData, const MeshData& meshData, mesh::LodMesh& lodMesh); From dd0f03f6524c0af850200af722506da59643aa32 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 18:02:22 +0300 Subject: [PATCH 10/28] FIX logic to set "MAX_SHADOW_MAP_COUNT" for shader --- shader/_globals.glsl | 2 +- shader/_uniform_matrices.glsl | 2 +- shader/g_deferred_pass.fs | 3 +-- src/asset/MatricesUBO.h | 2 +- src/asset/Shader.h | 3 +++ src/loader/MaterialLoader.cpp | 8 ++++++++ src/render/NodeDraw.cpp | 14 ++++++++++++-- src/renderer/ShadowMapRenderer.cpp | 2 +- 8 files changed, 28 insertions(+), 8 deletions(-) diff --git a/shader/_globals.glsl b/shader/_globals.glsl index d7e01514b..a45dbfc86 100644 --- a/shader/_globals.glsl +++ b/shader/_globals.glsl @@ -19,7 +19,7 @@ #define LIGHT_COUNT 128 #endif -#define MAX_SHADOW_MAP_COUNT_ABS 5 +#define MAX_SHADOW_MAP_COUNT_ABS 4 #ifndef MAX_SHADOW_MAP_COUNT #define MAX_SHADOW_MAP_COUNT 4 #endif diff --git a/shader/_uniform_matrices.glsl b/shader/_uniform_matrices.glsl index f61da257f..01fb59216 100644 --- a/shader/_uniform_matrices.glsl +++ b/shader/_uniform_matrices.glsl @@ -11,7 +11,7 @@ layout (std140, binding = UBO_MATRICES) uniform Matrices { mat4 u_viewMatrixSkybox; - mat4 u_shadowMatrix[MAX_SHADOW_MAP_COUNT]; + mat4 u_shadowMatrix[MAX_SHADOW_MAP_COUNT_ABS]; // top, bottom, left, right, near, far vec4 u_frustum[6]; diff --git a/shader/g_deferred_pass.fs b/shader/g_deferred_pass.fs index f20fc5836..a95ce46c1 100644 --- a/shader/g_deferred_pass.fs +++ b/shader/g_deferred_pass.fs @@ -53,8 +53,7 @@ const vec4 CASCADE_COLORS[MAX_SHADOW_MAP_COUNT_ABS] = vec4(0.2, 0.0, 0.0, 0.0), vec4(0.0, 0.2, 0.0, 0.0), vec4(0.0, 0.0, 0.5, 0.0), - vec4(0.2, 0.0, 0.2, 0.0), - vec4(0.2, 0.2, 0.0, 0.0) + vec4(0.2, 0.0, 0.2, 0.0) ); void main() diff --git a/src/asset/MatricesUBO.h b/src/asset/MatricesUBO.h index 858a184ce..1628b63fb 100644 --- a/src/asset/MatricesUBO.h +++ b/src/asset/MatricesUBO.h @@ -21,7 +21,7 @@ struct MatricesUBO { glm::mat4 u_viewSkybox{ 1.0f }; // NOTE KI calculated by shadow calculation - glm::mat4 u_shadow[MAX_SHADOW_MAP_COUNT]; + glm::mat4 u_shadow[MAX_SHADOW_MAP_COUNT_ABS]; // top, bottom, left, right, near, far glm::vec4 u_frustumPlanes[6]; diff --git a/src/asset/Shader.h b/src/asset/Shader.h index a13511a69..4e44abfb2 100644 --- a/src/asset/Shader.h +++ b/src/asset/Shader.h @@ -55,6 +55,8 @@ const std::string DEF_USE_NORMAL_PATTERN{ "USE_NORMAL_PATTERN" }; const std::string DEF_USE_BONES{ "USE_BONES" }; const std::string DEF_USE_BONES_DEBUG{ "USE_BONES_DEBUG" }; +const std::string DEF_MAX_SHADOW_MAP_COUNT{ "MAX_SHADOW_MAP_COUNT" }; + const std::string DEF_MAT_COUNT{ "MAT_COUNT" }; const std::string DEF_TEX_COUNT{ "TEX_COUNT" }; const std::string DEF_LIGHT_COUNT{ "LIGHT_COUNT" }; @@ -141,6 +143,7 @@ constexpr int UNIT_BDRF_LUT = 73; constexpr int UNIT_VIEWPORT = 74; +constexpr int MAX_SHADOW_MAP_COUNT_ABS = 4; constexpr int MAX_SHADOW_MAP_COUNT = 4; constexpr int UNIT_SHADOW_MAP_FIRST = 75; constexpr int UNIT_SHADOW_MAP_LAST = UNIT_SHADOW_MAP_FIRST + MAX_SHADOW_MAP_COUNT - 1; diff --git a/src/loader/MaterialLoader.cpp b/src/loader/MaterialLoader.cpp index 9e77661a7..19c12c76a 100644 --- a/src/loader/MaterialLoader.cpp +++ b/src/loader/MaterialLoader.cpp @@ -806,6 +806,14 @@ namespace loader { definitions); if (!shadowName.empty()) { + { + size_t shadowCount = std::min( + std::max(Assets::get().shadowPlanes.size() - 1, static_cast(1)), + static_cast(MAX_SHADOW_MAP_COUNT_ABS)); + + shadowDefinitions[DEF_MAX_SHADOW_MAP_COUNT] = std::to_string(shadowCount); + } + material.m_programs[MaterialProgramType::shadow] = ProgramRegistry::get().getProgram( shadowName, false, diff --git a/src/render/NodeDraw.cpp b/src/render/NodeDraw.cpp index 5ac661beb..bb8674c14 100644 --- a/src/render/NodeDraw.cpp +++ b/src/render/NodeDraw.cpp @@ -79,8 +79,18 @@ namespace render { m_plainQuad.prepare(); m_textureQuad.prepare(); - m_deferredProgram = ProgramRegistry::get().getProgram(SHADER_DEFERRED_PASS); - m_deferredProgram->prepareRT(); + { + std::map> definitions; + + size_t shadowCount = std::min( + std::max(Assets::get().shadowPlanes.size() - 1, static_cast(1)), + static_cast(MAX_SHADOW_MAP_COUNT_ABS)); + + definitions[DEF_MAX_SHADOW_MAP_COUNT] = std::to_string(shadowCount); + + m_deferredProgram = ProgramRegistry::get().getProgram(SHADER_DEFERRED_PASS, definitions); + m_deferredProgram->prepareRT(); + } m_oitProgram = ProgramRegistry::get().getProgram(SHADER_OIT_PASS); m_oitProgram->prepareRT(); diff --git a/src/renderer/ShadowMapRenderer.cpp b/src/renderer/ShadowMapRenderer.cpp index 09596a2d3..770299f17 100644 --- a/src/renderer/ShadowMapRenderer.cpp +++ b/src/renderer/ShadowMapRenderer.cpp @@ -46,7 +46,7 @@ void ShadowMapRenderer::prepareRT( m_planes = assets.shadowPlanes; m_mapSizes = assets.shadowMapSizes; - int maxCount = std::min(static_cast(m_planes.size()) - 1, MAX_SHADOW_MAP_COUNT); + int maxCount = std::min(static_cast(m_planes.size()) - 1, MAX_SHADOW_MAP_COUNT_ABS); for (int index = 0; index < maxCount; index++) { auto* cascade = new ShadowCascade( index, From 161ad8d5599ec4a35acca9910a6cd109e3a61122 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 18:11:49 +0300 Subject: [PATCH 11/28] FIX shadow is needed for further distance - forest line shadow cuts-off ugly if shorter distance --- scene/assets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/assets.yml b/scene/assets.yml index a175b55c8..ba0847788 100644 --- a/scene/assets.yml +++ b/scene/assets.yml @@ -131,7 +131,7 @@ assets: shadow_polygon_offset: [2, 0.5] xshadow_planes: [0.1, 25, 75, 150, 500] xshadow_map_sizes: [1024, 1024, 1024, 1024] - shadow_planes: [0.1, 40, 90, 300] + shadow_planes: [0.1, 40, 90, 500] shadow_map_sizes: [2048, 2048, 2048] shadow_render_frame_start: 0 shadow_render_frame_step: 1 From 95ed6d059da9921945c6a2d604124384e831dc44 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 18:27:54 +0300 Subject: [PATCH 12/28] FIX pine_tree lods --- scene/scene_forest.yml | 79 +++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/scene/scene_forest.yml b/scene/scene_forest.yml index fe5097eb7..1b9a8052f 100644 --- a/scene/scene_forest.yml +++ b/scene/scene_forest.yml @@ -166,17 +166,70 @@ entities: x_step: 20 z_step: -20 - xid: pine_tree_forest_{t} - mesh: - path: fbx/scenery/trees/SM_TreePine_01b.FBX - materials: - - name: pine_trunk_pbr - alias: MI_TreeBarkPine_01a - map_pbr: pine_trunk_pbr - - name: pine_leaf_pbr - alias: MI_PineTree_01a - map_pbr: pine_leaf_pbr - alpha: true - render_back: true + meshes: + - path: fbx/scenery/trees/SM_TreePine_01b.FBX + lods: + - level: 0 + distance: 100 + materials: + - name: pine_trunk_pbr + alias: MI_TreeBarkPine_01a + map_pbr: pine_trunk_pbr + - name: pine_leaf_pbr + alias: MI_PineTree_01a + map_pbr: pine_leaf_pbr + alpha: true + blend: true + render_back: true + - path: fbx/scenery/trees/SM_TreePine_01b.FBX + lods: + - level: 1 + distance: 200 + materials: + - name: pine_trunk_pbr + alias: MI_TreeBarkPine_01a + map_pbr: pine_trunk_pbr + - name: pine_leaf_pbr + alias: MI_PineTree_01a + map_pbr: pine_leaf_pbr + alpha: true + render_back: true + - path: fbx/scenery/trees/SM_TreePine_01b.FBX + lods: + - level: 2 + distance: 300 + materials: + - name: pine_trunk_pbr + alias: MI_TreeBarkPine_01a + map_kd: pine_trunk_pbr/T_TreePineBark_01a_A.PNG + - name: pine_leaf_pbr + alias: MI_PineTree_01a + map_kd: pine_leaf_pbr/T_PineBranch_01a_A.PNG + alpha: true + render_back: true + - path: fbx/scenery/trees/SM_TreePine_01b.FBX + lods: + - level: 3 + distance: 400 + materials: + - name: pine_trunk_pbr + alias: MI_TreeBarkPine_01a + map_kd: pine_trunk_pbr/T_TreePineBark_01a_A.PNG + - name: pine_leaf_pbr + alias: MI_PineTree_01a + map_kd: pine_leaf_pbr/T_PineBranch_01a_A.PNG + alpha: true + - path: fbx/scenery/trees/SM_TreePine_01b.FBX + lods: + - level: 4 + distance: 10000 + materials: + - name: pine_trunk_pbr + alias: MI_TreeBarkPine_01a + map_kd: pine_trunk_pbr/T_TreePineBark_01a_A.PNG + - name: pine_leaf_pbr + alias: MI_PineTree_01a + map_kd: pine_leaf_pbr/T_PineBranch_01a_A.PNG program: g_tex pos: [-1000, 0.0, 0.0] render_flags: @@ -188,8 +241,8 @@ entities: generator: type: grid repeat: - x_count: 20 - z_count: 20 + x_count: 200 + z_count: 200 x_step: 20 z_step: -20 - name: wooden floor From c781c0c2cddac2a4d23c366ea02e6a01a1e0a1f5 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 00:50:23 +0300 Subject: [PATCH 13/28] FIX per vertex material is not used --- src/mesh/AssimpLoader.cpp | 2 +- src/mesh/Vertex.cpp | 6 ++---- src/mesh/Vertex.h | 12 +++--------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/mesh/AssimpLoader.cpp b/src/mesh/AssimpLoader.cpp index 2a840fbfd..5106120cb 100644 --- a/src/mesh/AssimpLoader.cpp +++ b/src/mesh/AssimpLoader.cpp @@ -277,7 +277,7 @@ namespace mesh //KI_INFO_OUT(fmt::format("ASSIMP: offset={}, pos={}", vertexOffset, pos)); - modelMesh.m_vertices.emplace_back(pos, texCoord, normal, tangent, 0); + modelMesh.m_vertices.emplace_back(pos, texCoord, normal, tangent); } for (size_t faceIdx = 0; faceIdx < mesh->mNumFaces; faceIdx++) { diff --git a/src/mesh/Vertex.cpp b/src/mesh/Vertex.cpp index 4fb66ca41..6d0eecc2d 100644 --- a/src/mesh/Vertex.cpp +++ b/src/mesh/Vertex.cpp @@ -33,7 +33,6 @@ namespace mesh { // to reduce verteces return pos == b.pos && texture == b.texture && - materialID == b.materialID && //normal == b.normal && //tangent == b.tangent && glm::dot(normal, b.normal) >= DOT_NORMAL_SAME && @@ -48,11 +47,10 @@ namespace mesh { std::string Vertex::str() const noexcept { return fmt::format( - "", + "", pos.x, pos.y, pos.z, texture.x, texture.y, normal.x, normal.y, normal.z, - tangent.x, tangent.y, tangent.z, - materialID); + tangent.x, tangent.y, tangent.z); } } diff --git a/src/mesh/Vertex.h b/src/mesh/Vertex.h index 0823650e9..7c2e00013 100644 --- a/src/mesh/Vertex.h +++ b/src/mesh/Vertex.h @@ -15,13 +15,11 @@ namespace mesh { const glm::vec3& pos, const glm::vec2& texture, const glm::vec3& normal, - const glm::vec3& tangent, - const ki::material_id materialID) + const glm::vec3& tangent) : pos(pos), texture(texture), normal(normal), - tangent(tangent), - materialID(materialID) + tangent(tangent) { } @@ -29,8 +27,7 @@ namespace mesh { : pos(b.pos), texture(b.texture), normal(b.normal), - tangent(b.tangent), - materialID(b.materialID) + tangent(b.tangent) { } @@ -40,7 +37,6 @@ namespace mesh { texture = b.texture; normal = b.normal; tangent = b.tangent; - materialID = b.materialID; return *this; } @@ -56,7 +52,5 @@ namespace mesh { glm::vec2 texture; glm::vec3 normal; glm::vec3 tangent; - - ki::material_id materialID; }; } From ec03fb1a236c38916ccd80786a49c68a0afec0ec Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 02:07:54 +0300 Subject: [PATCH 14/28] WIP changing mesh vao into "reserve + update" cycle --- src/mesh/Mesh.h | 3 ++ src/mesh/ModelMesh.cpp | 8 +-- src/mesh/ModelMesh.h | 14 +++--- src/mesh/vao/IndexEntry.h | 2 + src/mesh/vao/PositionEntry.h | 2 + src/mesh/vao/SkinnedVAO.cpp | 15 ++++-- src/mesh/vao/SkinnedVAO.h | 2 +- src/mesh/vao/TexturedVAO.cpp | 47 +++++++++++++++--- src/mesh/vao/TexturedVAO.h | 7 ++- src/mesh/vao/VBO.h | 29 ++++++----- src/mesh/vao/VBO_impl.h | 87 ++++++++++++++++++--------------- src/mesh/vao/VertexIndexEBO.cpp | 31 +++++++----- src/mesh/vao/VertexIndexEBO.h | 10 +++- 13 files changed, 166 insertions(+), 91 deletions(-) diff --git a/src/mesh/Mesh.h b/src/mesh/Mesh.h index 6c52bd7c6..4e3596cb1 100644 --- a/src/mesh/Mesh.h +++ b/src/mesh/Mesh.h @@ -79,6 +79,9 @@ namespace mesh { glm::mat4 m_animationBaseTransform{ 1.f }; + uint32_t m_reserveVertexCount{ 0 }; + uint32_t m_reserveIndexCount{ 0 }; + protected: bool m_prepared{ false }; diff --git a/src/mesh/ModelMesh.cpp b/src/mesh/ModelMesh.cpp index 73535d63e..b5677573f 100644 --- a/src/mesh/ModelMesh.cpp +++ b/src/mesh/ModelMesh.cpp @@ -47,10 +47,6 @@ namespace mesh { m_vertexBones.size()); } - uint32_t ModelMesh::getBaseVertex() const noexcept { - return static_cast(m_positionVboOffset / sizeof(mesh::PositionEntry)); - } - AABB ModelMesh::calculateAABB() const noexcept { AABB aabb{ true }; @@ -69,10 +65,10 @@ namespace mesh { m_prepared = true; if (m_rig && m_rig->hasBones()) { - m_vao = ModelRegistry::get().getSkinnedVao()->registerModel(this); + m_vao = ModelRegistry::get().getSkinnedVao()->registerMesh(this); } else { - m_vao = ModelRegistry::get().getTexturedVao()->registerModel(this); + m_vao = ModelRegistry::get().getTexturedVao()->registerMesh(this); } return m_vao; diff --git a/src/mesh/ModelMesh.h b/src/mesh/ModelMesh.h index 23305576b..6f88b1d86 100644 --- a/src/mesh/ModelMesh.h +++ b/src/mesh/ModelMesh.h @@ -45,10 +45,12 @@ namespace mesh { virtual void prepareDrawOptions( backend::DrawOptions& drawOptions) override; - uint32_t getBaseVertex() const noexcept; + uint32_t getBaseVertex() const noexcept { + return m_vboIndex; + } inline uint32_t getBaseIndex() const noexcept { - return static_cast(m_indexEboOffset / sizeof(GLuint)); + return m_eboIndex * 3; } inline uint32_t getIndexCount() const noexcept { @@ -63,10 +65,10 @@ namespace mesh { animation::RigContainer* m_rig{ nullptr }; - // NOTE KI absolute offset into position VBO - size_t m_positionVboOffset{ 0 }; + // NOTE KI absolute index into VBO + uint32_t m_vboIndex{ 0 }; - // NOTE KI absolute offset into EBO - size_t m_indexEboOffset{ 0 }; + // NOTE KI absolute index into EBO + uint32_t m_eboIndex{ 0 }; }; } diff --git a/src/mesh/vao/IndexEntry.h b/src/mesh/vao/IndexEntry.h index 3f9bc0ea4..69ba04c3a 100644 --- a/src/mesh/vao/IndexEntry.h +++ b/src/mesh/vao/IndexEntry.h @@ -4,6 +4,8 @@ namespace mesh { struct IndexEntry { + IndexEntry() {} + IndexEntry(unsigned int a_x, unsigned int a_y, unsigned int a_z) : x{ a_x }, y{ a_y }, z{ a_z } {} diff --git a/src/mesh/vao/PositionEntry.h b/src/mesh/vao/PositionEntry.h index 99814fbe1..e50827038 100644 --- a/src/mesh/vao/PositionEntry.h +++ b/src/mesh/vao/PositionEntry.h @@ -7,6 +7,8 @@ namespace mesh { #pragma pack(push, 1) struct PositionEntry { + PositionEntry() {} + PositionEntry(const glm::vec3& v) : x{ v.x }, y{ v.y }, z{ v.z } {} diff --git a/src/mesh/vao/SkinnedVAO.cpp b/src/mesh/vao/SkinnedVAO.cpp index adfe92c71..6d7993872 100644 --- a/src/mesh/vao/SkinnedVAO.cpp +++ b/src/mesh/vao/SkinnedVAO.cpp @@ -35,12 +35,21 @@ namespace mesh { m_boneVbo.clear(); } - const kigl::GLVertexArray* SkinnedVAO::registerModel( + const kigl::GLVertexArray* SkinnedVAO::registerMesh( mesh::ModelMesh* mesh) { - TexturedVAO::registerModel(mesh); + TexturedVAO::registerMesh(mesh); - m_boneVbo.addVertices(mesh->m_vertexBones); + auto vertexCount = mesh->m_reserveVertexCount; + auto& vertices = mesh->m_vertices; + + if (vertexCount == 0) { + vertexCount = static_cast(vertices.size()); + } + + m_boneVbo.reserveVertices(vertexCount); + + m_boneVbo.updateVertices(mesh->m_vboIndex, mesh->m_vertexBones); return m_vao.get(); } diff --git a/src/mesh/vao/SkinnedVAO.h b/src/mesh/vao/SkinnedVAO.h index 2b91506ae..1629d38aa 100644 --- a/src/mesh/vao/SkinnedVAO.h +++ b/src/mesh/vao/SkinnedVAO.h @@ -13,7 +13,7 @@ namespace mesh { virtual void clear() override; // @return VAO - virtual const kigl::GLVertexArray* registerModel( + virtual const kigl::GLVertexArray* registerMesh( mesh::ModelMesh* mesh) override; virtual void updateRT() override; diff --git a/src/mesh/vao/TexturedVAO.cpp b/src/mesh/vao/TexturedVAO.cpp index 7cc3791f8..9def08443 100644 --- a/src/mesh/vao/TexturedVAO.cpp +++ b/src/mesh/vao/TexturedVAO.cpp @@ -75,28 +75,58 @@ namespace mesh { m_indexEbo.clear(); } - const kigl::GLVertexArray* TexturedVAO::registerModel( + const kigl::GLVertexArray* TexturedVAO::registerMesh( mesh::ModelMesh* mesh) { ASSERT_RT(); + auto vertexCount = mesh->m_reserveVertexCount; + auto indexCount = mesh->m_reserveIndexCount; + auto& vertices = mesh->m_vertices; auto& indeces = mesh->m_indeces; - assert(!vertices.empty()); - assert(!indeces.empty()); + if (vertexCount == 0) { + vertexCount = static_cast(vertices.size()); + } - { - mesh->m_positionVboOffset = m_positionVbo.addVertices(vertices); - mesh->m_indexEboOffset = m_indexEbo.addIndeces(indeces); + if (indexCount == 0) { + indexCount = static_cast(indeces.size()); } - m_normalVbo.addVertices(vertices); - m_textureVbo.addVertices(vertices); + mesh->m_vboIndex = m_positionVbo.reserveVertices(vertexCount); + mesh->m_eboIndex = m_indexEbo.reserveIndeces(indexCount); + + m_normalVbo.reserveVertices(vertexCount); + m_textureVbo.reserveVertices(vertexCount); + + if (vertices.size() > 0) { + updateMesh( + mesh->m_vboIndex, + mesh->m_eboIndex, + mesh); + } return m_vao.get(); } + void TexturedVAO::updateMesh( + uint32_t baseVbo, + uint32_t baseEbo, + mesh::ModelMesh* mesh) + { + ASSERT_RT(); + + auto& vertices = mesh->m_vertices; + auto& indeces = mesh->m_indeces; + + m_positionVbo.updateVertices(baseVbo, vertices); + m_normalVbo.updateVertices(baseVbo, vertices); + m_textureVbo.updateVertices(baseVbo, vertices); + + m_indexEbo.updateIndeces(baseEbo, indeces); + } + void TexturedVAO::updateRT() { ASSERT_RT(); @@ -104,6 +134,7 @@ namespace mesh { m_positionVbo.updateVAO(*m_vao); m_normalVbo.updateVAO(*m_vao); m_textureVbo.updateVAO(*m_vao); + m_indexEbo.updateVAO(*m_vao); } } diff --git a/src/mesh/vao/TexturedVAO.h b/src/mesh/vao/TexturedVAO.h index b4feb28b1..05ce5fe11 100644 --- a/src/mesh/vao/TexturedVAO.h +++ b/src/mesh/vao/TexturedVAO.h @@ -23,7 +23,12 @@ namespace mesh { void bind(); void unbind(); - virtual const kigl::GLVertexArray* registerModel( + virtual const kigl::GLVertexArray* registerMesh( + mesh::ModelMesh* mesh); + + void updateMesh( + uint32_t baseVbo, + uint32_t baseEbo, mesh::ModelMesh* mesh); const kigl::GLVertexArray* getVAO() const diff --git a/src/mesh/vao/VBO.h b/src/mesh/vao/VBO.h index 014c42c72..fccfa1afa 100644 --- a/src/mesh/vao/VBO.h +++ b/src/mesh/vao/VBO.h @@ -2,6 +2,7 @@ #include #include +#include #include @@ -25,21 +26,25 @@ namespace mesh { virtual ~VBO(); - // @return base *offset* into buffer - size_t addVertices( - const std::vector& vertices); + // @return base *index* into entries + uint32_t reserveVertices( + const uint32_t count); - size_t addVertex( - const T_Vertex& vertex); + void updateVertices( + uint32_t baseIndex, + const std::span& vertices); + + //size_t addVertex( + // const T_Vertex& vertex); virtual T_Entry convertVertex( const T_Vertex& vertex) = 0; - size_t addEntries( - const std::vector& entries); + //size_t addEntries( + // const std::vector& entries); - // @return base *offset* into buffer - size_t addEntry(const T_Entry& entry); + //// @return base *offset* into buffer + //size_t addEntry(const T_Entry& entry); void reserveSize(size_t count); @@ -49,9 +54,9 @@ namespace mesh { void clear(); - // @return base *offset* into buffer (for next new entry) - size_t getBaseOffset() const noexcept { - return m_entries.size(); + // @return base *index* into buffer (for next new entry) + uint32_t getBaseIndex() const noexcept { + return static_cast(m_entries.size()); } protected: diff --git a/src/mesh/vao/VBO_impl.h b/src/mesh/vao/VBO_impl.h index 4d4ec6a3d..aee3d2765 100644 --- a/src/mesh/vao/VBO_impl.h +++ b/src/mesh/vao/VBO_impl.h @@ -25,63 +25,70 @@ namespace mesh { {} template - size_t VBO::addVertices( - const std::vector& vertices) + uint32_t VBO::reserveVertices( + const uint32_t count) { - constexpr size_t sz = sizeof(T_Entry); + const uint32_t baseIndex = static_cast(m_entries.size()); - const size_t baseIndex = m_entries.size(); - const size_t baseOffset = baseIndex * sz; + reserveSize(count); + m_entries.resize(m_entries.size() + count); - reserveSize(vertices.size()); - for (const auto& vertex : vertices) { - addEntry(convertVertex(vertex)); - } - - return baseOffset; + return baseIndex; } template - size_t VBO::addVertex( - const T_Vertex& vertex) + void VBO::updateVertices( + uint32_t baseIndex, + const std::span& vertices) { - return addEntry(convertVertex(vertex)); + uint32_t index = baseIndex; + for (const auto& vertex : vertices) { + m_entries[index] = convertVertex(vertex); + index++; + } } - template - size_t VBO::addEntries( - const std::vector& entries) - { - constexpr size_t sz = sizeof(T_Entry); + //template + //size_t VBO::addVertex( + // const T_Vertex& vertex) + //{ + // return addEntry(convertVertex(vertex)); + //} - const size_t baseIndex = m_entries.size(); - const size_t baseOffset = baseIndex * sz; + //template + //size_t VBO::addEntries( + // const std::vector& entries) + //{ + // constexpr size_t sz = sizeof(T_Entry); - reserveSize(entries.size()); - for (const auto& entry: entries) { - addEntry(entry); - } + // const size_t baseIndex = m_entries.size(); + // const size_t baseOffset = baseIndex * sz; - return baseOffset; - } + // reserveSize(entries.size()); + // for (const auto& entry: entries) { + // addEntry(entry); + // } - template - size_t VBO::addEntry(const T_Entry& entry) - { - constexpr size_t sz = sizeof(T_Entry); + // return baseOffset; + //} - if (m_entries.size() >= MAX_VERTEX_COUNT) { - throw std::runtime_error{ fmt::format("MAX_VERTEX_COUNT: {}", MAX_VERTEX_COUNT) }; - } + //template + //size_t VBO::addEntry(const T_Entry& entry) + //{ + // constexpr size_t sz = sizeof(T_Entry); - const size_t baseIndex = m_entries.size(); - const size_t baseOffset = baseIndex * sz; + // if (m_entries.size() >= MAX_VERTEX_COUNT) { + // throw std::runtime_error{ fmt::format("MAX_VERTEX_COUNT: {}", MAX_VERTEX_COUNT) }; + // } - reserveSize(1); - m_entries.emplace_back(entry); + // const size_t baseIndex = m_entries.size(); + // const size_t baseOffset = baseIndex * sz; - return baseOffset; - } + // reserveSize(1); + // m_entries.emplace_back(entry); + + // return baseOffset; + //} template void VBO::reserveSize(size_t count) diff --git a/src/mesh/vao/VertexIndexEBO.cpp b/src/mesh/vao/VertexIndexEBO.cpp index a9f563e69..49316c889 100644 --- a/src/mesh/vao/VertexIndexEBO.cpp +++ b/src/mesh/vao/VertexIndexEBO.cpp @@ -15,30 +15,37 @@ namespace mesh { : m_ebo{ name } {} - size_t VertexIndexEBO::addIndeces(std::vector indeces) + uint32_t VertexIndexEBO::reserveIndeces(uint32_t count) { - const size_t count = indeces.size(); const size_t baseIndex = m_entries.size(); - const size_t baseOffset = baseIndex * sizeof(IndexEntry); if (m_entries.size() + count >= MAX_INDEX_COUNT) throw std::runtime_error{ fmt::format("MAX_INDEX_COUNT: {}", MAX_INDEX_COUNT) }; - baseOffset; - { - size_t size = m_entries.size() + std::max(INDEX_BLOCK_SIZE, count) + INDEX_BLOCK_SIZE; + size_t size = m_entries.size() + std::max(INDEX_BLOCK_SIZE, static_cast(count)) + INDEX_BLOCK_SIZE; size += INDEX_BLOCK_SIZE - size % INDEX_BLOCK_SIZE; size = std::min(size, MAX_INDEX_COUNT); m_entries.reserve(size); } - m_entries.insert( - m_entries.end(), - indeces.begin(), - indeces.end()); + m_entries.resize(m_entries.size() + count); + + return static_cast(baseIndex); + } + + void VertexIndexEBO::updateIndeces( + uint32_t baseIndex, + std::span indeces) noexcept + { + const size_t count = indeces.size(); + + assert(baseIndex + count >= m_entries.size()); - return baseOffset; + std::copy( + indeces.begin(), + indeces.end(), + m_entries.begin() + baseIndex); } void VertexIndexEBO::clear() @@ -50,8 +57,8 @@ namespace mesh { void VertexIndexEBO::prepareVAO(kigl::GLVertexArray& vao) { { - m_ebo.createEmpty(INDEX_BLOCK_SIZE * sizeof(IndexEntry), GL_DYNAMIC_STORAGE_BIT); m_entries.reserve(INDEX_BLOCK_SIZE); + m_ebo.createEmpty(INDEX_BLOCK_SIZE * sizeof(IndexEntry), GL_DYNAMIC_STORAGE_BIT); } glVertexArrayElementBuffer(vao, m_ebo); } diff --git a/src/mesh/vao/VertexIndexEBO.h b/src/mesh/vao/VertexIndexEBO.h index 45c68b32d..d7f7a9abe 100644 --- a/src/mesh/vao/VertexIndexEBO.h +++ b/src/mesh/vao/VertexIndexEBO.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include "kigl/GLBuffer.h" @@ -20,7 +20,13 @@ namespace mesh VertexIndexEBO( std::string_view name); - size_t addIndeces(std::vector indeces); + // @return baseIndex + uint32_t reserveIndeces(uint32_t count); + + void updateIndeces( + uint32_t baseIndex, + std::span indeces) noexcept; + void clear(); void prepareVAO(kigl::GLVertexArray& vao); From cf445ea4e75164d7d79c35c6bf2442fb98a78cd9 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 11:07:33 +0300 Subject: [PATCH 15/28] FIX added VertexVBO back (for comparison) --- src/kigl/kigl.h | 6 +++ src/mesh/ModelMesh.h | 2 +- src/mesh/TextMesh.cpp | 9 ++-- src/mesh/TextMesh.h | 24 ++++----- src/mesh/vao/VertexEntry.h | 30 +++++++++++ src/mesh/vao/VertexVBO.cpp | 101 +++++++++++++++++++++++++++++++++++++ src/mesh/vao/VertexVBO.h | 35 +++++++++++++ src/text/TextDraw.cpp | 63 +++++++++-------------- src/text/TextDraw.h | 1 - 9 files changed, 212 insertions(+), 59 deletions(-) create mode 100644 src/mesh/vao/VertexEntry.h create mode 100644 src/mesh/vao/VertexVBO.cpp create mode 100644 src/mesh/vao/VertexVBO.h diff --git a/src/kigl/kigl.h b/src/kigl/kigl.h index 7ef0d1a86..194a90935 100644 --- a/src/kigl/kigl.h +++ b/src/kigl/kigl.h @@ -59,6 +59,8 @@ namespace kigl { unsigned int b : 10; unsigned int a : 2; + RGB10_A2() {} + RGB10_A2(const glm::vec4& p) : RGB10_A2(p.r, p.g, p.b, p.a) {} @@ -88,6 +90,8 @@ namespace kigl { int z : 10; unsigned int not_used : 2; + VEC10() {} + VEC10(const glm::vec3& p) : VEC10(p.x, p.y, p.z) {} @@ -119,6 +123,8 @@ namespace kigl { unsigned short u; unsigned short v; + UV16() {} + UV16(const glm::vec2& t) : UV16(t.x, t.y) {} diff --git a/src/mesh/ModelMesh.h b/src/mesh/ModelMesh.h index 6f88b1d86..bd6e70a42 100644 --- a/src/mesh/ModelMesh.h +++ b/src/mesh/ModelMesh.h @@ -58,8 +58,8 @@ namespace mesh { } public: - std::vector m_indeces; std::vector m_vertices; + std::vector m_indeces; std::vector m_vertexBones; diff --git a/src/mesh/TextMesh.cpp b/src/mesh/TextMesh.cpp index d75728d4e..5058d8747 100644 --- a/src/mesh/TextMesh.cpp +++ b/src/mesh/TextMesh.cpp @@ -28,9 +28,7 @@ namespace mesh { } void TextMesh::clear() { - m_positions.clear(); - m_normals.clear(); - m_texCoords.clear(); + m_vertices.clear(); m_atlasCoords.clear(); m_indeces.clear(); } @@ -39,9 +37,10 @@ namespace mesh { { AABB aabb{ true }; - for (auto&& vertex : m_positions) + for (auto&& vertex : m_vertices) { - aabb.minmax({ vertex.x, vertex.y, vertex.z }); + const auto& p = vertex.pos; + aabb.minmax({ p.x, p.y, p.z }); } return aabb; diff --git a/src/mesh/TextMesh.h b/src/mesh/TextMesh.h index c9e0e5135..31063a214 100644 --- a/src/mesh/TextMesh.h +++ b/src/mesh/TextMesh.h @@ -6,8 +6,7 @@ #include "mesh/Index.h" -#include "mesh/vao/NormalEntry.h" -#include "mesh/vao/PositionEntry.h" +#include "mesh/Vertex.h" #include "mesh/vao/TextureEntry.h" namespace mesh { @@ -32,12 +31,12 @@ namespace mesh { virtual void prepareDrawOptions( backend::DrawOptions& drawOptions) override; - inline uint32_t getBaseVertex() const noexcept { - return static_cast(m_positionVboOffset / sizeof(mesh::PositionEntry)); + uint32_t getBaseVertex() const noexcept { + return m_vboIndex; } inline uint32_t getBaseIndex() const noexcept { - return static_cast(m_indexEboOffset / sizeof(GLuint)); + return m_eboIndex * 3; } inline uint32_t getIndexCount() const noexcept { @@ -45,18 +44,15 @@ namespace mesh { } public: - std::vector m_positions; - std::vector m_normals; - std::vector m_texCoords; - std::vector m_atlasCoords; - + std::vector m_vertices; std::vector m_indeces; - // NOTE KI absolute offset into position VBO - size_t m_positionVboOffset{ 0 }; + std::vector m_atlasCoords; - // NOTE KI absolute offset into EBO - size_t m_indexEboOffset{ 0 }; + // NOTE KI absolute index into VBO + uint32_t m_vboIndex{ 0 }; + // NOTE KI absolute index into EBO + uint32_t m_eboIndex{ 0 }; }; } diff --git a/src/mesh/vao/VertexEntry.h b/src/mesh/vao/VertexEntry.h new file mode 100644 index 000000000..173e8be40 --- /dev/null +++ b/src/mesh/vao/VertexEntry.h @@ -0,0 +1,30 @@ +#pragma once + +#include "glm/glm.hpp" + +#include "kigl/kigl.h" + +#include "mesh/Vertex.h" + +namespace mesh { +#pragma pack(push, 1) + struct VertexEntry { + VertexEntry() {} + + VertexEntry(const mesh::Vertex& v) + : u_pos(v.pos), + u_texture(v.texture), + u_normal(v.normal), + u_tangent(v.tangent) + {} + + glm::vec3 u_pos; + + //kigl::UV16 texCoord; + glm::vec2 u_texture; + + kigl::VEC10 u_normal; + kigl::VEC10 u_tangent; + }; +#pragma pack(pop) +} diff --git a/src/mesh/vao/VertexVBO.cpp b/src/mesh/vao/VertexVBO.cpp new file mode 100644 index 000000000..bf2583eb9 --- /dev/null +++ b/src/mesh/vao/VertexVBO.cpp @@ -0,0 +1,101 @@ +#include "VertexVBO.h" + +#include "glm/glm.hpp" + +#include "asset/Shader.h" + +#include "kigl/GLVertexArray.h" + +#include "mesh/Vertex.h" + +#include "VBO_impl.h" + + +namespace mesh { + VertexVBO::VertexVBO( + std::string_view name, + int binding) + : VBO(name, -1, binding) + {} + + VertexEntry VertexVBO::convertVertex( + const Vertex& vertex) + { + return { vertex }; + } + + void VertexVBO::prepareVAO(kigl::GLVertexArray& vao) + { + { + m_entries.reserve(VERTEX_BLOCK_SIZE); + m_vbo.createEmpty(VERTEX_BLOCK_SIZE * sizeof(VertexEntry), GL_DYNAMIC_STORAGE_BIT); + } + + { + // "Tile" based GPU can benefit from having separate position stream VBO for improved caching + // https://solidpixel.github.io/2022/07/21/vertexpacking.html + // https://www.intel.com/content/www/us/en/developer/articles/guide/developer-and-optimization-guide-for-intel-processor-graphics-gen11-api.html + + glVertexArrayVertexBuffer(vao, m_binding, m_vbo, 0, sizeof(VertexEntry)); + { + { + glEnableVertexArrayAttrib(vao, ATTR_POS); + + // https://stackoverflow.com/questions/37972229/glvertexattribpointer-and-glvertexattribformat-whats-the-difference + // https://www.khronos.org/opengl/wiki/Vertex_Specification + // + // vertex attr + glVertexArrayAttribFormat(vao, ATTR_POS, 3, GL_FLOAT, GL_FALSE, offsetof(VertexEntry, u_pos)); + + glVertexArrayAttribBinding(vao, ATTR_POS, m_binding); + } + { + glEnableVertexArrayAttrib(vao, ATTR_NORMAL); + glEnableVertexArrayAttrib(vao, ATTR_TANGENT); + + // https://stackoverflow.com/questions/37972229/glvertexattribpointer-and-glvertexattribformat-whats-the-difference + // https://www.khronos.org/opengl/wiki/Vertex_Specification + // + + // normal attr + glVertexArrayAttribFormat(vao, ATTR_NORMAL, 4, GL_INT_2_10_10_10_REV, GL_TRUE, offsetof(VertexEntry, u_normal)); + + // tangent attr + glVertexArrayAttribFormat(vao, ATTR_TANGENT, 4, GL_INT_2_10_10_10_REV, GL_TRUE, offsetof(VertexEntry, u_tangent)); + + glVertexArrayAttribBinding(vao, ATTR_NORMAL, m_binding); + glVertexArrayAttribBinding(vao, ATTR_TANGENT, m_binding); + } + { + glEnableVertexArrayAttrib(vao, ATTR_TEX); + + // https://stackoverflow.com/questions/37972229/glvertexattribpointer-and-glvertexattribformat-whats-the-difference + // https://www.khronos.org/opengl/wiki/Vertex_Specification + // + + // texture attr + glVertexArrayAttribFormat(vao, ATTR_TEX, 2, GL_FLOAT, GL_FALSE, offsetof(VertexEntry, u_texture)); + + glVertexArrayAttribBinding(vao, ATTR_TEX, m_binding); + } + } + + // https://community.khronos.org/t/direct-state-access-instance-attribute-buffer-specification/75611 + // https://www.khronos.org/opengl/wiki/Vertex_Specification + glVertexArrayBindingDivisor(vao, m_binding, 0); + } + } + + AABB VertexVBO::calculateAABB() const noexcept + { + AABB aabb{ true }; + + for (auto&& entry : m_entries) + { + const auto& p = entry.u_pos; + aabb.minmax({ p.x, p.y, p.z }); + } + + return aabb; + } +} diff --git a/src/mesh/vao/VertexVBO.h b/src/mesh/vao/VertexVBO.h new file mode 100644 index 000000000..9accc7c93 --- /dev/null +++ b/src/mesh/vao/VertexVBO.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include + +#include "asset/AABB.h" + +#include "mesh/Vertex.h" + +#include "VertexEntry.h" + +#include "VBO.h" + +namespace mesh { + // + // https://github.com/fendevel/Guide-to-Modern-OpenGL-Functions#storing-index-and-vertex-data-under-single-buffer + // + class VertexVBO : public VBO { + public: + VertexVBO( + std::string_view name, + int binding); + + virtual VertexEntry convertVertex( + const Vertex& vertex) override; + + virtual void prepareVAO(kigl::GLVertexArray& vao) override; + + AABB calculateAABB() const noexcept; + + public: + glm::vec3 m_positionOffset{ 0.f }; + }; +} diff --git a/src/text/TextDraw.cpp b/src/text/TextDraw.cpp index 6ff1492ed..6ec1a9cf1 100644 --- a/src/text/TextDraw.cpp +++ b/src/text/TextDraw.cpp @@ -14,6 +14,7 @@ #include "registry/Registry.h" #include "mesh/TextMesh.h" +#include "mesh/Vertex.h" #include "mesh/vao/VBO_impl.h" @@ -40,13 +41,6 @@ namespace const glm::vec3 tangent{ 1.f, 0.f, 0.f }; const char* prev = { nullptr }; - const mesh::NormalEntry normals[4]{ - { normal, tangent }, - { normal, tangent }, - { normal, tangent }, - { normal, tangent }, - }; - auto* font = fontAtlas->getFont()->m_font; // @see freetype-gl/text-buffer.c @@ -97,44 +91,38 @@ namespace const float glyphW = glyph->s1 - glyph->s0; const float glyphH = glyph->t1 - glyph->t0; - const GLuint index = (GLuint)mesh->m_normals.size(); + const GLuint index = (GLuint)mesh->m_vertices.size(); - const mesh::Index indeces[2] { - {index, index + 1, index + 2}, - {index, index + 2, index + 3}, + const glm::vec3 positions[4] { + { x0, y0, 0.f }, + { x0, y1, 0.f }, + { x1, y1, 0.f }, + { x1, y0, 0.f }, }; - const mesh::PositionEntry positions[4] { - { { x0, y0, 0.f } }, - { { x0, y1, 0.f } }, - { { x1, y1, 0.f } }, - { { x1, y0, 0.f } }, + const glm::vec2 atlasCoords[4] { + { s0, t0 }, + { s0, t1 }, + { s1, t1 }, + { s1, t0 }, }; - const mesh::TextureEntry atlasCoords[4] { - { {s0, t0} }, - { {s0, t1} }, - { {s1, t1} }, - { {s1, t0} }, + + const glm::vec2 materialCoords[4]{ + { 0, 0 }, + { 0, glyphH / glyphMaxH }, + { glyphW / glyphMaxW, glyphH / glyphMaxH }, + { glyphW / glyphMaxW, 0 }, }; - const mesh::TextureEntry materialCoords[4]{ - { {0, 0} }, - { {0, glyphH / glyphMaxH} }, - { {glyphW / glyphMaxW, glyphH / glyphMaxH} }, - { {glyphW / glyphMaxW, 0} }, + const mesh::Index indeces[2]{ + {index, index + 1, index + 2}, + {index, index + 2, index + 3}, }; - for (const auto& v : positions) { - mesh->m_positions.push_back(v); - } - for (const auto& v : normals) { - mesh->m_normals.push_back(v); - } - for (const auto& v : atlasCoords) { - mesh->m_atlasCoords.emplace_back(v); - } - for (const auto& v : materialCoords) { - mesh->m_texCoords.push_back(v); + for (int i = 0; i < 4; i++) { + mesh->m_vertices.emplace_back(positions[i], materialCoords[i], normal, tangent); + mesh->m_atlasCoords.emplace_back(atlasCoords[i]); } + for (const auto& v : indeces) { mesh->m_indeces.push_back(v); } @@ -166,7 +154,6 @@ namespace text } void TextDraw::render( - const RenderContext& ctx, text::font_id fontId, std::string_view text, glm::vec2& pen, diff --git a/src/text/TextDraw.h b/src/text/TextDraw.h index fd3f3763f..5c23a07bf 100644 --- a/src/text/TextDraw.h +++ b/src/text/TextDraw.h @@ -29,7 +29,6 @@ namespace text void updateRT(); void render( - const RenderContext& ctx, text::font_id fontId, std::string_view text, glm::vec2& pen, From 7b0595a6ed849b227852324a8d35fe9e7d353871 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 19:01:50 +0300 Subject: [PATCH 16/28] FIX smaller shadow map size --- scene/assets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/assets.yml b/scene/assets.yml index ba0847788..b35f98630 100644 --- a/scene/assets.yml +++ b/scene/assets.yml @@ -132,7 +132,7 @@ assets: xshadow_planes: [0.1, 25, 75, 150, 500] xshadow_map_sizes: [1024, 1024, 1024, 1024] shadow_planes: [0.1, 40, 90, 500] - shadow_map_sizes: [2048, 2048, 2048] + shadow_map_sizes: [2048, 1024, 1024] shadow_render_frame_start: 0 shadow_render_frame_step: 1 shadow_visual: false From 0e1c470197f60ce6cb28b2d425d2472cb1a80e50 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 19:23:27 +0300 Subject: [PATCH 17/28] FIX try to ensure OIT buffer is cleared --- src/render/NodeDraw.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/render/NodeDraw.cpp b/src/render/NodeDraw.cpp index bb8674c14..e3a63e748 100644 --- a/src/render/NodeDraw.cpp +++ b/src/render/NodeDraw.cpp @@ -375,9 +375,10 @@ namespace render { ctx.m_batch->flush(ctx); } + state.setStencil({}); + if (!ctx.m_forceSolid) { - state.setStencil({}); particleRenderer.render(ctx); } From f0793da97b72f4baa31ff4d49a38ced1dc8c0aba Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 20:49:05 +0300 Subject: [PATCH 18/28] FIX no need to re-orthagonalize tangent --- shader/g_font_render.vs | 2 +- shader/g_terrain.vs | 2 +- shader/g_tex.vs | 2 +- shader/g_water.vs | 2 +- shader/tex.vs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/shader/g_font_render.vs b/shader/g_font_render.vs index d03bf2078..4a356a8c4 100644 --- a/shader/g_font_render.vs +++ b/shader/g_font_render.vs @@ -136,7 +136,7 @@ void main() { { // NOTE KI Gram-Schmidt process to re-orthogonalize // https://learnopengl.com/Advanced-Lighting/Normal-Mapping - tangent = normalize(tangent - dot(tangent, normal) * normal); + //tangent = normalize(tangent - dot(tangent, normal) * normal); const vec3 bitangent = cross(normal, tangent); diff --git a/shader/g_terrain.vs b/shader/g_terrain.vs index 16e0d6f44..b597023fb 100644 --- a/shader/g_terrain.vs +++ b/shader/g_terrain.vs @@ -124,7 +124,7 @@ void main() { if (u_materials[materialIndex].normalMapTex.x > 0) { // NOTE KI Gram-Schmidt process to re-orthogonalize // https://learnopengl.com/Advanced-Lighting/Normal-Mapping - tangent = normalize(tangent - dot(tangent, normal) * normal); + //tangent = normalize(tangent - dot(tangent, normal) * normal); const vec3 bitangent = cross(normal, tangent); diff --git a/shader/g_tex.vs b/shader/g_tex.vs index 28668737b..7b1fba5d3 100644 --- a/shader/g_tex.vs +++ b/shader/g_tex.vs @@ -157,7 +157,7 @@ void main() { { // NOTE KI Gram-Schmidt process to re-orthogonalize // https://learnopengl.com/Advanced-Lighting/Normal-Mapping - tangent = normalize(tangent - dot(tangent, normal) * normal); + //tangent = normalize(tangent - dot(tangent, normal) * normal); const vec3 bitangent = cross(normal, tangent); diff --git a/shader/g_water.vs b/shader/g_water.vs index b93d93216..3b2a1d33b 100644 --- a/shader/g_water.vs +++ b/shader/g_water.vs @@ -77,7 +77,7 @@ void main() { if (u_materials[materialIndex].normalMapTex.x > 0) { vec3 tangent = a_tangent; - tangent = normalize(tangent - dot(tangent, normal) * normal); + //tangent = normalize(tangent - dot(tangent, normal) * normal); const vec3 bitangent = cross(normal, tangent); diff --git a/shader/tex.vs b/shader/tex.vs index cee80e05b..a07a73ebb 100644 --- a/shader/tex.vs +++ b/shader/tex.vs @@ -129,7 +129,7 @@ void main() { { // NOTE KI Gram-Schmidt process to re-orthogonalize // https://learnopengl.com/Advanced-Lighting/Normal-Mapping - tangent = normalize(tangent - dot(tangent, normal) * normal); + //tangent = normalize(tangent - dot(tangent, normal) * normal); const vec3 bitangent = cross(normal, tangent); From fd271c65528f6ab4a1ad4d120446223ccbdd22a9 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 21:25:21 +0300 Subject: [PATCH 19/28] FIX VAO does not need to know about Mesh --- src/mesh/ModelMesh.cpp | 30 +++++++++++++++++-- src/mesh/vao/SkinnedVAO.cpp | 23 +++++--------- src/mesh/vao/SkinnedVAO.h | 8 +++-- src/mesh/vao/TexturedVAO.cpp | 53 ++++++++++++--------------------- src/mesh/vao/TexturedVAO.h | 13 ++++---- src/mesh/vao/VBO.h | 12 +------- src/mesh/vao/VBO_impl.h | 45 +--------------------------- src/mesh/vao/VertexIndexEBO.cpp | 2 +- src/mesh/vao/VertexIndexEBO.h | 2 +- src/registry/ModelRegistry.cpp | 1 + 10 files changed, 72 insertions(+), 117 deletions(-) diff --git a/src/mesh/ModelMesh.cpp b/src/mesh/ModelMesh.cpp index b5677573f..b689d5f12 100644 --- a/src/mesh/ModelMesh.cpp +++ b/src/mesh/ModelMesh.cpp @@ -64,13 +64,39 @@ namespace mesh { if (m_prepared) return m_vao; m_prepared = true; + TexturedVAO* vao; + SkinnedVAO* skinnedVao = nullptr; + if (m_rig && m_rig->hasBones()) { - m_vao = ModelRegistry::get().getSkinnedVao()->registerMesh(this); + skinnedVao = ModelRegistry::get().getSkinnedVao(); + vao = skinnedVao; } else { - m_vao = ModelRegistry::get().getTexturedVao()->registerMesh(this); + vao = ModelRegistry::get().getTexturedVao(); + } + + m_vboIndex = vao->reserveVertices(m_vertices.size()); + m_eboIndex = vao->reserveIndeces(m_indeces.size()); + if (skinnedVao) { + skinnedVao->reserveVertexBones(m_vertexBones.size()); + } + + vao->updateVertices( + m_vboIndex, + m_vertices); + + vao->updateIndeces( + m_eboIndex, + m_indeces); + + if (skinnedVao) { + skinnedVao->updateVertexBones( + m_vboIndex, + m_vertexBones); } + m_vao = vao->getVAO(); + return m_vao; } diff --git a/src/mesh/vao/SkinnedVAO.cpp b/src/mesh/vao/SkinnedVAO.cpp index 6d7993872..62df74f9b 100644 --- a/src/mesh/vao/SkinnedVAO.cpp +++ b/src/mesh/vao/SkinnedVAO.cpp @@ -35,23 +35,16 @@ namespace mesh { m_boneVbo.clear(); } - const kigl::GLVertexArray* SkinnedVAO::registerMesh( - mesh::ModelMesh* mesh) + void SkinnedVAO::reserveVertexBones(size_t count) { - TexturedVAO::registerMesh(mesh); - - auto vertexCount = mesh->m_reserveVertexCount; - auto& vertices = mesh->m_vertices; - - if (vertexCount == 0) { - vertexCount = static_cast(vertices.size()); - } - - m_boneVbo.reserveVertices(vertexCount); - - m_boneVbo.updateVertices(mesh->m_vboIndex, mesh->m_vertexBones); + m_boneVbo.reserveVertices(count); + } - return m_vao.get(); + void SkinnedVAO::updateVertexBones( + uint32_t baseVbo, + std::span vertexBones) + { + m_boneVbo.updateVertices(baseVbo, vertexBones); } void SkinnedVAO::updateRT() diff --git a/src/mesh/vao/SkinnedVAO.h b/src/mesh/vao/SkinnedVAO.h index 1629d38aa..9327746a0 100644 --- a/src/mesh/vao/SkinnedVAO.h +++ b/src/mesh/vao/SkinnedVAO.h @@ -12,9 +12,11 @@ namespace mesh { virtual void clear() override; - // @return VAO - virtual const kigl::GLVertexArray* registerMesh( - mesh::ModelMesh* mesh) override; + void reserveVertexBones(size_t count); + + void updateVertexBones( + uint32_t baseVbo, + std::span vertexBones); virtual void updateRT() override; diff --git a/src/mesh/vao/TexturedVAO.cpp b/src/mesh/vao/TexturedVAO.cpp index 9def08443..39ac5e3ef 100644 --- a/src/mesh/vao/TexturedVAO.cpp +++ b/src/mesh/vao/TexturedVAO.cpp @@ -9,8 +9,6 @@ #include "kigl/GLState.h" -#include "mesh/ModelMesh.h" - #include "VBO_impl.h" @@ -75,54 +73,41 @@ namespace mesh { m_indexEbo.clear(); } - const kigl::GLVertexArray* TexturedVAO::registerMesh( - mesh::ModelMesh* mesh) + uint32_t TexturedVAO::reserveVertices(size_t count) { ASSERT_RT(); - auto vertexCount = mesh->m_reserveVertexCount; - auto indexCount = mesh->m_reserveIndexCount; - - auto& vertices = mesh->m_vertices; - auto& indeces = mesh->m_indeces; + auto baseIndex = m_positionVbo.reserveVertices(count); - if (vertexCount == 0) { - vertexCount = static_cast(vertices.size()); - } - - if (indexCount == 0) { - indexCount = static_cast(indeces.size()); - } + m_normalVbo.reserveVertices(count); + m_textureVbo.reserveVertices(count); - mesh->m_vboIndex = m_positionVbo.reserveVertices(vertexCount); - mesh->m_eboIndex = m_indexEbo.reserveIndeces(indexCount); - - m_normalVbo.reserveVertices(vertexCount); - m_textureVbo.reserveVertices(vertexCount); + return baseIndex; + } - if (vertices.size() > 0) { - updateMesh( - mesh->m_vboIndex, - mesh->m_eboIndex, - mesh); - } + uint32_t TexturedVAO::reserveIndeces(size_t count) + { + ASSERT_RT(); - return m_vao.get(); + return m_indexEbo.reserveIndeces(count); } - void TexturedVAO::updateMesh( + void TexturedVAO::updateVertices( uint32_t baseVbo, - uint32_t baseEbo, - mesh::ModelMesh* mesh) + std::span vertices) { ASSERT_RT(); - auto& vertices = mesh->m_vertices; - auto& indeces = mesh->m_indeces; - m_positionVbo.updateVertices(baseVbo, vertices); m_normalVbo.updateVertices(baseVbo, vertices); m_textureVbo.updateVertices(baseVbo, vertices); + } + + void TexturedVAO::updateIndeces( + uint32_t baseEbo, + std::span indeces) + { + ASSERT_RT(); m_indexEbo.updateIndeces(baseEbo, indeces); } diff --git a/src/mesh/vao/TexturedVAO.h b/src/mesh/vao/TexturedVAO.h index 05ce5fe11..db72de4a8 100644 --- a/src/mesh/vao/TexturedVAO.h +++ b/src/mesh/vao/TexturedVAO.h @@ -4,8 +4,6 @@ #include "kigl/GLVertexArray.h" -#include "mesh/ModelMesh.h" - #include "VertexPositionVBO.h" #include "VertexNormalVBO.h" #include "VertexTextureVBO.h" @@ -23,13 +21,16 @@ namespace mesh { void bind(); void unbind(); - virtual const kigl::GLVertexArray* registerMesh( - mesh::ModelMesh* mesh); + uint32_t reserveVertices(size_t count); + uint32_t reserveIndeces(size_t count); - void updateMesh( + void updateVertices( uint32_t baseVbo, + std::span vertices); + + void updateIndeces( uint32_t baseEbo, - mesh::ModelMesh* mesh); + std::span indeces); const kigl::GLVertexArray* getVAO() const { diff --git a/src/mesh/vao/VBO.h b/src/mesh/vao/VBO.h index fccfa1afa..9c4abf063 100644 --- a/src/mesh/vao/VBO.h +++ b/src/mesh/vao/VBO.h @@ -27,25 +27,15 @@ namespace mesh { virtual ~VBO(); // @return base *index* into entries - uint32_t reserveVertices( - const uint32_t count); + uint32_t reserveVertices(size_t count); void updateVertices( uint32_t baseIndex, const std::span& vertices); - //size_t addVertex( - // const T_Vertex& vertex); - virtual T_Entry convertVertex( const T_Vertex& vertex) = 0; - //size_t addEntries( - // const std::vector& entries); - - //// @return base *offset* into buffer - //size_t addEntry(const T_Entry& entry); - void reserveSize(size_t count); virtual void prepareVAO(kigl::GLVertexArray& vao) = 0; diff --git a/src/mesh/vao/VBO_impl.h b/src/mesh/vao/VBO_impl.h index aee3d2765..5a6f58e25 100644 --- a/src/mesh/vao/VBO_impl.h +++ b/src/mesh/vao/VBO_impl.h @@ -25,8 +25,7 @@ namespace mesh { {} template - uint32_t VBO::reserveVertices( - const uint32_t count) + uint32_t VBO::reserveVertices(size_t count) { const uint32_t baseIndex = static_cast(m_entries.size()); @@ -48,48 +47,6 @@ namespace mesh { } } - //template - //size_t VBO::addVertex( - // const T_Vertex& vertex) - //{ - // return addEntry(convertVertex(vertex)); - //} - - //template - //size_t VBO::addEntries( - // const std::vector& entries) - //{ - // constexpr size_t sz = sizeof(T_Entry); - - // const size_t baseIndex = m_entries.size(); - // const size_t baseOffset = baseIndex * sz; - - // reserveSize(entries.size()); - // for (const auto& entry: entries) { - // addEntry(entry); - // } - - // return baseOffset; - //} - - //template - //size_t VBO::addEntry(const T_Entry& entry) - //{ - // constexpr size_t sz = sizeof(T_Entry); - - // if (m_entries.size() >= MAX_VERTEX_COUNT) { - // throw std::runtime_error{ fmt::format("MAX_VERTEX_COUNT: {}", MAX_VERTEX_COUNT) }; - // } - - // const size_t baseIndex = m_entries.size(); - // const size_t baseOffset = baseIndex * sz; - - // reserveSize(1); - // m_entries.emplace_back(entry); - - // return baseOffset; - //} - template void VBO::reserveSize(size_t count) { diff --git a/src/mesh/vao/VertexIndexEBO.cpp b/src/mesh/vao/VertexIndexEBO.cpp index 49316c889..d13161a74 100644 --- a/src/mesh/vao/VertexIndexEBO.cpp +++ b/src/mesh/vao/VertexIndexEBO.cpp @@ -15,7 +15,7 @@ namespace mesh { : m_ebo{ name } {} - uint32_t VertexIndexEBO::reserveIndeces(uint32_t count) + uint32_t VertexIndexEBO::reserveIndeces(size_t count) { const size_t baseIndex = m_entries.size(); diff --git a/src/mesh/vao/VertexIndexEBO.h b/src/mesh/vao/VertexIndexEBO.h index d7f7a9abe..0199aa9b3 100644 --- a/src/mesh/vao/VertexIndexEBO.h +++ b/src/mesh/vao/VertexIndexEBO.h @@ -21,7 +21,7 @@ namespace mesh std::string_view name); // @return baseIndex - uint32_t reserveIndeces(uint32_t count); + uint32_t reserveIndeces(size_t count); void updateIndeces( uint32_t baseIndex, diff --git a/src/registry/ModelRegistry.cpp b/src/registry/ModelRegistry.cpp index 710f5615c..41bf2da87 100644 --- a/src/registry/ModelRegistry.cpp +++ b/src/registry/ModelRegistry.cpp @@ -5,6 +5,7 @@ #include "asset/Assets.h" #include "mesh/MeshSet.h" +#include "mesh/Mesh.h" #include "mesh/vao/TexturedVAO.h" #include "mesh/vao/SkinnedVAO.h" From 2f2ccb2e2de9c85c87911a62748ea92ceb46bd49 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Fri, 21 Jun 2024 23:33:57 +0300 Subject: [PATCH 20/28] FIX text draw using shared TextVAO --- learnopengl.vcxproj | 7 ++++ learnopengl.vcxproj.filters | 33 +++++++++++++++---- src/asset/TextureSpec.h | 2 +- src/generator/TextGenerator.cpp | 56 +++++++++++++++----------------- src/generator/TextGenerator.h | 7 ---- src/mesh/TextMesh.cpp | 35 ++++++++++++++++---- src/mesh/TextMesh.h | 3 +- src/mesh/vao/VBO.h | 2 +- src/mesh/vao/VBO_impl.h | 13 ++++++-- src/mesh/vao/VertexIndexEBO.cpp | 9 +++-- src/registry/Registry.cpp | 9 ++++- src/text/TextDraw.cpp | 10 ++++-- src/text/TextSystem.cpp | 33 +++++++++++++++++++ src/text/TextSystem.h | 35 ++++++++++++++++++++ src/text/vao/AtlasTextureVBO.cpp | 13 ++++---- src/text/vao/AtlasTextureVBO.h | 6 ++-- src/text/vao/TextVAO.cpp | 53 ++++++++++++++++++++++++++++++ src/text/vao/TextVAO.h | 29 +++++++++++++++++ 18 files changed, 284 insertions(+), 71 deletions(-) create mode 100644 src/text/TextSystem.cpp create mode 100644 src/text/TextSystem.h create mode 100644 src/text/vao/TextVAO.cpp create mode 100644 src/text/vao/TextVAO.h diff --git a/learnopengl.vcxproj b/learnopengl.vcxproj index a02d29ef2..53b95deca 100644 --- a/learnopengl.vcxproj +++ b/learnopengl.vcxproj @@ -223,8 +223,10 @@ + + @@ -354,6 +356,8 @@ + + @@ -442,6 +446,8 @@ + + @@ -486,6 +492,7 @@ + diff --git a/learnopengl.vcxproj.filters b/learnopengl.vcxproj.filters index 9e2249165..10de84054 100644 --- a/learnopengl.vcxproj.filters +++ b/learnopengl.vcxproj.filters @@ -537,9 +537,6 @@ Source Files - - Source Files - Source Files @@ -699,6 +696,21 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -1424,9 +1436,6 @@ Header Files - - Header Files - Header Files @@ -1739,6 +1748,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/src/asset/TextureSpec.h b/src/asset/TextureSpec.h index 4338cdada..e8b3aab49 100644 --- a/src/asset/TextureSpec.h +++ b/src/asset/TextureSpec.h @@ -2,7 +2,7 @@ #include "kigl/kigl.h" -constexpr int MIP_MAP_LEVELS = 12; +inline constexpr int MIP_MAP_LEVELS = 12; struct TextureSpec { // NOTE KI opengl default is GL_REPEAT diff --git a/src/generator/TextGenerator.cpp b/src/generator/TextGenerator.cpp index 6745f33ce..61358aba6 100644 --- a/src/generator/TextGenerator.cpp +++ b/src/generator/TextGenerator.cpp @@ -22,14 +22,14 @@ #include "registry/EntityRegistry.h" #include "text/FontRegistry.h" -#include "text/TextDraw.h" #include "text/FontAtlas.h" -namespace { -} +#include "text/TextDraw.h" +#include "text/TextSystem.h" +#include "text/vao/TextVAO.h" + TextGenerator::TextGenerator() - : m_vboAtlasTex{ "vbo_font", ATTR_FONT_ATLAS_TEX, VBO_FONT_ATLAS_BINDING } {} TextGenerator::~TextGenerator() = default; @@ -47,9 +47,6 @@ void TextGenerator::prepareRT( { m_draw = std::make_unique(); m_draw->prepareRT(ctx); - m_vao.prepare(); - - m_vboAtlasTex.prepareVAO(*m_vao.modifyVAO()); } void TextGenerator::updateWT( @@ -89,12 +86,9 @@ void TextGenerator::updateVAO( mesh->clear(); - m_vboAtlasTex.clear(); - glm::vec2 pen{ 0.f }; m_draw->render( - ctx, m_fontId, m_text, pen, @@ -102,27 +96,35 @@ void TextGenerator::updateVAO( m_aabb = mesh->calculateAABB(); - m_vao.clear(); + text::TextVAO* vao = text::TextSystem::get().getTextVAO(); - { - m_vao.m_positionVbo.m_positionOffset = m_aabb.getVolume(); - mesh->m_positionVboOffset = m_vao.m_positionVbo.addEntries(mesh->m_positions); - mesh->m_indexEboOffset = m_vao.m_indexEbo.addIndeces(mesh->m_indeces); + vao->updateVertices( + mesh->m_vboIndex, + mesh->m_vertices); - m_vao.m_normalVbo.addEntries(mesh->m_normals); - m_vao.m_textureVbo.addEntries(mesh->m_texCoords); + vao->updateIndeces( + mesh->m_eboIndex, + mesh->m_indeces); - m_vboAtlasTex.addEntries(mesh->m_atlasCoords); - m_vboAtlasTex.updateVAO(*m_vao.modifyVAO()); + vao->updateAtlasCoords( + mesh->m_vboIndex, + mesh->m_atlasCoords); - m_vao.updateRT(); - } + lod.m_indexCount = mesh->getIndexCount(); - lodMesh->m_vao = m_vao.getVAO(); + //{ + // m_vao.m_positionVbo.m_positionOffset = m_aabb.getVolume(); + // mesh->m_positionVboOffset = m_vao.m_positionVbo.addEntries(mesh->m_positions); + // mesh->m_indexEboOffset = m_vao.m_indexEbo.addIndeces(mesh->m_indeces); - lod.m_baseVertex = mesh->getBaseVertex(); - lod.m_baseIndex = mesh->getBaseIndex(); - lod.m_indexCount = mesh->getIndexCount(); + // m_vao.m_normalVbo.addEntries(mesh->m_normals); + // m_vao.m_textureVbo.addEntries(mesh->m_texCoords); + + // m_vboAtlasTex.addEntries(mesh->m_atlasCoords); + // m_vboAtlasTex.updateVAO(*m_vao.modifyVAO()); + + // m_vao.updateRT(); + //} } void TextGenerator::bindBatch( @@ -153,8 +155,4 @@ GLuint64 TextGenerator::getAtlasTextureHandle() const noexcept void TextGenerator::clear() { - //auto* mesh = m_mesh.get(); - //mesh->clear(); - //m_vboAtlasTex.clear(); - //m_vao.clear(); } diff --git a/src/generator/TextGenerator.h b/src/generator/TextGenerator.h index ba983c930..0a64fd83e 100644 --- a/src/generator/TextGenerator.h +++ b/src/generator/TextGenerator.h @@ -9,10 +9,6 @@ #include "backend/DrawOptions.h" -#include "mesh/vao/TexturedVAO.h" - -#include "text/vao/AtlasTextureVBO.h" - #include "text/size.h" namespace mesh { @@ -84,9 +80,6 @@ class TextGenerator final : public NodeGenerator { AABB m_aabb; - mesh::AtlasTextureVBO m_vboAtlasTex; - mesh::TexturedVAO m_vao{ "text" }; - std::unique_ptr m_draw; text::font_id m_fontId{ 0 }; diff --git a/src/mesh/TextMesh.cpp b/src/mesh/TextMesh.cpp index 5058d8747..1d89eb716 100644 --- a/src/mesh/TextMesh.cpp +++ b/src/mesh/TextMesh.cpp @@ -9,6 +9,10 @@ #include "text/TextDraw.h" +#include "text/vao/TextVAO.h" +#include "text/TextSystem.h" + + namespace { } @@ -33,14 +37,12 @@ namespace mesh { m_indeces.clear(); } - AABB TextMesh::calculateAABB() const noexcept - { + AABB TextMesh::calculateAABB() const noexcept { AABB aabb{ true }; for (auto&& vertex : m_vertices) { - const auto& p = vertex.pos; - aabb.minmax({ p.x, p.y, p.z }); + aabb.minmax(vertex.pos); } return aabb; @@ -52,15 +54,34 @@ namespace mesh { if (m_prepared) return m_vao; m_prepared = true; + text::TextVAO* vao = text::TextSystem::get().getTextVAO(); + + if (m_reserveVertexCount <= 0) { + m_reserveVertexCount = 100 * 4; + } + + if (m_reserveIndexCount <= 0) { + m_reserveIndexCount = 100 * 2; + } + + m_vboIndex = vao->reserveVertices(m_reserveVertexCount); + vao->reserveAtlasCoords(m_reserveVertexCount); + + m_eboIndex = vao->reserveIndeces(m_reserveIndexCount); + + m_vao = vao->getVAO(); + return m_vao; } void TextMesh::prepareLod( mesh::LodMesh& lodMesh) { - lodMesh.m_lod.m_baseVertex = 0; - lodMesh.m_lod.m_baseIndex = 0; - lodMesh.m_lod.m_indexCount = 0; + auto& lod = lodMesh.m_lod; + + lod.m_baseVertex = getBaseVertex(); + lod.m_baseIndex = getBaseIndex(); + lod.m_indexCount = getIndexCount(); } void TextMesh::prepareDrawOptions( diff --git a/src/mesh/TextMesh.h b/src/mesh/TextMesh.h index 31063a214..722a6c2c3 100644 --- a/src/mesh/TextMesh.h +++ b/src/mesh/TextMesh.h @@ -7,7 +7,6 @@ #include "mesh/Index.h" #include "mesh/Vertex.h" -#include "mesh/vao/TextureEntry.h" namespace mesh { class TextMesh final : public Mesh @@ -47,7 +46,7 @@ namespace mesh { std::vector m_vertices; std::vector m_indeces; - std::vector m_atlasCoords; + std::vector m_atlasCoords; // NOTE KI absolute index into VBO uint32_t m_vboIndex{ 0 }; diff --git a/src/mesh/vao/VBO.h b/src/mesh/vao/VBO.h index 9c4abf063..e80195b55 100644 --- a/src/mesh/vao/VBO.h +++ b/src/mesh/vao/VBO.h @@ -56,7 +56,7 @@ namespace mesh { bool m_prepared{ false }; kigl::GLBuffer m_vbo; - size_t m_lastBufferSize = 0; + size_t m_lastSize{ 0 }; kigl::GLVertexArray* m_vao{ nullptr }; diff --git a/src/mesh/vao/VBO_impl.h b/src/mesh/vao/VBO_impl.h index 5a6f58e25..a85dea40b 100644 --- a/src/mesh/vao/VBO_impl.h +++ b/src/mesh/vao/VBO_impl.h @@ -40,11 +40,18 @@ namespace mesh { uint32_t baseIndex, const std::span& vertices) { + assert(baseIndex + vertices.size() <= m_entries.size()); + uint32_t index = baseIndex; for (const auto& vertex : vertices) { m_entries[index] = convertVertex(vertex); index++; } + + // NOTE KI not optimal at all, should handle each case as separate dirty span + if (m_lastSize > baseIndex) { + m_lastSize = baseIndex; + } } template @@ -59,7 +66,7 @@ namespace mesh { template void VBO::updateVAO(kigl::GLVertexArray& vao) { - const size_t index = m_lastBufferSize; + const size_t index = m_lastSize; const size_t totalCount = m_entries.size(); if (index == totalCount) return; @@ -84,13 +91,13 @@ namespace mesh { &m_entries[updateIndex]); } - m_lastBufferSize = totalCount; + m_lastSize = totalCount; } template void VBO::clear() { m_entries.clear(); - m_lastBufferSize = 0; + m_lastSize = 0; } } diff --git a/src/mesh/vao/VertexIndexEBO.cpp b/src/mesh/vao/VertexIndexEBO.cpp index d13161a74..0ecac3f95 100644 --- a/src/mesh/vao/VertexIndexEBO.cpp +++ b/src/mesh/vao/VertexIndexEBO.cpp @@ -38,14 +38,17 @@ namespace mesh { uint32_t baseIndex, std::span indeces) noexcept { - const size_t count = indeces.size(); - - assert(baseIndex + count >= m_entries.size()); + assert(baseIndex + indeces.size() <= m_entries.size()); std::copy( indeces.begin(), indeces.end(), m_entries.begin() + baseIndex); + + // NOTE KI not optimal at all, should handle each case as separate dirty span + if (m_lastSize > baseIndex) { + m_lastSize = baseIndex; + } } void VertexIndexEBO::clear() diff --git a/src/registry/Registry.cpp b/src/registry/Registry.cpp index 13e60b73d..fc0824a01 100644 --- a/src/registry/Registry.cpp +++ b/src/registry/Registry.cpp @@ -24,7 +24,9 @@ #include "terrain/TerrainTileRegistry.h" #include "mesh/TransformRegistry.h" + #include "text/FontRegistry.h" +#include "text/TextSystem.h" #include "registry/MaterialRegistry.h" #include "registry/NodeRegistry.h" @@ -84,6 +86,8 @@ void Registry::prepareShared() animation::AnimationSystem::get().prepare(); terrain::TerrrainTileRegistry::get().prepare(); + + text::TextSystem::get().prepare(); } void Registry::prepareWT() @@ -114,7 +118,7 @@ void Registry::updateWT(const UpdateContext& ctx) void Registry::updateRT(const UpdateContext& ctx) { ASSERT_RT(); - text::FontRegistry::get().updateRT(ctx); + mesh::TransformRegistry::get().updateRT(ctx); MaterialRegistry::get().updateRT(ctx); ModelRegistry::get().updateRT(ctx); @@ -123,6 +127,9 @@ void Registry::updateRT(const UpdateContext& ctx) particle::ParticleSystem::get().updateRT(ctx); animation::AnimationSystem::get().updateRT(ctx); terrain::TerrrainTileRegistry::get().updateRT(ctx); + + text::FontRegistry::get().updateRT(ctx); + text::TextSystem::get().updateRT(ctx); } void Registry::postRT(const UpdateContext& ctx) diff --git a/src/text/TextDraw.cpp b/src/text/TextDraw.cpp index 6ec1a9cf1..d15c2cd82 100644 --- a/src/text/TextDraw.cpp +++ b/src/text/TextDraw.cpp @@ -34,7 +34,8 @@ namespace mesh::TextMesh* mesh, text::FontAtlas* fontAtlas, std::string_view text, - glm::vec2& pen) + glm::vec2& pen, + size_t maxCount) { const auto penOrigin = pen; const glm::vec3 normal{ 0.f, 0.f, 1.f }; @@ -54,8 +55,11 @@ namespace const float glyphMaxW = m_glyph->s1 - m_glyph->s0; const float glyphMaxH = m_glyph->t1 - m_glyph->t0; + size_t textIndex = 0; // https://stackoverflow.com/questions/9438209/for-every-character-in-string for (const char& ch : text) { + if (textIndex >= maxCount) break; + float line_top = pen.y + line_ascender; if (ch == '\n') { @@ -129,6 +133,8 @@ namespace pen.x += glyph->advance_x; prev = &ch; + + textIndex++; } } } @@ -162,7 +168,7 @@ namespace text auto* font = text::FontRegistry::get().getFont(fontId); if (!font) return; - addText(mesh, font, text, pen); + addText(mesh, font, text, pen, mesh->m_reserveIndexCount); // HACK KI need to encode font somehow int drawOptions and/or VBO // => can use VBO, sinse are not shared mesh VBOs like in ModelRegistry diff --git a/src/text/TextSystem.cpp b/src/text/TextSystem.cpp new file mode 100644 index 000000000..3ea7a96b7 --- /dev/null +++ b/src/text/TextSystem.cpp @@ -0,0 +1,33 @@ +#include "TextSystem.h" + +#include "asset/Shader.h" + +#include "text/vao/TextVAO.h" + +namespace { + static text::TextSystem s_instance; +} + +namespace text +{ + text::TextSystem& TextSystem::get() noexcept + { + return s_instance; + } + + TextSystem::TextSystem() + : m_textVao{ std::make_unique("text") } + {} + + TextSystem::~TextSystem() = default; + + void TextSystem::prepare() + { + m_textVao->prepare(); + } + + void TextSystem::updateRT(const UpdateContext& ctx) + { + m_textVao->updateRT(); + } +} diff --git a/src/text/TextSystem.h b/src/text/TextSystem.h new file mode 100644 index 000000000..dcd28fa02 --- /dev/null +++ b/src/text/TextSystem.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include "util/Util.h" + +struct UpdateContext; + +namespace mesh { + class TextMesh; +} + +namespace text { + class TextVAO; + + class TextSystem { + public: + static text::TextSystem& get() noexcept; + + TextSystem(); + ~TextSystem(); + + void prepare(); + + void updateRT(const UpdateContext& ctx); + + text::TextVAO* getTextVAO() + { + return m_textVao.get(); + } + + private: + std::unique_ptr m_textVao; + }; +} diff --git a/src/text/vao/AtlasTextureVBO.cpp b/src/text/vao/AtlasTextureVBO.cpp index 3d7436f7a..4f755100c 100644 --- a/src/text/vao/AtlasTextureVBO.cpp +++ b/src/text/vao/AtlasTextureVBO.cpp @@ -1,8 +1,9 @@ #include "AtlasTextureVBO.h" #include "mesh/vao/VBO_impl.h" +#include "mesh/vao/TextureEntry.h" -namespace mesh { +namespace text { AtlasTextureVBO::AtlasTextureVBO( std::string_view name, int attr, @@ -10,7 +11,7 @@ namespace mesh { : VBO(name, attr, binding) {} - TextureEntry AtlasTextureVBO::convertVertex( + mesh::TextureEntry AtlasTextureVBO::convertVertex( const glm::vec2& vertex) { return { vertex }; @@ -18,10 +19,10 @@ namespace mesh { void AtlasTextureVBO::prepareVAO(kigl::GLVertexArray& vao) { - constexpr size_t sz = sizeof(TextureEntry); + constexpr size_t sz = sizeof(mesh::TextureEntry); { - m_entries.reserve(VERTEX_BLOCK_SIZE); - m_vbo.createEmpty(VERTEX_BLOCK_SIZE * sz, GL_DYNAMIC_STORAGE_BIT); + m_entries.reserve(mesh::VERTEX_BLOCK_SIZE); + m_vbo.createEmpty(mesh::VERTEX_BLOCK_SIZE * sz, GL_DYNAMIC_STORAGE_BIT); } { @@ -37,7 +38,7 @@ namespace mesh { // https://www.khronos.org/opengl/wiki/Vertex_Specification // // vertex attr - glVertexArrayAttribFormat(vao, m_attr, 2, GL_FLOAT, GL_FALSE, offsetof(TextureEntry, texCoord)); + glVertexArrayAttribFormat(vao, m_attr, 2, GL_FLOAT, GL_FALSE, offsetof(mesh::TextureEntry, texCoord)); glVertexArrayAttribBinding(vao, m_attr, m_binding); diff --git a/src/text/vao/AtlasTextureVBO.h b/src/text/vao/AtlasTextureVBO.h index 6f7a01307..8c2d9b78e 100644 --- a/src/text/vao/AtlasTextureVBO.h +++ b/src/text/vao/AtlasTextureVBO.h @@ -6,15 +6,15 @@ #include "mesh/vao/VBO.h" -namespace mesh { - class AtlasTextureVBO : public VBO { +namespace text { + class AtlasTextureVBO : public mesh::VBO { public: AtlasTextureVBO( std::string_view name, int attr, int binding); - virtual TextureEntry convertVertex( + virtual mesh::TextureEntry convertVertex( const glm::vec2& vertex) override; virtual void prepareVAO(kigl::GLVertexArray& vao) override; diff --git a/src/text/vao/TextVAO.cpp b/src/text/vao/TextVAO.cpp new file mode 100644 index 000000000..57c77c33a --- /dev/null +++ b/src/text/vao/TextVAO.cpp @@ -0,0 +1,53 @@ +#include "TextVAO.h" + +#include +#include + +#include "asset/Shader.h" + +#include "mesh/vao/TextureEntry.h" +#include "mesh/vao/VBO_impl.h" + +namespace text { + TextVAO::TextVAO(std::string_view name) + : mesh::TexturedVAO{ name }, + m_atlaxTexVbo{ "vbo_font", ATTR_FONT_ATLAS_TEX, VBO_FONT_ATLAS_BINDING } + {} + + TextVAO::~TextVAO() = default; + + void TextVAO::prepareVAO() + { + TexturedVAO::prepareVAO(); + + auto& vao = *m_vao; + + m_atlaxTexVbo.prepareVAO(vao); + } + + void TextVAO::clear() + { + TexturedVAO::clear(); + + m_atlaxTexVbo.clear(); + } + + uint32_t TextVAO::reserveAtlasCoords(size_t count) + { + return m_atlaxTexVbo.reserveVertices(count); + } + + void TextVAO::updateAtlasCoords( + uint32_t baseVbo, + std::span atlasCoords) + { + m_atlaxTexVbo.updateVertices(baseVbo, atlasCoords); + } + + void TextVAO::updateRT() + { + TexturedVAO::updateRT(); + + m_atlaxTexVbo.updateVAO(*m_vao); + } +} diff --git a/src/text/vao/TextVAO.h b/src/text/vao/TextVAO.h new file mode 100644 index 000000000..0afd797da --- /dev/null +++ b/src/text/vao/TextVAO.h @@ -0,0 +1,29 @@ +#pragma once + +#include "mesh/vao/TexturedVAO.h" + +#include "AtlasTextureVBO.h" + +namespace text { + class TextVAO : public mesh::TexturedVAO { + public: + TextVAO(std::string_view name); + ~TextVAO(); + + virtual void clear() override; + + virtual void updateRT() override; + + uint32_t reserveAtlasCoords(size_t count); + + void updateAtlasCoords( + uint32_t baseVbo, + std::span atlasCoords); + + protected: + virtual void prepareVAO() override; + + public: + text::AtlasTextureVBO m_atlaxTexVbo; + }; +} From 35471183419d3c41dc2ffc02b2d7bbc6b69cabf1 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sat, 22 Jun 2024 00:11:08 +0300 Subject: [PATCH 21/28] FIX billboard flag not working --- src/render/Batch.cpp | 11 ++++++++--- src/render/BatchCommand.h | 4 +++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/render/Batch.cpp b/src/render/Batch.cpp index c20b877e0..453dd2a7f 100644 --- a/src/render/Batch.cpp +++ b/src/render/Batch.cpp @@ -118,7 +118,8 @@ namespace render { } } - auto& lodInstances = top->m_lodInstances[{ &lodMesh.m_lod }]; + const LodKey lodKey{ &lodMesh.m_lod, drawOptions.m_flags }; + auto& lodInstances = top->m_lodInstances[lodKey]; lodInstances.reserve(100); lodInstances.emplace_back(entityIndex, lodMesh.m_meshIndex); m_pendingCount++; @@ -232,7 +233,7 @@ namespace render { } } - auto& lodInstances = top->m_lodInstances[{ &lodMesh.m_lod }]; + auto& lodInstances = top->m_lodInstances[{ &lodMesh.m_lod, drawOptions.m_flags }]; lodInstances.reserve(100); lodInstances.emplace_back(entityBaseIndex + i, lodMesh.m_meshIndex); m_pendingCount++; @@ -348,7 +349,11 @@ namespace render { instance.u_entityIndex = lodEntry.m_entityIndex; instance.u_meshIndex = lodEntry.m_meshIndex; instance.u_materialIndex = lod->m_materialIndex; - instance.u_shapeIndex = key.m_drawOptions.m_flags; + + // NOTE KI BatchKey does not take in account m_flags + // => can draw different instances in same batch + //instance.u_shapeIndex = key.m_drawOptions.m_flags; + instance.u_shapeIndex = lodInstance.first.m_flags; } } } diff --git a/src/render/BatchCommand.h b/src/render/BatchCommand.h index db3b0fedb..05f4e9b03 100644 --- a/src/render/BatchCommand.h +++ b/src/render/BatchCommand.h @@ -40,8 +40,10 @@ namespace render { struct LodKey { const backend::Lod* m_lod; + uint32_t m_flags; + bool operator<(const LodKey& o) const noexcept { - return *m_lod < *o.m_lod; + return std::tie(*m_lod, m_flags) < std::tie(*o.m_lod, o.m_flags); } }; From 2f51c35a0ebc4c107f2f6f5cf23b2e2c2e6879de Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sat, 22 Jun 2024 10:37:10 +0300 Subject: [PATCH 22/28] FIX missing asserts --- src/mesh/vao/SkinnedVAO.cpp | 6 ++++++ src/mesh/vao/TexturedVAO.cpp | 10 ++++++++++ src/text/vao/TextVAO.cpp | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/src/mesh/vao/SkinnedVAO.cpp b/src/mesh/vao/SkinnedVAO.cpp index 62df74f9b..e03d6ea81 100644 --- a/src/mesh/vao/SkinnedVAO.cpp +++ b/src/mesh/vao/SkinnedVAO.cpp @@ -3,6 +3,8 @@ #include #include +#include "util/thread.h" + #include "asset/Shader.h" #include "mesh/ModelMesh.h" @@ -37,6 +39,8 @@ namespace mesh { void SkinnedVAO::reserveVertexBones(size_t count) { + ASSERT_RT(); + m_boneVbo.reserveVertices(count); } @@ -44,6 +48,8 @@ namespace mesh { uint32_t baseVbo, std::span vertexBones) { + ASSERT_RT(); + m_boneVbo.updateVertices(baseVbo, vertexBones); } diff --git a/src/mesh/vao/TexturedVAO.cpp b/src/mesh/vao/TexturedVAO.cpp index 39ac5e3ef..407e9e781 100644 --- a/src/mesh/vao/TexturedVAO.cpp +++ b/src/mesh/vao/TexturedVAO.cpp @@ -32,6 +32,8 @@ namespace mesh { void TexturedVAO::prepare() { + ASSERT_RT(); + if (m_prepared) return; m_prepared = true; @@ -47,16 +49,22 @@ namespace mesh { void TexturedVAO::bind() { + ASSERT_RT(); + kigl::GLState::get().bindVAO(*m_vao); } void TexturedVAO::unbind() { + ASSERT_RT(); + kigl::GLState::get().bindVAO(0); } void TexturedVAO::prepareVAO() { + ASSERT_RT(); + auto& vao = *m_vao; m_positionVbo.prepareVAO(vao); @@ -67,6 +75,8 @@ namespace mesh { void TexturedVAO::clear() { + ASSERT_RT(); + m_positionVbo.clear(); m_normalVbo.clear(); m_textureVbo.clear(); diff --git a/src/text/vao/TextVAO.cpp b/src/text/vao/TextVAO.cpp index 57c77c33a..9f43049ab 100644 --- a/src/text/vao/TextVAO.cpp +++ b/src/text/vao/TextVAO.cpp @@ -3,6 +3,8 @@ #include #include +#include "util/thread.h" + #include "asset/Shader.h" #include "mesh/vao/TextureEntry.h" @@ -34,6 +36,8 @@ namespace text { uint32_t TextVAO::reserveAtlasCoords(size_t count) { + ASSERT_RT(); + return m_atlaxTexVbo.reserveVertices(count); } @@ -41,6 +45,8 @@ namespace text { uint32_t baseVbo, std::span atlasCoords) { + ASSERT_RT(); + m_atlaxTexVbo.updateVertices(baseVbo, atlasCoords); } From a44edb60c0b217a16cfb5c74be1ba57a6cf799d1 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sat, 22 Jun 2024 11:14:48 +0300 Subject: [PATCH 23/28] FIX dirty tracking for VBO/EBO buffer updates --- src/mesh/vao/VBO.h | 15 ++++++++--- src/mesh/vao/VBO_impl.h | 44 ++++++++++++++++++------------- src/mesh/vao/VertexIndexEBO.cpp | 46 +++++++++++++++++++++------------ src/mesh/vao/VertexIndexEBO.h | 10 ++++++- 4 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/mesh/vao/VBO.h b/src/mesh/vao/VBO.h index e80195b55..9da003631 100644 --- a/src/mesh/vao/VBO.h +++ b/src/mesh/vao/VBO.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include @@ -26,6 +28,8 @@ namespace mesh { virtual ~VBO(); + void clear(); + // @return base *index* into entries uint32_t reserveVertices(size_t count); @@ -42,13 +46,17 @@ namespace mesh { void updateVAO(kigl::GLVertexArray& vao); - void clear(); - // @return base *index* into buffer (for next new entry) uint32_t getBaseIndex() const noexcept { return static_cast(m_entries.size()); } + protected: + bool updateSpan( + kigl::GLVertexArray& vao, + size_t updateIndex, + size_t updateCount); + protected: const int m_binding; const int m_attr; @@ -56,10 +64,11 @@ namespace mesh { bool m_prepared{ false }; kigl::GLBuffer m_vbo; - size_t m_lastSize{ 0 }; kigl::GLVertexArray* m_vao{ nullptr }; + std::vector> m_dirty; + std::vector m_entries; }; } diff --git a/src/mesh/vao/VBO_impl.h b/src/mesh/vao/VBO_impl.h index a85dea40b..c25f16631 100644 --- a/src/mesh/vao/VBO_impl.h +++ b/src/mesh/vao/VBO_impl.h @@ -24,6 +24,13 @@ namespace mesh { VBO::~VBO() {} + template + void VBO::clear() + { + m_entries.clear(); + m_dirty.clear(); + } + template uint32_t VBO::reserveVertices(size_t count) { @@ -48,10 +55,7 @@ namespace mesh { index++; } - // NOTE KI not optimal at all, should handle each case as separate dirty span - if (m_lastSize > baseIndex) { - m_lastSize = baseIndex; - } + m_dirty.push_back({baseIndex, vertices.size()}); } template @@ -66,38 +70,42 @@ namespace mesh { template void VBO::updateVAO(kigl::GLVertexArray& vao) { - const size_t index = m_lastSize; + if (m_dirty.empty()) return; + + for (const auto& range : m_dirty) { + if (updateSpan(vao, range.first, range.second)) break; + } + + m_dirty.clear(); + } + + template + bool VBO::updateSpan( + kigl::GLVertexArray & vao, + size_t updateIndex, + size_t updateCount) + { const size_t totalCount = m_entries.size(); - if (index == totalCount) return; - if (totalCount == 0) return; + if (totalCount == 0) return true; { constexpr size_t sz = sizeof(T_Entry); - size_t updateIndex = index; // NOTE KI *reallocate* SSBO if needed if (m_vbo.m_size < totalCount * sz) { m_vbo.resizeBuffer(m_entries.capacity() * sz); glVertexArrayVertexBuffer(vao, m_binding, m_vbo, 0, sz); updateIndex = 0; + updateCount = totalCount; } - const size_t updateCount = totalCount - updateIndex; - m_vbo.update( updateIndex * sz, updateCount * sz, &m_entries[updateIndex]); } - m_lastSize = totalCount; - } - - template - void VBO::clear() - { - m_entries.clear(); - m_lastSize = 0; + return updateCount == totalCount; } } diff --git a/src/mesh/vao/VertexIndexEBO.cpp b/src/mesh/vao/VertexIndexEBO.cpp index 0ecac3f95..f927e11e0 100644 --- a/src/mesh/vao/VertexIndexEBO.cpp +++ b/src/mesh/vao/VertexIndexEBO.cpp @@ -15,8 +15,17 @@ namespace mesh { : m_ebo{ name } {} + void VertexIndexEBO::clear() + { + m_entries.clear(); + m_dirty.clear(); + } + + uint32_t VertexIndexEBO::reserveIndeces(size_t count) { + if (count == 0) return 0; + const size_t baseIndex = m_entries.size(); if (m_entries.size() + count >= MAX_INDEX_COUNT) @@ -40,21 +49,14 @@ namespace mesh { { assert(baseIndex + indeces.size() <= m_entries.size()); + if (indeces.size() == 0) return; + std::copy( indeces.begin(), indeces.end(), m_entries.begin() + baseIndex); - // NOTE KI not optimal at all, should handle each case as separate dirty span - if (m_lastSize > baseIndex) { - m_lastSize = baseIndex; - } - } - - void VertexIndexEBO::clear() - { - m_entries.clear(); - m_lastSize = 0; + m_dirty.push_back({ baseIndex, indeces.size() }); } void VertexIndexEBO::prepareVAO(kigl::GLVertexArray& vao) @@ -68,25 +70,35 @@ namespace mesh { void VertexIndexEBO::updateVAO(kigl::GLVertexArray& vao) { - const size_t index = m_lastSize; + if (m_dirty.empty()) return; + + for (const auto& range : m_dirty) { + if (updateSpan(vao, range.first, range.second)) break; + } + + m_dirty.clear(); + } + + bool VertexIndexEBO::updateSpan( + kigl::GLVertexArray& vao, + size_t updateIndex, + size_t updateCount) + { const size_t totalCount = m_entries.size(); - if (index == totalCount) return; - if (totalCount == 0) return; + if (totalCount == 0) return true; { constexpr size_t sz = sizeof(IndexEntry); - size_t updateIndex = index; // NOTE KI *reallocate* SSBO if needed if (m_ebo.m_size < totalCount * sz) { m_ebo.resizeBuffer(m_entries.capacity() * sz); glVertexArrayElementBuffer(vao, m_ebo); updateIndex = 0; + updateCount = totalCount; } - const size_t updateCount = totalCount - updateIndex; - //m_ebo.invalidateRange( // updateIndex * sz, // updateCount * sz); @@ -97,6 +109,6 @@ namespace mesh { &m_entries[updateIndex]); } - m_lastSize = totalCount; + return updateCount == totalCount; } } diff --git a/src/mesh/vao/VertexIndexEBO.h b/src/mesh/vao/VertexIndexEBO.h index 0199aa9b3..f7a18d17c 100644 --- a/src/mesh/vao/VertexIndexEBO.h +++ b/src/mesh/vao/VertexIndexEBO.h @@ -2,6 +2,8 @@ #include #include +#include +#include #include "kigl/GLBuffer.h" @@ -32,10 +34,16 @@ namespace mesh void prepareVAO(kigl::GLVertexArray& vao); void updateVAO(kigl::GLVertexArray& vao); + protected: + bool updateSpan( + kigl::GLVertexArray& vao, + size_t updateIndex, + size_t updateCount); + private: kigl::GLBuffer m_ebo; + std::vector < std::pair> m_dirty; std::vector m_entries; - size_t m_lastSize = 0; }; } From 42158bf2e6ebc521e923ab2c33771eede6f93241 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sat, 22 Jun 2024 11:22:54 +0300 Subject: [PATCH 24/28] FIX text volume centered to text itself --- src/generator/TextGenerator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/generator/TextGenerator.cpp b/src/generator/TextGenerator.cpp index 61358aba6..acbd825f1 100644 --- a/src/generator/TextGenerator.cpp +++ b/src/generator/TextGenerator.cpp @@ -64,7 +64,8 @@ void TextGenerator::updateEntity( auto& snapshot = snapshotRegistry.modifySnapshot(container.m_snapshotIndex); auto* entity = entityRegistry.modifyEntity(container.m_entityIndex, true); - const glm::vec4 volume{ 0.f, 0.f, 0.f, m_aabb.getVolume().w }; + //const glm::vec4 volume{ 0.f, 0.f, 0.f, m_aabb.getVolume().w }; + const glm::vec4& volume = m_aabb.getVolume(); transform.setVolume(volume); snapshot.m_volume = volume; From baf9f87c8673a0d02a9a8858e083fc3dccd13219 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sun, 23 Jun 2024 12:18:31 +0300 Subject: [PATCH 25/28] FIX clones share material - sharing material for non-clones is errorprone; not supported for now --- scene/scene_airboat.yml | 8 +++++--- scene/scene_audio.yml | 2 +- scene/scene_full.yml | 25 +++++++++++-------------- scene/scene_lucy.yml | 2 +- scene/scene_mirrors.yml | 4 ++-- scene/scene_origo.yml | 4 ++-- scene/scene_particle.yml | 2 +- scene/scene_physics.yml | 2 +- scene/scene_player.yml | 2 +- scene/scene_pool.yml | 4 ++-- scene/scene_pool_side.yml | 2 +- src/loader/SceneLoader.cpp | 2 +- src/render/BatchCommand.h | 3 ++- 13 files changed, 31 insertions(+), 31 deletions(-) diff --git a/scene/scene_airboat.yml b/scene/scene_airboat.yml index 90e39fd08..2e058a7f4 100644 --- a/scene/scene_airboat.yml +++ b/scene/scene_airboat.yml @@ -33,11 +33,13 @@ entities: tiling: 5 program: g_tex pos: [0.0, 0.0, -20.0] - - name: Airboat + - id: airboat_{t}_{c} mesh: path: airboat_fixed_colors program: g_tex - pos: [0.0, 0.0, 0.0] + clones: + - pos: [0.0, 0.0, 0.0] + - pos: [20.0, 00.0, 0.0] - name: Directional light type: origo pos: [0, 25, 25] @@ -45,7 +47,7 @@ entities: type: directional diffuse: [0.9, 0.9, 0.7, 1.0] intensity: 40000 - - name: Giant wooden box + - id: giant_wooden_box_{t}_{c} mesh: path: quad material: diff --git a/scene/scene_audio.yml b/scene/scene_audio.yml index 8c8236462..82e2fbced 100644 --- a/scene/scene_audio.yml +++ b/scene/scene_audio.yml @@ -48,7 +48,7 @@ entities: reference_distance: 6 xautoplay: true xlooping: true - - name: Four cubes + - id: four_cubes_{t}_{c} mesh: path: texture_cube_3 program: g_tex diff --git a/scene/scene_full.yml b/scene/scene_full.yml index 8df42843e..f7f840c8c 100644 --- a/scene/scene_full.yml +++ b/scene/scene_full.yml @@ -124,7 +124,7 @@ entities: target_id: dir-light-target diffuse: [0.4, 0.4, 0.4, 1.0] intensity: 20000 - - name: Moving point light origo + - id: moving_point_light_origo_{t}_{c} parent_id: zero-origo type: origo pos: [0, 14, 0] @@ -146,7 +146,7 @@ entities: - pos: [25.0, 10.0, 25.0] id: light-8 script_file: scripts/anim_moving_point_light - - id: moving_point_light_{c} + - id: moving_point_light_{t}_{c} desc: "NOTE overriding material in clones is *NOT* supported" parent_id: zero-origo mesh: @@ -463,18 +463,15 @@ entities: render_flags: mirror: true script_file: scripts/anim_mirror - - name: Airboat + - id: airboat_{t}_{c} mesh: path: airboat_fixed_colors program: g_tex - pos: [24.0, 11.0, 15.0] scale: 1.0 - - name: Airboat 2 - mesh: - path: airboat_fixed_colors - program: g_tex - pos: [6.0, 19.0, 22.0] - scale: 0.5 + clones: + - pos: [24.0, 11.0, 15.0] + - pos: [6.0, 19.0, 22.0] + scale: 0.5 - xid: spyro mesh: path: spyro2 @@ -772,7 +769,7 @@ entities: program: g_tex pos: [5.0, 25.0, 5.0] scale: 1 - - id: four_cubes_{c} + - id: four_cubes_{t}_{c} mesh: path: texture_cube_3 program: g_tex @@ -791,7 +788,7 @@ entities: id: cube-3 - pos: [5.0, 20.0, 5.0] id: cube-4 - - id: blend_cubes_{c} + - id: blend_cubes_{t}_{c} mesh: path: rubik_cube.fbx material_modifier: @@ -869,7 +866,7 @@ entities: geom: type: plane rot: [0, 0, 0] - - id: pool_side_{c} + - id: pool_side_{t}_{c} mesh: path: pool_brick material_modifier: @@ -1297,7 +1294,7 @@ entities: type: capsule size: [0.9, 4, 0] script_file: scripts/seq_skeleton_army - - xid: giant_wooden_box_{c} + - xid: giant_wooden_box_{t}_{c} mesh: path: quad material: diff --git a/scene/scene_lucy.yml b/scene/scene_lucy.yml index 782d0fdf8..a5bf32533 100644 --- a/scene/scene_lucy.yml +++ b/scene/scene_lucy.yml @@ -76,7 +76,7 @@ entities: no_shadow: true water: true script_file: scripts/anim_water_lucy - - name: Pool side + - id: pool_side_{t}_{c} mesh: path: pool_brick material_modifier: diff --git a/scene/scene_mirrors.yml b/scene/scene_mirrors.yml index d7ea4f5ef..66805076a 100644 --- a/scene/scene_mirrors.yml +++ b/scene/scene_mirrors.yml @@ -58,7 +58,7 @@ entities: program: g_tex pos: [5.0, 5.0, -5.0] scale: 1 - - name: Four cubes + - id: four_cubes_{t}_{c} mesh: path: texture_cube_3 program: g_tex @@ -134,7 +134,7 @@ entities: repeat: x_count: 2 x_step: 4 - - name: Giant wooden box + - id: giant_wooden_box_{t}_{c} mesh: path: quad material: diff --git a/scene/scene_origo.yml b/scene/scene_origo.yml index 4ea4dcab4..60b2767bc 100644 --- a/scene/scene_origo.yml +++ b/scene/scene_origo.yml @@ -67,7 +67,7 @@ entities: pos: [5.0, 5.0, -5.0] scale: 1 enabled: false - - name: Four cubes + - id: four_cubes_{t}_{c} mesh: path: texture_cube_3 material_modifier: @@ -146,7 +146,7 @@ entities: x_count: 2 x_step: 4 enabled: false - - name: Giant wooden box + - id: giant_wooden_box_{t}_{c} mesh: path: quad material: diff --git a/scene/scene_particle.yml b/scene/scene_particle.yml index b81f48ddf..a532c5f46 100644 --- a/scene/scene_particle.yml +++ b/scene/scene_particle.yml @@ -74,7 +74,7 @@ entities: sprites_x: 8 texture_spec: wrap: GL_CLAMP_TO_EDGE - - id: four_cubes_{c} + - id: four_cubes_{t}_{c} mesh: path: texture_cube_3 program: g_tex diff --git a/scene/scene_physics.yml b/scene/scene_physics.yml index 76d74cde4..4dc9f66c6 100644 --- a/scene/scene_physics.yml +++ b/scene/scene_physics.yml @@ -301,7 +301,7 @@ entities: - id: cube_origo type: origo pos: [0.0, 30.0, 0.0] - - name: Four cubes + - id: four_cubes_{t}_{c} parent_id: cube_origo mesh: path: texture_cube_3 diff --git a/scene/scene_player.yml b/scene/scene_player.yml index 9bdc21997..a0404cc03 100644 --- a/scene/scene_player.yml +++ b/scene/scene_player.yml @@ -34,7 +34,7 @@ entities: type: camera_zoom camera: default: true - - id: four_cubes_{c} + - id: four_cubes_{t}_{c} mesh: path: texture_cube_3 program: g_tex diff --git a/scene/scene_pool.yml b/scene/scene_pool.yml index c8de6ef65..bf98e74e4 100644 --- a/scene/scene_pool.yml +++ b/scene/scene_pool.yml @@ -130,7 +130,7 @@ entities: y_step: 0 z_step: 60 script_file: scripts/anim_water - - name: Pool side + - id: pool_side_{t}_{c} mesh: path: pool_brick material_modifier: @@ -363,7 +363,7 @@ entities: no_shadow: true water: true xxscript_file: scripts/cycle_water - - name: Pool side - SINGLE + - id: pool_side_single_{t}_{c} mesh: path: pool_brick material_modifier: diff --git a/scene/scene_pool_side.yml b/scene/scene_pool_side.yml index c06d4c664..79a77a79e 100644 --- a/scene/scene_pool_side.yml +++ b/scene/scene_pool_side.yml @@ -20,7 +20,7 @@ entities: default: true controllers: - type: camera_zoom - - name: Pool side + - id: pool_side_{t}_{c} mesh: path: pool_brick material_modifier: diff --git a/src/loader/SceneLoader.cpp b/src/loader/SceneLoader.cpp index b56bcfa66..73feb83d6 100644 --- a/src/loader/SceneLoader.cpp +++ b/src/loader/SceneLoader.cpp @@ -448,7 +448,7 @@ namespace loader { { auto typeHandle = pool::TypeHandle::allocate(); auto* type = typeHandle.toType(); - type->setName(entityData.baseId.m_path); + type->setName(entityData.baseId.m_path.empty() ? entityData.name : entityData.baseId.m_path); assignTypeFlags(entityData, typeHandle); diff --git a/src/render/BatchCommand.h b/src/render/BatchCommand.h index 05f4e9b03..ea9fbf796 100644 --- a/src/render/BatchCommand.h +++ b/src/render/BatchCommand.h @@ -43,7 +43,8 @@ namespace render { uint32_t m_flags; bool operator<(const LodKey& o) const noexcept { - return std::tie(*m_lod, m_flags) < std::tie(*o.m_lod, o.m_flags); + return std::tie( m_lod->m_baseVertex, m_lod->m_baseIndex, m_lod->m_materialIndex, m_flags) < + std::tie(o.m_lod->m_baseVertex, o.m_lod->m_baseIndex, o.m_lod->m_materialIndex, o.m_flags); } }; From db0b80c6d8edf9aeb4ffa12229985b9aa3de73fc Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sun, 23 Jun 2024 13:42:49 +0300 Subject: [PATCH 26/28] FIX cleanup of logic - tesselation == patches --- scene/scene_full.yml | 8 +++++--- src/backend/DrawBuffer.cpp | 7 +++---- src/backend/DrawOptions.h | 7 +++---- src/mesh/LodMesh.cpp | 3 +-- src/mesh/Mesh.h | 5 +---- src/mesh/MeshFlags.h | 1 + src/mesh/MeshType.cpp | 2 +- src/mesh/ModelMesh.cpp | 9 +++------ src/mesh/ModelMesh.h | 5 +---- src/mesh/QuadMesh.cpp | 7 ++----- src/mesh/QuadMesh.h | 5 +---- src/mesh/TextMesh.cpp | 7 ++----- src/mesh/TextMesh.h | 5 +---- src/render/BatchCommand.h | 4 ++-- src/terrain/TerrainGenerator.cpp | 3 ++- 15 files changed, 29 insertions(+), 49 deletions(-) diff --git a/scene/scene_full.yml b/scene/scene_full.yml index f7f840c8c..641328e16 100644 --- a/scene/scene_full.yml +++ b/scene/scene_full.yml @@ -589,7 +589,7 @@ entities: sprites_x: 9 texture_spec: wrap: GL_CLAMP_TO_EDGE - - name: Cow + - id: cow_{t}_{c} mesh: path: cow material: @@ -598,11 +598,13 @@ entities: map_pbr: textures/Plastic 01 [4K] xreflection: 0.4 program: g_tex - pos: [5.0, 25.0, -5.0] rotation: [0, 180, 0] scale: 0.8 xrender_flags: selected: false + clones: + - pos: [5.0, 25.0, -5.0] + - pos: [5.0, 25.0, -15.0] - xname: Cow fur mesh: path: cow @@ -620,7 +622,7 @@ entities: rotation: [0, 180, 0] scale: 0.8 xrender_flags: - - name: Cow 2 + - xname: Cow 2 mesh: path: cow material_modifier: diff --git a/src/backend/DrawBuffer.cpp b/src/backend/DrawBuffer.cpp index 200cb6c60..028b0dab5 100644 --- a/src/backend/DrawBuffer.cpp +++ b/src/backend/DrawBuffer.cpp @@ -224,8 +224,7 @@ namespace backend { cd.m_wireframe == sd.m_wireframe && cd.m_blend == sd.m_blend && cd.m_mode == sd.m_mode && - cd.m_type == sd.m_type && - cd.m_tessellation == sd.m_tessellation; + cd.m_type == sd.m_type; } if (!sameDraw) { @@ -377,8 +376,8 @@ namespace backend { auto& state = kigl::GLState::get(); const auto& drawOptions = drawRange.m_drawOptions; - state.useProgram(*drawRange.m_program); state.bindVAO(*drawRange.m_vao); + state.useProgram(*drawRange.m_program); state.setEnabled(GL_CULL_FACE, !drawOptions.m_renderBack); @@ -386,7 +385,7 @@ namespace backend { state.polygonFrontAndBack(wireframe ? GL_LINE : GL_FILL); - if (drawOptions.m_tessellation) { + if (drawOptions.m_mode == DrawOptions::Mode::patches) { glPatchParameteri(GL_PATCH_VERTICES, drawOptions.m_patchVertices); } diff --git a/src/backend/DrawOptions.h b/src/backend/DrawOptions.h index aaf56445c..9573a61e8 100644 --- a/src/backend/DrawOptions.h +++ b/src/backend/DrawOptions.h @@ -10,6 +10,8 @@ namespace backend { struct DrawOptions { enum class Mode : std::underlying_type_t { points, + // NOTE KI https://www.khronos.org/opengl/wiki/Primitive + // patches == tessellation patches, triangles, triangle_strip, @@ -36,8 +38,6 @@ namespace backend { bool m_renderBack : 1 {false}; bool m_wireframe : 1 {false}; - bool m_tessellation : 1 {false}; - bool m_gbuffer : 1 {false}; uint8_t m_flags : 3 { 0 }; @@ -75,8 +75,7 @@ namespace backend { (forceWireframe ? true : m_wireframe == o.m_wireframe) && (forceSolid ? true : m_blend == o.m_blend) && m_mode == o.m_mode && - m_type == o.m_type && - m_tessellation == o.m_tessellation; + m_type == o.m_type; } // NOTE KI for MeshTypeKey diff --git a/src/mesh/LodMesh.cpp b/src/mesh/LodMesh.cpp index 382628698..23f38c55c 100644 --- a/src/mesh/LodMesh.cpp +++ b/src/mesh/LodMesh.cpp @@ -218,8 +218,7 @@ namespace mesh { { if (m_mesh) { m_vao = m_mesh->prepareRT(ctx); - m_mesh->prepareLod(*this); - m_mesh->prepareDrawOptions(m_drawOptions); + m_mesh->prepareLodMesh(*this); if (m_flags.billboard) m_drawOptions.m_flags |= INSTANCE_BILLBOARD_BIT; } diff --git a/src/mesh/Mesh.h b/src/mesh/Mesh.h index 4e3596cb1..572815a21 100644 --- a/src/mesh/Mesh.h +++ b/src/mesh/Mesh.h @@ -47,12 +47,9 @@ namespace mesh { virtual const kigl::GLVertexArray* prepareRT( const PrepareContext& ctx) = 0; - virtual void prepareLod( + virtual void prepareLodMesh( mesh::LodMesh& lodMesh) = 0; - virtual void prepareDrawOptions( - backend::DrawOptions& drawOptions) = 0; - void setAABB(const AABB& aabb) { m_aabb = aabb; } diff --git a/src/mesh/MeshFlags.h b/src/mesh/MeshFlags.h index b642cd397..a014fe14f 100644 --- a/src/mesh/MeshFlags.h +++ b/src/mesh/MeshFlags.h @@ -3,5 +3,6 @@ namespace mesh { struct MeshFlags { bool billboard : 1 {false}; + bool tessellation : 1 {false}; }; } diff --git a/src/mesh/MeshType.cpp b/src/mesh/MeshType.cpp index 79927d260..5e20c9bed 100644 --- a/src/mesh/MeshType.cpp +++ b/src/mesh/MeshType.cpp @@ -116,7 +116,7 @@ namespace mesh { m_preparedRT = true; for (auto& lodMesh : *m_lodMeshes) { - lodMesh.m_drawOptions.m_tessellation = m_flags.tessellation; + lodMesh.m_flags.tessellation = m_flags.tessellation; lodMesh.prepareRT(ctx); } diff --git a/src/mesh/ModelMesh.cpp b/src/mesh/ModelMesh.cpp index b689d5f12..e303fd464 100644 --- a/src/mesh/ModelMesh.cpp +++ b/src/mesh/ModelMesh.cpp @@ -100,7 +100,7 @@ namespace mesh { return m_vao; } - void ModelMesh::prepareLod( + void ModelMesh::prepareLodMesh( mesh::LodMesh& lodMesh) { auto& lod = lodMesh.m_lod; @@ -108,13 +108,10 @@ namespace mesh { lod.m_baseVertex = getBaseVertex(); lod.m_baseIndex = getBaseIndex(); lod.m_indexCount = getIndexCount(); - } - void ModelMesh::prepareDrawOptions( - backend::DrawOptions& drawOptions) - { + auto& drawOptions = lodMesh.m_drawOptions; drawOptions.m_type = backend::DrawOptions::Type::elements; - drawOptions.m_mode = drawOptions.m_tessellation + drawOptions.m_mode = lodMesh.m_flags.tessellation ? backend::DrawOptions::Mode::patches : backend::DrawOptions::Mode::triangles; } diff --git a/src/mesh/ModelMesh.h b/src/mesh/ModelMesh.h index bd6e70a42..126321060 100644 --- a/src/mesh/ModelMesh.h +++ b/src/mesh/ModelMesh.h @@ -39,12 +39,9 @@ namespace mesh { virtual const kigl::GLVertexArray* prepareRT( const PrepareContext& ctx) override; - virtual void prepareLod( + virtual void prepareLodMesh( mesh::LodMesh& lodMesh); - virtual void prepareDrawOptions( - backend::DrawOptions& drawOptions) override; - uint32_t getBaseVertex() const noexcept { return m_vboIndex; } diff --git a/src/mesh/QuadMesh.cpp b/src/mesh/QuadMesh.cpp index 148481a08..37dc15279 100644 --- a/src/mesh/QuadMesh.cpp +++ b/src/mesh/QuadMesh.cpp @@ -54,15 +54,12 @@ namespace mesh { return m_vao; } - void QuadMesh::prepareLod( + void QuadMesh::prepareLodMesh( mesh::LodMesh& lodMesh) { lodMesh.m_lod.m_indexCount = INDEX_COUNT; - } - void QuadMesh::prepareDrawOptions( - backend::DrawOptions& drawOptions) - { + auto& drawOptions = lodMesh.m_drawOptions; drawOptions.m_type = backend::DrawOptions::Type::arrays; drawOptions.m_mode = backend::DrawOptions::Mode::triangle_strip; } diff --git a/src/mesh/QuadMesh.h b/src/mesh/QuadMesh.h index 12ffcc4ed..782f21c27 100644 --- a/src/mesh/QuadMesh.h +++ b/src/mesh/QuadMesh.h @@ -20,12 +20,9 @@ namespace mesh { virtual const kigl::GLVertexArray* prepareRT( const PrepareContext& ctx) override; - virtual void prepareLod( + virtual void prepareLodMesh( mesh::LodMesh& lodMesh) override; - virtual void prepareDrawOptions( - backend::DrawOptions& drawOptions) override; - protected: std::vector m_material; diff --git a/src/mesh/TextMesh.cpp b/src/mesh/TextMesh.cpp index 1d89eb716..4b8da986c 100644 --- a/src/mesh/TextMesh.cpp +++ b/src/mesh/TextMesh.cpp @@ -74,7 +74,7 @@ namespace mesh { return m_vao; } - void TextMesh::prepareLod( + void TextMesh::prepareLodMesh( mesh::LodMesh& lodMesh) { auto& lod = lodMesh.m_lod; @@ -82,11 +82,8 @@ namespace mesh { lod.m_baseVertex = getBaseVertex(); lod.m_baseIndex = getBaseIndex(); lod.m_indexCount = getIndexCount(); - } - void TextMesh::prepareDrawOptions( - backend::DrawOptions& drawOptions) - { + auto& drawOptions = lodMesh.m_drawOptions; drawOptions.m_type = backend::DrawOptions::Type::elements; drawOptions.m_mode = backend::DrawOptions::Mode::triangles; } diff --git a/src/mesh/TextMesh.h b/src/mesh/TextMesh.h index 722a6c2c3..84c834811 100644 --- a/src/mesh/TextMesh.h +++ b/src/mesh/TextMesh.h @@ -24,12 +24,9 @@ namespace mesh { virtual const kigl::GLVertexArray* prepareRT( const PrepareContext& ctx) override; - virtual void prepareLod( + virtual void prepareLodMesh( mesh::LodMesh& lodMesh) override; - virtual void prepareDrawOptions( - backend::DrawOptions& drawOptions) override; - uint32_t getBaseVertex() const noexcept { return m_vboIndex; } diff --git a/src/render/BatchCommand.h b/src/render/BatchCommand.h index ea9fbf796..aba980298 100644 --- a/src/render/BatchCommand.h +++ b/src/render/BatchCommand.h @@ -30,8 +30,8 @@ namespace render { bool operator<(const BatchKey& o) const noexcept; - const Program* m_program{ nullptr }; - const kigl::GLVertexArray* m_vao{ nullptr }; + const Program* m_program; + const kigl::GLVertexArray* m_vao; backend::DrawOptions m_drawOptions; diff --git a/src/terrain/TerrainGenerator.cpp b/src/terrain/TerrainGenerator.cpp index 678096497..5093c5b6f 100644 --- a/src/terrain/TerrainGenerator.cpp +++ b/src/terrain/TerrainGenerator.cpp @@ -293,7 +293,8 @@ namespace terrain { lodMesh->m_shadowProgram = m_material.getProgram(MaterialProgramType::shadow); lodMesh->m_preDepthProgram = m_material.getProgram(MaterialProgramType::pre_depth); - lodMesh->m_drawOptions.m_tessellation = true; + lodMesh->m_flags.tessellation = true; + lodMesh->m_drawOptions.m_mode = backend::DrawOptions::Mode::patches; lodMesh->m_drawOptions.m_patchVertices = 3; } } From c0d6e21562db74e7705e7ca3f919c15fc706ab3b Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sun, 23 Jun 2024 14:46:35 +0300 Subject: [PATCH 27/28] FIX multidraw batching logic fixes - MUST keep baseIndeces per multidraw - strange artifacts happen if not - much more efficient batching with multidraw --- scene/assets.yml | 4 ++-- src/mesh/Mesh.h | 3 --- src/mesh/TextMesh.cpp | 15 +++++-------- src/mesh/TextMesh.h | 2 ++ src/render/Batch.cpp | 45 +++++++++++++++++-------------------- src/render/BatchCommand.cpp | 18 +++++++++++++++ src/render/BatchCommand.h | 29 +++++++++++++++++------- src/render/NodeDraw.cpp | 2 +- src/text/TextDraw.cpp | 2 +- 9 files changed, 72 insertions(+), 48 deletions(-) diff --git a/scene/assets.yml b/scene/assets.yml index b35f98630..aec6535f8 100644 --- a/scene/assets.yml +++ b/scene/assets.yml @@ -104,8 +104,8 @@ assets: terrain_grid_size: 64 - batch_size: 1000 - batch_buffers: 300 + batch_size: 50 + batch_buffers: 200 batch_debug: false draw_debug: false diff --git a/src/mesh/Mesh.h b/src/mesh/Mesh.h index 572815a21..13475f02a 100644 --- a/src/mesh/Mesh.h +++ b/src/mesh/Mesh.h @@ -76,9 +76,6 @@ namespace mesh { glm::mat4 m_animationBaseTransform{ 1.f }; - uint32_t m_reserveVertexCount{ 0 }; - uint32_t m_reserveIndexCount{ 0 }; - protected: bool m_prepared{ false }; diff --git a/src/mesh/TextMesh.cpp b/src/mesh/TextMesh.cpp index 4b8da986c..da010a732 100644 --- a/src/mesh/TextMesh.cpp +++ b/src/mesh/TextMesh.cpp @@ -14,6 +14,7 @@ namespace { + constexpr uint32_t DEF_SIZE = 100; } namespace mesh { @@ -56,18 +57,14 @@ namespace mesh { text::TextVAO* vao = text::TextSystem::get().getTextVAO(); - if (m_reserveVertexCount <= 0) { - m_reserveVertexCount = 100 * 4; + if (m_maxSize == 0) { + m_maxSize = DEF_SIZE; } - if (m_reserveIndexCount <= 0) { - m_reserveIndexCount = 100 * 2; - } - - m_vboIndex = vao->reserveVertices(m_reserveVertexCount); - vao->reserveAtlasCoords(m_reserveVertexCount); + m_vboIndex = vao->reserveVertices(m_maxSize * 4); + vao->reserveAtlasCoords(m_maxSize * 4); - m_eboIndex = vao->reserveIndeces(m_reserveIndexCount); + m_eboIndex = vao->reserveIndeces(m_maxSize * 2); m_vao = vao->getVAO(); diff --git a/src/mesh/TextMesh.h b/src/mesh/TextMesh.h index 84c834811..d4ffcf111 100644 --- a/src/mesh/TextMesh.h +++ b/src/mesh/TextMesh.h @@ -45,6 +45,8 @@ namespace mesh { std::vector m_atlasCoords; + uint32_t m_maxSize{ 0 }; + // NOTE KI absolute index into VBO uint32_t m_vboIndex{ 0 }; diff --git a/src/render/Batch.cpp b/src/render/Batch.cpp index 453dd2a7f..bb184073d 100644 --- a/src/render/Batch.cpp +++ b/src/render/Batch.cpp @@ -19,7 +19,6 @@ #include "backend/gl/DrawIndirectCommand.h" #include "backend/DrawRange.h" #include "backend/DrawBuffer.h" -#include "backend/Lod.h" #include "mesh/LodMesh.h" #include "mesh/MeshType.h" @@ -118,10 +117,10 @@ namespace render { } } - const LodKey lodKey{ &lodMesh.m_lod, drawOptions.m_flags }; + const LodKey lodKey{ lodMesh.m_lod, drawOptions.m_flags }; auto& lodInstances = top->m_lodInstances[lodKey]; lodInstances.reserve(100); - lodInstances.emplace_back(entityIndex, lodMesh.m_meshIndex); + lodInstances.emplace_back(entityIndex, lodMesh.m_meshIndex, lodMesh.m_lod.m_materialIndex); m_pendingCount++; } } @@ -233,9 +232,10 @@ namespace render { } } - auto& lodInstances = top->m_lodInstances[{ &lodMesh.m_lod, drawOptions.m_flags }]; + const LodKey lodKey{ lodMesh.m_lod, drawOptions.m_flags }; + auto& lodInstances = top->m_lodInstances[lodKey]; lodInstances.reserve(100); - lodInstances.emplace_back(entityBaseIndex + i, lodMesh.m_meshIndex); + lodInstances.emplace_back(entityBaseIndex + i, lodMesh.m_meshIndex, lodMesh.m_lod.m_materialIndex); m_pendingCount++; } } @@ -321,6 +321,8 @@ namespace render { } m_entityIndeces.clear(); m_pendingCount = 0; + + //m_batches.clear(); } size_t Batch::flush( @@ -328,27 +330,23 @@ namespace render { { size_t flushCount = 0; - std::map> programLodBaseIndex; - { m_entityIndeces.clear(); - for (const auto& it : m_batches) { + for (auto& it : m_batches) { const auto& key = it.first; - const auto& curr = it.second; - - auto& lodBaseIndex = programLodBaseIndex[key.m_program]; + auto& curr = it.second; for (const auto& lodInstance : curr.m_lodInstances) { - const auto* lod = lodInstance.first.m_lod; + const auto& lodKey = lodInstance.first; const auto& lodEntries = lodInstance.second; if (lodEntries.empty()) continue; - lodBaseIndex[lodInstance.first] = static_cast(m_entityIndeces.size()); + curr.m_baseIndeces[lodInstance.first] = static_cast(m_entityIndeces.size()); for (auto& lodEntry : lodEntries) { auto& instance = m_entityIndeces.emplace_back(); instance.u_entityIndex = lodEntry.m_entityIndex; instance.u_meshIndex = lodEntry.m_meshIndex; - instance.u_materialIndex = lod->m_materialIndex; + instance.u_materialIndex = lodEntry.m_materialIndex; // NOTE KI BatchKey does not take in account m_flags // => can draw different instances in same batch @@ -390,14 +388,13 @@ namespace render { const auto& drawOptions = key.m_drawOptions; for (const auto& lodEntry : curr.m_lodInstances) { - auto& lodBaseIndex = programLodBaseIndex[key.m_program]; - auto baseInstance = lodBaseIndex[lodEntry.first]; + const auto baseInstance = curr.getBaseIndex(lodEntry.first); const auto& lodEntries = lodEntry.second; if (lodEntries.empty()) continue; GLuint instanceCount = static_cast(lodEntries.size()); - const auto* lod = lodEntry.first.m_lod; + const auto& lodKey = lodEntry.first; if (drawOptions.m_type == backend::DrawOptions::Type::elements) { backend::gl::DrawElementsIndirectCommand& cmd = indirect.element; @@ -406,12 +403,12 @@ namespace render { cmd.u_instanceCount = instanceCount; cmd.u_baseInstance = baseInstance; - cmd.u_baseVertex = lod->m_baseVertex; - cmd.u_firstIndex = lod->m_baseIndex; - cmd.u_count = lod->m_indexCount; + cmd.u_baseVertex = lodKey.m_baseVertex; + cmd.u_firstIndex = lodKey.m_baseIndex; + cmd.u_count = lodKey.m_indexCount; //KI_INFO_OUT(fmt::format("draw: {}", instanceCount)); - draw->sendDirect(drawRange, indirect); + draw->send(drawRange, indirect); } else if (drawOptions.m_type == backend::DrawOptions::Type::arrays) { @@ -421,10 +418,10 @@ namespace render { cmd.u_instanceCount = instanceCount; cmd.u_baseInstance = baseInstance; - cmd.u_vertexCount = lod->m_indexCount; - cmd.u_firstVertex = lod->m_baseIndex; + cmd.u_vertexCount = lodKey.m_indexCount; + cmd.u_firstVertex = lodKey.m_baseIndex; - draw->sendDirect(drawRange, indirect); + draw->send(drawRange, indirect); } else { // NOTE KI "none" no drawing diff --git a/src/render/BatchCommand.cpp b/src/render/BatchCommand.cpp index 5e698a054..d59358c74 100644 --- a/src/render/BatchCommand.cpp +++ b/src/render/BatchCommand.cpp @@ -40,4 +40,22 @@ namespace render { std::tie(o.m_vao->m_id, od.m_renderBack, o.m_priority, o.m_program->m_id, od.m_blend, od.m_wireframe, od.m_type, od.m_mode); //return tie ? true : (m_drawOptions < o.m_drawOptions); } + + LodKey::LodKey(const backend::Lod& lod, uint32_t flags) + : m_baseVertex{ lod.m_baseVertex }, + m_baseIndex{ lod.m_baseIndex}, + m_indexCount{ lod.m_indexCount }, + m_flags{ flags } + { + } + + bool LodKey::operator<(const LodKey& o) const noexcept { + // NOTE KI baseVertex identifies Lod; cannot have multiple in same index + // - *BUT* indexCount *CAN* very for mesh::TextMesh + // NOTE KI material is now per instance (not Entity) + // => Thus new need to check material here m_lod->m_materialIndex + return std::tie(m_baseVertex, m_indexCount, m_flags) < + std::tie(o.m_baseVertex, o.m_indexCount, o.m_flags); + } + } diff --git a/src/render/BatchCommand.h b/src/render/BatchCommand.h index aba980298..a8d5ea6c4 100644 --- a/src/render/BatchCommand.h +++ b/src/render/BatchCommand.h @@ -19,6 +19,10 @@ namespace backend { } namespace render { + // NOTE KI identifies multi-draw batch + // => max amount of meshes what can be drawn in same draw call + // => i.e. vao, program & al. + // @see DrawBuffer::bindDrawRange struct BatchKey { BatchKey( int8_t priority, @@ -39,21 +43,30 @@ namespace render { }; struct LodKey { - const backend::Lod* m_lod; - uint32_t m_flags; + const uint32_t m_baseVertex; + const uint32_t m_baseIndex; + const uint32_t m_indexCount; + const uint32_t m_flags; - bool operator<(const LodKey& o) const noexcept { - return std::tie( m_lod->m_baseVertex, m_lod->m_baseIndex, m_lod->m_materialIndex, m_flags) < - std::tie(o.m_lod->m_baseVertex, o.m_lod->m_baseIndex, o.m_lod->m_materialIndex, o.m_flags); - } + LodKey(const backend::Lod& lod, uint32_t flags); + + bool operator<(const LodKey& o) const noexcept; }; struct LodEntry { - uint32_t m_entityIndex; - uint32_t m_meshIndex; + const uint32_t m_entityIndex; + const uint32_t m_meshIndex; + const uint32_t m_materialIndex; }; struct BatchCommand { std::map> m_lodInstances; + std::map m_baseIndeces; + + uint32_t getBaseIndex(const LodKey& lodKey) const noexcept + { + const auto& it = m_baseIndeces.find(lodKey); + return it != m_baseIndeces.end() ? it->second : 0; + } }; } diff --git a/src/render/NodeDraw.cpp b/src/render/NodeDraw.cpp index e3a63e748..b55d31a78 100644 --- a/src/render/NodeDraw.cpp +++ b/src/render/NodeDraw.cpp @@ -375,10 +375,10 @@ namespace render { ctx.m_batch->flush(ctx); } - state.setStencil({}); if (!ctx.m_forceSolid) { + state.setStencil({}); particleRenderer.render(ctx); } diff --git a/src/text/TextDraw.cpp b/src/text/TextDraw.cpp index d15c2cd82..970ea7181 100644 --- a/src/text/TextDraw.cpp +++ b/src/text/TextDraw.cpp @@ -168,7 +168,7 @@ namespace text auto* font = text::FontRegistry::get().getFont(fontId); if (!font) return; - addText(mesh, font, text, pen, mesh->m_reserveIndexCount); + addText(mesh, font, text, pen, mesh->m_maxSize); // HACK KI need to encode font somehow int drawOptions and/or VBO // => can use VBO, sinse are not shared mesh VBOs like in ModelRegistry From c2a684e6bea4dd7564ddc94030d59eb7127d2113 Mon Sep 17 00:00:00 2001 From: Kari Ikonen Date: Sun, 23 Jun 2024 14:46:59 +0300 Subject: [PATCH 28/28] FIX pine tree needs blend further away --- scene/scene_forest.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scene/scene_forest.yml b/scene/scene_forest.yml index 1b9a8052f..356b0e5e2 100644 --- a/scene/scene_forest.yml +++ b/scene/scene_forest.yml @@ -170,7 +170,7 @@ entities: - path: fbx/scenery/trees/SM_TreePine_01b.FBX lods: - level: 0 - distance: 100 + distance: 200 materials: - name: pine_trunk_pbr alias: MI_TreeBarkPine_01a @@ -184,7 +184,7 @@ entities: - path: fbx/scenery/trees/SM_TreePine_01b.FBX lods: - level: 1 - distance: 200 + distance: 300 materials: - name: pine_trunk_pbr alias: MI_TreeBarkPine_01a @@ -197,7 +197,7 @@ entities: - path: fbx/scenery/trees/SM_TreePine_01b.FBX lods: - level: 2 - distance: 300 + distance: 400 materials: - name: pine_trunk_pbr alias: MI_TreeBarkPine_01a @@ -210,7 +210,7 @@ entities: - path: fbx/scenery/trees/SM_TreePine_01b.FBX lods: - level: 3 - distance: 400 + distance: 500 materials: - name: pine_trunk_pbr alias: MI_TreeBarkPine_01a