From 4b7a9d57142e7b38412408520bf3d0623bacc6e8 Mon Sep 17 00:00:00 2001 From: mrq Date: Mon, 13 Jun 2022 01:15:00 -0500 Subject: [PATCH] Commit for 2022.06.13 01-15-08.7z --- bin/data/config.json | 22 +- bin/data/entities/model.json | 6 +- bin/data/scenes/mcdonalds/mcdonalds.json | 3 +- bin/data/scenes/mcdonalds/scene.json | 10 +- bin/data/scenes/ss2/medsci.json | 5 +- bin/data/shaders/common/shadows.h | 3 + bin/data/shaders/common/structs.h | 2 +- bin/data/shaders/common/vxgi.h | 4 +- bin/dreamcast/config.json | 13 +- engine/inc/uf/ext/opengl/rendermode.h | 3 +- engine/inc/uf/ext/vulkan/rendermode.h | 11 +- engine/inc/uf/ext/xatlas/xatlas.h | 5 +- engine/inc/uf/macros.h | 2 +- engine/inc/uf/utils/thread/perthread.h | 10 +- engine/inc/uf/utils/thread/perthread.inl | 11 +- engine/src/engine/behavior/behavior.cpp | 1 + engine/src/engine/entity/entity.cpp | 14 + engine/src/engine/graph/graph.cpp | 45 ++- engine/src/ext/gltf/gltf.cpp | 3 +- engine/src/ext/opengl/opengl.cpp | 58 +-- engine/src/ext/opengl/rendermode.cpp | 3 - engine/src/ext/opengl/rendermodes/base.cpp | 7 +- engine/src/ext/vulkan/buffer.cpp | 2 +- engine/src/ext/vulkan/graphic.cpp | 15 +- engine/src/ext/vulkan/rendermode.cpp | 17 +- engine/src/ext/vulkan/vulkan.cpp | 15 +- engine/src/ext/xatlas/xatlas.cpp | 443 +++++++++++++++------ engine/src/utils/mesh/grid.cpp | 8 +- ext/behaviors/baking/behavior.cpp | 10 +- ext/behaviors/scene/behavior.cpp | 16 +- ext/behaviors/scene/behavior.h | 3 +- ext/behaviors/voxelizer/behavior.cpp | 6 +- ext/behaviors/voxelizer/behavior.h | 1 + ext/main.cpp | 4 + 34 files changed, 520 insertions(+), 261 deletions(-) diff --git a/bin/data/config.json b/bin/data/config.json index e628eafb..5b43007a 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -1,7 +1,7 @@ { "engine": { "scenes": { - "start": "SS2", + "start": "McDonalds", "meshes": { "interleaved": false }, "matrix": { "reverseInfinite": true }, "lights": { "enabled": true, @@ -12,13 +12,12 @@ "enabled": true, "update": 2, "max": 8, - "samples": 1, - "experimental mode": 1 + "samples": 1 }, "textures": { "max": { - "2D": 256, - "cube": 32, + "2D": 1024, + "cube": 256, "3D": 1 } }, @@ -31,6 +30,7 @@ "granularity": 12, "voxelizeScale": 1, "occlusionFalloff": 2, + "traceStartOffsetFactor": 2, "shadows": 0, "extents": { "min": [ -8, -1, -8 ], @@ -76,7 +76,7 @@ }, "gpu": "auto", "experimental": { - "batch queue submissions": true, + "batch queue submissions": false, "dedicated thread": false }, "invariant": {}, @@ -198,15 +198,15 @@ "streams by default": true }, "memory pool": { - "enabled": true, + "enabled": false, "subPools": true, "alignment": 64, "override": false, - "size": "1024 MiB", + "size": "512 MiB", "pools": { - "entity": "256 MiB", - "userdata": "256 MiB", - "component": "256 MiB" + "entity": "128 MiB", + "userdata": "128 MiB", + "component": "128 MiB" } }, "render modes": { "gui": true, "deferred": true }, diff --git a/bin/data/entities/model.json b/bin/data/entities/model.json index 0a1e3a2e..e79f44bb 100644 --- a/bin/data/entities/model.json +++ b/bin/data/entities/model.json @@ -25,7 +25,9 @@ "combined": false, "encode buffers": true, "unwrap": true, + // "unwrap": "tagged", "optimize": "tagged", + // "optimize": true, "quit": true, "mesh": { // "print": true @@ -41,7 +43,7 @@ "output": "./lightmap.%i.png", "settings": { "useInputMeshUvs": true, - "maxIterations": 8, + "maxIterations": 16, // "maxChartSize": 0, "padding": 4, // "texelsPerUnit": 0, @@ -49,7 +51,7 @@ "blockAlign": true, "bruteForce": true, - // "rotateChartsToAxis": false, + "rotateChartsToAxis": false, "rotateCharts": true } }, diff --git a/bin/data/scenes/mcdonalds/mcdonalds.json b/bin/data/scenes/mcdonalds/mcdonalds.json index be74ffd0..5929cc57 100644 --- a/bin/data/scenes/mcdonalds/mcdonalds.json +++ b/bin/data/scenes/mcdonalds/mcdonalds.json @@ -23,7 +23,8 @@ "/^worldspawn/": { "physics": { "type": "mesh", "static": true }, "grid": { "size": [4,1,4], "epsilon": 1.0, "cleanup": true, "print": true }, - "optimize mesh": { "simplify": 0 } + "optimize mesh": { "simplify": 0 }, + "unwrap mesh": true }, "info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true }, diff --git a/bin/data/scenes/mcdonalds/scene.json b/bin/data/scenes/mcdonalds/scene.json index 6c9c134d..b2b02dae 100644 --- a/bin/data/scenes/mcdonalds/scene.json +++ b/bin/data/scenes/mcdonalds/scene.json @@ -34,15 +34,16 @@ "exposure": 1.0, "gamma": 1.0, "brightnessThreshold": 1.2, - "ambient": [ 0, 0, 0 ], + // "ambient": [ 0, 0, 0 ], + "ambient": [ 0.025, 0.025, 0.025 ], // "ambient": [ 0.1, 0.1, 0.1 ], // "ambient": [ 0.4, 0.4, 0.4 ], - "fog-": { + "fog": { "color": [ 0.5, 0.5, 0.5 ], "range": [ 16, 32 ], "step scale": 2, - "absorbtion": 0.07, + "absorbtion": 0.01, "density": { "threshold": 0.35, "multiplier": 5.0, @@ -68,7 +69,8 @@ "shadows": 0, */ "occlusionFalloff": 2, - "granularity": 4, + "traceStartOffsetFactor": 1, + "granularity": 2, "extents": { "min": [ -1.5, -1.5, -1.5 ], "max": [ 1.5, 1.5, 1.5 ] diff --git a/bin/data/scenes/ss2/medsci.json b/bin/data/scenes/ss2/medsci.json index f70bfce4..bab160cd 100644 --- a/bin/data/scenes/ss2/medsci.json +++ b/bin/data/scenes/ss2/medsci.json @@ -26,8 +26,9 @@ "tags": { "/^worldspawn/": { "physics": { "type": "mesh", "static": true }, - "grid": { "size": [5,1,5], "epsilon": 1.0, "cleanup": true, "print": true }, - "optimize mesh": { "simplify": 0 } + "grid": { "size": [3,1,3], "epsilon": 0.0001, "cleanup": true, "print": true }, + "optimize mesh": { "simplify": 0 }, + "unwrap mesh": true }, "info_player_spawn": { "action": "attach", diff --git a/bin/data/shaders/common/shadows.h b/bin/data/shaders/common/shadows.h index a645c105..076d628a 100644 --- a/bin/data/shaders/common/shadows.h +++ b/bin/data/shaders/common/shadows.h @@ -71,6 +71,7 @@ float omniShadowMap( const Light light, float def ) { float sampled = 0; const int samples = int(SHADOW_SAMPLES); + // cubemap point light if ( light.typeMap == 1 ) { if ( samples < 1 ) { sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D).r * sampledDepthScale; @@ -84,6 +85,7 @@ float omniShadowMap( const Light light, float def ) { } return factor; } + // separated point lights } else if ( light.typeMap == 2 ) { const vec2 uv = positionClip.xy * 0.5 + 0.5; if ( samples < 1 ) { @@ -102,6 +104,7 @@ float omniShadowMap( const Light light, float def ) { #endif float shadowFactor( const Light light, float def ) { if ( light.typeMap != 0 ) return omniShadowMap( light, def ); + if ( !validTextureIndex(light.indexMap) ) #if VXGI return voxelShadowFactor( light, def ); diff --git a/bin/data/shaders/common/structs.h b/bin/data/shaders/common/structs.h index 5afc57db..07ab058f 100644 --- a/bin/data/shaders/common/structs.h +++ b/bin/data/shaders/common/structs.h @@ -180,8 +180,8 @@ struct Vxgi { float voxelizeScale; float occlusionFalloff; + float traceStartOffsetFactor; uint shadows; - uint padding1; uint padding2; uint padding3; }; diff --git a/bin/data/shaders/common/vxgi.h b/bin/data/shaders/common/vxgi.h index 7ee90c5a..bf81ceea 100644 --- a/bin/data/shaders/common/vxgi.h +++ b/bin/data/shaders/common/vxgi.h @@ -28,9 +28,9 @@ vec4 voxelTrace( inout Ray ray, float aperture, float maxDistance ) { const float tStart = rayBoxInfoA.x; const float tEnd = maxDistance > 0 ? min(maxDistance, rayBoxInfoB.y) : rayBoxInfoB.y; - const float tDelta = voxelInfo.radianceSizeRecip * granularityRecip * 1.5; + const float tDelta = voxelInfo.radianceSizeRecip * granularityRecip; // marcher - ray.distance = tStart; + ray.distance = tStart + tDelta * ubo.vxgi.traceStartOffsetFactor; ray.position = vec3(0); vec4 radiance = vec4(0); diff --git a/bin/dreamcast/config.json b/bin/dreamcast/config.json index 7085792d..4e1cad53 100644 --- a/bin/dreamcast/config.json +++ b/bin/dreamcast/config.json @@ -6,14 +6,13 @@ "matrix": { "reverseInfinite": false }, "lights": { "enabled": false, "useLightmaps": true, - "max": 0 + "max": 1 }, "shadows": { "enabled": false, "update": 2, "max": 8, - "samples": 2, - "experimental mode": 1 + "samples": 1 }, "textures": { "max": { @@ -54,7 +53,7 @@ "compression": "gz" }, "reactphysics": { - "timescale": 0.03333333333, + "timescale": 0.06666666666, "interpolate": false, "debug draw": { "enabled": false, @@ -77,11 +76,11 @@ "streams by default": true }, "memory pool": { - "enabled": false, + "enabled": true, "subPools": true, "alignment": 32, - "override": true, - "size": "8 MiB", + "override": false, + "size": "512 KiB", "pools": { "entity": "96 KiB", "userdata": "96 KiB", diff --git a/engine/inc/uf/ext/opengl/rendermode.h b/engine/inc/uf/ext/opengl/rendermode.h index 9e5b9dcd..7df1443e 100644 --- a/engine/inc/uf/ext/opengl/rendermode.h +++ b/engine/inc/uf/ext/opengl/rendermode.h @@ -50,8 +50,7 @@ namespace ext { virtual ext::opengl::Graphic* getBlitter(size_t = 0); virtual uf::stl::vector getBlitters(); - virtual CommandBuffer& getCommands(); - virtual CommandBuffer& getCommands( std::thread::id ); + virtual CommandBuffer& getCommands( std::thread::id = std::this_thread::get_id() ); virtual GraphicDescriptor bindGraphicDescriptor( const GraphicDescriptor&, size_t = 0 ); virtual void bindGraphicPushConstants( ext::opengl::Graphic*, size_t = 0 ); diff --git a/engine/inc/uf/ext/vulkan/rendermode.h b/engine/inc/uf/ext/vulkan/rendermode.h index 9ecf515e..6b246a24 100644 --- a/engine/inc/uf/ext/vulkan/rendermode.h +++ b/engine/inc/uf/ext/vulkan/rendermode.h @@ -60,12 +60,11 @@ namespace ext { uf::Image screenshot(size_t = 0, size_t = 0); - commands_container_t& getCommands(); - commands_container_t& getCommands( std::thread::id ); - void lockMutex(); - void lockMutex( std::thread::id ); - void unlockMutex(); - void unlockMutex( std::thread::id ); + commands_container_t& getCommands( std::thread::id = std::this_thread::get_id() ); + void lockMutex( std::thread::id = std::this_thread::get_id() ); + bool tryMutex( std::thread::id = std::this_thread::get_id() ); + void unlockMutex( std::thread::id = std::this_thread::get_id() ); + std::lock_guard guardMutex( std::thread::id = std::this_thread::get_id() ); virtual ~RenderMode(); // RAII diff --git a/engine/inc/uf/ext/xatlas/xatlas.h b/engine/inc/uf/ext/xatlas/xatlas.h index 358df8a0..d022eb3a 100644 --- a/engine/inc/uf/ext/xatlas/xatlas.h +++ b/engine/inc/uf/ext/xatlas/xatlas.h @@ -5,7 +5,10 @@ #if UF_USE_XATLAS namespace ext { namespace xatlas { - size_t UF_API unwrap( pod::Graph&, bool = false ); + size_t UF_API unwrap( pod::Graph& ); + + size_t UF_API unwrapLazy( pod::Graph& ); + size_t UF_API unwrapExperimental( pod::Graph& ); } } #endif \ No newline at end of file diff --git a/engine/inc/uf/macros.h b/engine/inc/uf/macros.h index 0ac0a1f8..59320ab9 100644 --- a/engine/inc/uf/macros.h +++ b/engine/inc/uf/macros.h @@ -96,7 +96,7 @@ #define UF_TIMER_MULTITRACE(X) {\ TIMER_TRACE_CUR = TIMER_TRACE.elapsed().asMicroseconds();\ - UF_MSG_DEBUG(std::setfill(' ') << std::setw(4) << TIMER_TRACE_CUR << " ns\t" << std::setfill(' ') << std::setw(4) << (TIMER_TRACE_CUR - TIMER_TRACE_PREV) << " ns\t" << X);\ + UF_MSG_DEBUG(std::setfill(' ') << std::setw(4) << TIMER_TRACE_CUR << " us\t" << std::setfill(' ') << std::setw(4) << (TIMER_TRACE_CUR - TIMER_TRACE_PREV) << " us\t" << X);\ TIMER_TRACE_PREV = TIMER_TRACE_CUR;\ } diff --git a/engine/inc/uf/utils/thread/perthread.h b/engine/inc/uf/utils/thread/perthread.h index 0d4593b4..db785141 100644 --- a/engine/inc/uf/utils/thread/perthread.h +++ b/engine/inc/uf/utils/thread/perthread.h @@ -20,12 +20,12 @@ namespace uf { bool has( id_t id = std::this_thread::get_id() ) const; T& get( id_t id = std::this_thread::get_id() ); - - void lock( id_t id = std::this_thread::get_id() ); - void unlock( id_t id = std::this_thread::get_id() ); - std::lock_guard guard( id_t id = std::this_thread::get_id() ); - container_t& container(); + + void lockMutex( id_t id = std::this_thread::get_id() ); + bool tryMutex( id_t id = std::this_thread::get_id() ); + void unlockMutex( id_t id = std::this_thread::get_id() ); + std::lock_guard guardMutex( id_t id = std::this_thread::get_id() ); }; } diff --git a/engine/inc/uf/utils/thread/perthread.inl b/engine/inc/uf/utils/thread/perthread.inl index b0737048..a419bd53 100644 --- a/engine/inc/uf/utils/thread/perthread.inl +++ b/engine/inc/uf/utils/thread/perthread.inl @@ -16,17 +16,22 @@ T& uf::ThreadUnique::get( id_t id ) { return m_container[id]; } template -void uf::ThreadUnique::lock( id_t id ) { +void uf::ThreadUnique::lockMutex( id_t id ) { if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex; m_mutex_container[id]->lock(); } template -void uf::ThreadUnique::unlock( id_t id ) { +bool uf::ThreadUnique::tryMutex( id_t id ) { + if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex; + return m_mutex_container[id]->try_lock(); +} +template +void uf::ThreadUnique::unlockMutex( id_t id ) { if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex; m_mutex_container[id]->unlock(); } template -std::lock_guard uf::ThreadUnique::guard( id_t id ) { +std::lock_guard uf::ThreadUnique::guardMutex( id_t id ) { if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex; return std::lock_guard(*m_mutex_container[id]); } diff --git a/engine/src/engine/behavior/behavior.cpp b/engine/src/engine/behavior/behavior.cpp index a0e7015e..8f1b61a6 100644 --- a/engine/src/engine/behavior/behavior.cpp +++ b/engine/src/engine/behavior/behavior.cpp @@ -89,6 +89,7 @@ void uf::Behaviors::tick() { if ( m_graph.tick.empty() ) return; #if UF_GRAPH_PRINT_TRACE UF_TIMER_MULTITRACE_START("Starting tick " << self.getName() << ": " << self.getUid()); +// for ( auto& behavior : m_behaviors ) if ( behavior.traits.ticks ) UF_MSG_DEBUG( behavior.type.name() ); for ( auto& fun : m_graph.tick ) { fun(self); UF_TIMER_MULTITRACE(""); diff --git a/engine/src/engine/entity/entity.cpp b/engine/src/engine/entity/entity.cpp index d104619c..f909ccf1 100644 --- a/engine/src/engine/entity/entity.cpp +++ b/engine/src/engine/entity/entity.cpp @@ -131,6 +131,13 @@ uf::Entity* uf::Entity::globalFindByUid( size_t uid ) { uf::Entity* entity = (uf::Entity*) (allocation.pointer); if ( entity->getUid() == uid ) return entity; } + { + auto& scene = uf::scene::getCurrentScene(); + auto& graph = scene.getGraph(); + for ( uf::Entity* entity : graph ) { + if ( entity->getUid() == uid ) return entity; + } + } return NULL; } uf::Entity* uf::Entity::globalFindByName( const uf::stl::string& name ) { @@ -139,5 +146,12 @@ uf::Entity* uf::Entity::globalFindByName( const uf::stl::string& name ) { if ( !entity->isValid() ) continue; if ( entity->getName() == name ) return entity; } + { + auto& scene = uf::scene::getCurrentScene(); + auto& graph = scene.getGraph(); + for ( uf::Entity* entity : graph ) { + if ( entity->getName() == name ) return entity; + } + } return NULL; } \ No newline at end of file diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index e394917d..c2b5e257 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -760,6 +760,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) if ( key == "transform" ) return; metadataLight[key] = value; }); + #if !UF_USE_OPENGL if ( !(graph.metadata["lightmapped"].as() && !(metadataLight["shadows"].as() || metadataLight["dynamic"].as())) ) { // { auto& metadataJson = entity.getComponent(); @@ -769,6 +770,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) metadataJson["light"][key] = value; }); } + #endif } } @@ -806,7 +808,8 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) } size_t objectID = uf::graph::storage.entities.keys.size(); - uf::graph::storage.entities[std::to_string(objectID)] = &entity; + auto objectKeyName = std::to_string(objectID); + uf::graph::storage.entities[objectKeyName] = &entity; if ( 0 <= node.mesh && node.mesh < graph.meshes.size() ) { auto model = uf::transform::model( transform ); @@ -819,7 +822,9 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) auto& primitive = primitives[i]; size_t instanceID = uf::graph::storage.instances.keys.size(); - auto& instance = uf::graph::storage.instances[graph.instances.emplace_back(std::to_string(instanceID))]; + auto instanceKeyName = graph.instances.emplace_back(std::to_string(instanceID)); + + auto& instance = uf::graph::storage.instances[instanceKeyName]; instance = primitive.instance; instance.model = model; @@ -973,15 +978,30 @@ void uf::graph::update( pod::Graph& graph ) { } void uf::graph::update( pod::Graph& graph, float delta ) { // update our instances +#if !UF_ENV_DREAMCAST +// UF_TIMER_MULTITRACE_START("Tick Start"); + uf::stl::unordered_map instanceCache; for ( auto& name : uf::graph::storage.instances.keys ) { auto& instance = uf::graph::storage.instances[name]; + if ( instanceCache.count( instance.objectID ) > 0 ) { + instance.model = instanceCache[instance.objectID]; + continue; + } + auto& entity = *uf::graph::storage.entities[std::to_string(instance.objectID)]; + auto& metadata = entity.getComponent(); + if ( metadata.system.ignoreGraph ) continue; + auto& transform = entity.getComponent>(); - instance.model = uf::transform::model( transform ); + instance.model = (instanceCache[instance.objectID] = uf::transform::model( transform )); } +// UF_TIMER_MULTITRACE_END("Tick End"); +#endif // no skins - if ( !(graph.metadata["flags"]["SKINNED"].as()) ) return; + if ( !(graph.metadata["flags"]["SKINNED"].as()) ) { + return; + } if ( graph.sequence.empty() ) goto UPDATE; if ( graph.settings.animations.override.a >= 0 ) goto OVERRIDE; @@ -1053,15 +1073,6 @@ void uf::graph::update( pod::Graph& graph, pod::Node& node ) { joints[i] = inverseTransform * (uf::graph::matrix(graph, skin.joints[i]) * skin.inverseBindMatrices[i]); } } - /* - if ( node.entity && node.entity->hasComponent() ) { - auto& graphic = node.entity->getComponent(); - if ( node.buffers.joint < graphic.buffers.size() ) { - auto& buffer = graphic.buffers.at(node.buffers.joint); - shader.updateBuffer( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f), buffer ); - } - } - */ } } void uf::graph::destroy( pod::Graph& graph ) { @@ -1099,18 +1110,16 @@ void uf::graph::initialize() { } void uf::graph::tick() { uf::stl::vector instances; instances.reserve(uf::graph::storage.instances.map.size()); - uf::stl::vector joints; joints.reserve(uf::graph::storage.joints.map.size()); - for ( auto key : uf::graph::storage.instances.keys ) instances.emplace_back( uf::graph::storage.instances.map[key] ); + if ( !instances.empty() ) uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ); + uf::stl::vector joints; joints.reserve(uf::graph::storage.joints.map.size()); for ( auto key : uf::graph::storage.joints.keys ) { auto& matrices = uf::graph::storage.joints[key]; joints.reserve( joints.size() + matrices.size() ); for ( auto& mat : matrices ) joints.emplace_back( mat ); } - - uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ); - uf::graph::storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) ); + if ( !joints.empty() ) uf::graph::storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) ); if ( ::newGraphAdded ) { uf::stl::vector drawCommands; drawCommands.reserve(uf::graph::storage.drawCommands.map.size()); diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index 2ea3fdce..31f53608 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -239,6 +239,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize } // load meshes { + size_t masterAuxID = 0; graph.meshes.reserve(model.meshes.size()); /*graph.storage*/uf::graph::storage.meshes.reserve(model.meshes.size()); @@ -466,7 +467,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize } #if UF_USE_XATLAS // generate STs - if ( graph.metadata["exporter"]["unwrap"].as(true) ) { + if ( graph.metadata["exporter"]["unwrap"].as(true) || graph.metadata["exporter"]["unwrap"].as() == "tagged" ) { UF_MSG_DEBUG( "Generating ST's..." ); size_t atlases = ext::xatlas::unwrap( graph ); UF_MSG_DEBUG( "Generated ST's for " << atlases << " lightmaps" ); diff --git a/engine/src/ext/opengl/opengl.cpp b/engine/src/ext/opengl/opengl.cpp index 45ad4267..6ac2c93c 100644 --- a/engine/src/ext/opengl/opengl.cpp +++ b/engine/src/ext/opengl/opengl.cpp @@ -16,7 +16,7 @@ uint32_t ext::opengl::settings::width = 640; uint32_t ext::opengl::settings::height = 480; uint8_t ext::opengl::settings::msaa = 1; -bool ext::opengl::settings::validation = true; +bool ext::opengl::settings::validation = false; // constexpr size_t ext::opengl::settings::maxViews = 6; size_t ext::opengl::settings::viewCount = 1; @@ -28,24 +28,29 @@ uf::stl::vector ext::opengl::settings::requestedInstanceExtensi ext::opengl::enums::Filter::type_t ext::opengl::settings::swapchainUpscaleFilter = ext::opengl::enums::Filter::LINEAR; // these go hand in hand for the above +#if UF_ENV_DREAMCAST bool ext::opengl::settings::experimental::dedicatedThread = false; +#else +bool ext::opengl::settings::experimental::dedicatedThread = true; +#endif bool ext::opengl::settings::experimental::rebuildOnTickBegin = false; // not so experimental bool ext::opengl::settings::invariant::waitOnRenderEnd = false; bool ext::opengl::settings::invariant::individualPipelines = true; + bool ext::opengl::settings::invariant::multithreadedRecording = true; uf::stl::string ext::opengl::settings::invariant::deferredMode = ""; bool ext::opengl::settings::invariant::deferredReconstructPosition = false; -bool ext::opengl::settings::invariant::deferredAliasOutputToSwapchain = true; -bool ext::opengl::settings::invariant::deferredSampling = true; +bool ext::opengl::settings::invariant::deferredAliasOutputToSwapchain = false; +bool ext::opengl::settings::invariant::deferredSampling = false; -bool ext::opengl::settings::invariant::multiview = true; +bool ext::opengl::settings::invariant::multiview = false; // pipelines bool ext::opengl::settings::pipelines::vsync = true; -bool ext::opengl::settings::pipelines::hdr = true; -bool ext::opengl::settings::pipelines::vxgi = true; +bool ext::opengl::settings::pipelines::hdr = false; +bool ext::opengl::settings::pipelines::vxgi = false; bool ext::opengl::settings::pipelines::culling = false; bool ext::opengl::settings::pipelines::bloom = false; @@ -97,7 +102,22 @@ ext::opengl::RenderMode& ext::opengl::addRenderMode( ext::opengl::RenderMode* mo renderModes.push_back(mode); if ( ext::opengl::settings::validation ) UF_MSG_DEBUG("Adding RenderMode: " << name << ": " << mode->getType()); // reorder + if ( hasRenderMode("Gui", true) ) { + RenderMode& primary = getRenderMode("Gui", true); + auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); + if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); + } + if ( hasRenderMode("", true) ) { + RenderMode& primary = getRenderMode("", true); + auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); + if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); + } else { + RenderMode& primary = getRenderMode("Swapchain", true); + auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); + if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); + } ext::opengl::states::rebuild = true; + return *mode; } ext::opengl::RenderMode& ext::opengl::getRenderMode( const uf::stl::string& name, bool isName ) { @@ -366,13 +386,7 @@ void UF_API ext::opengl::tick(){ } uf::thread::execute( tasks ); -/* - ext::opengl::device.activateContext(); - ext::opengl::device.commandBuffer.end(); - ext::opengl::device.commandBuffer.submit(); - ext::opengl::device.commandBuffer.flush(); - ext::opengl::device.commandBuffer.start(); -*/ + ext::opengl::states::rebuild = false; ext::opengl::states::resized = false; ext::opengl::mutex.unlock(); @@ -380,22 +394,6 @@ void UF_API ext::opengl::tick(){ void UF_API ext::opengl::render(){ ext::opengl::mutex.lock(); #if !UF_ENV_DREAMCAST -#if 1 - if ( hasRenderMode("", true) ) { - RenderMode& primary = getRenderMode("", true); - auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); - if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); - } else { - RenderMode& primary = getRenderMode("Swapchain", true); - auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); - if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); - } - if ( hasRenderMode("Gui", true) ) { - RenderMode& primary = getRenderMode("Gui", true); - auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); - if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); - } -#endif ext::opengl::device.activateContext(); #endif @@ -460,6 +458,7 @@ void UF_API ext::opengl::destroy() { synchronize(); Texture2D::empty.destroy(); +/* auto& scene = uf::scene::getCurrentScene(); auto& graph = scene.getGraph(); for ( auto entity : graph ) { @@ -467,6 +466,7 @@ void UF_API ext::opengl::destroy() { uf::Graphic& graphic = entity->getComponent(); graphic.destroy(); } +*/ for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; renderMode->destroy(); diff --git a/engine/src/ext/opengl/rendermode.cpp b/engine/src/ext/opengl/rendermode.cpp index f5699ad7..62a5bf2d 100644 --- a/engine/src/ext/opengl/rendermode.cpp +++ b/engine/src/ext/opengl/rendermode.cpp @@ -73,9 +73,6 @@ void ext::opengl::RenderMode::createCommandBuffers() { this->mostRecentCommandPoolId = std::this_thread::get_id(); this->rebuild = false; } -ext::opengl::CommandBuffer& ext::opengl::RenderMode::getCommands() { - return getCommands( std::this_thread::get_id() ); -} ext::opengl::CommandBuffer& ext::opengl::RenderMode::getCommands( std::thread::id id ) { bool exists = this->commands.has(id); //this->commands.count(id) > 0; auto& commands = this->commands.get(id); //this->commands[id]; diff --git a/engine/src/ext/opengl/rendermodes/base.cpp b/engine/src/ext/opengl/rendermodes/base.cpp index 990a52ad..bbef633f 100644 --- a/engine/src/ext/opengl/rendermodes/base.cpp +++ b/engine/src/ext/opengl/rendermodes/base.cpp @@ -13,6 +13,7 @@ const uf::stl::string ext::opengl::BaseRenderMode::getType() const { return "Swapchain"; } void ext::opengl::BaseRenderMode::createCommandBuffers( const uf::stl::vector& graphics ) { +#if 0 float width = this->width > 0 ? this->width : ext::opengl::settings::width; float height = this->height > 0 ? this->height : ext::opengl::settings::height; @@ -53,6 +54,7 @@ void ext::opengl::BaseRenderMode::createCommandBuffers( const uf::stl::vectorrecord( commands, descriptor, currentPass, currentDraw++ ); } } commands.end(); +#endif } void ext::opengl::BaseRenderMode::initialize( Device& device ) { @@ -72,11 +74,12 @@ void ext::opengl::BaseRenderMode::initialize( Device& device ) { GL_ERROR_CHECK(glEnable(GL_DEPTH_TEST)); GL_ERROR_CHECK(glEnable(GL_TEXTURE_2D)); +#if 0 && !UF_ENV_DREAMCAST GL_ERROR_CHECK(glEnable(GL_ALPHA_TEST)); GL_ERROR_CHECK(glAlphaFunc(GL_GREATER, 0.1f)); GL_ERROR_CHECK(glEnable(GL_BLEND)); GL_ERROR_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - +#endif // GL_ERROR_CHECK(glEnable(GL_LIGHTING)); // GL_ERROR_CHECK(glEnable(GL_NORMALIZE)); @@ -106,7 +109,9 @@ void ext::opengl::BaseRenderMode::tick() { ext::opengl::RenderMode::tick(); } void ext::opengl::BaseRenderMode::render() { +#if 0 ext::opengl::RenderMode::render(); +#endif } void ext::opengl::BaseRenderMode::destroy() { diff --git a/engine/src/ext/vulkan/buffer.cpp b/engine/src/ext/vulkan/buffer.cpp index 86cc375d..ac6a1952 100644 --- a/engine/src/ext/vulkan/buffer.cpp +++ b/engine/src/ext/vulkan/buffer.cpp @@ -35,7 +35,7 @@ void ext::vulkan::Buffer::aliasBuffer( const ext::vulkan::Buffer& buffer ) { } void* ext::vulkan::Buffer::map( VkDeviceSize size, VkDeviceSize offset ) { - VK_CHECK_RESULT(vmaMapMemory( allocator, allocation, &mapped )); + if ( !mapped ) VK_CHECK_RESULT(vmaMapMemory( allocator, allocation, &mapped )); return mapped; } void ext::vulkan::Buffer::unmap() { diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 84270047..a116c90a 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -631,15 +631,12 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip } } - renderMode.rebuild = true; - - vkUpdateDescriptorSets( - *device, - writeDescriptorSets.size(), - writeDescriptorSets.data(), - 0, - NULL - ); + { + // bool locked = renderMode.tryMutex(); + renderMode.rebuild = true; + vkUpdateDescriptorSets( *device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL ); + // if ( locked ) renderMode.unlockMutex(); + } return; PIPELINE_UPDATE_INVALID: diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index e6226ae9..d65ab9d0 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -204,9 +204,6 @@ void ext::vulkan::RenderMode::createCommandBuffers() { this->mostRecentCommandPoolId = std::this_thread::get_id(); this->rebuild = false; } -ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands() { - return getCommands( std::this_thread::get_id() ); -} ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands( std::thread::id id ) { bool exists = this->commands.has(id); //this->commands.count(id) > 0; auto& commands = this->commands.get(id); //this->commands[id]; @@ -223,17 +220,17 @@ ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getComma } return commands; } -void ext::vulkan::RenderMode::lockMutex() { - return lockMutex( std::this_thread::get_id() ); -} void ext::vulkan::RenderMode::lockMutex( std::thread::id id ) { - this->commands.lock( id ); + this->commands.lockMutex( id ); } -void ext::vulkan::RenderMode::unlockMutex() { - return unlockMutex( std::this_thread::get_id() ); +bool ext::vulkan::RenderMode::tryMutex( std::thread::id id ) { + this->commands.tryMutex( id ); } void ext::vulkan::RenderMode::unlockMutex( std::thread::id id ) { - this->commands.unlock( id ); + this->commands.unlockMutex( id ); +} +std::lock_guard ext::vulkan::RenderMode::guardMutex( std::thread::id id ) { + return this->commands.guardMutex( id ); } void ext::vulkan::RenderMode::createCommandBuffers( const uf::stl::vector& graphics ) { diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index a83d24aa..63ed7b6d 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -316,10 +316,11 @@ void ext::vulkan::initialize() { auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread ? "Aux" : "Main"); for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; tasks.queue([&]{ - renderMode->lockMutex(); + auto guard = renderMode->guardMutex(); + // renderMode->lockMutex(); if ( settings::invariant::individualPipelines ) renderMode->bindPipelines(); renderMode->createCommandBuffers(); - renderMode->unlockMutex(); + // renderMode->unlockMutex(); }); } uf::thread::execute( tasks ); @@ -395,10 +396,11 @@ void ext::vulkan::tick() { auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread ? "Aux" : "Main"); for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; if ( ext::vulkan::states::rebuild || renderMode->rebuild ) tasks.queue([&]{ - renderMode->lockMutex(); + auto guard = renderMode->guardMutex(); + // renderMode->lockMutex(); if ( settings::invariant::individualPipelines ) renderMode->bindPipelines(); renderMode->createCommandBuffers(); - renderMode->unlockMutex(); + // renderMode->unlockMutex(); }); } uf::thread::execute( tasks ); @@ -468,13 +470,14 @@ void ext::vulkan::render() { for ( auto& renderMode : renderModes ) { if ( !renderMode || !renderMode->execute || !renderMode->metadata.limiter.execute ) continue; - renderMode->lockMutex( renderMode->mostRecentCommandPoolId ); + // renderMode->lockMutex( renderMode->mostRecentCommandPoolId ); + auto guard = renderMode->guardMutex( renderMode->mostRecentCommandPoolId ); ext::vulkan::setCurrentRenderMode(renderMode); uf::graph::render(); uf::scene::render(); renderMode->render(); ext::vulkan::setCurrentRenderMode(NULL); - renderMode->unlockMutex( renderMode->mostRecentCommandPoolId ); + // renderMode->unlockMutex( renderMode->mostRecentCommandPoolId ); } } diff --git a/engine/src/ext/xatlas/xatlas.cpp b/engine/src/ext/xatlas/xatlas.cpp index 0045f78c..1116a500 100644 --- a/engine/src/ext/xatlas/xatlas.cpp +++ b/engine/src/ext/xatlas/xatlas.cpp @@ -3,9 +3,12 @@ #include #define UF_XATLAS_UNWRAP_MULTITHREAD 1 -#define UF_XATLAS_LAZY 1 // i do not understand why it needs to insert extra vertices for it to not even be used in the indices buffer, this flag avoids having to account for it +#define UF_XATLAS_LAZY 0 // i do not understand why it needs to insert extra vertices for it to not even be used in the indices buffer, this flag avoids having to account for it -size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { +size_t UF_API ext::xatlas::unwrap( pod::Graph& graph ) { + return graph.metadata["exporter"]["unwrap lazy"].as(false) ? unwrapLazy( graph ) : unwrapExperimental( graph ); +} +size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { struct Entry { size_t index = 0; size_t commandID = 0; @@ -23,18 +26,35 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { uf::stl::unordered_map atlases; atlases.reserve(graph.meshes.size()); - uf::stl::vector sizes( graph.meshes.size(), 0 ); + uf::stl::unordered_map sizesVertex; + uf::stl::unordered_map sizesIndex; // copy source meshes // create mesh decls for passing to xatlas for ( auto index = 0; index < graph.meshes.size(); ++index ) { auto& name = graph.meshes[index]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; - + sources.emplace_back(mesh).updateDescriptor(); if ( mesh.isInterleaved() ) { UF_EXCEPTION("unwrapping interleaved mesh is not supported"); } - sources.emplace_back(mesh).updateDescriptor(); + + bool should = false; + if ( graph.metadata["exporter"]["unwrap"].is() && graph.metadata["exporter"]["unwrap"].as() ) { + should = true; + } else { + ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) { + // if ( ext::json::isNull( value["unwrap mesh"] ) ) return; + if ( !value["unwrap mesh"].as(false) ) return; + + if ( uf::string::isRegex( key ) ) { + if ( !uf::string::matched( name, key ) ) return; + } else if ( name != key ) return; + should = true; + }); + } + if ( !should ) continue; + uf::Mesh::Input vertexInput = mesh.vertex; @@ -65,7 +85,7 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); for ( auto i = 0; i < mesh.indirect.count; ++i ) { - size_t atlasID = combined ? 0 : drawCommands[i].auxID; + size_t atlasID = drawCommands[i].auxID; vertexInput = mesh.remapVertexInput( i ); indexInput = mesh.remapIndexInput( i ); @@ -152,27 +172,22 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { tasks.queue([&]{ auto& atlas = pair.second; ::xatlas::Generate(atlas.pointer, chartOptions, packOptions); - #if !UF_XATLAS_LAZY - // get vertices size ahead of time - for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) { - auto& xmesh = atlas.pointer->meshes[i]; - auto& entry = atlas.entries[i]; - // atlas.vertices += xmesh.vertexCount; - sizes[entry.index] += xmesh.vertexCount; - } - #endif }); } uf::thread::execute( tasks ); -#if !UF_XATLAS_LAZY for ( auto& pair : atlases ) { auto& atlas = pair.second; // get vertices size ahead of time for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) { auto& xmesh = atlas.pointer->meshes[i]; auto& entry = atlas.entries[i]; - sizes[entry.index] += xmesh.vertexCount; + + if ( sizesVertex.count(entry.index) == 0 ) sizesVertex[entry.index] = 0; + if ( sizesIndex.count(entry.index) == 0 ) sizesIndex[entry.index] = 0; + + sizesVertex[entry.index] += xmesh.vertexCount; + sizesIndex[entry.index] += xmesh.indexCount; } } @@ -180,12 +195,65 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { for ( auto i = 0; i < graph.meshes.size(); ++i ) { auto& name = graph.meshes[i]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; - if ( sizes[i] != mesh.vertex.count ) { - mesh.resizeVertices( sizes[i] ); - mesh.updateDescriptor(); + if ( sizesVertex[i] != mesh.vertex.count ) { + mesh.resizeVertices( sizesVertex[i] ); + } + if ( sizesIndex[i] != mesh.index.count ) { + mesh.resizeIndices( sizesIndex[i] ); + } + mesh.updateDescriptor(); + } + + // update vertices count + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) { + auto& xmesh = atlas.pointer->meshes[i]; + auto& entry = atlas.entries[i]; + auto& name = graph.meshes[entry.index]; + auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; + auto& source = sources[entry.index]; + source.updateDescriptor(); + + // draw commands + if ( !mesh.indirect.count ) continue; + + auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; + pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); + + auto& primitive = primitives[entry.commandID]; + auto& drawCommand = drawCommands[entry.commandID]; + + drawCommand.vertices = xmesh.vertexCount; + drawCommand.indices = xmesh.indexCount; + } + } + + // update vertexID offsets for indirect commands + for ( auto index = 0; index < graph.meshes.size(); ++index ) { + auto& name = graph.meshes[index]; + auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; + + if ( !mesh.indirect.count ) continue; + + auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; + pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); + + size_t vertexID = 0; + size_t indexID = 0; + + for ( auto i = 0; i < mesh.indirect.count; ++i ) { + auto& primitive = primitives[i]; + auto& drawCommand = drawCommands[i]; + + drawCommand.vertexID = vertexID; + drawCommand.indexID = indexID; + primitive.drawCommand = drawCommand; + + vertexID += drawCommand.vertices; + indexID += drawCommand.indices; } } -#endif // update vertices for ( auto& pair : atlases ) { @@ -204,51 +272,44 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { auto srcInput = source.remapVertexInput( entry.commandID ); auto dstInput = mesh.remapVertexInput( entry.commandID ); - #if UF_XATLAS_LAZY - for ( auto j = 0; j < xmesh.vertexCount; ++j ) { - auto& vertex = xmesh.vertexArray[j]; - auto ref = vertex.xref; - - for ( auto k = 0; k < srcInput.attributes.size(); ++k ) { - auto dstAttribute = dstInput.attributes[k]; - if ( dstAttribute.descriptor.name != "st" ) continue; - pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (ref + dstInput.first) ); - st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };; - } - } - #else auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); - bool mismatched = xmesh.vertexCount != drawCommands[entry.commandID].vertices; - vertexIDOffset += xmesh.vertexCount - drawCommands[entry.commandID].vertices; - - drawCommands[entry.commandID].vertices = xmesh.vertexCount; - primitives[entry.commandID].drawCommand.vertices = xmesh.vertexCount; - drawCommands[entry.commandID].vertexID += vertexIDOffset; - primitives[entry.commandID].drawCommand.vertexID += vertexIDOffset; + auto& drawCommand = drawCommands[entry.commandID]; + auto& primitive = primitives[entry.commandID]; for ( auto j = 0; j < xmesh.vertexCount; ++j ) { auto& vertex = xmesh.vertexArray[j]; auto ref = vertex.xref; - for ( auto k = 0; k < srcInput.attributes.size(); ++k ) { - auto srcAttribute = srcInput.attributes[k]; - auto dstAttribute = dstInput.attributes[k]; + for ( auto _ = 0; _ < srcInput.attributes.size(); ++_ ) { + auto srcAttribute = srcInput.attributes[_]; + auto dstAttribute = dstInput.attributes[_]; - if ( dstAttribute.descriptor.name == "st" ) { - pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) ); - st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };; - } else { - memcpy( static_cast(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride ); - } + memcpy( + static_cast(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), + static_cast(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), + srcAttribute.stride + ); } } + + for ( auto j = 0; j < xmesh.vertexCount; ++j ) { + auto& vertex = xmesh.vertexArray[j]; + auto ref = vertex.xref; + + for ( auto _ = 0; _ < srcInput.attributes.size(); ++_ ) { + auto dstAttribute = dstInput.attributes[_]; + if ( dstAttribute.descriptor.name != "st" ) continue; + pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) ); + st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };; + } + } + // indices if ( mesh.index.count ) { uf::Mesh::Input indexInput = mesh.remapIndexInput( entry.commandID ); - uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front(); - // uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.commandID ); + uf::Mesh::Attribute indexAttribute = indexInput.attributes.front(); uint8_t* pointer = (uint8_t*) static_cast(indexAttribute.pointer) + indexAttribute.stride * indexInput.first; for ( auto index = 0; index < xmesh.indexCount; ++index ) { switch ( mesh.index.size ) { @@ -258,29 +319,12 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { } } } - #endif } else { uf::Mesh::Attribute stAttribute; for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "st" ) stAttribute = attribute; UF_ASSERT( stAttribute.descriptor.name == "st" ); // vertices - #if UF_XATLAS_LAZY - auto srcInput = source.vertex; - auto dstInput = mesh.vertex; - - for ( auto j = 0; j < xmesh.vertexCount; ++j ) { - auto& vertex = xmesh.vertexArray[j]; - auto ref = vertex.xref; - - for ( auto k = 0; k < srcInput.attributes.size(); ++k ) { - auto dstAttribute = dstInput.attributes[k]; - if ( dstAttribute.descriptor.name != "st" ) continue; - pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (ref + dstInput.first) ); - st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };; - } - } - #else for ( auto j = 0; j < xmesh.vertexCount; ++j ) { auto& vertex = xmesh.vertexArray[j]; auto ref = vertex.xref; @@ -290,33 +334,12 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { auto dstAttribute = mesh.vertex.attributes[k]; if ( dstAttribute.descriptor.name == "st" ) { - pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j); + pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * (mesh.vertex.first + j)); st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height }; } else { memcpy( static_cast(dstAttribute.pointer) + dstAttribute.stride * j, static_cast(srcAttribute.pointer) + srcAttribute.stride * ref, srcAttribute.stride ); } } - /* - if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) { - uint8_t* srcAttribute = source.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size; - uint8_t* dstAttribute = mesh.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size; - - memcpy( dstAttribute, srcAttribute, mesh.vertex.size ); - - pod::Vector2f& st = *(pod::Vector2f*) (dstAttribute + stAttribute.descriptor.offset); - st = { vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height }; - } else for ( auto& attribute : mesh.vertex.attributes ) { - uint8_t* srcAttribute = source.buffers[attribute.buffer].data() + j * attribute.descriptor.size; - uint8_t* dstAttribute = mesh.buffers[attribute.buffer].data() + j * attribute.descriptor.size; - - if ( attribute.descriptor.name == "st" ) { - pod::Vector2f& st = *(pod::Vector2f*) dstAttribute; - st = { vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height }; - } else { - memcpy( dstAttribute, srcAttribute, attribute.descriptor.size ); - } - } - */ } // indices if ( mesh.index.count ) { @@ -330,37 +353,223 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { } } } - #endif } mesh.updateDescriptor(); } } -#if !UF_XATLAS_LAZY - // update vertexID offsets for indirect commands - for ( auto index = 0; index < graph.meshes.size(); ++index ) { - auto& name = graph.meshes[index]; - auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; - - if ( !mesh.indirect.count ) continue; - - auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; - pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); - - - size_t vertexID = 0; - for ( auto i = 0; i < mesh.indirect.count; ++i ) { - auto& primitive = primitives[i]; - auto& drawCommand = drawCommands[i]; - - drawCommand.vertexID = vertexID; - primitive.drawCommand.vertexID = vertexID; - - vertexID += drawCommand.vertices; - } - } -#endif - + // cleanup + size_t atlasCount = 0; + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + ::xatlas::Destroy(atlas.pointer); + ++atlasCount; + } + return atlasCount; +} + +size_t UF_API ext::xatlas::unwrapLazy( pod::Graph& graph ) { + struct Entry { + size_t index = 0; + size_t commandID = 0; + ::xatlas::MeshDecl decl; + }; + struct Atlas { + ::xatlas::Atlas* pointer = NULL; + uf::stl::vector entries; + size_t vertexOffset = 0; + }; + + uf::stl::unordered_map atlases; + atlases.reserve(graph.meshes.size()); + + // copy source meshes + // create mesh decls for passing to xatlas + for ( auto index = 0; index < graph.meshes.size(); ++index ) { + auto& name = graph.meshes[index]; + auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; + + if ( mesh.isInterleaved() ) { + UF_EXCEPTION("unwrapping interleaved mesh is not supported"); + } + + bool should = false; + if ( graph.metadata["exporter"]["unwrap"].is() && graph.metadata["exporter"]["unwrap"].as() ) { + should = true; + } else { + ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) { + // if ( ext::json::isNull( value["unwrap mesh"] ) ) return; + if ( !value["unwrap mesh"].as(false) ) return; + + if ( uf::string::isRegex( key ) ) { + if ( !uf::string::matched( name, key ) ) return; + } else if ( name != key ) return; + should = true; + }); + } + if ( !should ) continue; + + + uf::Mesh::Input vertexInput = mesh.vertex; + + uf::Mesh::Attribute positionAttribute; + uf::Mesh::Attribute uvAttribute; + uf::Mesh::Attribute stAttribute; + + for ( auto& attribute : mesh.vertex.attributes ) { + if ( attribute.descriptor.name == "position" ) positionAttribute = attribute; + else if ( attribute.descriptor.name == "uv" ) uvAttribute = attribute; + else if ( attribute.descriptor.name == "st" ) stAttribute = attribute; + } + UF_ASSERT( positionAttribute.descriptor.name == "position" && uvAttribute.descriptor.name == "uv" && stAttribute.descriptor.name == "st" ); + + if ( mesh.index.count ) { + uf::Mesh::Input indexInput = mesh.index; + uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front(); + + ::xatlas::IndexFormat indexType = ::xatlas::IndexFormat::UInt32; + switch ( mesh.index.size ) { + case sizeof(uint16_t): indexType = ::xatlas::IndexFormat::UInt16; break; + case sizeof(uint32_t): indexType = ::xatlas::IndexFormat::UInt32; break; + default: UF_EXCEPTION("unsupported index type"); break; + } + + if ( mesh.indirect.count ) { + auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; + pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); + + for ( auto i = 0; i < mesh.indirect.count; ++i ) { + size_t atlasID = drawCommands[i].auxID; + + vertexInput = mesh.remapVertexInput( i ); + indexInput = mesh.remapIndexInput( i ); + + auto& atlas = atlases[atlasID]; + auto& entry = atlas.entries.emplace_back(); + entry.index = index; + entry.commandID = i; + + auto& decl = entry.decl; + + decl.vertexPositionData = static_cast(positionAttribute.pointer) + positionAttribute.stride * vertexInput.first; + decl.vertexPositionStride = positionAttribute.stride; + + decl.vertexUvData = static_cast(uvAttribute.pointer) + uvAttribute.stride * vertexInput.first; + decl.vertexUvStride = uvAttribute.stride; + + decl.vertexCount = vertexInput.count; + + decl.indexCount = indexInput.count; + decl.indexData = static_cast(indexAttribute.pointer) + indexAttribute.stride * indexInput.first; + decl.indexFormat = indexType; + } + } else { + size_t atlasID = 0; + auto& atlas = atlases[atlasID]; + auto& entry = atlas.entries.emplace_back(); + entry.index = index; + + auto& decl = entry.decl; + decl.vertexPositionData = static_cast(positionAttribute.pointer) + positionAttribute.stride * vertexInput.first; + decl.vertexPositionStride = positionAttribute.stride; + + decl.vertexUvData = static_cast(uvAttribute.pointer) + uvAttribute.stride * vertexInput.first; + decl.vertexUvStride = uvAttribute.stride; + + decl.vertexCount = vertexInput.count; + + decl.indexCount = indexInput.count; + decl.indexData = static_cast(indexAttribute.pointer) + indexAttribute.stride * indexInput.first; + decl.indexFormat = indexType; + } + } else UF_EXCEPTION("to-do: not require indices for meshes"); + } + + // add mesh decls to mesh atlases + // done after the fact since we'll know the total amount of meshes added + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create(); + + for ( auto& entry : atlas.entries ) { + ::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size()); + if (error != ::xatlas::AddMeshError::Success) { + ::xatlas::Destroy(atlas.pointer); + UF_EXCEPTION(::xatlas::StringForEnum(error)); + } + } + } + + ::xatlas::ChartOptions chartOptions{}; + chartOptions.useInputMeshUvs = graph.metadata["baking"]["settings"]["useInputMeshUvs"].as(chartOptions.useInputMeshUvs); + chartOptions.maxIterations = graph.metadata["baking"]["settings"]["maxIterations"].as(chartOptions.maxIterations); + + ::xatlas::PackOptions packOptions{}; + packOptions.maxChartSize = graph.metadata["baking"]["settings"]["maxChartSize"].as(packOptions.maxChartSize); + packOptions.padding = graph.metadata["baking"]["settings"]["padding"].as(packOptions.padding); + packOptions.texelsPerUnit = graph.metadata["baking"]["settings"]["texelsPerUnit"].as(packOptions.texelsPerUnit); + packOptions.bilinear = graph.metadata["baking"]["settings"]["bilinear"].as(packOptions.bilinear); + packOptions.blockAlign = graph.metadata["baking"]["settings"]["blockAlign"].as(packOptions.blockAlign); + packOptions.bruteForce = graph.metadata["baking"]["settings"]["bruteForce"].as(packOptions.bruteForce); + packOptions.createImage = graph.metadata["baking"]["settings"]["createImage"].as(packOptions.createImage); + packOptions.rotateChartsToAxis = graph.metadata["baking"]["settings"]["rotateChartsToAxis"].as(packOptions.rotateChartsToAxis); + packOptions.rotateCharts = graph.metadata["baking"]["settings"]["rotateCharts"].as(packOptions.rotateCharts); + packOptions.resolution = graph.metadata["baking"]["resolution"].as(packOptions.resolution); + + // pack +#if UF_XATLAS_UNWRAP_MULTITHREAD + auto tasks = uf::thread::schedule("Async"); +#else + auto tasks = uf::thread::schedule("Main"); +#endif + for ( auto& pair : atlases ) { + tasks.queue([&]{ + auto& atlas = pair.second; + ::xatlas::Generate(atlas.pointer, chartOptions, packOptions); + }); + } + uf::thread::execute( tasks ); + + // update vertices + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + + for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) { + auto& xmesh = atlas.pointer->meshes[i]; + auto& entry = atlas.entries[i]; + auto& name = graph.meshes[entry.index]; + auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; + + // draw commands + if ( mesh.indirect.count ) { + auto vertexInput = mesh.remapVertexInput( entry.commandID ); + for ( auto j = 0; j < xmesh.vertexCount; ++j ) { + auto& vertex = xmesh.vertexArray[j]; + auto ref = vertex.xref; + + for ( auto k = 0; k < vertexInput.attributes.size(); ++k ) { + auto dstAttribute = vertexInput.attributes[k]; + if ( dstAttribute.descriptor.name != "st" ) continue; + pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (ref + vertexInput.first) ); + st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };; + } + } + } else { + for ( auto j = 0; j < xmesh.vertexCount; ++j ) { + auto& vertex = xmesh.vertexArray[j]; + auto ref = vertex.xref; + + for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) { + auto dstAttribute = mesh.vertex.attributes[k]; + if ( dstAttribute.descriptor.name != "st" ) continue; + pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (ref + mesh.vertex.first) ); + st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };; + } + } + } + mesh.updateDescriptor(); + } + } // cleanup size_t atlasCount = 0; for ( auto& pair : atlases ) { diff --git a/engine/src/utils/mesh/grid.cpp b/engine/src/utils/mesh/grid.cpp index 40c7fb1c..aa5d2641 100644 --- a/engine/src/utils/mesh/grid.cpp +++ b/engine/src/utils/mesh/grid.cpp @@ -187,8 +187,8 @@ void uf::meshgrid::partition( uf::meshgrid::Grid& grid, for ( auto& pair : grid.nodes ) { auto& node = pair.second; auto& meshlet = node.meshlets[primitive.instance.primitiveID]; - // if ( isInside( tri.vertices[0], node.extents.min, node.extents.max ) || isInside( tri.vertices[1], node.extents.min, node.extents.max ) || isInside( tri.vertices[2], node.extents.min, node.extents.max ) ) { - if ( isInside( tri.center, node.extents.min, node.extents.max ) ) { + if ( isInside( tri.vertices[0], node.extents.min, node.extents.max ) || isInside( tri.vertices[1], node.extents.min, node.extents.max ) || isInside( tri.vertices[2], node.extents.min, node.extents.max ) ) { + // if ( isInside( tri.center, node.extents.min, node.extents.max ) ) { meshlet.indices.emplace_back( tri.indices[0] ); meshlet.indices.emplace_back( tri.indices[1] ); meshlet.indices.emplace_back( tri.indices[2] ); @@ -202,8 +202,8 @@ void uf::meshgrid::partition( uf::meshgrid::Grid& grid, found = true; break; } - if ( isInside( tri.vertices[0], node.extents.min, node.extents.max ) || isInside( tri.vertices[1], node.extents.min, node.extents.max ) || isInside( tri.vertices[2], node.extents.min, node.extents.max ) ) { - // if ( isInside( tri.center, node.extents.min, node.extents.max ) ) { + // if ( isInside( tri.vertices[0], node.extents.min, node.extents.max ) || isInside( tri.vertices[1], node.extents.min, node.extents.max ) || isInside( tri.vertices[2], node.extents.min, node.extents.max ) ) { + if ( isInside( tri.center, node.extents.min, node.extents.max ) ) { meshlet.indices.emplace_back( tri.indices[0] ); meshlet.indices.emplace_back( tri.indices[1] ); meshlet.indices.emplace_back( tri.indices[2] ); diff --git a/ext/behaviors/baking/behavior.cpp b/ext/behaviors/baking/behavior.cpp index 385e90c0..c7926bf9 100644 --- a/ext/behaviors/baking/behavior.cpp +++ b/ext/behaviors/baking/behavior.cpp @@ -56,7 +56,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { auto& renderMode = this->getComponent(); renderMode.execute = false; - renderMode.metadata.type = "single"; + renderMode.metadata.type = "depth"; // "single"; renderMode.metadata.pipeline = "baking"; renderMode.metadata.samples = 1; // renderMode.metadata.views = metadata.max.layers; // gl_Layer doesn't work @@ -88,10 +88,10 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { shader.textures.emplace_back().aliasTexture( metadata.buffers.baked ); }); - UF_MSG_DEBUG("Finished initialiation."); - uf::thread::queue([&]{ + // uf::thread::queue([&]{ uf::renderer::addRenderMode( &renderMode, metadata.renderModeName ); - }); + // }); + UF_MSG_DEBUG("Finished initialiation."); }); this->queueHook( "entity:PostInitialization.%UID%", ext::json::null(), 1 ); @@ -132,7 +132,7 @@ SAVE: { auto tasks = uf::thread::schedule("Main"); #endif // 0 is always broken, do not save it - for ( size_t i = 1; i < metadata.max.layers; ++i ) { + for ( size_t i = 0; i < metadata.max.layers; ++i ) { tasks.queue([&, i]{ // auto image = renderMode.screenshot(0, i); auto image = metadata.buffers.baked.screenshot(i); diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 4f44cfd9..3b1bfcf3 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -481,11 +481,14 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { renderMode.execute = true; renderMode.metadata.limiter.execute = true; } + constexpr uint32_t MODE_SPLIT = 0; + constexpr uint32_t MODE_CUBEMAP = 1; + constexpr uint32_t MODE_SEPARATE_2DS = 2; // if point light, and combining is requested - if ( metadata.shadow.experimentalMode > 0 && renderMode.renderTarget.views == 6 ) { + if ( metadata.shadow.typeMap > MODE_SPLIT && renderMode.renderTarget.views == 6 ) { int32_t index = -1; // separated texture2Ds - if ( metadata.shadow.experimentalMode == 2 ) { + if ( metadata.shadow.typeMap == MODE_SEPARATE_2DS ) { index = uf::graph::storage.shadow2Ds.size(); for ( auto& attachment : renderMode.renderTarget.attachments ) { if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; @@ -495,7 +498,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { break; } // cubemapped - } else { + } else if ( metadata.shadow.typeMap == MODE_CUBEMAP ) { index = uf::graph::storage.shadowCubes.size(); for ( auto& attachment : renderMode.renderTarget.attachments ) { if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; @@ -511,7 +514,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { .color = info.color, .intensity = info.intensity, .type = info.type, - .typeMap = metadata.shadow.experimentalMode, + .typeMap = metadata.shadow.typeMap, .indexMap = index, .depthBias = info.bias, }); @@ -604,7 +607,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali /*this->*/shadow.samples = ext::config["engine"]["scenes"]["shadows"]["samples"].as(); /*this->*/shadow.max = ext::config["engine"]["scenes"]["shadows"]["max"].as(); /*this->*/shadow.update = ext::config["engine"]["scenes"]["shadows"]["update"].as(); - /*this->*/shadow.experimentalMode = ext::config["engine"]["scenes"]["shadows"]["experimental mode"].as(0); + /*this->*/shadow.typeMap = ext::config["engine"]["scenes"]["shadows"]["map type"].as(1); /*this->*/light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as(true) && serializer["light"]["should"].as(true); /*this->*/light.max = ext::config["engine"]["scenes"]["lights"]["max"].as(/*this->*/light.max); @@ -737,8 +740,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string alignas(4) float voxelizeScale; alignas(4) float occlusionFalloff; + alignas(4) float traceStartOffsetFactor; alignas(4) uint32_t shadows; - alignas(4) uint32_t padding1; alignas(4) uint32_t padding2; alignas(4) uint32_t padding3; } vxgi; @@ -842,6 +845,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string .voxelizeScale = 1.0f / (metadataVxgi.voxelizeScale * std::max( metadataVxgi.voxelSize.x, std::max(metadataVxgi.voxelSize.y, metadataVxgi.voxelSize.z))), .occlusionFalloff = metadataVxgi.occlusionFalloff, + .traceStartOffsetFactor = metadataVxgi.traceStartOffsetFactor, .shadows = metadataVxgi.shadows, }; diff --git a/ext/behaviors/scene/behavior.h b/ext/behaviors/scene/behavior.h index 71977537..3057edec 100644 --- a/ext/behaviors/scene/behavior.h +++ b/ext/behaviors/scene/behavior.h @@ -38,8 +38,7 @@ namespace ext { int samples = 4; int max = 8; uint32_t update = 4; - - uint32_t experimentalMode = 0; + uint32_t typeMap = 1; } shadow; struct { uint32_t mode; diff --git a/ext/behaviors/voxelizer/behavior.cpp b/ext/behaviors/voxelizer/behavior.cpp index c264bdd6..5029f4ee 100644 --- a/ext/behaviors/voxelizer/behavior.cpp +++ b/ext/behaviors/voxelizer/behavior.cpp @@ -397,8 +397,8 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) { /*alignas(4)*/ float voxelizeScale; /*alignas(4)*/ float occlusionFalloff; + /*alignas(4)*/ float traceStartOffsetFactor; /*alignas(4)*/ uint32_t shadows; - /*alignas(4)*/ uint32_t padding1; /*alignas(4)*/ uint32_t padding2; /*alignas(4)*/ uint32_t padding3; }; @@ -415,6 +415,7 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) { .voxelizeScale = 1.0f / (metadata.voxelizeScale * std::max( metadata.voxelSize.x, std::max(metadata.voxelSize.y, metadata.voxelSize.z))), .occlusionFalloff = metadata.occlusionFalloff, + .traceStartOffsetFactor = metadata.traceStartOffsetFactor, .shadows = metadata.shadows, }; shader.updateUniform( "UBO", uniform ); @@ -426,6 +427,7 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) { .voxelizeScale = 1.0f / (metadata.voxelizeScale * std::max( metadata.voxelSize.x, std::max(metadata.voxelSize.y, metadata.voxelSize.z))), .occlusionFalloff = metadata.occlusionFalloff, + .traceStartOffsetFactor = metadata.traceStartOffsetFactor, .shadows = metadata.shadows, }; shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") ); @@ -459,6 +461,7 @@ void ext::VoxelizerBehavior::Metadata::serialize( uf::Object& self, uf::Serializ serializer["vxgi"]["granularity"] = /*this->*/granularity; serializer["vxgi"]["voxelizeScale"] = /*this->*/voxelizeScale; serializer["vxgi"]["occlusionFalloff"] = /*this->*/occlusionFalloff; + serializer["vxgi"]["traceStartOffsetFactor"] = /*this->*/traceStartOffsetFactor; serializer["vxgi"]["shadows"] = /*this->*/shadows; serializer["vxgi"]["extents"]["min"] = uf::vector::encode(/*this->*/extents.min); @@ -480,6 +483,7 @@ void ext::VoxelizerBehavior::Metadata::deserialize( uf::Object& self, uf::Serial /*this->*/granularity = serializer["vxgi"]["granularity"].as(4); /*this->*/voxelizeScale = serializer["vxgi"]["voxelizeScale"].as(1); /*this->*/occlusionFalloff = serializer["vxgi"]["occlusionFalloff"].as(128); + /*this->*/traceStartOffsetFactor = serializer["vxgi"]["traceStartOffsetFactor"].as(1.0f); /*this->*/shadows = serializer["vxgi"]["shadows"].as(0); /*this->*/extents.min = uf::vector::decode( serializer["vxgi"]["extents"]["min"], pod::Vector3f{-32, -32, -32} ); diff --git a/ext/behaviors/voxelizer/behavior.h b/ext/behaviors/voxelizer/behavior.h index 0124b9e9..f794a4be 100644 --- a/ext/behaviors/voxelizer/behavior.h +++ b/ext/behaviors/voxelizer/behavior.h @@ -23,6 +23,7 @@ namespace ext { float granularity = 0; float voxelizeScale = 0; float occlusionFalloff = 0; + float traceStartOffsetFactor = 1.0f; uint32_t shadows = 0; struct { diff --git a/ext/main.cpp b/ext/main.cpp index 2592a001..893d2760 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -210,7 +210,11 @@ void EXT_API ext::initialize() { } { uf::Mesh::defaultInterleaved = ::json["engine"]["scenes"]["meshes"]["interleaved"].as( uf::Mesh::defaultInterleaved ); + #if UF_USE_OPENGL + uf::matrix::reverseInfiniteProjection = false; + #else uf::matrix::reverseInfiniteProjection = ::json["engine"]["scenes"]["matrix"]["reverseInfinite"].as( uf::matrix::reverseInfiniteProjection ); + #endif } /* Create initial scene (kludge) */ {