Commit for 2022.06.13 01-15-08.7z
This commit is contained in:
parent
e38c08ff85
commit
4b7a9d5714
@ -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 },
|
||||
|
||||
@ -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
|
||||
}
|
||||
},
|
||||
|
||||
@ -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 },
|
||||
|
||||
|
||||
@ -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 ]
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -180,8 +180,8 @@ struct Vxgi {
|
||||
float voxelizeScale;
|
||||
float occlusionFalloff;
|
||||
|
||||
float traceStartOffsetFactor;
|
||||
uint shadows;
|
||||
uint padding1;
|
||||
uint padding2;
|
||||
uint padding3;
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -50,8 +50,7 @@ namespace ext {
|
||||
virtual ext::opengl::Graphic* getBlitter(size_t = 0);
|
||||
virtual uf::stl::vector<ext::opengl::Graphic*> 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 );
|
||||
|
||||
@ -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<std::mutex> guardMutex( std::thread::id = std::this_thread::get_id() );
|
||||
|
||||
virtual ~RenderMode();
|
||||
// RAII
|
||||
|
||||
@ -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
|
||||
@ -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;\
|
||||
}
|
||||
|
||||
|
||||
@ -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<std::mutex> 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<std::mutex> guardMutex( id_t id = std::this_thread::get_id() );
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -16,17 +16,22 @@ T& uf::ThreadUnique<T>::get( id_t id ) {
|
||||
return m_container[id];
|
||||
}
|
||||
template<typename T>
|
||||
void uf::ThreadUnique<T>::lock( id_t id ) {
|
||||
void uf::ThreadUnique<T>::lockMutex( id_t id ) {
|
||||
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
|
||||
m_mutex_container[id]->lock();
|
||||
}
|
||||
template<typename T>
|
||||
void uf::ThreadUnique<T>::unlock( id_t id ) {
|
||||
bool uf::ThreadUnique<T>::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<typename T>
|
||||
void uf::ThreadUnique<T>::unlockMutex( id_t id ) {
|
||||
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
|
||||
m_mutex_container[id]->unlock();
|
||||
}
|
||||
template<typename T>
|
||||
std::lock_guard<std::mutex> uf::ThreadUnique<T>::guard( id_t id ) {
|
||||
std::lock_guard<std::mutex> uf::ThreadUnique<T>::guardMutex( id_t id ) {
|
||||
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
|
||||
return std::lock_guard<std::mutex>(*m_mutex_container[id]);
|
||||
}
|
||||
|
||||
@ -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("");
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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<bool>() && !(metadataLight["shadows"].as<bool>() || metadataLight["dynamic"].as<bool>())) ) {
|
||||
// {
|
||||
auto& metadataJson = entity.getComponent<uf::Serializer>();
|
||||
@ -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<size_t, pod::Matrix4f> 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<uf::ObjectBehavior::Metadata>();
|
||||
if ( metadata.system.ignoreGraph ) continue;
|
||||
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
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<bool>()) ) return;
|
||||
if ( !(graph.metadata["flags"]["SKINNED"].as<bool>()) ) {
|
||||
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<uf::Graphic>() ) {
|
||||
auto& graphic = node.entity->getComponent<uf::Graphic>();
|
||||
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<pod::Instance> instances; instances.reserve(uf::graph::storage.instances.map.size());
|
||||
uf::stl::vector<pod::Matrix4f> 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<pod::Matrix4f> 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<pod::DrawCommand> drawCommands; drawCommands.reserve(uf::graph::storage.drawCommands.map.size());
|
||||
|
||||
@ -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<bool>(true) ) {
|
||||
if ( graph.metadata["exporter"]["unwrap"].as<bool>(true) || graph.metadata["exporter"]["unwrap"].as<uf::stl::string>() == "tagged" ) {
|
||||
UF_MSG_DEBUG( "Generating ST's..." );
|
||||
size_t atlases = ext::xatlas::unwrap( graph );
|
||||
UF_MSG_DEBUG( "Generated ST's for " << atlases << " lightmaps" );
|
||||
|
||||
@ -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<uf::stl::string> 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<uf::Graphic>();
|
||||
graphic.destroy();
|
||||
}
|
||||
*/
|
||||
for ( auto& renderMode : renderModes ) {
|
||||
if ( !renderMode ) continue;
|
||||
renderMode->destroy();
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -13,6 +13,7 @@ const uf::stl::string ext::opengl::BaseRenderMode::getType() const {
|
||||
return "Swapchain";
|
||||
}
|
||||
void ext::opengl::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ext::opengl::Graphic*>& 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::vector<ex
|
||||
graphic->record( 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() {
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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<std::mutex> ext::vulkan::RenderMode::guardMutex( std::thread::id id ) {
|
||||
return this->commands.guardMutex( id );
|
||||
}
|
||||
void ext::vulkan::RenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
|
||||
|
||||
|
||||
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,9 +3,12 @@
|
||||
#include <xatlas/xatlas.h>
|
||||
|
||||
#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<bool>(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<size_t, Atlas> atlases;
|
||||
atlases.reserve(graph.meshes.size());
|
||||
|
||||
uf::stl::vector<size_t> sizes( graph.meshes.size(), 0 );
|
||||
uf::stl::unordered_map<size_t, size_t> sizesVertex;
|
||||
uf::stl::unordered_map<size_t, size_t> 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<bool>() && graph.metadata["exporter"]["unwrap"].as<bool>() ) {
|
||||
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<bool>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride );
|
||||
}
|
||||
memcpy(
|
||||
static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first),
|
||||
static_cast<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * j, static_cast<uint8_t*>(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<Entry> entries;
|
||||
size_t vertexOffset = 0;
|
||||
};
|
||||
|
||||
uf::stl::unordered_map<size_t, Atlas> 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<bool>() && graph.metadata["exporter"]["unwrap"].as<bool>() ) {
|
||||
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<bool>(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<uint8_t*>(positionAttribute.pointer) + positionAttribute.stride * vertexInput.first;
|
||||
decl.vertexPositionStride = positionAttribute.stride;
|
||||
|
||||
decl.vertexUvData = static_cast<uint8_t*>(uvAttribute.pointer) + uvAttribute.stride * vertexInput.first;
|
||||
decl.vertexUvStride = uvAttribute.stride;
|
||||
|
||||
decl.vertexCount = vertexInput.count;
|
||||
|
||||
decl.indexCount = indexInput.count;
|
||||
decl.indexData = static_cast<uint8_t*>(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<uint8_t*>(positionAttribute.pointer) + positionAttribute.stride * vertexInput.first;
|
||||
decl.vertexPositionStride = positionAttribute.stride;
|
||||
|
||||
decl.vertexUvData = static_cast<uint8_t*>(uvAttribute.pointer) + uvAttribute.stride * vertexInput.first;
|
||||
decl.vertexUvStride = uvAttribute.stride;
|
||||
|
||||
decl.vertexCount = vertexInput.count;
|
||||
|
||||
decl.indexCount = indexInput.count;
|
||||
decl.indexData = static_cast<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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 ) {
|
||||
|
||||
@ -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] );
|
||||
|
||||
@ -56,7 +56,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
|
||||
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);
|
||||
|
||||
@ -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<uint32_t>();
|
||||
/*this->*/shadow.max = ext::config["engine"]["scenes"]["shadows"]["max"].as<uint32_t>();
|
||||
/*this->*/shadow.update = ext::config["engine"]["scenes"]["shadows"]["update"].as<uint32_t>();
|
||||
/*this->*/shadow.experimentalMode = ext::config["engine"]["scenes"]["shadows"]["experimental mode"].as<uint32_t>(0);
|
||||
/*this->*/shadow.typeMap = ext::config["engine"]["scenes"]["shadows"]["map type"].as<uint32_t>(1);
|
||||
|
||||
/*this->*/light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as<bool>(true) && serializer["light"]["should"].as<bool>(true);
|
||||
/*this->*/light.max = ext::config["engine"]["scenes"]["lights"]["max"].as<uint32_t>(/*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<uint32_t>( metadataVxgi.voxelSize.x, std::max<uint32_t>(metadataVxgi.voxelSize.y, metadataVxgi.voxelSize.z))),
|
||||
.occlusionFalloff = metadataVxgi.occlusionFalloff,
|
||||
|
||||
.traceStartOffsetFactor = metadataVxgi.traceStartOffsetFactor,
|
||||
.shadows = metadataVxgi.shadows,
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<uint32_t>( metadata.voxelSize.x, std::max<uint32_t>(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<uint32_t>( metadata.voxelSize.x, std::max<uint32_t>(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<float>(4);
|
||||
/*this->*/voxelizeScale = serializer["vxgi"]["voxelizeScale"].as<float>(1);
|
||||
/*this->*/occlusionFalloff = serializer["vxgi"]["occlusionFalloff"].as<float>(128);
|
||||
/*this->*/traceStartOffsetFactor = serializer["vxgi"]["traceStartOffsetFactor"].as<float>(1.0f);
|
||||
/*this->*/shadows = serializer["vxgi"]["shadows"].as<size_t>(0);
|
||||
|
||||
/*this->*/extents.min = uf::vector::decode( serializer["vxgi"]["extents"]["min"], pod::Vector3f{-32, -32, -32} );
|
||||
|
||||
@ -23,6 +23,7 @@ namespace ext {
|
||||
float granularity = 0;
|
||||
float voxelizeScale = 0;
|
||||
float occlusionFalloff = 0;
|
||||
float traceStartOffsetFactor = 1.0f;
|
||||
uint32_t shadows = 0;
|
||||
|
||||
struct {
|
||||
|
||||
@ -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) */ {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user