more engine cleanup and fixes (removed the footgun of texture2Ds/instanceAddresses, parse VMT values into material information, re-parent nodes for BSP loader, hopefully final VFS integration fixes)
This commit is contained in:
parent
98ec4933da
commit
22fb850709
@ -4,7 +4,7 @@
|
||||
"start": "StartMenu",
|
||||
"matrix": { "reverseInfinite": true },
|
||||
"lights": { "enabled": true,
|
||||
"lightmaps": true,
|
||||
"lightmaps": false,
|
||||
"max": 32,
|
||||
"shadows": {
|
||||
"enabled": true,
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
// regexp matches
|
||||
// "/^worldspawn_/": { "physics": { "type": "mesh", "static": true } },
|
||||
"/^func_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"/^prop_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
// "/^prop_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"/^prop_static/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ },
|
||||
"/^prop_dynamic/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ },
|
||||
"/^func_physbox/": { "action": "load", "payload": { "import": "/prop.json" } },
|
||||
|
||||
@ -355,38 +355,38 @@ uvec4 uvec2_16x4( uvec2 i ) {
|
||||
}
|
||||
|
||||
#if BUFFER_REFERENCE
|
||||
void populateSurface( InstanceAddresses instanceAddresses, uvec3 indices ) {
|
||||
void populateSurface( InstanceAddresses addresses, uvec3 indices ) {
|
||||
Triangle triangle;
|
||||
Vertex points[3];
|
||||
if ( false && isValidAddress(instanceAddresses.vertex) ) {
|
||||
// Vertices vertices = Vertices(nonuniformEXT(instanceAddresses.vertex));
|
||||
if ( false && isValidAddress(addresses.vertex) ) {
|
||||
// Vertices vertices = Vertices(nonuniformEXT(addresses.vertex));
|
||||
// #pragma unroll 3
|
||||
// for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_] = vertices.v[/*triangle.*/indices[_]];
|
||||
} else {
|
||||
if ( isValidAddress(instanceAddresses.position) ) {
|
||||
VPos buf = VPos(nonuniformEXT(instanceAddresses.position));
|
||||
if ( isValidAddress(addresses.position) ) {
|
||||
VPos buf = VPos(nonuniformEXT(addresses.position));
|
||||
#pragma unroll 3
|
||||
for ( uint _ = 0; _ < 3; ++_ ) points[_].position = vec3( buf.v[indices[_]*3+0], buf.v[indices[_]*3+1], buf.v[indices[_]*3+2] );
|
||||
//for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].position[_] = buf.v[/*triangle.*/indices[_]*3+_];
|
||||
}
|
||||
if ( isValidAddress(instanceAddresses.uv) ) {
|
||||
VUv buf = VUv(nonuniformEXT(instanceAddresses.uv));
|
||||
if ( isValidAddress(addresses.uv) ) {
|
||||
VUv buf = VUv(nonuniformEXT(addresses.uv));
|
||||
#pragma unroll 3
|
||||
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].uv/*[_]*/ = buf.v[/*triangle.*/indices[_]];
|
||||
}
|
||||
if ( isValidAddress(instanceAddresses.st) ) {
|
||||
VSt buf = VSt(nonuniformEXT(instanceAddresses.st));
|
||||
if ( isValidAddress(addresses.st) ) {
|
||||
VSt buf = VSt(nonuniformEXT(addresses.st));
|
||||
#pragma unroll 3
|
||||
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].st/*[_]*/ = buf.v[/*triangle.*/indices[_]];
|
||||
}
|
||||
if ( isValidAddress(instanceAddresses.normal) ) {
|
||||
VNormal buf = VNormal(nonuniformEXT(instanceAddresses.normal));
|
||||
if ( isValidAddress(addresses.normal) ) {
|
||||
VNormal buf = VNormal(nonuniformEXT(addresses.normal));
|
||||
#pragma unroll 3
|
||||
for ( uint _ = 0; _ < 3; ++_ ) points[_].normal = vec3( buf.v[indices[_]*3+0], buf.v[indices[_]*3+1], buf.v[indices[_]*3+2] );
|
||||
// for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].normal[_] = buf.v[/*triangle.*/indices[_]*3+_];
|
||||
}
|
||||
if ( isValidAddress(instanceAddresses.tangent) ) {
|
||||
VTangent buf = VTangent(nonuniformEXT(instanceAddresses.tangent));
|
||||
if ( isValidAddress(addresses.tangent) ) {
|
||||
VTangent buf = VTangent(nonuniformEXT(addresses.tangent));
|
||||
#pragma unroll 3
|
||||
for ( uint _ = 0; _ < 3; ++_ ) points[_].tangent = vec3( buf.v[indices[_]*3+0], buf.v[indices[_]*3+1], buf.v[indices[_]*3+2] );
|
||||
// for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].tangent[_] = buf.v[/*triangle.*/indices[_]*3+_];
|
||||
@ -475,23 +475,23 @@ void populateSurface( uint instanceID, uint primitiveID ) {
|
||||
surface.instance = instances[instanceID];
|
||||
surface.object = objects[surface.instance.objectID];
|
||||
|
||||
const InstanceAddresses instanceAddresses = instanceAddresses[instanceID];
|
||||
if ( !isValidAddress(instanceAddresses.index) ) return;
|
||||
const DrawCommand drawCommand = Indirects(nonuniformEXT(instanceAddresses.indirect)).dc[instanceAddresses.drawID];
|
||||
const InstanceAddresses addresses = addresses[instanceID];
|
||||
if ( !isValidAddress(addresses.index) ) return;
|
||||
const DrawCommand drawCommand = Indirects(nonuniformEXT(addresses.indirect)).dc[addresses.drawID];
|
||||
const uint triangleID = primitiveID + (drawCommand.indexID / 3);
|
||||
//uvec3 indices = Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID];
|
||||
//uvec3 indices = Indices(nonuniformEXT(addresses.index)).i[triangleID];
|
||||
|
||||
uvec3 indices = uvec3(
|
||||
Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID*3+0],
|
||||
Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID*3+1],
|
||||
Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID*3+2]
|
||||
Indices(nonuniformEXT(addresses.index)).i[triangleID*3+0],
|
||||
Indices(nonuniformEXT(addresses.index)).i[triangleID*3+1],
|
||||
Indices(nonuniformEXT(addresses.index)).i[triangleID*3+2]
|
||||
);
|
||||
|
||||
|
||||
#pragma unroll 3
|
||||
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/indices[_] += drawCommand.vertexID;
|
||||
|
||||
populateSurface( instanceAddresses, indices );
|
||||
populateSurface( addresses, indices );
|
||||
}
|
||||
void populateSurface( RayTracePayload payload ) {
|
||||
surface.fragment = vec4(0);
|
||||
|
||||
@ -67,7 +67,7 @@ struct Material {
|
||||
|
||||
int indexMetallicRoughness;
|
||||
int padding1;
|
||||
int padding2;
|
||||
int modeCull;
|
||||
int modeAlpha;
|
||||
};
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ layout (std140, binding = 13, set = 0) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 14, set = 0) readonly buffer InstanceAddresseses {
|
||||
InstanceAddresses instanceAddresses[];
|
||||
InstanceAddresses addresses[];
|
||||
};
|
||||
layout (std140, binding = 15, set = 0) readonly buffer Objects {
|
||||
Object objects[];
|
||||
|
||||
@ -34,7 +34,7 @@ layout (std140, binding = 2) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 3) readonly buffer InstanceAddresseses {
|
||||
InstanceAddresses instanceAddresses[];
|
||||
InstanceAddresses addresses[];
|
||||
};
|
||||
layout (std140, binding = 4) readonly buffer Objects {
|
||||
Object objects[];
|
||||
|
||||
@ -45,7 +45,7 @@ layout (std140, binding = 11) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 12) readonly buffer InstanceAddresseses {
|
||||
InstanceAddresses instanceAddresses[];
|
||||
InstanceAddresses addresses[];
|
||||
};
|
||||
layout (std140, binding = 13) readonly buffer Materials {
|
||||
Material materials[];
|
||||
|
||||
@ -35,7 +35,7 @@ layout (std140, binding = 8) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 9) readonly buffer InstanceAddresseses {
|
||||
InstanceAddresses instanceAddresses[];
|
||||
InstanceAddresses addresses[];
|
||||
};
|
||||
layout (std140, binding = 10) readonly buffer Materials {
|
||||
Material materials[];
|
||||
|
||||
@ -17,7 +17,7 @@ layout (std140, binding = 8) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 9) readonly buffer InstanceAddresseses {
|
||||
InstanceAddresses instanceAddresses[];
|
||||
InstanceAddresses addresses[];
|
||||
};
|
||||
layout (std140, binding = 10) readonly buffer Materials {
|
||||
Material materials[];
|
||||
|
||||
@ -24,7 +24,7 @@ layout (std140, binding = 8) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 9) readonly buffer InstanceAddresseses {
|
||||
InstanceAddresses instanceAddresses[];
|
||||
InstanceAddresses addresses[];
|
||||
};
|
||||
|
||||
layout (std140, binding = 10) readonly buffer Materials {
|
||||
|
||||
@ -48,7 +48,7 @@ layout (std140, binding = 4) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 5) readonly buffer InstanceAddresseses {
|
||||
InstanceAddresses instanceAddresses[];
|
||||
InstanceAddresses addresses[];
|
||||
};
|
||||
layout (std140, binding = 6) readonly buffer Objects {
|
||||
Object objects[];
|
||||
|
||||
@ -87,11 +87,11 @@ namespace pod {
|
||||
};
|
||||
|
||||
uf::stl::KeyMap<uf::stl::vector<pod::Instance>> groupedInstances;
|
||||
uf::stl::KeyMap<uf::stl::vector<pod::Instance::Addresses>> instanceAddresses;
|
||||
uf::stl::KeyMap<uf::stl::vector<pod::Instance::Addresses>> addresses;
|
||||
uf::stl::KeyMap<uf::stl::vector<pod::Primitive>> primitives;
|
||||
uf::stl::KeyMap<uf::Mesh> meshes;
|
||||
|
||||
uf::stl::KeyMap<uf::Image> images;
|
||||
uf::stl::KeyMap<pod::ImageTexture> images;
|
||||
uf::stl::KeyMap<pod::Material> materials;
|
||||
uf::stl::KeyMap<pod::Texture> textures;
|
||||
uf::stl::KeyMap<uf::renderer::Sampler> samplers;
|
||||
@ -103,7 +103,6 @@ namespace pod {
|
||||
uf::stl::KeyMap<uf::Atlas> atlases;
|
||||
uf::stl::KeyMap<pod::Instance::Object> objects;
|
||||
uf::stl::KeyMap<uf::stl::vector<pod::Matrix4f>> joints;
|
||||
uf::stl::KeyMap<uf::renderer::Texture2D> texture2Ds;
|
||||
uf::stl::KeyMap<uf::Entity*> entities;
|
||||
|
||||
uf::stl::vector<uf::renderer::Texture2D> shadow2Ds;
|
||||
@ -113,7 +112,7 @@ namespace pod {
|
||||
uf::renderer::Buffer camera;
|
||||
uf::renderer::Buffer drawCommands;
|
||||
uf::renderer::Buffer instance;
|
||||
uf::renderer::Buffer instanceAddresses;
|
||||
uf::renderer::Buffer addresses;
|
||||
uf::renderer::Buffer lodMetadata;
|
||||
uf::renderer::Buffer joint;
|
||||
uf::renderer::Buffer object;
|
||||
@ -155,7 +154,7 @@ namespace uf {
|
||||
const pod::Graph::Storage& UF_API getStorage( const uf::Object& );
|
||||
|
||||
// void UF_API process( uf::Object& entity );
|
||||
void UF_API initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::Mesh& mesh, uf::stl::vector<pod::Instance::Addresses>& );
|
||||
void UF_API initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::Mesh& mesh, uf::stl::vector<pod::Primitive>& );
|
||||
void UF_API process( pod::Graph& graph );
|
||||
void UF_API process( pod::Graph& graph, int32_t, uf::Object& parent );
|
||||
void UF_API reload( pod::Graph& );
|
||||
|
||||
@ -4,8 +4,8 @@ namespace pod {
|
||||
pod::Vector4f colorEmissive = { 0, 0, 0, 0 };
|
||||
|
||||
float factorMetallic = 0.0f;
|
||||
float factorRoughness = 0.0f;
|
||||
float factorOcclusion = 0.0f;
|
||||
float factorRoughness = 1.0f;
|
||||
float factorOcclusion = 1.0f;
|
||||
float factorAlphaCutoff = 1.0f;
|
||||
|
||||
int32_t indexAlbedo = -1;
|
||||
@ -15,7 +15,7 @@ namespace pod {
|
||||
|
||||
int32_t indexMetallicRoughness = -1;
|
||||
int32_t padding1 = -1;
|
||||
int32_t padding2 = -1;
|
||||
int32_t modeCull = -1;
|
||||
int32_t modeAlpha = -1;
|
||||
};
|
||||
|
||||
@ -92,4 +92,9 @@ namespace pod {
|
||||
pod::Transform<> transform;
|
||||
uf::Serializer metadata;
|
||||
};
|
||||
|
||||
struct UF_API ImageTexture {
|
||||
uf::Image data;
|
||||
uf::renderer::Texture2D handle;
|
||||
};
|
||||
}
|
||||
@ -21,6 +21,7 @@ namespace pod {
|
||||
std::function<size_t(const uf::stl::string&)> mtime;
|
||||
std::function<bool(const uf::stl::string&, uf::stl::vector<uint8_t>&)> read;
|
||||
std::function<size_t(const uf::stl::string&, const void*, size_t)> write;
|
||||
std::function<bool(const uf::stl::string&)> mkdir;
|
||||
|
||||
std::function<bool(const uf::stl::string&, size_t, size_t, uf::stl::vector<uint8_t>&)> readRange;
|
||||
std::function<bool(const uf::stl::string&, const uf::stl::vector<pod::Range>&, uf::stl::vector<uint8_t>&)> readRanges;
|
||||
@ -42,6 +43,7 @@ namespace uf {
|
||||
|
||||
size_t UF_API write( const uf::stl::string& path, const void* data, size_t len );
|
||||
size_t UF_API write( const uf::stl::string& path, uf::stl::vector<uint8_t>& buffer );
|
||||
bool UF_API mkdir( const uf::stl::string& path );
|
||||
|
||||
bool UF_API readRange( const uf::stl::string& path, size_t start, size_t len, uf::stl::vector<uint8_t>& buffer );
|
||||
bool UF_API readRanges( const uf::stl::string& path, const uf::stl::vector<pod::Range>& ranges, uf::stl::vector<uint8_t>& buffer );
|
||||
|
||||
@ -143,6 +143,7 @@ namespace pod {
|
||||
pod::DrawCommand drawCommand;
|
||||
pod::Instance instance;
|
||||
pod::LODMetadata lod;
|
||||
pod::Instance::Addresses addresses;
|
||||
};
|
||||
}
|
||||
|
||||
@ -261,6 +262,7 @@ namespace uf {
|
||||
|
||||
uf::Mesh& copy( const uf::Mesh& );
|
||||
uf::Mesh copy() const;
|
||||
uf::Mesh alias() const;
|
||||
uf::Mesh expand();
|
||||
|
||||
void updateDescriptor();
|
||||
|
||||
@ -86,7 +86,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
uf::stl::vector<uf::renderer::Texture2D> textures2D;
|
||||
uf::stl::vector<uf::renderer::TextureCube> texturesCube;
|
||||
// bind scene textures
|
||||
for ( auto& key : storage.texture2Ds.keys ) textures2D.emplace_back().aliasTexture( storage.texture2Ds.map[key] );
|
||||
for ( auto& key : storage.images.keys ) textures2D.emplace_back().aliasTexture( storage.images.map[key].handle );
|
||||
// bind shadow maps
|
||||
for ( auto& texture : storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture);
|
||||
for ( auto& texture : storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture);
|
||||
|
||||
@ -211,7 +211,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
|
||||
size_t maxCascades = uf::config["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
|
||||
|
||||
shader.aliasBuffer( storage.buffers.instance );
|
||||
shader.aliasBuffer( storage.buffers.instanceAddresses );
|
||||
shader.aliasBuffer( storage.buffers.addresses );
|
||||
shader.aliasBuffer( storage.buffers.object );
|
||||
shader.aliasBuffer( storage.buffers.material );
|
||||
shader.aliasBuffer( storage.buffers.texture );
|
||||
|
||||
@ -1139,7 +1139,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
||||
texturesCube.reserve( metadata.max.texturesCube );
|
||||
|
||||
// bind scene textures
|
||||
for ( auto& key : storage.texture2Ds.keys ) textures2D.emplace_back().aliasTexture( storage.texture2Ds.map[key] );
|
||||
for ( auto& key : storage.images.keys ) textures2D.emplace_back().aliasTexture( storage.images.map[key].handle );
|
||||
|
||||
size_t indexSkybox = 0;
|
||||
size_t indexNoise = 0;
|
||||
|
||||
@ -49,12 +49,12 @@ namespace {
|
||||
size_t materialID = graph.materials.size();
|
||||
for ( auto& t : textures ) {
|
||||
size_t textureID = graph.textures.size();
|
||||
size_t texture2DID = graph.texture2Ds.size();
|
||||
size_t texture2DID = graph.images.size();
|
||||
|
||||
uf::stl::string subName = keyName + "[" + std::to_string(sub++) + "]";
|
||||
auto& material = storage.materials[graph.materials.emplace_back(subName)];
|
||||
auto& texture = storage.textures[graph.textures.emplace_back(subName)];
|
||||
auto& texture2D = storage.texture2Ds[graph.texture2Ds.emplace_back(subName)];
|
||||
auto& texture2D = storage.images[graph.images.emplace_back(subName)].handle;
|
||||
|
||||
material.indexAlbedo = textureID;
|
||||
material.colorBase = {1, 1, 1, 1};
|
||||
@ -66,7 +66,6 @@ namespace {
|
||||
node.mesh = meshID;
|
||||
auto& primitives = storage.primitives[graph.primitives.emplace_back(keyName)];
|
||||
auto& mesh = (storage.meshes[graph.meshes.emplace_back(keyName)] = object.getComponent<uf::Mesh>());
|
||||
auto& instanceAddresses = storage.instanceAddresses[keyName];
|
||||
|
||||
pod::Vector3f boundsMin = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
||||
pod::Vector3f boundsMax = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
|
||||
@ -128,7 +127,7 @@ namespace {
|
||||
primitive.lod.levels[0].vertices = drawCommand.vertices;
|
||||
}
|
||||
|
||||
uf::graph::initializeGraphics( graph, object, mesh, instanceAddresses );
|
||||
uf::graph::initializeGraphics( graph, object, mesh, primitives );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -338,6 +338,7 @@ namespace {
|
||||
.skin = json["skin"].as<int32_t>(-1),
|
||||
.entity = NULL,
|
||||
.transform = uf::transform::decode( json["transform"], pod::Transform<>{} ),
|
||||
.metadata = json["metadata"],
|
||||
};
|
||||
|
||||
node.children.reserve( json["children"].size() );
|
||||
@ -447,7 +448,6 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
auto name = key + value["name"].as<uf::stl::string>();
|
||||
// UF_MSG_DEBUG("{}", name);
|
||||
storage.primitives[name] = decodePrimitives( value, graph );
|
||||
storage.instanceAddresses[name] = {};
|
||||
|
||||
graph.primitives.emplace_back(name);
|
||||
});
|
||||
@ -478,7 +478,9 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
ext::json::forEach( serializer["images"], [&]( ext::json::Value& value ){
|
||||
auto name = key + value["name"].as<uf::stl::string>();
|
||||
// UF_MSG_DEBUG("{}", name);
|
||||
storage.images[name] = decodeImage( value, graph );
|
||||
storage.images[name] = {
|
||||
.data = decodeImage( value, graph ),
|
||||
};
|
||||
graph.images.emplace_back(name);
|
||||
});
|
||||
UF_DEBUG_TIMER_MULTITRACE("Read images");
|
||||
@ -509,9 +511,6 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
// UF_MSG_DEBUG("{}", name);
|
||||
storage.textures[name] = decodeTexture( value, graph );
|
||||
graph.textures.emplace_back(name);
|
||||
|
||||
// pre-allocate
|
||||
storage.texture2Ds[name];
|
||||
});
|
||||
UF_DEBUG_TIMER_MULTITRACE("Read texture information");
|
||||
#if UF_ENV_DREAMCAST
|
||||
|
||||
@ -225,6 +225,7 @@ namespace {
|
||||
for ( auto& child : node.children ) json["children"].emplace_back(child);
|
||||
|
||||
json["transform"] = uf::transform::encode( node.transform, false, settings );
|
||||
json["metadata"] = node.metadata;
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@ -331,7 +332,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
if ( !settings.combined ) {
|
||||
for ( size_t i = 0; i < graph.images.size(); ++i ) {
|
||||
auto& name = graph.images[i];
|
||||
auto& image = /*graph.storage*/storage.images.map.at(name);
|
||||
auto& image = /*graph.storage*/storage.images.map.at(name).data;
|
||||
uf::stl::string f = "image."+std::to_string(i)+".png";
|
||||
image.save(directory + "/" + f);
|
||||
|
||||
@ -350,7 +351,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
}
|
||||
} else {
|
||||
for ( auto& name : graph.images ) {
|
||||
auto& image = /*graph.storage*/storage.images.map.at(name);
|
||||
auto& image = /*graph.storage*/storage.images.map.at(name).data;
|
||||
auto json = encode(image, settings, graph);
|
||||
json["name"] = name;
|
||||
serializer["images"].emplace_back( json );
|
||||
|
||||
@ -69,7 +69,7 @@ namespace {
|
||||
|
||||
auto& storage = uf::graph::getStorage( graph );
|
||||
|
||||
for ( auto& key : storage.texture2Ds.keys ) graphic.material.textures.emplace_back().aliasTexture( storage.texture2Ds.map[key] );
|
||||
for ( auto& key : storage.images.keys ) graphic.material.textures.emplace_back().aliasTexture( storage.images.map[key].handle );
|
||||
|
||||
// bind scene's voxel texture
|
||||
#if 0 && UF_USE_VULKAN
|
||||
@ -395,7 +395,7 @@ namespace {
|
||||
::resetBuffers( shader );
|
||||
shader.aliasBuffer( "drawCommands", storage.buffers.drawCommands );
|
||||
shader.aliasBuffer( "instance", storage.buffers.instance );
|
||||
shader.aliasBuffer( "instanceAddresses", storage.buffers.instanceAddresses );
|
||||
shader.aliasBuffer( "addresses", storage.buffers.addresses );
|
||||
shader.aliasBuffer( "material", storage.buffers.material );
|
||||
shader.aliasBuffer( "texture", storage.buffers.texture );
|
||||
shader.aliasBuffer( "light", storage.buffers.light );
|
||||
@ -413,7 +413,7 @@ namespace {
|
||||
::resetBuffers( shader );
|
||||
shader.aliasBuffer( "drawCommands", storage.buffers.drawCommands );
|
||||
shader.aliasBuffer( "instance", storage.buffers.instance );
|
||||
shader.aliasBuffer( "instanceAddresses", storage.buffers.instanceAddresses );
|
||||
shader.aliasBuffer( "addresses", storage.buffers.addresses );
|
||||
shader.aliasBuffer( "material", storage.buffers.material );
|
||||
shader.aliasBuffer( "texture", storage.buffers.texture );
|
||||
shader.aliasBuffer( "light", storage.buffers.light );
|
||||
@ -445,7 +445,7 @@ namespace {
|
||||
::resetBuffers( shader );
|
||||
shader.aliasBuffer( "drawCommands", storage.buffers.drawCommands );
|
||||
shader.aliasBuffer( "instance", storage.buffers.instance );
|
||||
shader.aliasBuffer( "instanceAddresses", storage.buffers.instanceAddresses );
|
||||
shader.aliasBuffer( "addresses", storage.buffers.addresses );
|
||||
shader.aliasBuffer( "material", storage.buffers.material );
|
||||
shader.aliasBuffer( "texture", storage.buffers.texture );
|
||||
shader.aliasBuffer( "light", storage.buffers.light );
|
||||
@ -474,7 +474,7 @@ namespace {
|
||||
::resetBuffers( shader );
|
||||
shader.aliasBuffer( "drawCommands", storage.buffers.drawCommands );
|
||||
shader.aliasBuffer( "instance", storage.buffers.instance );
|
||||
shader.aliasBuffer( "instanceAddresses", storage.buffers.instanceAddresses );
|
||||
shader.aliasBuffer( "addresses", storage.buffers.addresses );
|
||||
shader.aliasBuffer( "material", storage.buffers.material );
|
||||
shader.aliasBuffer( "texture", storage.buffers.texture );
|
||||
shader.aliasBuffer( "light", storage.buffers.light );
|
||||
@ -483,38 +483,37 @@ namespace {
|
||||
#endif
|
||||
}
|
||||
|
||||
void bindInstanceAddresses( pod::Graph& graph, uf::renderer::Graphic& graphic, uf::Mesh& mesh, uf::stl::vector<pod::Instance::Addresses>& addresses ) {
|
||||
void bindAddresses( pod::Graph& graph, uf::renderer::Graphic& graphic, uf::Mesh& mesh, uf::stl::vector<pod::Primitive>& primitives ) {
|
||||
#if UF_USE_VULKAN
|
||||
if ( !uf::renderer::settings::invariant::deviceAddressing || !mesh.indirect.count ) return;
|
||||
addresses.resize( mesh.indirect.count );
|
||||
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer( mesh.indirect ).data();
|
||||
pod::Instance::Addresses addresses;
|
||||
if ( mesh.vertex.count ) {
|
||||
for ( auto& attribute : graphic.descriptor.inputs.vertex.attributes ) {
|
||||
if ( attribute.buffer < 0 ) continue;
|
||||
if ( attribute.descriptor.name == "position" ) addresses.position = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "uv" ) addresses.uv = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "color" ) addresses.color = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "st" ) addresses.st = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "normal" ) addresses.normal = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "tangent" ) addresses.tangent = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "joints" ) addresses.joints = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "weights" ) addresses.weights = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
}
|
||||
}
|
||||
if ( mesh.index.count ) {
|
||||
addresses.index = graphic.buffers.at(graphic.descriptor.inputs.index.attributes.front().buffer).getAddress();
|
||||
}
|
||||
|
||||
if ( mesh.indirect.count ) {
|
||||
addresses.indirect = graphic.buffers.at(graphic.descriptor.inputs.indirect.attributes.front().buffer).getAddress();
|
||||
}
|
||||
|
||||
for ( size_t drawID = 0; drawID < mesh.indirect.count; ++drawID ) {
|
||||
auto& drawCommand = drawCommands[drawID];
|
||||
auto instanceID = drawCommand.instanceID;
|
||||
|
||||
auto& instanceAddresses = addresses[drawID]; // THIS IS WRONG (to-do: actually use instanceIDs)
|
||||
if ( mesh.vertex.count ) {
|
||||
for ( auto& attribute : graphic.descriptor.inputs.vertex.attributes ) {
|
||||
if ( attribute.buffer < 0 ) continue;
|
||||
if ( attribute.descriptor.name == "position" ) instanceAddresses.position = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "uv" ) instanceAddresses.uv = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "color" ) instanceAddresses.color = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "st" ) instanceAddresses.st = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "normal" ) instanceAddresses.normal = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "tangent" ) instanceAddresses.tangent = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "joints" ) instanceAddresses.joints = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
else if ( attribute.descriptor.name == "weights" ) instanceAddresses.weights = graphic.buffers.at(attribute.buffer).getAddress();
|
||||
}
|
||||
}
|
||||
if ( mesh.index.count ) {
|
||||
instanceAddresses.index = graphic.buffers.at(graphic.descriptor.inputs.index.attributes.front().buffer).getAddress();
|
||||
}
|
||||
|
||||
if ( mesh.indirect.count ) {
|
||||
instanceAddresses.indirect = graphic.buffers.at(graphic.descriptor.inputs.indirect.attributes.front().buffer).getAddress();
|
||||
instanceAddresses.drawID = drawID;
|
||||
}
|
||||
// copy address
|
||||
primitives[drawID].addresses = addresses;
|
||||
// bind draw ID (necessary for deferred pass where we store <instanceID + primitiveID>, to fetch the drawID, to fetch the triangleID) (or something)
|
||||
primitives[drawID].addresses.drawID = drawID;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -696,7 +695,7 @@ const pod::Graph::Storage& uf::graph::getStorage( const pod::Graph& graph ) {
|
||||
return uf::graph::getStorage( g );
|
||||
}
|
||||
|
||||
void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::Mesh& mesh, uf::stl::vector<pod::Instance::Addresses>& addresses ) {
|
||||
void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::Mesh& mesh, uf::stl::vector<pod::Primitive>& primitives ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
|
||||
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
|
||||
@ -731,6 +730,20 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
|
||||
}
|
||||
else UF_MSG_WARNING("Invalid Face enum string specified: {}", mode);
|
||||
}
|
||||
|
||||
// query materials if culling needs to be disabled
|
||||
for ( auto& primitive : primitives ) {
|
||||
auto materialID = primitive.instance.materialID;
|
||||
if ( 0 < materialID && materialID <= graph.materials.size() ) {
|
||||
auto& materialName = graph.materials[materialID];
|
||||
auto& material = storage.materials[materialName];
|
||||
if ( material.modeCull == 0 ) {
|
||||
tag["renderer"]["cull mode"] = "none";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( tag["renderer"]["cull mode"].is<uf::stl::string>() ) {
|
||||
const auto mode = uf::string::lowercase( tag["renderer"]["cull mode"].as<uf::stl::string>() );
|
||||
if ( mode == "back" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BACK;
|
||||
@ -740,10 +753,11 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
|
||||
else UF_MSG_WARNING("Invalid CullMode enum string specified: {}", mode);
|
||||
}
|
||||
|
||||
|
||||
::bindTextures( graph, graphic );
|
||||
::bindShaders( graph, entity, mesh );
|
||||
::bindBuffers( graph, graphic, mesh );
|
||||
::bindInstanceAddresses( graph, graphic, mesh, addresses );
|
||||
::bindAddresses( graph, graphic, mesh, primitives );
|
||||
|
||||
graphic.process = true;
|
||||
}
|
||||
@ -869,7 +883,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
auto imageID = graph.images.size();
|
||||
|
||||
auto& texture = storage.textures[graph.textures.emplace_back(f)];
|
||||
auto& image = storage.images[graph.images.emplace_back(f)];
|
||||
auto& image = storage.images[graph.images.emplace_back(f)].data;
|
||||
if ( !graph.settings.stream.textures ) {
|
||||
image.open( f, false );
|
||||
}
|
||||
@ -894,9 +908,6 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
}
|
||||
}
|
||||
|
||||
// setup textures
|
||||
storage.texture2Ds.reserve( storage.images.map.size() );
|
||||
|
||||
// figure out what texture is what exactly
|
||||
UF_DEBUG_TIMER_MULTITRACE("Determining format of textures");
|
||||
for ( auto& key : graph.materials ) {
|
||||
@ -911,8 +922,8 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
|
||||
UF_DEBUG_TIMER_MULTITRACE("Processing images...");
|
||||
for ( auto& key : graph.images ) {
|
||||
auto& image = storage.images[key];
|
||||
auto& texture = storage.texture2Ds[key];
|
||||
auto& image = storage.images[key].data;
|
||||
auto& texture = storage.images[key].handle;
|
||||
if ( !texture.generated() ) {
|
||||
// set as null
|
||||
if ( graph.settings.stream.textures ) {
|
||||
@ -1177,7 +1188,6 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
if ( graphMetadataJson["baking"]["enabled"].as<bool>(false) && !tag["bake"].as<bool>(true) ) ignore = true;
|
||||
if ( tag["ignore"].as<bool>() ) ignore = true;
|
||||
}
|
||||
bool isLight = graph.lights.count(node.name) > 0;
|
||||
|
||||
if ( ignore ) return;
|
||||
|
||||
@ -1188,6 +1198,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
uf::Object& entity = *pointer;
|
||||
node.entity = &entity;
|
||||
|
||||
auto nameID = ::fmt::format( "{}_{}", node.name, index );
|
||||
bool setName = entity.getName() == "Entity";
|
||||
auto& metadata = entity.getComponent<uf::ObjectBehavior::Metadata>();
|
||||
auto& metadataJson = entity.getComponent<uf::Serializer>();
|
||||
@ -1220,8 +1231,11 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
|
||||
// create as light
|
||||
{
|
||||
if ( isLight ) {
|
||||
auto& l = graph.lights[node.name];
|
||||
// attempt to resolve a light name
|
||||
auto lightName = node.name;
|
||||
if ( graph.lights.count( nameID ) > 0 ) lightName = nameID;
|
||||
if ( graph.lights.count( lightName ) > 0 ) {
|
||||
auto& l = graph.lights[lightName];
|
||||
|
||||
#if UF_USE_OPENGL
|
||||
metadata.system.ignoreGraph = true;
|
||||
@ -1319,10 +1333,9 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
};
|
||||
}
|
||||
|
||||
auto primitiveName = graph.primitives[node.mesh];
|
||||
auto& mesh = storage.meshes.map[graph.meshes[node.mesh]];
|
||||
auto primitiveName = graph.primitives[node.mesh];
|
||||
auto& primitives = storage.primitives.map[primitiveName];
|
||||
auto& grouped = storage.groupedInstances[primitiveName];
|
||||
|
||||
node.object = ::allocateObjectID( storage );
|
||||
auto objectKeyName = std::to_string( node.object );
|
||||
@ -1335,6 +1348,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
|
||||
pod::Instance::Bounds bounds = {};
|
||||
|
||||
auto& grouped = storage.groupedInstances[primitiveName];
|
||||
for ( auto drawID = 0; drawID < primitives.size(); ++drawID ) {
|
||||
pod::Instance newInstance = primitives[drawID].instance;
|
||||
newInstance.objectID = node.object;
|
||||
@ -1349,14 +1363,13 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
bool isFirstInstance = ( grouped.size() == primitives.size() );
|
||||
#if !UF_GRAPH_EXTENDED
|
||||
if ( graphMetadataJson["renderer"]["render"].as<bool>() && isFirstInstance ) {
|
||||
uf::graph::initializeGraphics( graph, entity, mesh, addresses );
|
||||
uf::graph::initializeGraphics( graph, entity, mesh, primitives );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
auto& mesh = storage.meshes.map[graph.meshes[node.mesh]];
|
||||
auto& primitives = storage.primitives.map[graph.primitives[node.mesh]];
|
||||
auto& instanceAddresses = storage.instanceAddresses.map[graph.primitives[node.mesh]];
|
||||
|
||||
pod::Instance::Bounds bounds = {};
|
||||
size_t baseInstanceID = ::allocateInstanceID( storage, graph.primitives[node.mesh] );
|
||||
@ -1449,7 +1462,7 @@ void uf::graph::initialize( pod::Graph::Storage& storage, size_t initialElements
|
||||
// to-do: check if opengl really needs these
|
||||
if ( !storage.buffers.drawCommands.buffer ) storage.buffers.drawCommands.initialize( (const void*) nullptr, sizeof(pod::DrawCommand) * initialElements, uf::renderer::enums::Buffer::STORAGE );
|
||||
if ( !storage.buffers.instance.buffer ) storage.buffers.instance.initialize( (const void*) nullptr, sizeof(pod::Instance) * initialElements, uf::renderer::enums::Buffer::STORAGE );
|
||||
if ( !storage.buffers.instanceAddresses.buffer ) storage.buffers.instanceAddresses.initialize( (const void*) nullptr, sizeof(pod::Instance::Addresses) * initialElements, uf::renderer::enums::Buffer::STORAGE );
|
||||
if ( !storage.buffers.addresses.buffer ) storage.buffers.addresses.initialize( (const void*) nullptr, sizeof(pod::Instance::Addresses) * initialElements, uf::renderer::enums::Buffer::STORAGE );
|
||||
if ( !storage.buffers.lodMetadata.buffer ) storage.buffers.lodMetadata.initialize( (const void*) nullptr, sizeof(pod::LODMetadata) * initialElements, uf::renderer::enums::Buffer::STORAGE );
|
||||
if ( !storage.buffers.joint.buffer ) storage.buffers.joint.initialize( (const void*) nullptr, sizeof(pod::Matrix4f) * initialElements, uf::renderer::enums::Buffer::STORAGE );
|
||||
if ( !storage.buffers.object.buffer ) storage.buffers.object.initialize( (const void*) nullptr, sizeof(pod::Instance::Object) * initialElements, uf::renderer::enums::Buffer::STORAGE );
|
||||
@ -1515,7 +1528,7 @@ bool uf::graph::tick( pod::Graph::Storage& storage ) {
|
||||
bool rebuild = false;
|
||||
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Instance>, instances);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Instance::Addresses>, instanceAddresses);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Instance::Addresses>, addresses);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::LODMetadata>, lodMetadata);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Matrix4f>, joints);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Instance::Object>, objects);
|
||||
@ -1549,44 +1562,40 @@ bool uf::graph::tick( pod::Graph::Storage& storage ) {
|
||||
|
||||
if ( storage.stale ) {
|
||||
for ( auto& key : storage.primitives.keys ) {
|
||||
auto& submeshes = storage.primitives.map[key];
|
||||
auto& primitives = storage.primitives.map[key];
|
||||
auto& grouped = storage.groupedInstances.map[key];
|
||||
auto& submeshAddresses = storage.instanceAddresses.map[key];
|
||||
|
||||
auto& mesh = storage.meshes.map[key];
|
||||
pod::DrawCommand* meshIndirectCmds = nullptr;
|
||||
pod::DrawCommand* commands = nullptr;
|
||||
|
||||
if (mesh.indirect.count > 0) {
|
||||
if ( mesh.indirect.count > 0 ) {
|
||||
auto& attr = mesh.indirect.attributes.front();
|
||||
meshIndirectCmds = (pod::DrawCommand*) mesh.buffers[attr.buffer].data();
|
||||
commands = (pod::DrawCommand*) mesh.buffers[attr.buffer].data();
|
||||
}
|
||||
|
||||
size_t nodesCount = submeshes.empty() ? 0 : grouped.size() / submeshes.size();
|
||||
|
||||
for ( size_t drawID = 0; drawID < submeshes.size(); ++drawID ) {
|
||||
auto& primitive = submeshes[drawID];
|
||||
size_t count = primitives.empty() ? 0 : grouped.size() / primitives.size();
|
||||
for ( size_t drawID = 0; drawID < primitives.size(); ++drawID ) {
|
||||
auto& primitive = primitives[drawID];
|
||||
|
||||
primitive.drawCommand.instanceID = instances.size();
|
||||
primitive.drawCommand.instances = nodesCount;
|
||||
primitive.drawCommand.instances = count;
|
||||
|
||||
if (meshIndirectCmds) {
|
||||
meshIndirectCmds[drawID].instanceID = primitive.drawCommand.instanceID;
|
||||
meshIndirectCmds[drawID].instances = primitive.drawCommand.instances;
|
||||
if ( commands ) {
|
||||
commands[drawID].instanceID = primitive.drawCommand.instanceID;
|
||||
commands[drawID].instances = primitive.drawCommand.instances;
|
||||
}
|
||||
|
||||
drawCommands.emplace_back( primitive.drawCommand );
|
||||
lodMetadata.emplace_back( primitive.lod );
|
||||
|
||||
bool hasAddresses = (drawID < submeshAddresses.size());
|
||||
|
||||
for (size_t i = 0; i < nodesCount; ++i) {
|
||||
size_t strideIndex = (i * submeshes.size()) + drawID;
|
||||
for ( size_t i = 0; i < count; ++i ) {
|
||||
size_t strideIndex = (i * primitives.size()) + drawID;
|
||||
instances.emplace_back( grouped[strideIndex] );
|
||||
instanceAddresses.emplace_back( hasAddresses ? submeshAddresses[drawID] : pod::Instance::Addresses{} );
|
||||
addresses.emplace_back( primitive.addresses );
|
||||
}
|
||||
}
|
||||
|
||||
if (meshIndirectCmds && !grouped.empty()) {
|
||||
if ( commands && !grouped.empty() ) {
|
||||
auto hostKeyName = std::to_string(grouped.front().objectID);
|
||||
if (storage.entities.map.count(hostKeyName) > 0) {
|
||||
auto* hostEntity = storage.entities.map[hostKeyName];
|
||||
@ -1602,7 +1611,7 @@ bool uf::graph::tick( pod::Graph::Storage& storage ) {
|
||||
for ( auto& key : storage.materials.keys ) materials.emplace_back( storage.materials.map[key] );
|
||||
|
||||
rebuild = storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ) || rebuild;
|
||||
rebuild = storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::Instance::Addresses) ) || rebuild;
|
||||
rebuild = storage.buffers.addresses.update( (const void*) addresses.data(), addresses.size() * sizeof(pod::Instance::Addresses) ) || rebuild;
|
||||
rebuild = storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) ) || rebuild;
|
||||
rebuild = storage.buffers.lodMetadata.update( (const void*) lodMetadata.data(), lodMetadata.size() * sizeof(pod::LODMetadata) ) || rebuild;
|
||||
rebuild = storage.buffers.material.update( (const void*) materials.data(), materials.size() * sizeof(pod::Material) ) || rebuild;
|
||||
@ -1627,7 +1636,7 @@ bool uf::graph::tick( pod::Graph::Storage& storage ) {
|
||||
|
||||
shader.aliasBuffer( "drawCommands", storage.buffers.drawCommands );
|
||||
shader.aliasBuffer( "instance", storage.buffers.instance );
|
||||
shader.aliasBuffer( "instanceAddresses", storage.buffers.instanceAddresses );
|
||||
shader.aliasBuffer( "addresses", storage.buffers.addresses );
|
||||
shader.aliasBuffer( "material", storage.buffers.material );
|
||||
shader.aliasBuffer( "texture", storage.buffers.texture );
|
||||
shader.aliasBuffer( "light", storage.buffers.light );
|
||||
@ -1644,7 +1653,7 @@ void uf::graph::aggregate() {
|
||||
}
|
||||
void uf::graph::aggregate( uf::Object& object, pod::Graph::Storage& storage ) {
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Instance>, instances);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Instance::Addresses>, instanceAddresses);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Instance::Addresses>, addresses);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::LODMetadata>, lodMetadata);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Matrix4f>, joints);
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<pod::Instance::Object>, objects);
|
||||
@ -1703,14 +1712,14 @@ void uf::graph::aggregate( uf::Object& object, pod::Graph::Storage& storage ) {
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto& key : storage.instanceAddresses.keys ) {
|
||||
instanceAddresses.insert( instanceAddresses.end(), storage.instanceAddresses.map[key].begin(), storage.instanceAddresses.map[key].end() );
|
||||
for ( auto& key : storage.addresses.keys ) {
|
||||
addresses.insert( addresses.end(), storage.addresses.map[key].begin(), storage.addresses.map[key].end() );
|
||||
}
|
||||
}
|
||||
|
||||
bool rebuild = false;
|
||||
rebuild = storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ) || rebuild;
|
||||
rebuild = storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::Instance::Addresses) ) || rebuild;
|
||||
rebuild = storage.buffers.addresses.update( (const void*) addresses.data(), addresses.size() * sizeof(pod::Instance::Addresses) ) || rebuild;
|
||||
rebuild = storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) ) || rebuild;
|
||||
rebuild = storage.buffers.lodMetadata.update( (const void*) lodMetadata.data(), lodMetadata.size() * sizeof(pod::LODMetadata) ) || rebuild;
|
||||
rebuild = storage.buffers.material.update( (const void*) materials.data(), materials.size() * sizeof(pod::Material) ) || rebuild;
|
||||
@ -1800,16 +1809,17 @@ void uf::graph::destroy( pod::Graph::Storage& storage, bool soft ) {
|
||||
#endif
|
||||
|
||||
// cleanup graphic handles
|
||||
for ( auto pair : storage.texture2Ds.map ) pair.second.destroy();
|
||||
for ( auto pair : storage.images.map ) {
|
||||
pair.second.data.clear();
|
||||
pair.second.handle.destroy();
|
||||
}
|
||||
for ( auto& t : storage.shadow2Ds ) t.destroy();
|
||||
for ( auto& t : storage.shadowCubes ) t.destroy();
|
||||
|
||||
for ( auto pair : storage.atlases.map ) pair.second.clear();
|
||||
for ( auto pair : storage.images.map ) pair.second.clear();
|
||||
for ( auto pair : storage.meshes.map ) pair.second.destroy();
|
||||
|
||||
// cleanup storage cache
|
||||
storage.instanceAddresses.clear();
|
||||
storage.primitives.clear();
|
||||
storage.meshes.clear();
|
||||
storage.images.clear();
|
||||
@ -1820,7 +1830,6 @@ void uf::graph::destroy( pod::Graph::Storage& storage, bool soft ) {
|
||||
storage.animations.clear();
|
||||
storage.atlases.clear();
|
||||
storage.joints.clear();
|
||||
storage.texture2Ds.clear();
|
||||
storage.entities.clear();
|
||||
storage.shadow2Ds.clear();
|
||||
storage.shadowCubes.clear();
|
||||
@ -1831,7 +1840,7 @@ void uf::graph::destroy( pod::Graph::Storage& storage, bool soft ) {
|
||||
storage.buffers.drawCommands.destroy(true);
|
||||
storage.buffers.lodMetadata.destroy(true);
|
||||
storage.buffers.instance.destroy(true);
|
||||
storage.buffers.instanceAddresses.destroy(true);
|
||||
storage.buffers.addresses.destroy(true);
|
||||
storage.buffers.joint.destroy(true);
|
||||
storage.buffers.object.destroy(true);
|
||||
storage.buffers.material.destroy(true);
|
||||
@ -1880,7 +1889,6 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) {
|
||||
auto model = uf::transform::model( transform );
|
||||
auto& mesh = storage.meshes.map[graph.meshes[node.mesh]];
|
||||
auto& primitives = storage.primitives.map[graph.primitives[node.mesh]];
|
||||
auto& instanceAddresses = storage.instanceAddresses.map[graph.primitives[node.mesh]];
|
||||
|
||||
float radius = graph.settings.stream.radius;
|
||||
float radiusSquared = radius * radius;
|
||||
@ -2133,8 +2141,8 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) {
|
||||
|
||||
// iterate through our ref counts
|
||||
for ( auto& [ key, count ] : textureReferences ) {
|
||||
auto& texture = storage.texture2Ds[key];
|
||||
auto& image = storage.images[key];
|
||||
auto& image = storage.images[key].data;
|
||||
auto& texture = storage.images[key].handle;
|
||||
bool visible = count > 0;
|
||||
|
||||
if ( visible && (!texture.generated() || texture.aliased) ) {
|
||||
@ -2240,11 +2248,11 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) {
|
||||
if ( rebuild ) {
|
||||
::bindBuffers( graph, graphic, mesh );
|
||||
|
||||
::bindInstanceAddresses( graph, graphic, mesh, instanceAddresses );
|
||||
::bindAddresses( graph, graphic, mesh, primitives );
|
||||
uf::renderer::states::rebuild = true;
|
||||
}
|
||||
} else {
|
||||
uf::graph::initializeGraphics( graph, entity, mesh, instanceAddresses );
|
||||
uf::graph::initializeGraphics( graph, entity, mesh, primitives );
|
||||
}
|
||||
}
|
||||
// bind mesh to physics state
|
||||
@ -2306,10 +2314,10 @@ void uf::graph::update( pod::Graph& graph, float delta ) {
|
||||
|
||||
auto& graphic = entity.getComponent<uf::renderer::Graphic>();
|
||||
auto& mesh = storage.meshes.map[graph.meshes[node.mesh]];
|
||||
auto& instanceAddresses = storage.instanceAddresses.map[graph.primitives[node.mesh]];
|
||||
auto& primitives = storage.primitives.map[graph.primitives[node.mesh]];
|
||||
|
||||
::bindBuffers( graph, graphic, mesh );
|
||||
::bindInstanceAddresses( graph, graphic, mesh, instanceAddresses );
|
||||
::bindAddresses( graph, graphic, mesh, primitives );
|
||||
}
|
||||
storage.shouldRebind = false;
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
for ( auto& i : model.images ) {
|
||||
auto imageID = graph.images.size();
|
||||
auto keyName = graph.images.emplace_back(key + i.name);
|
||||
auto& image = storage.images[keyName];
|
||||
auto& image = storage.images[keyName].data;
|
||||
if ( graph.metadata["debug"]["print"]["images"].as<bool>() ) {
|
||||
UF_MSG_DEBUG("Image: {}", i.name );
|
||||
}
|
||||
@ -290,7 +290,6 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
|
||||
auto& primitives = storage.primitives[keyName];
|
||||
auto& mesh = storage.meshes[keyName];
|
||||
storage.instanceAddresses[keyName] = {};
|
||||
|
||||
struct {
|
||||
uf::meshgrid::Grid grid;
|
||||
@ -472,14 +471,13 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
auto atlasImageIndex = graph.images.size();
|
||||
auto atlasTextureIndex = graph.textures.size();
|
||||
|
||||
for ( auto& keyName : graph.images ) atlas.addImage( storage.images[keyName] );
|
||||
for ( auto& keyName : graph.images ) atlas.addImage( storage.images[keyName].data );
|
||||
atlas.generate();
|
||||
|
||||
for ( auto& keyName : graph.images ) {
|
||||
auto& texture = storage.textures[keyName];
|
||||
storage.texture2Ds[keyName];
|
||||
if ( texture.index < 0 ) continue;
|
||||
auto& image = storage.images[keyName];
|
||||
auto& image = storage.images[keyName].data;
|
||||
|
||||
const auto& hash = image.getHash();
|
||||
auto min = atlas.mapUv( {0, 0}, hash );
|
||||
@ -491,7 +489,7 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
|
||||
{
|
||||
graph.images.emplace_back(atlasName);
|
||||
auto& image = storage.images[atlasName];
|
||||
auto& image = storage.images[atlasName].data;
|
||||
image = atlas.getAtlas();
|
||||
|
||||
graph.textures.emplace_back(atlasName);
|
||||
|
||||
@ -342,8 +342,8 @@ namespace impl {
|
||||
v.uv.y = uf::vector::dot( vertex, info.textureVecs[1] ) / (float) data.height;
|
||||
}
|
||||
|
||||
v.st.x = (uf::vector::dot( vertex, info.lightmapVecs[0] ) - face.lightmapTextureMins.x) / (face.lightmapTextureSize.x + 1.0f);
|
||||
v.st.y = (uf::vector::dot( vertex, info.lightmapVecs[1] ) - face.lightmapTextureMins.y) / (face.lightmapTextureSize.y + 1.0f);
|
||||
v.st.x = (uf::vector::dot( vertex, info.lightmapVecs[0] ) + 0.5f - face.lightmapTextureMins.x) / (face.lightmapTextureSize.x + 1.0f);
|
||||
v.st.y = (uf::vector::dot( vertex, info.lightmapVecs[1] ) + 0.5f - face.lightmapTextureMins.y) / (face.lightmapTextureSize.y + 1.0f);
|
||||
|
||||
v.st = uf::atlas::mapUv( context.lightmapAtlas, v.st, impl::faceHash( faceID ) );
|
||||
|
||||
@ -386,15 +386,17 @@ namespace impl {
|
||||
|
||||
int32_t spawnID = -1;
|
||||
uf::stl::vector<size_t> spawns;
|
||||
uf::stl::unordered_map<uf::stl::string, size_t> targets;
|
||||
|
||||
for ( auto nodeID : graph.root.children ) {
|
||||
auto& node = graph.nodes[nodeID];
|
||||
auto classname = node.metadata["classname"].as<uf::stl::string>("");
|
||||
auto& metadata = node.metadata["valve"];
|
||||
auto classname = metadata["classname"].as<uf::stl::string>("");
|
||||
//UF_MSG_INFO("Entity found: {}", classname);
|
||||
node.name = classname;
|
||||
|
||||
// parse origin
|
||||
auto origin = node.metadata["origin"].as<uf::stl::string>("");
|
||||
auto origin = metadata["origin"].as<uf::stl::string>("");
|
||||
if ( origin != "" ) {
|
||||
auto position = impl::str2vec<pod::Vector3f>( origin );
|
||||
node.transform.position = impl::convertPos( position, scale );
|
||||
@ -402,7 +404,7 @@ namespace impl {
|
||||
|
||||
// parse angles
|
||||
// to-do: fix oddities
|
||||
auto angles = node.metadata["angles"].as<uf::stl::string>("");
|
||||
auto angles = metadata["angles"].as<uf::stl::string>("");
|
||||
if ( angles != "" ) {
|
||||
auto pyr = impl::str2vec<pod::Vector3f>( angles ) * DEG_2_RAD;
|
||||
pyr.x = -pyr.x;
|
||||
@ -411,7 +413,7 @@ namespace impl {
|
||||
}
|
||||
|
||||
// parse model
|
||||
auto model = node.metadata["model"].as<uf::stl::string>();
|
||||
auto model = metadata["model"].as<uf::stl::string>();
|
||||
if ( classname == "worldspawn" ) {
|
||||
node.mesh = context.modelToMesh[0]; // implicitly bind to model 0
|
||||
} else if ( model.starts_with("*") ) {
|
||||
@ -420,26 +422,26 @@ namespace impl {
|
||||
node.mesh = context.modelToMesh[modelID];
|
||||
}
|
||||
} else if ( model.length() > 4 && model.ends_with(".mdl") ) {
|
||||
auto it = std::find(graph.meshes.begin(), graph.meshes.end(), model);
|
||||
if ( it == graph.meshes.end() ) {
|
||||
if ( ext::valve::loadMdl(graph, model) ) {
|
||||
node.mesh = (int32_t)(graph.meshes.size() - 1);
|
||||
}
|
||||
} else {
|
||||
node.mesh = (int32_t)std::distance(graph.meshes.begin(), it);
|
||||
}
|
||||
}
|
||||
auto it = std::find(graph.meshes.begin(), graph.meshes.end(), model);
|
||||
if ( it == graph.meshes.end() ) {
|
||||
if ( ext::valve::loadMdl(graph, model) ) {
|
||||
node.mesh = (int32_t)(graph.meshes.size() - 1);
|
||||
}
|
||||
} else {
|
||||
node.mesh = (int32_t)std::distance(graph.meshes.begin(), it);
|
||||
}
|
||||
}
|
||||
|
||||
// parse lighting info
|
||||
if ( classname.starts_with("light") ) {
|
||||
auto lightKeyName = ::fmt::format( "{}_{}", classname, lights++ );
|
||||
auto lightKeyName = ::fmt::format( "{}_{}", classname, nodeID );
|
||||
auto& light = graph.lights[lightKeyName];
|
||||
light.color = { 1.0f, 1.0f, 1.0f };
|
||||
light.intensity = 1.0f;
|
||||
light.intensity = 200.0f;
|
||||
light.range = 0.0f;
|
||||
|
||||
// read color and intensity
|
||||
auto _light = node.metadata["_light"].as<uf::stl::string>("");
|
||||
auto _light = metadata["_light"].as<uf::stl::string>("");
|
||||
if ( _light != "" ) {
|
||||
// to-do: do not use stringstream
|
||||
std::istringstream stream(_light);
|
||||
@ -449,10 +451,9 @@ namespace impl {
|
||||
light.color /= 255.0f;
|
||||
|
||||
if (!(stream >> light.intensity)) light.intensity = 200.0f;
|
||||
light.intensity /= 10.0f;
|
||||
}
|
||||
|
||||
// to-do: read range
|
||||
light.intensity *= 0.2f; // scale down
|
||||
}
|
||||
|
||||
// parse player spawn info
|
||||
@ -462,9 +463,32 @@ namespace impl {
|
||||
spawns.emplace_back(nodeID);
|
||||
}
|
||||
|
||||
auto targetname = metadata["targetname"].as<uf::stl::string>("");
|
||||
if ( targetname != "" ) {
|
||||
targets[targetname] = nodeID;
|
||||
}
|
||||
|
||||
// to-do: add additional parsing
|
||||
}
|
||||
|
||||
uf::stl::vector<int32_t> newChildren;
|
||||
for ( auto nodeID : graph.root.children ) {
|
||||
auto& node = graph.nodes[nodeID];
|
||||
auto& metadata = node.metadata["valve"];
|
||||
|
||||
auto parentname = metadata["parentname"].as<uf::stl::string>("");
|
||||
if ( parentname != "" && targets.count(parentname) > 0 ) {
|
||||
auto parentID = targets[parentname];
|
||||
auto& parentNode = graph.nodes[parentID];
|
||||
parentNode.children.emplace_back(nodeID);
|
||||
|
||||
node.transform = uf::transform::relative( parentNode.transform, node.transform );
|
||||
} else {
|
||||
newChildren.emplace_back(nodeID);
|
||||
}
|
||||
}
|
||||
graph.root.children = newChildren;
|
||||
|
||||
// no valid spawn
|
||||
UF_ASSERT( !(spawnID == -1 && spawns.empty()) ); // to-do: make the engine implicitly spawn the player at origin
|
||||
// pick a random candidate if none was found
|
||||
@ -537,12 +561,11 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
|
||||
size_t imageID = graph.images.size();
|
||||
auto imgKeyName = graph.images.emplace_back(matName);
|
||||
auto& image = storage.images[imgKeyName];
|
||||
auto& image = storage.images[imgKeyName].data;
|
||||
|
||||
size_t textureID = graph.textures.size();
|
||||
auto texKeyName = graph.textures.emplace_back(matName);
|
||||
storage.textures[texKeyName].index = imageID;
|
||||
storage.texture2Ds[texKeyName];
|
||||
|
||||
size_t materialID = graph.materials.size();
|
||||
context.texdataToMaterial[texDataID] = materialID;
|
||||
@ -551,6 +574,9 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
auto& material = storage.materials[matKeyName];
|
||||
material.indexAlbedo = textureID;
|
||||
material.colorBase = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
material.factorMetallic = 0.0f;
|
||||
material.factorRoughness = 1.0f;
|
||||
material.factorOcclusion = 1.0f;
|
||||
|
||||
//UF_MSG_INFO("Material found: {}", matName);
|
||||
}
|
||||
@ -559,13 +585,18 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
auto atlasImageID = graph.images.size();
|
||||
auto atlasTextureID = graph.textures.size();
|
||||
|
||||
for ( size_t i = 3; i < context.lighting.size(); i += 4 ) {
|
||||
int8_t exp = (int8_t)context.lighting[i];
|
||||
context.lighting[i] = (uint8_t)(exp + 128);
|
||||
}
|
||||
for ( auto faceID = 0; faceID < context.faces.size(); ++faceID ) {
|
||||
const auto& face = context.faces[faceID];
|
||||
if ( face.lightofs == -1 || context.lighting.empty() ) continue;
|
||||
|
||||
size_t width = face.lightmapTextureSize.x + 1;
|
||||
size_t height = face.lightmapTextureSize.y + 1;
|
||||
|
||||
|
||||
|
||||
uf::Image image;
|
||||
image.loadFromBuffer( (uint8_t*)(context.lighting.data() + face.lightofs), { width, height }, 8, 4 );
|
||||
|
||||
@ -580,9 +611,8 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
auto& imageKey = graph.images.emplace_back("lightmap_atlas");
|
||||
auto& textureKey = graph.textures.emplace_back("lightmap_atlas");
|
||||
|
||||
storage.images[imageKey] = uf::atlas::get( context.lightmapAtlas );
|
||||
storage.images[imageKey].data = uf::atlas::get( context.lightmapAtlas );
|
||||
storage.textures[textureKey].index = atlasImageID;
|
||||
storage.texture2Ds[textureKey];
|
||||
}
|
||||
|
||||
// read models
|
||||
@ -605,7 +635,10 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
// read brush
|
||||
auto& meshlet = meshlets[materialID];
|
||||
meshlet.primitive.instance.materialID = materialID;
|
||||
meshlet.primitive.instance.lightmapID = atlasTextureID;
|
||||
|
||||
if ( 0 <= face.lightofs ) {
|
||||
meshlet.primitive.instance.lightmapID = atlasTextureID;
|
||||
}
|
||||
|
||||
if ( face.dispinfo != -1 ) {
|
||||
impl::buildDisplacement( context, meshlet, faceID );
|
||||
@ -644,7 +677,6 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
|
||||
auto& mesh = storage.meshes[meshName];
|
||||
auto& primitives = storage.primitives[meshName];
|
||||
storage.instanceAddresses[meshName] = {};
|
||||
|
||||
mesh.compile( meshlets, primitives );
|
||||
}
|
||||
@ -667,7 +699,8 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
// create node
|
||||
auto nodeID = graph.nodes.size();
|
||||
auto& node = graph.nodes.emplace_back();
|
||||
for ( const auto& [k, v] : dict ) node.metadata[k] = v; // store as metadata for later parsing
|
||||
auto& metadata = node.metadata["valve"];
|
||||
for ( const auto& [k, v] : dict ) metadata[k] = v; // store as metadata for later parsing
|
||||
|
||||
// add node as child
|
||||
graph.root.children.emplace_back( nodeID );
|
||||
@ -722,11 +755,12 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
if ( type < dict.size() ) {
|
||||
auto nodeID = graph.nodes.size();
|
||||
auto& node = graph.nodes.emplace_back();
|
||||
auto& metadata = node.metadata["valve"];
|
||||
|
||||
node.metadata["classname"] = "prop_static";
|
||||
node.metadata["model"] = dict[type];
|
||||
node.metadata["origin"] = ::fmt::format("{} {} {}", origin.x, origin.y, origin.z);
|
||||
node.metadata["angles"] = ::fmt::format("{} {} {}", angles.x, angles.y, angles.z);
|
||||
metadata["classname"] = "prop_static";
|
||||
metadata["model"] = dict[type];
|
||||
metadata["origin"] = ::fmt::format("{} {} {}", origin.x, origin.y, origin.z);
|
||||
metadata["angles"] = ::fmt::format("{} {} {}", angles.x, angles.y, angles.z);
|
||||
|
||||
graph.root.children.emplace_back( nodeID );
|
||||
}
|
||||
@ -743,9 +777,28 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
uf::Serializer vmt;
|
||||
auto vmtPath = ::fmt::format("materials/{}.vmt", matName);
|
||||
auto vtfPath = ::fmt::format("materials/{}.vtf", matName);
|
||||
auto& image = storage.images[matName];
|
||||
auto& image = storage.images[matName].data;
|
||||
auto& material = storage.materials[matName];
|
||||
|
||||
if ( !ext::valve::loadVmt( vmt, vmtPath ) ) goto PEETAH;
|
||||
|
||||
material.factorMetallic = vmt["$metalness"].as<float>(0.0f);
|
||||
material.factorRoughness = vmt["$roughness"].as<float>(1.0f);
|
||||
|
||||
if ( vmt["$envmap"].as<uf::stl::string>() != "" ) material.factorRoughness = 0.3f;
|
||||
if ( vmt["$phong"].as<uf::stl::string>("0") == "1" ) material.factorRoughness = std::min(material.factorRoughness, 0.5f);
|
||||
|
||||
if ( vmt["$translucent"].as<uf::stl::string>("0") == "1" ) {
|
||||
material.modeAlpha = 1; // BLEND
|
||||
} else if ( vmt["$alphatest"].as<uf::stl::string>("0") == "1" ) {
|
||||
material.modeAlpha = 2; // MASK
|
||||
material.factorAlphaCutoff = vmt["$alphatestreference"].as<float>(0.5f);
|
||||
}
|
||||
if ( vmt["$nocull"].as<uf::stl::string>("0") == "1" ) material.modeCull = 0;
|
||||
|
||||
// VMTs usually define emissive masks in the albedo's alpha channel or a separate mask
|
||||
// set it to a white glow for now until I can patch the shader
|
||||
if ( vmt["$selfillum"].as<uf::stl::string>("0") == "1" ) material.colorEmissive = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
if ( !vmt["$basetexture"].is<uf::stl::string>() ) goto PEETAH;
|
||||
|
||||
vtfPath = ::fmt::format("materials/{}.vtf", vmt["$basetexture"].as<uf::stl::string>());
|
||||
|
||||
@ -288,19 +288,22 @@ bool ext::valve::loadMdl( pod::Graph& graph, const uf::stl::string& filename ) {
|
||||
// does not exist, register
|
||||
size_t imageID = graph.images.size();
|
||||
auto imgKeyName = graph.images.emplace_back(matName);
|
||||
auto& image = storage.images[imgKeyName];
|
||||
auto& image = storage.images[imgKeyName].data;
|
||||
|
||||
size_t textureID = graph.textures.size();
|
||||
auto texKeyName = graph.textures.emplace_back(matName);
|
||||
storage.textures[texKeyName].index = imageID;
|
||||
storage.texture2Ds[texKeyName];
|
||||
|
||||
materialID = graph.materials.size();
|
||||
auto matKeyName = graph.materials.emplace_back(matName);
|
||||
auto& material = storage.materials[matKeyName];
|
||||
material.indexAlbedo = textureID;
|
||||
material.colorBase = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
}
|
||||
material.factorMetallic = 0.0f;
|
||||
material.factorRoughness = 1.0f;
|
||||
material.factorOcclusion = 1.0f;
|
||||
}
|
||||
|
||||
meshlet.primitive.instance.materialID = materialID;
|
||||
}
|
||||
}
|
||||
@ -313,7 +316,6 @@ bool ext::valve::loadMdl( pod::Graph& graph, const uf::stl::string& filename ) {
|
||||
|
||||
auto& mesh = storage.meshes[meshName];
|
||||
auto& primitives = storage.primitives[meshName];
|
||||
storage.instanceAddresses[meshName] = {};
|
||||
|
||||
mesh.compile( meshlets, primitives );
|
||||
}
|
||||
|
||||
@ -1198,9 +1198,8 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
|
||||
#define PARSE_INPUT_INITIALIZE(NAME, USAGE){\
|
||||
for ( size_t i = 0; i < descriptor.inputs.NAME.attributes.size(); ++i ) {\
|
||||
auto& attribute = descriptor.inputs.NAME.attributes[i];\
|
||||
auto& buffer = mesh.buffers[attribute.buffer];\
|
||||
if ( !buffer.empty() ) {\
|
||||
attribute.buffer = initializeBuffer( (const void*) buffer.data(), buffer.size(), USAGE | baseUsage );\
|
||||
if ( attribute.pointer && attribute.length > 0 ) {\
|
||||
attribute.buffer = initializeBuffer( (const void*) attribute.pointer, attribute.length, USAGE | baseUsage );\
|
||||
this->metadata.buffers[#NAME"["+attribute.descriptor.name+"]"] = attribute.buffer;\
|
||||
} else attribute.buffer = -1;\
|
||||
}\
|
||||
@ -1239,9 +1238,8 @@ bool ext::vulkan::Graphic::updateMesh( uf::Mesh& mesh ) {
|
||||
#define PARSE_INPUT_UPDATE(NAME, USAGE){\
|
||||
for ( size_t i = 0; i < descriptor.inputs.NAME.attributes.size(); ++i ) {\
|
||||
auto& attribute = descriptor.inputs.NAME.attributes[i];\
|
||||
auto& buffer = mesh.buffers[attribute.buffer];\
|
||||
if ( !buffer.empty() ) {\
|
||||
rebuild = updateBuffer( (const void*) buffer.data(), buffer.size(), this->metadata.buffers[#NAME"["+attribute.descriptor.name+"]"] ) || rebuild;\
|
||||
if ( attribute.pointer && attribute.length > 0 ) {\
|
||||
rebuild = updateBuffer( (const void*) attribute.pointer, attribute.length, this->metadata.buffers[#NAME"["+attribute.descriptor.name+"]"] ) || rebuild;\
|
||||
} else attribute.buffer = -1;\
|
||||
}\
|
||||
}
|
||||
|
||||
@ -553,7 +553,7 @@ void ext::vulkan::DeferredRenderMode::build( bool resized ) {
|
||||
// shader.aliasBuffer( storage.buffers.joint );
|
||||
shader.aliasBuffer( storage.buffers.drawCommands );
|
||||
shader.aliasBuffer( storage.buffers.instance );
|
||||
shader.aliasBuffer( storage.buffers.instanceAddresses );
|
||||
shader.aliasBuffer( storage.buffers.addresses );
|
||||
shader.aliasBuffer( storage.buffers.object );
|
||||
shader.aliasBuffer( storage.buffers.material );
|
||||
shader.aliasBuffer( storage.buffers.texture );
|
||||
|
||||
@ -229,7 +229,7 @@ void ext::vulkan::RenderTargetRenderMode::build( bool resized ) {
|
||||
// shader.aliasBuffer( storage.buffers.joint );
|
||||
shader.aliasBuffer( storage.buffers.drawCommands );
|
||||
shader.aliasBuffer( storage.buffers.instance );
|
||||
shader.aliasBuffer( storage.buffers.instanceAddresses );
|
||||
shader.aliasBuffer( storage.buffers.addresses );
|
||||
shader.aliasBuffer( storage.buffers.object );
|
||||
shader.aliasBuffer( storage.buffers.material );
|
||||
shader.aliasBuffer( storage.buffers.texture );
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include <uf/utils/string/ext.h>
|
||||
#include <uf/utils/string/hash.h>
|
||||
#include <uf/utils/io/iostream.h>
|
||||
#include <uf/utils/io/vfs.h>
|
||||
#include <fstream> // std::fstream
|
||||
#include <iostream> // std::fstream
|
||||
#include <png/png.h> // libpng
|
||||
@ -13,6 +14,14 @@
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
#include <uf/utils/string/ext.h>
|
||||
|
||||
namespace {
|
||||
void stbi_buffer_write_func(void *context, void *data, int size) {
|
||||
auto* buffer = static_cast<uf::stl::vector<uint8_t>*>(context);
|
||||
auto* bytes = static_cast<uint8_t*>(data);
|
||||
buffer->insert(buffer->end(), bytes, bytes + size);
|
||||
}
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
pod::Image scaleNearest( const pod::Image& image, const pod::Vector2ui& size ) {
|
||||
pod::Image out = image;
|
||||
@ -203,12 +212,20 @@ bool uf::image::save( const pod::Image& image, const uf::stl::string& filename,
|
||||
auto* pixels = &image.pixels[0];
|
||||
uf::stl::string extension = uf::io::extension(filename);
|
||||
stbi_flip_vertically_on_write(flip);
|
||||
if ( extension == "png" ) {
|
||||
stbi_write_png(filename.c_str(), w, h, image.channels, &pixels[0], w * image.channels);
|
||||
} else if ( extension == "jpg" || extension == "jpeg" ) {
|
||||
stbi_write_jpg(filename.c_str(), w, h, image.channels, &pixels[0], w * image.channels);
|
||||
}
|
||||
return true;
|
||||
|
||||
uf::stl::vector<uint8_t> buffer;
|
||||
|
||||
if ( extension == "png" ) {
|
||||
stbi_write_png_to_func(stbi_buffer_write_func, &buffer, w, h, image.channels, pixels, w * image.channels);
|
||||
} else if ( extension == "jpg" || extension == "jpeg" ) {
|
||||
stbi_write_jpg_to_func(stbi_buffer_write_func, &buffer, w, h, image.channels, pixels, 90); // 90 is quality
|
||||
} else {
|
||||
UF_MSG_ERROR("Unsupported image save format: {}", extension);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( buffer.empty() ) return false;
|
||||
return uf::vfs::write( filename, buffer.data(), buffer.size() ) > 0;
|
||||
}
|
||||
void uf::image::save( const pod::Image& image, std::ostream& stream ) {
|
||||
|
||||
|
||||
@ -216,14 +216,8 @@ bool uf::io::exists( const uf::stl::string& filename ) {
|
||||
size_t uf::io::mtime( const uf::stl::string& filename ) {
|
||||
return uf::vfs::mtime( uf::io::resolveURI(filename) );
|
||||
}
|
||||
bool uf::io::mkdir( const uf::stl::string& _filename ) {
|
||||
#if UF_ENV_DREAMCAST || UF_ENV_LINUX
|
||||
return false;
|
||||
#else
|
||||
uf::stl::string filename = uf::io::normalize(_filename);
|
||||
int status = ::mkdir(filename.c_str());
|
||||
return status != -1;
|
||||
#endif
|
||||
bool uf::io::mkdir( const uf::stl::string& filename ) {
|
||||
return uf::vfs::mkdir( uf::io::resolveURI(filename) );
|
||||
}
|
||||
|
||||
uf::stl::string uf::io::assetType( const uf::stl::string& _filename ) {
|
||||
|
||||
@ -61,6 +61,15 @@ pod::Mount uf::vfs::createDiskMount( const uf::stl::string& uri, int priority) {
|
||||
output.close();
|
||||
return size;
|
||||
},
|
||||
.mkdir = [path](const uf::stl::string& file) -> bool {
|
||||
uf::stl::string fullPath = path + file;
|
||||
#if UF_ENV_DREAMCAST || UF_ENV_LINUX
|
||||
return false;
|
||||
#else
|
||||
int status = ::mkdir(fullPath.c_str());
|
||||
return status != -1;
|
||||
#endif
|
||||
},
|
||||
.readRange = [path](const uf::stl::string& file, size_t start, size_t len, uf::stl::vector<uint8_t>& buffer) -> bool {
|
||||
uf::stl::string fullPath = path + file;
|
||||
std::ifstream is(fullPath, std::ios::binary);
|
||||
@ -166,6 +175,19 @@ bool uf::vfs::exists( const uf::stl::string& path ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool uf::vfs::mkdir( const uf::stl::string& path ) {
|
||||
uf::stl::string prefix, relative;
|
||||
uf::io::splitUri(path, prefix, relative);
|
||||
|
||||
for ( const auto& mount : mounts ) {
|
||||
if ( prefix.empty() && mount.priority < 0 ) continue;
|
||||
if ( prefix.empty() || mount.prefix == prefix ) {
|
||||
if ( mount.mkdir(relative) ) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t uf::vfs::size( const uf::stl::string& path ) {
|
||||
uf::stl::string prefix, relative;
|
||||
uf::io::splitUri(path, prefix, relative);
|
||||
|
||||
@ -130,6 +130,12 @@ uf::Mesh& uf::Mesh::copy( const uf::Mesh& src ) {
|
||||
|
||||
return *this;
|
||||
}
|
||||
uf::Mesh uf::Mesh::alias() const {
|
||||
uf::Mesh alias = *this;
|
||||
for ( auto& buf : alias.buffers ) buf.clear();
|
||||
alias.updateDescriptor();
|
||||
return alias;
|
||||
}
|
||||
void uf::Mesh::updateDescriptor() {
|
||||
_updateDescriptor(vertex);
|
||||
_updateDescriptor(index);
|
||||
@ -150,7 +156,7 @@ void uf::Mesh::insert( const uf::Mesh& mesh ) {
|
||||
|
||||
insertVertices(mesh);
|
||||
insertIndices(mesh);
|
||||
insertInstances(mesh);
|
||||
// insertInstances(mesh);
|
||||
insertIndirects(mesh);
|
||||
|
||||
updateDescriptor();
|
||||
@ -282,25 +288,25 @@ const uf::Mesh::buffer_t& uf::Mesh::getBuffer( const uf::Mesh::Input& input, con
|
||||
|
||||
uf::Mesh::View uf::Mesh::makeView( const uf::stl::vector<uf::stl::string>& wanted, size_t lod ) const {
|
||||
uf::Mesh::View view;
|
||||
view.vertex = vertex;
|
||||
view.index = index;
|
||||
view.vertex = vertex;
|
||||
view.index = index;
|
||||
|
||||
if ( wanted.size() ) {
|
||||
for ( auto& attr : vertex.attributes ) {
|
||||
if ( std::find(wanted.begin(), wanted.end(), attr.descriptor.name ) == wanted.end() ) continue;
|
||||
view.attributes[uf::string::fnv1a(attr.descriptor.name)] = { attr };
|
||||
}
|
||||
} else {
|
||||
for ( auto& attr : vertex.attributes ) {
|
||||
view.attributes[uf::string::fnv1a(attr.descriptor.name)] = { attr };
|
||||
}
|
||||
}
|
||||
if ( wanted.size() ) {
|
||||
for ( auto& attr : vertex.attributes ) {
|
||||
if ( std::find(wanted.begin(), wanted.end(), attr.descriptor.name ) == wanted.end() ) continue;
|
||||
view.attributes[uf::string::fnv1a(attr.descriptor.name)] = { attr };
|
||||
}
|
||||
} else {
|
||||
for ( auto& attr : vertex.attributes ) {
|
||||
view.attributes[uf::string::fnv1a(attr.descriptor.name)] = { attr };
|
||||
}
|
||||
}
|
||||
|
||||
if ( !index.attributes.empty() ) {
|
||||
view.attributes["index"_hash] = { index.attributes[lod] };
|
||||
}
|
||||
if ( !index.attributes.empty() ) {
|
||||
view.attributes["index"_hash] = { index.attributes[lod] };
|
||||
}
|
||||
|
||||
return view;
|
||||
return view;
|
||||
}
|
||||
uf::Mesh::View uf::Mesh::makeView( size_t i, const uf::stl::vector<uf::stl::string>& wanted, size_t lod ) const {
|
||||
uf::Mesh::View view;
|
||||
@ -398,9 +404,11 @@ void uf::Mesh::_bind() {
|
||||
void uf::Mesh::_updateDescriptor( uf::Mesh::Input& input ) {
|
||||
input.size = 0;
|
||||
for ( auto& attribute : input.attributes ) {
|
||||
auto& buffer = buffers[attribute.buffer];
|
||||
attribute.length = buffer.size();
|
||||
attribute.pointer = buffer.data() + attribute.offset;
|
||||
if ( attribute.buffer >= 0 && attribute.buffer < buffers.size() && !buffers[attribute.buffer].empty() ) {
|
||||
auto& buffer = buffers[attribute.buffer];
|
||||
attribute.length = buffer.size();
|
||||
attribute.pointer = buffer.data() + attribute.offset;
|
||||
}
|
||||
|
||||
if ( &input == &index || &input == &indirect ) input.size = attribute.descriptor.size;
|
||||
else input.size += attribute.descriptor.size;
|
||||
@ -510,24 +518,24 @@ void uf::Mesh::_insertV( uf::Mesh::Input& input, const void* data ) {
|
||||
}
|
||||
void uf::Mesh::_insertVs( uf::Mesh::Input& input, const void* data, size_t size ) {
|
||||
size_t count = input.count;
|
||||
input.count += size;
|
||||
input.count += size;
|
||||
|
||||
_resizeVs( input, input.count );
|
||||
_resizeVs( input, input.count );
|
||||
|
||||
const uint8_t* pointer = static_cast<const uint8_t*>(data);
|
||||
for ( auto& attribute : input.attributes ) {
|
||||
uint8_t* dstBase = buffers[attribute.buffer].data() + (count * attribute.descriptor.size);
|
||||
const uint8_t* pointer = static_cast<const uint8_t*>(data);
|
||||
for ( auto& attribute : input.attributes ) {
|
||||
uint8_t* dstBase = buffers[attribute.buffer].data() + (count * attribute.descriptor.size);
|
||||
|
||||
size_t srcOffset = attribute.descriptor.offset;
|
||||
size_t attrSize = attribute.descriptor.size;
|
||||
size_t srcOffset = attribute.descriptor.offset;
|
||||
size_t attrSize = attribute.descriptor.size;
|
||||
|
||||
for ( size_t i = 0; i < size; ++i ) {
|
||||
const uint8_t* srcAddr = pointer + (i * input.size) + srcOffset;
|
||||
uint8_t* dstAddr = dstBase + (i * attrSize);
|
||||
for ( size_t i = 0; i < size; ++i ) {
|
||||
const uint8_t* srcAddr = pointer + (i * input.size) + srcOffset;
|
||||
uint8_t* dstAddr = dstBase + (i * attrSize);
|
||||
|
||||
memcpy( dstAddr, srcAddr, attrSize );
|
||||
}
|
||||
}
|
||||
memcpy( dstAddr, srcAddr, attrSize );
|
||||
}
|
||||
}
|
||||
}
|
||||
// Indices
|
||||
void uf::Mesh::_bindI( uf::Mesh::Input& input, size_t size, ext::RENDERER::enums::Type::type_t type, size_t count ) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user