From bdd35fc2af40496b4cff9121ea5a3a364259642d Mon Sep 17 00:00:00 2001 From: Quentin LADEVIE Date: Thu, 3 Mar 2022 17:49:03 +0100 Subject: Primitive renderpass api & use handle for low level api resources --- src/gltf.cpp | 512 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 256 insertions(+), 256 deletions(-) (limited to 'src/gltf.cpp') diff --git a/src/gltf.cpp b/src/gltf.cpp index b05e71e..2f37a3c 100644 --- a/src/gltf.cpp +++ b/src/gltf.cpp @@ -1,256 +1,256 @@ -#include "gltf.hpp" - -#include -#include - -#define STB_IMAGE_IMPLEMENTATION -#include "thirdparty/stb_image.h" - -#include "utils.hpp" - -node gltf::load(std::filesystem::path &path, std::string &filename, vkrenderer &renderer) { - std::fstream f(path / filename); - json gltf_json; - - f >> gltf_json; - - auto &scene = gltf_json["scenes"][0]; - - auto &buffers = gltf_json["buffers"]; - auto buffer_index = 0; - auto buffers_content = std::vector>(buffers.size()); - for (auto &buffer: buffers) { - auto buffer_path = (path / buffer["uri"].get()).string(); - buffers_content[buffer_index] = read_file(buffer_path); - buffer_index++; - } - - auto textures = load_textures(gltf_json, path, renderer); - auto materials = load_materials(gltf_json, textures); - - auto meshes = load_meshes(gltf_json, buffers_content, materials); - - node root_node; - auto &root_children = scene["nodes"]; - uint32_t root_children_count = scene["nodes"].size(); - root_node.children.resize(root_children_count); - - for (size_t child_index = 0; child_index < root_children_count; child_index++) { - load_node(gltf_json, root_children[child_index].get(), root_node.children[child_index], meshes); - } - - return std::move(root_node); -} - -void gltf::load_node(json &gltf_json, uint32_t index, node &parent, std::vector &meshes) { - auto &gltf_node = gltf_json["nodes"][index]; - - if (gltf_node.contains("children")) { - auto &children = gltf_node["children"]; - uint32_t children_count = gltf_node["children"]; - parent.children.resize(children_count); - - for (size_t child_index = 0; child_index < children_count; child_index++) { - load_node(gltf_json, children[child_index].get(), parent.children[child_index], meshes); - } - } - - if (gltf_node.contains("mesh")) { - parent.mesh = std::make_optional(meshes[gltf_node["mesh"].get()]); - } -} - -std::vector gltf::load_meshes(json &gltf_json, std::vector> &buffers_content, std::vector &materials) { - auto &gltf_meshes = gltf_json["meshes"]; - auto meshes_count = gltf_meshes.size(); - std::vector meshes { meshes_count }; - - for(size_t mesh_index = 0; mesh_index < meshes_count; mesh_index++) { - auto &gltf_mesh = gltf_meshes[mesh_index]; - auto &primitives = gltf_mesh["primitives"]; - auto &mesh = meshes[mesh_index]; - - for (auto& primitive: primitives) { - auto &&part = load_primitive(gltf_json, primitive, buffers_content, materials); - mesh.vertices_count += part.vertices_count; - mesh.triangles_count += part.triangles_count; - mesh.parts.emplace_back(std::move(part)); - } - } - - return std::move(meshes); -} - -std::vector gltf::load_textures(json &gltf_json, std::filesystem::path &path, vkrenderer &renderer) { - auto &gltf_images = gltf_json["images"]; - auto images_count = gltf_images.size(); - std::vector images { images_count }; - - for (size_t image_index = 0; image_index < images_count; image_index++) { - auto &gltf_image = gltf_images[image_index]; - int x,y,n; - auto filepath = (path / gltf_image["uri"].get()).string(); - unsigned char *data = stbi_load(filepath.c_str(), &x, &y, &n, 4); - auto img = renderer.create_2d_texture(static_cast(x), static_cast(y), VK_FORMAT_R8G8B8A8_UNORM); - - renderer.update_image(img, data, x * y * 4); - - stbi_image_free(data); - - images[image_index] = std::move(img); - } - - auto &gltf_samplers = gltf_json["samplers"]; - auto samplers_count = gltf_samplers.size(); - std::vector samplers { samplers_count }; - - for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) { - samplers[sampler_index] = renderer.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT); - } - - auto &gltf_textures = gltf_json["textures"]; - auto textures_count = gltf_textures.size(); - std::vector textures { textures_count }; - - for (size_t texture_index = 0; texture_index < textures_count; texture_index++) { - auto gltf_texture = gltf_textures[texture_index]; - - auto image_index = gltf_texture["source"].get(); - auto &image = images[image_index]; - - uint32_t sampler_id = 0; - if (gltf_texture.contains("sampler")) { - auto sampler_index = gltf_texture["sampler"].get(); - auto &sampler = samplers[sampler_index]; - sampler_id = sampler->device_sampler.bindless_index; - } - - textures[texture_index] = texture { - .image_id = image->device_image.bindless_sampled_index, - .sampler_id = sampler_id - }; - } - - return std::move(textures); -} - -std::vector gltf::load_materials(json &gltf_json, std::vector &textures) { - auto &gltf_materials = gltf_json["materials"]; - auto materials_count = gltf_materials.size(); - std::vector materials { materials_count }; - - for(size_t material_index = 0; material_index < materials_count; material_index++) { - auto& gltf_material = gltf_materials[material_index]; - auto& material = materials[material_index]; - - if (gltf_material.contains("pbrMetallicRoughness")) { - auto &pbr_params = gltf_material["pbrMetallicRoughness"]; - - if (pbr_params.contains("baseColorFactor")) { - auto &base_color = pbr_params["baseColorFactor"]; - material.base_color.v[0] = base_color[0].get(); - material.base_color.v[1] = base_color[1].get(); - material.base_color.v[2] = base_color[2].get(); - material.base_color.v[3] = base_color[3].get(); - } else - material.base_color = vec3(1.f); - - if (pbr_params.contains("baseColorTexture")) { - auto base_color_index = pbr_params["baseColorTexture"]["index"].get(); - material.base_color_texture = textures[base_color_index]; - } - - if (pbr_params.contains("metallicFactor")) - material.metalness = pbr_params["metallicFactor"].get(); - else - material.metalness = 1.0; - - if (pbr_params.contains("roughnessFactor")) - material.roughness = pbr_params["roughnessFactor"].get(); - else - material.roughness = 1.0; - - if (pbr_params.contains("metallicRoughnessTexture")) { - auto metallic_roughness_index = pbr_params["metallicRoughnessTexture"]["index"].get(); - material.metallic_roughness_texture = textures[metallic_roughness_index]; - } - } - } - - return std::move(materials); -} - -mesh_part gltf::load_primitive(json &gltf_json, json &primitive, std::vector> &buffers_content, std::vector &materials) { - auto part = mesh_part(); - auto &accessors = gltf_json["accessors"]; - - { - auto indices_accessor_index = primitive["indices"].get(); - auto indices_view_index = accessors[indices_accessor_index]["bufferView"].get(); - auto &indices_view = gltf_json["bufferViews"][indices_view_index]; - - auto indices_buffer_index = indices_view["buffer"].get(); - auto indices_offset = indices_view["byteOffset"].get(); - auto indices_length = indices_view["byteLength"].get(); - - auto &indices_buffer = buffers_content[indices_buffer_index]; - uint16_t* indices_start = (uint16_t*)(indices_buffer.data() + indices_offset); - - part.indices.resize(indices_length / sizeof(uint16_t)); - std::memcpy(part.indices.data(), indices_start, indices_length); - } - - { - auto positions_accessor_index = primitive["attributes"]["POSITION"].get(); - auto positions_view_index = accessors[positions_accessor_index]["bufferView"].get(); - auto &positions_view = gltf_json["bufferViews"][positions_view_index]; - - auto positions_buffer_index = positions_view["buffer"].get(); - auto positions_offset = positions_view["byteOffset"].get(); - auto positions_length = positions_view["byteLength"].get(); - - auto &positions_buffer = buffers_content[positions_buffer_index]; - float* positions_start = (float*)(positions_buffer.data() + positions_offset); - - part.positions.resize(positions_length / sizeof(float)); - std::memcpy(part.positions.data(), positions_start, positions_length); - } - - { - auto normals_accessor_index = primitive["attributes"]["NORMAL"].get(); - auto normals_view_index = accessors[normals_accessor_index]["bufferView"].get(); - auto &normals_view = gltf_json["bufferViews"][normals_view_index]; - - auto normals_buffer_index = normals_view["buffer"].get(); - auto normals_offset = normals_view["byteOffset"].get(); - auto normals_length = normals_view["byteLength"].get(); - - auto &normals_buffer = buffers_content[normals_buffer_index]; - float* normals_start = (float*)(normals_buffer.data() + normals_offset); - - part.normals.resize(normals_length / sizeof(float)); - std::memcpy(part.normals.data(), normals_start, normals_length); - } - - { - auto uvs_accessor_index = primitive["attributes"]["TEXCOORD_0"].get(); - auto uvs_view_index = accessors[uvs_accessor_index]["bufferView"].get(); - auto &uvs_view = gltf_json["bufferViews"][uvs_view_index]; - - auto uvs_buffer_index = uvs_view["buffer"].get(); - auto uvs_offset = uvs_view["byteOffset"].get(); - auto uvs_length = uvs_view["byteLength"].get(); - - auto &uvs_buffer = buffers_content[uvs_buffer_index]; - float* uvs_start = (float*)(uvs_buffer.data() + uvs_offset); - - part.uvs.resize(uvs_length / sizeof(float)); - std::memcpy(part.uvs.data(), uvs_start, uvs_length); - } - - part.mat = materials[primitive["material"].get()]; - part.vertices_count = part.positions.size() / 3; - part.triangles_count = part.indices.size() / 3; - - return std::move(part); -} +#include "gltf.hpp" + +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "thirdparty/stb_image.h" + +#include "utils.hpp" + +node gltf::load(std::filesystem::path &path, std::string &filename, vkrenderer &renderer) { + std::fstream f(path / filename); + json gltf_json; + + f >> gltf_json; + + auto &scene = gltf_json["scenes"][0]; + + auto &buffers = gltf_json["buffers"]; + auto buffer_index = 0; + auto buffers_content = std::vector>(buffers.size()); + for (auto &buffer: buffers) { + auto buffer_path = (path / buffer["uri"].get()).string(); + buffers_content[buffer_index] = read_file(buffer_path); + buffer_index++; + } + + auto textures = load_textures(gltf_json, path, renderer); + auto materials = load_materials(gltf_json, textures); + + auto meshes = load_meshes(gltf_json, buffers_content, materials); + + node root_node; + auto &root_children = scene["nodes"]; + uint32_t root_children_count = scene["nodes"].size(); + root_node.children.resize(root_children_count); + + for (size_t child_index = 0; child_index < root_children_count; child_index++) { + load_node(gltf_json, root_children[child_index].get(), root_node.children[child_index], meshes); + } + + return std::move(root_node); +} + +void gltf::load_node(json &gltf_json, uint32_t index, node &parent, std::vector &meshes) { + auto &gltf_node = gltf_json["nodes"][index]; + + if (gltf_node.contains("children")) { + auto &children = gltf_node["children"]; + uint32_t children_count = gltf_node["children"]; + parent.children.resize(children_count); + + for (size_t child_index = 0; child_index < children_count; child_index++) { + load_node(gltf_json, children[child_index].get(), parent.children[child_index], meshes); + } + } + + if (gltf_node.contains("mesh")) { + parent.mesh = std::make_optional(meshes[gltf_node["mesh"].get()]); + } +} + +std::vector gltf::load_meshes(json &gltf_json, std::vector> &buffers_content, std::vector &materials) { + auto &gltf_meshes = gltf_json["meshes"]; + auto meshes_count = gltf_meshes.size(); + std::vector meshes { meshes_count }; + + for(size_t mesh_index = 0; mesh_index < meshes_count; mesh_index++) { + auto &gltf_mesh = gltf_meshes[mesh_index]; + auto &primitives = gltf_mesh["primitives"]; + auto &mesh = meshes[mesh_index]; + + for (auto& primitive: primitives) { + auto &&part = load_primitive(gltf_json, primitive, buffers_content, materials); + mesh.vertices_count += part.vertices_count; + mesh.triangles_count += part.triangles_count; + mesh.parts.emplace_back(std::move(part)); + } + } + + return std::move(meshes); +} + +std::vector gltf::load_textures(json &gltf_json, std::filesystem::path &path, vkrenderer &renderer) { + auto &gltf_images = gltf_json["images"]; + auto images_count = gltf_images.size(); + std::vector images { images_count }; + + for (size_t image_index = 0; image_index < images_count; image_index++) { + auto &gltf_image = gltf_images[image_index]; + int x,y,n; + auto filepath = (path / gltf_image["uri"].get()).string(); + unsigned char *data = stbi_load(filepath.c_str(), &x, &y, &n, 4); + auto img = renderer.create_2d_texture(static_cast(x), static_cast(y), VK_FORMAT_R8G8B8A8_UNORM); + + renderer.update_image(img, data); + + stbi_image_free(data); + + images[image_index] = std::move(img); + } + + auto &gltf_samplers = gltf_json["samplers"]; + auto samplers_count = gltf_samplers.size(); + std::vector samplers { samplers_count }; + + for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) { + samplers[sampler_index] = renderer.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT); + } + + auto &gltf_textures = gltf_json["textures"]; + auto textures_count = gltf_textures.size(); + std::vector textures { textures_count }; + + for (size_t texture_index = 0; texture_index < textures_count; texture_index++) { + auto gltf_texture = gltf_textures[texture_index]; + + auto image_index = gltf_texture["source"].get(); + auto &image = images[image_index]; + + uint32_t sampler_id = 0; + // if (gltf_texture.contains("sampler")) { + // auto sampler_index = gltf_texture["sampler"].get(); + // auto &sampler = samplers[sampler_index]; + // sampler_id = sampler->device_sampler.bindless_index; + // } + + // textures[texture_index] = texture { + // .image_id = image->device_image.bindless_sampled_index, + // .sampler_id = sampler_id + // }; + } + + return std::move(textures); +} + +std::vector gltf::load_materials(json &gltf_json, std::vector &textures) { + auto &gltf_materials = gltf_json["materials"]; + auto materials_count = gltf_materials.size(); + std::vector materials { materials_count }; + + for(size_t material_index = 0; material_index < materials_count; material_index++) { + auto& gltf_material = gltf_materials[material_index]; + auto& material = materials[material_index]; + + if (gltf_material.contains("pbrMetallicRoughness")) { + auto &pbr_params = gltf_material["pbrMetallicRoughness"]; + + if (pbr_params.contains("baseColorFactor")) { + auto &base_color = pbr_params["baseColorFactor"]; + material.base_color.v[0] = base_color[0].get(); + material.base_color.v[1] = base_color[1].get(); + material.base_color.v[2] = base_color[2].get(); + material.base_color.v[3] = base_color[3].get(); + } else + material.base_color = vec3(1.f); + + if (pbr_params.contains("baseColorTexture")) { + auto base_color_index = pbr_params["baseColorTexture"]["index"].get(); + material.base_color_texture = textures[base_color_index]; + } + + if (pbr_params.contains("metallicFactor")) + material.metalness = pbr_params["metallicFactor"].get(); + else + material.metalness = 1.0; + + if (pbr_params.contains("roughnessFactor")) + material.roughness = pbr_params["roughnessFactor"].get(); + else + material.roughness = 1.0; + + if (pbr_params.contains("metallicRoughnessTexture")) { + auto metallic_roughness_index = pbr_params["metallicRoughnessTexture"]["index"].get(); + material.metallic_roughness_texture = textures[metallic_roughness_index]; + } + } + } + + return std::move(materials); +} + +mesh_part gltf::load_primitive(json &gltf_json, json &primitive, std::vector> &buffers_content, std::vector &materials) { + auto part = mesh_part(); + auto &accessors = gltf_json["accessors"]; + + { + auto indices_accessor_index = primitive["indices"].get(); + auto indices_view_index = accessors[indices_accessor_index]["bufferView"].get(); + auto &indices_view = gltf_json["bufferViews"][indices_view_index]; + + auto indices_buffer_index = indices_view["buffer"].get(); + auto indices_offset = indices_view["byteOffset"].get(); + auto indices_length = indices_view["byteLength"].get(); + + auto &indices_buffer = buffers_content[indices_buffer_index]; + uint16_t* indices_start = (uint16_t*)(indices_buffer.data() + indices_offset); + + part.indices.resize(indices_length / sizeof(uint16_t)); + std::memcpy(part.indices.data(), indices_start, indices_length); + } + + { + auto positions_accessor_index = primitive["attributes"]["POSITION"].get(); + auto positions_view_index = accessors[positions_accessor_index]["bufferView"].get(); + auto &positions_view = gltf_json["bufferViews"][positions_view_index]; + + auto positions_buffer_index = positions_view["buffer"].get(); + auto positions_offset = positions_view["byteOffset"].get(); + auto positions_length = positions_view["byteLength"].get(); + + auto &positions_buffer = buffers_content[positions_buffer_index]; + float* positions_start = (float*)(positions_buffer.data() + positions_offset); + + part.positions.resize(positions_length / sizeof(float)); + std::memcpy(part.positions.data(), positions_start, positions_length); + } + + { + auto normals_accessor_index = primitive["attributes"]["NORMAL"].get(); + auto normals_view_index = accessors[normals_accessor_index]["bufferView"].get(); + auto &normals_view = gltf_json["bufferViews"][normals_view_index]; + + auto normals_buffer_index = normals_view["buffer"].get(); + auto normals_offset = normals_view["byteOffset"].get(); + auto normals_length = normals_view["byteLength"].get(); + + auto &normals_buffer = buffers_content[normals_buffer_index]; + float* normals_start = (float*)(normals_buffer.data() + normals_offset); + + part.normals.resize(normals_length / sizeof(float)); + std::memcpy(part.normals.data(), normals_start, normals_length); + } + + { + auto uvs_accessor_index = primitive["attributes"]["TEXCOORD_0"].get(); + auto uvs_view_index = accessors[uvs_accessor_index]["bufferView"].get(); + auto &uvs_view = gltf_json["bufferViews"][uvs_view_index]; + + auto uvs_buffer_index = uvs_view["buffer"].get(); + auto uvs_offset = uvs_view["byteOffset"].get(); + auto uvs_length = uvs_view["byteLength"].get(); + + auto &uvs_buffer = buffers_content[uvs_buffer_index]; + float* uvs_start = (float*)(uvs_buffer.data() + uvs_offset); + + part.uvs.resize(uvs_length / sizeof(float)); + std::memcpy(part.uvs.data(), uvs_start, uvs_length); + } + + part.mat = materials[primitive["material"].get()]; + part.vertices_count = part.positions.size() / 3; + part.triangles_count = part.indices.size() / 3; + + return std::move(part); +} -- cgit v1.3