From 4433d34e32d0148254aa6276c9c8837bb0233324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Con=C3=A1l?= Date: Thu, 22 Feb 2024 13:44:40 -0500 Subject: [PATCH] Shifted to Half Life BSPs, learned how to unwind their really weird triangle fans --- CMakeLists.txt | 2 +- Renderer/CommandBuffer.cpp | 2 +- Renderer/CommandBuffer.hpp | 2 +- Renderer/Pipeline.cpp | 68 ++++++--- Renderer/Pipeline.hpp | 42 +++++- Renderer/Renderer.cpp | 21 +-- Renderer/Renderer.hpp | 5 +- Scene/BSP.cpp | 156 ++++++++++++------- Scene/BSP.hpp | 294 +++++++++++++++++------------------- UI/UI.cpp | 20 ++- assets/shaders/map/bsp.frag | 6 +- assets/shaders/map/bsp.vert | 13 +- pléascach.cpp | 5 +- 13 files changed, 363 insertions(+), 273 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fc1358..f8a6e47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) if(WIN32) set(CMAKE_CXX_FLAGS "-D_DEBUG") else() -set(CMAKE_CXX_FLAGS "-D_DEBUG -Wall -O3") +set(CMAKE_CXX_FLAGS "-D_DEBUG -Wall") endif() project(Pleascach) diff --git a/Renderer/CommandBuffer.cpp b/Renderer/CommandBuffer.cpp index 08ccc99..80a960c 100644 --- a/Renderer/CommandBuffer.cpp +++ b/Renderer/CommandBuffer.cpp @@ -82,7 +82,7 @@ void CommandBuffer::bind(Terrain* terrain) { command_buffer.bindIndexBuffer(*terrain->index_buffer, 0, vk::IndexType::eUint32); } -void CommandBuffer::bind(Q3BSP::BSP* bsp) { +void CommandBuffer::bind(HLBSP::BSP* bsp) { bind(*bsp->pipeline); bind(*bsp->vertex_buffer); command_buffer.bindIndexBuffer(*bsp->index_buffer, 0, vk::IndexType::eUint32); diff --git a/Renderer/CommandBuffer.hpp b/Renderer/CommandBuffer.hpp index 56b5678..74a415d 100644 --- a/Renderer/CommandBuffer.hpp +++ b/Renderer/CommandBuffer.hpp @@ -43,7 +43,7 @@ struct CommandBuffer { void bind(std::shared_ptr model); void bind(Terrain* terrain); - void bind(Q3BSP::BSP* bsp); + void bind(HLBSP::BSP* bsp); void draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex = 0, uint32_t first_instance = 0); diff --git a/Renderer/Pipeline.cpp b/Renderer/Pipeline.cpp index 3c8c97d..d3f494d 100644 --- a/Renderer/Pipeline.cpp +++ b/Renderer/Pipeline.cpp @@ -10,7 +10,8 @@ #include -GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& shaders, const vk::Extent2D& extent, const RenderPass& render_pass, vk::ArrayProxy bindings, const vk::VertexInputBindingDescription& vertex_binding, const std::vector& vertex_attrs, enum Type type) : dev(dev) { +GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& shaders, const vk::Extent2D& extent, const RenderPass& render_pass, vk::ArrayProxy bindings, const vk::VertexInputBindingDescription& vertex_binding, const std::vector& vertex_attrs, enum Type type, bool wireframe) + : dev(dev), shaders(shaders), extent(extent), render_pass(render_pass), bindings(bindings), vertex_binding(vertex_binding), vertex_attrs(vertex_attrs), type(type) { /* create layout * Eventually add a graphicspipline constructor that allows specification of layouts etc * kinda like how Image::Image has all those versions @@ -56,24 +57,23 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& sh })[0]; /* shader setup */ - std::vector shader_info; shader_info.reserve(shaders.size()); for (const auto& shader : shaders) shader_info.push_back(shader.info()); /* vertex input setup */ - const std::vector vertex_bindings = { + vertex_bindings = { vertex_binding, }; - const auto vertex_input_info = vk::PipelineVertexInputStateCreateInfo{ + vertex_input_info = vk::PipelineVertexInputStateCreateInfo { .vertexBindingDescriptionCount = static_cast(vertex_bindings.size()), .pVertexBindingDescriptions = vertex_bindings.data(), .vertexAttributeDescriptionCount = static_cast(vertex_attrs.size()), .pVertexAttributeDescriptions = vertex_attrs.data(), }; - auto input_asm_info = vk::PipelineInputAssemblyStateCreateInfo { + input_asm_info = vk::PipelineInputAssemblyStateCreateInfo { /* matters later if we use strip primitives */ .primitiveRestartEnable = vk::False, }; @@ -94,7 +94,7 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& sh const vk::PipelineTessellationStateCreateInfo* ptesselation_info = nullptr; - const auto tess_info = vk::PipelineTessellationStateCreateInfo { + tess_info = vk::PipelineTessellationStateCreateInfo { /* quads*/ .patchControlPoints = 4, }; @@ -103,22 +103,22 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& sh ptesselation_info = &tess_info; } - const auto raster_info = vk::PipelineRasterizationStateCreateInfo { + raster_info = vk::PipelineRasterizationStateCreateInfo { .depthClampEnable = vk::False, - .polygonMode = type == eBOX ? vk::PolygonMode::eLine : vk::PolygonMode::eFill, - .cullMode = type == eBOX ? vk::CullModeFlagBits::eNone : vk::CullModeFlagBits::eBack, + .polygonMode = (type == eBOX || wireframe) ? vk::PolygonMode::eLine : vk::PolygonMode::eFill, + .cullMode = type == eBOX ? vk::CullModeFlagBits::eNone : vk::CullModeFlagBits::eNone, .frontFace = vk::FrontFace::eCounterClockwise, .depthBiasEnable = type == eBOX, .depthBiasConstantFactor = 0.01, .lineWidth = 1.0, }; - const auto multisample_info = vk::PipelineMultisampleStateCreateInfo { + multisample_info = vk::PipelineMultisampleStateCreateInfo { .rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = vk::False, }; - const auto depth_stencil_info = vk::PipelineDepthStencilStateCreateInfo{ + depth_stencil_info = vk::PipelineDepthStencilStateCreateInfo{ .depthTestEnable = vk::True, .depthWriteEnable = type != eBOX, .depthCompareOp = vk::CompareOp::eLess, @@ -128,7 +128,7 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& sh .maxDepthBounds = 1.0, }; - const auto color_blend_attachment = vk::PipelineColorBlendAttachmentState { + color_blend_attachment = vk::PipelineColorBlendAttachmentState { /* only the box has blending */ .blendEnable = type == eBOX, .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, @@ -142,8 +142,8 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& sh }; - std::array blend_constants = {0.0f, 0.0f, 0.0f, 0.0f }; - auto color_blend_info = vk::PipelineColorBlendStateCreateInfo{ + blend_constants = {0.0f, 0.0f, 0.0f, 0.0f }; + color_blend_info = vk::PipelineColorBlendStateCreateInfo{ .logicOpEnable = vk::False, .logicOp = vk::LogicOp::eCopy, .attachmentCount = 1, @@ -152,36 +152,34 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& sh }; /* temporary viewport and scissor, since it is a dynamic state due to the existence of window resizing */ - const auto viewport = vk::Viewport{ + viewport = vk::Viewport{ .x = 0.0, .y = static_cast(extent.height), .width = static_cast(extent.width), .height = -static_cast(extent.height), }; - const auto scissor = vk::Rect2D { + scissor = vk::Rect2D { .offset = 0, .extent = extent, }; - const auto viewport_info = vk::PipelineViewportStateCreateInfo { + viewport_info = vk::PipelineViewportStateCreateInfo { .viewportCount = 1, .pViewports = &viewport, .scissorCount = 1, .pScissors = &scissor, }; - const vk::DynamicState dyn_states[] = { - vk::DynamicState::eScissor, - vk::DynamicState::eViewport, - }; + dyn_states[0] = vk::DynamicState::eScissor; + dyn_states[1] = vk::DynamicState::eViewport; - const auto dyn_info = vk::PipelineDynamicStateCreateInfo{ - .dynamicStateCount = std::size(dyn_states), + dyn_info = vk::PipelineDynamicStateCreateInfo { + .dynamicStateCount = (uint32_t)std::size(dyn_states), .pDynamicStates = dyn_states, }; - const auto pipeline_info = vk::GraphicsPipelineCreateInfo { + pipeline_info = vk::GraphicsPipelineCreateInfo { .stageCount = static_cast(shaders.size()), .pStages = shader_info.data(), .pVertexInputState = &vertex_input_info, @@ -237,7 +235,29 @@ void GraphicsPipeline::update(uint32_t binding, const Texture& tex) { }, nullptr); } +void GraphicsPipeline::rebuild(bool wireframe) { + vertex_input_info = vk::PipelineVertexInputStateCreateInfo { + .vertexBindingDescriptionCount = static_cast(vertex_bindings.size()), + .pVertexBindingDescriptions = vertex_bindings.data(), + .vertexAttributeDescriptionCount = static_cast(vertex_attrs.size()), + .pVertexAttributeDescriptions = vertex_attrs.data(), + }; + + raster_info.polygonMode = wireframe ? vk::PolygonMode::eLine : vk::PolygonMode::eFill; + auto res = dev.createGraphicsPipeline(nullptr, pipeline_info); + if (res.result != vk::Result::eSuccess) { + Log::error("Failed to create pipeline: (Vulkan error code: %d)\n", res.result); + } + + defunct_pipelines.push_back(pipeline); + + pipeline = res.value; +} + GraphicsPipeline::~GraphicsPipeline() { + for(auto& p : defunct_pipelines) { + dev.destroyPipeline(p); + } dev.destroyDescriptorSetLayout(desc_layout); dev.destroyPipelineLayout(layout); dev.destroyDescriptorPool(desc_pool); diff --git a/Renderer/Pipeline.hpp b/Renderer/Pipeline.hpp index 3dd69a7..12eaffc 100644 --- a/Renderer/Pipeline.hpp +++ b/Renderer/Pipeline.hpp @@ -3,6 +3,8 @@ #define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS #include +#include + #include struct Shader; @@ -22,14 +24,49 @@ struct GraphicsPipeline { GraphicsPipeline(vk::Device dev, const std::vector& shaders, const vk::Extent2D& extent, const RenderPass& render_pass, vk::ArrayProxy bindings, - const vk::VertexInputBindingDescription& vertex_binding, const std::vector& vertex_attrs, enum Type type = Type::eVERTEX); + const vk::VertexInputBindingDescription& vertex_binding, + const std::vector& vertex_attrs, + enum Type type = Type::eVERTEX, bool wireframe = false); + + /* everything needed for recreation */ vk::Device dev; + const std::vector shaders; + const vk::Extent2D extent; + const RenderPass& render_pass; + const vk::ArrayProxy bindings; + const vk::VertexInputBindingDescription vertex_binding; + const std::vector vertex_attrs; + const Type type; + + vk::Pipeline pipeline; vk::PipelineLayout layout; vk::DescriptorSetLayout desc_layout; vk::DescriptorPool desc_pool; vk::DescriptorSet desc_set; + /* pipeline creation info cached for rebuilding */ + std::vector shader_info; + std::vector vertex_bindings; + vk::PipelineVertexInputStateCreateInfo vertex_input_info; + vk::PipelineInputAssemblyStateCreateInfo input_asm_info; + vk::PipelineTessellationStateCreateInfo tess_info; + vk::PipelineRasterizationStateCreateInfo raster_info; + vk::PipelineMultisampleStateCreateInfo multisample_info; + vk::PipelineDepthStencilStateCreateInfo depth_stencil_info; + vk::PipelineColorBlendAttachmentState color_blend_attachment; + std::array blend_constants; + vk::PipelineColorBlendStateCreateInfo color_blend_info; + vk::Viewport viewport; + vk::Rect2D scissor; + vk::PipelineViewportStateCreateInfo viewport_info; + vk::DynamicState dyn_states[2]; + vk::PipelineDynamicStateCreateInfo dyn_info; + vk::GraphicsPipelineCreateInfo pipeline_info; + + + std::vector defunct_pipelines; + inline operator vk::Pipeline&() { return pipeline; } @@ -38,6 +75,9 @@ struct GraphicsPipeline { void update(uint32_t binding, const UniformBuffer& uni); void update(uint32_t binding, const Texture& tex); + + void rebuild(bool wireframe); + ~GraphicsPipeline(); }; diff --git a/Renderer/Renderer.cpp b/Renderer/Renderer.cpp index cac26d0..654199a 100644 --- a/Renderer/Renderer.cpp +++ b/Renderer/Renderer.cpp @@ -199,24 +199,25 @@ Renderer::Renderer(Window& win) : win(win) { }; /* BSP loader */ - bsp = std::make_unique(phys_dev, dev, "assets/maps/git.bsp"); - std::vector bsp_shaders = { + bsp = std::make_unique(phys_dev, dev, "assets/maps/hl1.bsp"); + bsp_shaders = { { dev, "assets/shaders/bin/bsp.vert.spv", vk::ShaderStageFlagBits::eVertex }, { dev, "assets/shaders/bin/bsp.frag.spv", vk::ShaderStageFlagBits::eFragment }, }; + bsp->pipeline = std::make_unique(dev, bsp_shaders, swapchain->extent, *render_pass, bindings, bsp->vertex_buffer->binding(0), bsp->vertex_buffer->attrs(0)); bsp->pipeline->update(0, *uniform_buffer); /* bounding and hitboxs */ - std::vector box_shaders = { + box_shaders = { { dev, "assets/shaders/bin/box.vert.spv", vk::ShaderStageFlagBits::eVertex }, { dev, "assets/shaders/bin/box.geom.spv", vk::ShaderStageFlagBits::eGeometry }, { dev, "assets/shaders/bin/box.frag.spv", vk::ShaderStageFlagBits::eFragment }, }; std::vector boxes; - boxes.reserve(bsp->leafs.size()); - for (auto& leaf : bsp->leafs) { + boxes.reserve(bsp->leaves.size()); + for (auto& leaf : bsp->leaves) { boxes.push_back(BoxVertex{ .mins = leaf.bb_mins, .maxes = leaf.bb_maxes, @@ -228,11 +229,6 @@ Renderer::Renderer(Window& win) : win(win) { box_pipeline = std::make_unique(dev, box_shaders, swapchain->extent, *render_pass, bindings, box_buffer->binding(0), box_buffer->attrs(0), GraphicsPipeline::Type::eBOX); box_pipeline->update(0, *uniform_buffer); - for (auto& shader : box_shaders) - shader.cleanup(); - for (auto& shader : bsp_shaders) - shader.cleanup(); - ui = std::make_unique(this); } @@ -351,6 +347,7 @@ void Renderer::draw() { bsp->load_indices(cam.pos, visibility_testing, p * uni.view); command_buffer->bind(bsp.get()); + /*command_buffer->draw(bsp->vertices.size(), 1);*/ command_buffer->command_buffer.drawIndexed(bsp->indices.size(), 1, 0, 0, 0); n_indices = bsp->indices.size(); @@ -422,6 +419,10 @@ Renderer::~Renderer() { box_pipeline.reset(); uniform_buffer.reset(); + for (auto& shader : box_shaders) + shader.cleanup(); + for (auto& shader : bsp_shaders) + shader.cleanup(); for (auto& tex : textures) { tex.cleanup(); diff --git a/Renderer/Renderer.hpp b/Renderer/Renderer.hpp index 0414ac6..283e193 100644 --- a/Renderer/Renderer.hpp +++ b/Renderer/Renderer.hpp @@ -51,11 +51,13 @@ struct Renderer { std::unique_ptr command_buffer; std::unique_ptr render_pass; + std::vector box_shaders; std::unique_ptr box_pipeline; std::unique_ptr> box_buffer; std::unique_ptr uniform_buffer; - std::unique_ptr bsp; + std::vector bsp_shaders; + std::unique_ptr bsp; std::vector textures; @@ -77,6 +79,7 @@ struct Renderer { bool visibility_testing = false; bool show_bboxes = false; bool should_close = false; + bool wireframe_mode = false; size_t n_indices; diff --git a/Scene/BSP.cpp b/Scene/BSP.cpp index 96b0fc9..6bb5b47 100644 --- a/Scene/BSP.cpp +++ b/Scene/BSP.cpp @@ -11,7 +11,7 @@ #include -using namespace Q3BSP; +using namespace HLBSP; static inline void copy_data(void* file_data, std::string& dst, Lump& lump) { dst.resize(lump.len); @@ -20,6 +20,7 @@ static inline void copy_data(void* file_data, std::string& dst, Lump& lump) { template static inline void copy_data(void* file_data, std::vector& dst, Lump& lump) { + Log::debug("%zu items\n", lump.len / sizeof(T)); dst.resize(lump.len / sizeof(T)); std::memcpy(dst.data(), ((u8*)file_data) + lump.offset, lump.len); } @@ -27,7 +28,8 @@ static inline void copy_data(void* file_data, std::vector& dst, Lump& lump) { void BSP::load_indices(const glm::vec3& cam_pos, bool visibility_test, const glm::mat4& view) { std::set present_faces; std::vector visible_faces; - if (visibility_test) { + // if (visibility_test) { + if(false) { auto leaf_idx = determine_leaf(cam_pos); auto fr_planes = frustum(view); @@ -36,11 +38,11 @@ void BSP::load_indices(const glm::vec3& cam_pos, bool visibility_test, const glm index_buffer->upload(indices); last_leaf = leaf_idx; - auto& cam_leaf = leafs[leaf_idx]; + auto& cam_leaf = leaves[leaf_idx]; std::vector visible_leafs; - for (auto& leaf : leafs) { + for (auto& leaf : leaves) { const auto min = leaf.bb_mins; const auto max = leaf.bb_maxes; @@ -61,8 +63,8 @@ void BSP::load_indices(const glm::vec3& cam_pos, bool visibility_test, const glm } for (const auto& leaf : visible_leafs) { - for (size_t i = 0; i < leaf.n_leaf_faces; i++) { - auto idx = leaf_faces[leaf.first_leaf_face_idx + i].face_idx; + for (size_t i = 0; i < leaf.n_mark_surfaces; i++) { + auto idx = mark_surfaces[leaf.first_mark_surface_idx + i]; if (present_faces.contains(idx)) continue; @@ -77,22 +79,27 @@ void BSP::load_indices(const glm::vec3& cam_pos, bool visibility_test, const glm indices.clear(); for (auto& face : visible_faces) { - switch (face.type) { - case Face::ePATCH: - break; - case Face::ePOLYGON: - case Face::eMESH: - for (size_t i = 0; i < face.n_mesh_vertices; i++) - indices.push_back(face.first_vertex_idx + mesh_vertices[face.first_mesh_vertex_idx+i].idx); - break; + for (i16 i = 1, j = 2; j < face.n_surf_edges; i++, j++) { + indices.push_back(face.first_surf_edge_idx); + indices.push_back(face.first_surf_edge_idx+i); + indices.push_back(face.first_surf_edge_idx+j); } +// indices.push_back(get_index_from_surfedge(face.first_surf_edge_idx)); } - assert(indices.size() % 3 == 0); - index_buffer->upload(indices); } +int BSP::get_index_from_surfedge(int surfedge) { + int surf = surfedges[surfedge]; + if(surf >= 0) { + return edges[surf].vertex_indices[0]; + } + else { + return edges[-surf].vertex_indices[1]; + } +} + int BSP::determine_leaf(glm::vec3 cam_pos) { /* use SDF of planes to determine relative position with respect to partitioning planes */ int idx = 0; @@ -112,16 +119,6 @@ int BSP::determine_leaf(glm::vec3 cam_pos) { bool BSP::determine_visibility(const Leaf& cam_leaf, const Leaf& leaf, const std::array& frustum, const glm::vec3 box_verts[8]) { - int vis = cam_leaf.cluster_idx, cluster = leaf.cluster_idx; - if (vis_info.vectors.size() == 0 || vis < 0) - return true; - - int i = (vis * vis_info.sz_vectors) + (cluster >> 3); - u8 set = vis_info.vectors[i]; - - if (!(set & (1 << (cluster & 0x7)))) - return false; - /* perform fustrum culling */ return box_in_frustum(frustum, box_verts); } @@ -134,64 +131,109 @@ static inline void change_swizzle(T& v) { v.z = tmp; } +static std::vector> load_entities(const std::string& in) { + /* TODO */ + return { + {{"test", "this"}}, + }; +} + +static std::vector load_mip_textures(const u8* data, u32 offset) { + const TextureLump* lump = reinterpret_cast(data + offset); + std::vector ret; + ret.resize(lump->n_mip_textures); + + for(size_t i = 0; i < ret.size(); i++) { + ret[i] = *reinterpret_cast(data + lump->offsets[i]); + } + + return ret; +} + BSP::BSP(vk::PhysicalDevice phys_dev, vk::Device dev, const std::string& fname) : dev(dev), filename(fname) { file_data = file::slurpb(fname); - Log::debug("File size: %zu\n", file_data.size()); + Log::debug("BSP file size: %zu\n", file_data.size()); header = reinterpret_cast(file_data.data()); Log::info("Loading BSP: %s\n", fname.c_str()); - if(header->magic != BSP_MAGIC) { - Log::error("BSP file missing magic!\n"); + if(header->version != 30) { + Log::error("BSP file not expected version (Half Life has version 30)!\n"); } - copy_data(file_data.data(), entities, header->entities); - copy_data(file_data.data(), textures, header->textures); + Log::debug("Loading entities\n"); + std::string entities_buff; + copy_data(file_data.data(), entities_buff, header->entities); + entities = load_entities(entities_buff); + + Log::debug("Loading planes\n"); copy_data(file_data.data(), planes, header->planes); /* change swizzle */ for (auto& plane : planes) { change_swizzle(plane.norm); } + + Log::debug("Loading textures\n"); + textures = load_mip_textures(file_data.data(), header->textures.offset); + + Log::debug("Loading vertices\n"); + copy_data(file_data.data(), vertices, header->vertices); + for (auto& vertex : vertices) { + change_swizzle(vertex.pos); + } + + Log::debug("Loading nodes\n"); copy_data(file_data.data(), nodes, header->nodes); for (auto& node : nodes) { change_swizzle(node.bb_mins); change_swizzle(node.bb_maxes); } - copy_data(file_data.data(), leafs, header->leafs); - for (auto& leaf : leafs) { + + Log::debug("Loading texinfo\n"); + copy_data(file_data.data(), tex_infos, header->texinfo); + + Log::debug("Loading faces\n"); + copy_data(file_data.data(), faces, header->faces); + + Log::debug("Loading lightmap\n"); + lightmap.lights = reinterpret_cast(file_data.data()+header->lighting.offset); + + Log::debug("Loading clip nodes\n"); + copy_data(file_data.data(), clip_nodes, header->clip_nodes); + + Log::debug("Loading leaves\n"); + copy_data(file_data.data(), leaves, header->leaves); + for (auto& leaf : leaves) { change_swizzle(leaf.bb_mins); change_swizzle(leaf.bb_maxes); } - copy_data(file_data.data(), leaf_faces, header->leaf_faces); - copy_data(file_data.data(), leaf_brushes, header->leaf_brushes); + + Log::debug("Loading mark surfaces\n"); + copy_data(file_data.data(), mark_surfaces, header->mark_surfaces); + + Log::debug("Loading edges\n"); + copy_data(file_data.data(), edges, header->edges); + + Log::debug("Loading surfedges\n"); + copy_data(file_data.data(), surfedges, header->surf_edges); + vertices_prime.reserve(surfedges.size()); + /* use this to build our vertices_prime, idea thanks to gzalo's HalfMapper */ + for(const auto& s : surfedges) { + vertices_prime.push_back(vertices[edges[s > 0? s : -s].vertex_indices[s<=0]]); + } + + Log::debug("Loading models\n"); copy_data(file_data.data(), models, header->models); for (auto& model : models) { change_swizzle(model.bb_mins); change_swizzle(model.bb_maxes); } - copy_data(file_data.data(), brushes, header->brushes); - copy_data(file_data.data(), brush_sides, header->brush_sides); - copy_data(file_data.data(), vertices, header->vertices); - /* correct for handedness */ - for (auto& vertex : vertices) { - change_swizzle(vertex.pos); - change_swizzle(vertex.norm); - } - - copy_data(file_data.data(), mesh_vertices, header->mesh_vertices); - copy_data(file_data.data(), effects, header->effects); - copy_data(file_data.data(), faces, header->faces); - copy_data(file_data.data(), lightmaps, header->lightmaps); - copy_data(file_data.data(), lightvols, header->lightvols); - - vis_info.sz_vectors = reinterpret_cast(file_data.data() + header->vis_info.offset)[1]; - auto sz = header->vis_info.len; - vis_info.vectors.resize(sz); - std::memcpy(vis_info.vectors.data(), file_data.data() + header->vis_info.offset + 2*sizeof(u32), sz); - - vertex_buffer = std::make_unique>(phys_dev, dev, vertices.size()); - vertex_buffer->upload(vertices); + + Log::debug("Creating vertex buffer of size %zu\n", vertices.size()); + vertex_buffer = std::make_unique>(phys_dev, dev, vertices_prime.size()); + vertex_buffer->upload(vertices_prime); + Log::debug("Creating index buffer\n"); /* set limit at 256Mi indices */ index_buffer = std::make_unique(phys_dev, dev, 100000 * sizeof(u32), vk::BufferUsageFlagBits::eIndexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible diff --git a/Scene/BSP.hpp b/Scene/BSP.hpp index d506f1a..1f128b9 100644 --- a/Scene/BSP.hpp +++ b/Scene/BSP.hpp @@ -12,8 +12,14 @@ #include #include -/* contains loading functions for Quake III-style BSPs */ -namespace Q3BSP { + +#define MAX_TEXTURE_NAME 16 +#define MIP_LEVELS 4 + +#define MAX_MAP_HULLS 4 +/* contains loading functions for Half Life BSPs */ +namespace HLBSP { + struct Lump { u32 offset; u32 len; @@ -21,106 +27,63 @@ namespace Q3BSP { using rgb = glm::u8vec3; using rgba = glm::u8vec4; - /* "IBSP" */ - const uint32_t BSP_MAGIC = 0x50534249U; + using vec3 = glm::vec3; + using ivec3 = glm::vec<3, i16>; + struct Header { - u32 magic; u32 version; union { - Lump lumps[17]; + Lump lumps[15]; struct { Lump entities, - textures, planes, - nodes, - leafs, - leaf_faces, - leaf_brushes, - models, - brushes, - brush_sides, + textures, vertices, - mesh_vertices, - effects, + visibility, + nodes, + texinfo, faces, - lightmaps, - lightvols, - vis_info; + lighting, + clip_nodes, + leaves, + mark_surfaces, + edges, + surf_edges, + models; }; }; }; - struct Texture { - char name[64]; - /* values of unknown meaning - TODO: check darkplaces or some other 3rd party loader */ - i32 flags; - i32 contents; - }; - struct Plane { - glm::vec3 norm; + vec3 norm; float dist; + /* exists for certain optimizations (swaped y and z) */ + enum PlaneType { + eX, + eZ, + eY, + eAnyX, + eAnyZ, + eAnyY, + } type; }; - struct Node { - u32 plane; - /* negative numbers are leaf indices */ - i32 children[2]; - - /* bounding box coords (integer) */ - glm::ivec3 bb_mins; - glm::ivec3 bb_maxes; + struct TextureLump { + u32 n_mip_textures; + i32 offsets[]; }; - struct Leaf { - i32 cluster_idx; - u32 area; - glm::ivec3 bb_mins; - glm::ivec3 bb_maxes; - i32 first_leaf_face_idx; - u32 n_leaf_faces; - i32 first_leaf_brush_idx; - u32 n_leaf_brushes; - }; - - struct LeafFaces { - /* list of face indices (one list per leaf) */ - i32 face_idx; - }; - - struct LeafBrush { - /* list of brush indices (one list leaf) */ - i32 brush_idx; - }; - - struct Model { - glm::vec3 bb_mins; - glm::vec3 bb_maxes; - i32 first_face_idx; - u32 n_faces; - i32 first_brush_idx; - u32 n_brushes; - }; - - struct Brush { - i32 first_brushside_idx; - u32 n_brushsides; - i32 texture_idx; - }; - - struct BrushSide { - i32 plane_idx; - i32 texture_idx; + struct MipTexture { + char name[MAX_TEXTURE_NAME]; + u32 width, height; + /* is 0 if stored in WAD, otherwise, offset is from beginning of this struct */ + u32 mip_offsets[MIP_LEVELS]; }; struct Vertex { - glm::vec3 pos; - glm::vec2 uv; - glm::vec2 lightmap_coords; - glm::vec3 norm; - glm::u8vec4 color; - + vec3 pos; + static inline std::vector attrs(uint32_t binding) { return std::vector { { @@ -128,109 +91,132 @@ namespace Q3BSP { .binding = binding, .format = vk::Format::eR32G32B32Sfloat, .offset = offsetof(Vertex, pos), - }, { - .location = 1, - .binding = binding, - .format = vk::Format::eR32G32Sfloat, - .offset = offsetof(Vertex, uv), - }, { - .location = 2, - .binding = binding, - .format = vk::Format::eR32G32Sfloat, - .offset = offsetof(Vertex, lightmap_coords), - }, { - .location = 3, - .binding = binding, - .format = vk::Format::eR32G32B32Sfloat, - .offset = offsetof(Vertex, norm), - }, { - .location = 4, - .binding = binding, - .format = vk::Format::eR32Uint, - .offset = offsetof(Vertex, color), } }; } }; - struct MeshVertex { - i32 idx; + struct Vis {}; + + struct Node { + i32 plane; + /* negative numbers are leaf indices */ + i16 children[2]; + + /* bounding box coords (integer) */ + ivec3 bb_mins; + ivec3 bb_maxes; + + i16 first_face_idx; + i16 n_faces; }; - struct Effect { - char name[64]; - i32 brush_idx; - /* almost always 5 for some reason */ - i32 unknown; + struct TexInfo { + vec3 shift_s_dir; + float shift_s; + vec3 shift_t_dir; + float shift_t; + u32 mip_tex_idx; + /* seems to always be 0 */ + u32 flags; + }; struct Face { - i32 texture_idx; - /* -1 if no effect */ - i32 effect_idx; - enum FaceType { - ePOLYGON = 1, - ePATCH = 2, - eMESH = 3, - eBILLBOARD = 4, - } type; - i32 first_vertex_idx; - u32 n_vertices; - i32 first_mesh_vertex_idx; - u32 n_mesh_vertices; - i32 lightmap_idx; - glm::vec2 lightmap_start; - glm::vec2 lightmap_end; - - glm::vec3 lightmap_origin; - glm::vec3 lightmap_unit_vectors[2]; - glm::vec3 norm; - glm::ivec2 patch_dimensions; + u16 plane_idx; + /* set if different normals orientation */ + u16 plane_side; + u32 first_surf_edge_idx; + i16 n_surf_edges; + i16 tex_info_idx; + u8 lighting_styles[4]; + u32 lightmap_offset; }; struct Lightmap { - u8 map[128][128][3]; + rgb* lights; }; - struct Lightvol { - rgb ambient; - rgb directional; - /* spherical coordinates */ - glm::u8vec2 direction; + struct ClipNode { + i32 plane_idx; + /* negative numbers are contents */ + i16 children[2]; }; - struct VisibilityInfo { - u32 sz_vectors; - std::vector vectors; + struct Leaf { + enum { + eEmpty = -1, + eSolid = -2, + eWater = -3, + eSlime = -4, + eLava = -5, + eSky = -6, + eOrigin = -7, + eClip = -8, + eCurrent0 = -9, + eCurrent90 = -10, + eCurrent180 = -11, + eCurrent270 = -12, + eCurrentUp = -13, + eCurrentDown = -14, + eTranslucent = -15, + } contents; + /* if this is -1, no VIS data */ + i32 vis_offset; + ivec3 bb_mins; + ivec3 bb_maxes; + u16 first_mark_surface_idx; + u16 n_mark_surfaces; + u8 ambient_sound_levels[4]; + }; + + typedef u16 MarkSurface; + + struct Edge { + u16 vertex_indices[2]; + }; + + typedef i32 Surfedge; + + struct Model { + vec3 bb_mins; + vec3 bb_maxes; + vec3 origin; + i32 head_node_indices[MAX_MAP_HULLS]; + i32 vis_leafs; + i32 first_face_idx; + i32 n_faces; }; struct BSP { BSP(vk::PhysicalDevice phys_dev, vk::Device dev, const std::string& fname); - void load_indices(const glm::vec3& cam_pos, bool visibility_testing, const glm::mat4& view); - int determine_leaf(glm::vec3 cam_pos); - bool determine_visibility(const Leaf& cam_leaf, const Leaf& leaf, const std::array& frustum, const glm::vec3 box_verts[8]); + void load_indices(const vec3& cam_pos, bool visibility_testing, const glm::mat4& view); + int determine_leaf(vec3 cam_pos); + bool determine_visibility(const Leaf& cam_leaf, const Leaf& leaf, const std::array& frustum, const vec3 box_verts[8]); + int get_index_from_surfedge(int surfedge); + vk::Device dev; Header* header; std::string filename; std::vector file_data; - std::string entities; - std::vector textures; + + std::vector<::std::map<::std::string, std::string>> entities; std::vector planes; - std::vector nodes; - std::vector leafs; - std::vector leaf_brushes; - std::vector leaf_faces; - std::vector models; - std::vector brushes; - std::vector brush_sides; + std::vector textures; std::vector vertices; - std::vector mesh_vertices; - std::vector effects; + std::vector vertices_prime; + /* skipping vis for now */ + std::vector nodes; + std::vector tex_infos; std::vector faces; - std::vector lightmaps; - std::vector lightvols; - VisibilityInfo vis_info; + Lightmap lightmap; + std::vector clip_nodes; + std::vector leaves; + std::vector mark_surfaces; + std::vector edges; + std::vector surfedges; + std::vector models; std::vector indices; std::unique_ptr index_buffer; diff --git a/UI/UI.cpp b/UI/UI.cpp index 16b7466..28b6008 100644 --- a/UI/UI.cpp +++ b/UI/UI.cpp @@ -12,6 +12,9 @@ #include +/* this pains me to do, but its the only way :( */ +Renderer* __ren; + static csys::ItemLog& operator<<(csys::ItemLog& log, ImVector& vec) { if (!vec.size()) return log << "vector {}"; @@ -21,12 +24,15 @@ static csys::ItemLog& operator<<(csys::ItemLog& log, ImVector& vec) { return log << vec[vec.size() - 1] << " }"; } -/*static void vec_setter(ImVector& v, std::vector in) { - v.reserve(in.size()); - std::memcpy(v.Data, in.data(), sizeof(float) * in.size()); -}*/ +static void wireframe_setter(bool& v, bool in) { + if(v == in) + return; + v = in; + __ren->bsp->pipeline->rebuild(in); +} UI::UI(Renderer* ren) : ren(ren), dev(ren->dev) { + __ren = ren; IMGUI_CHECKVERSION(); ImGui::CreateContext(); @@ -117,6 +123,7 @@ UI::UI(Renderer* ren) : ren(ren), dev(ren->dev) { "flycam", "speed", "max_fps", + "wireframe", }; for(const auto& name : names) @@ -129,6 +136,8 @@ UI::UI(Renderer* ren) : ren(ren), dev(ren->dev) { console->System().RegisterVariable("speed", ren->speed, csys::Arg("value")); console->System().RegisterVariable("max_fps", ren->max_fps, csys::Arg("value")); + console->System().RegisterVariable("wireframe", ren->wireframe_mode, wireframe_setter); + console->System().Log(csys::ItemType::eINFO) << "Welcome to Pleascach!" << csys::endl; } @@ -157,9 +166,8 @@ void UI::render(vk::CommandBuffer cmd) { } UI::~UI() { - dev.destroyDescriptorPool(desc_pool); - console.reset(); + dev.destroyDescriptorPool(desc_pool); ImGui_ImplVulkan_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); diff --git a/assets/shaders/map/bsp.frag b/assets/shaders/map/bsp.frag index 0d2766b..d88277f 100644 --- a/assets/shaders/map/bsp.frag +++ b/assets/shaders/map/bsp.frag @@ -1,8 +1,6 @@ #version 460 core -layout (location = 0) in vec3 norm; -layout (location = 1) in vec2 texCoord; -layout (location = 2) in vec4 color; +layout (location = 0) in vec4 color; layout (location = 0) out vec4 FragColor; layout (set = 0, binding = 0) uniform Matrices { @@ -20,5 +18,5 @@ layout (set = 0, binding = 0) uniform Matrices { layout (set = 0, binding = 1) uniform sampler2D tex; void main() { - FragColor = color; + FragColor = (color + vec4(1.0)) / 2.0; } \ No newline at end of file diff --git a/assets/shaders/map/bsp.vert b/assets/shaders/map/bsp.vert index 0180762..48e5d2c 100644 --- a/assets/shaders/map/bsp.vert +++ b/assets/shaders/map/bsp.vert @@ -1,13 +1,7 @@ #version 460 core layout (location = 0) in vec3 aPos; -layout (location = 1) in vec2 aTexCoord; -layout (location = 2) in vec2 lightmapCoord; -layout (location = 3) in vec3 aNorm; -layout (location = 4) in uint aColor; -layout (location = 0) out vec3 norm; -layout (location = 1) out vec2 texCoord; -layout (location = 2) out vec4 color; +layout (location = 0) out vec4 color; layout (set = 0, binding = 0) uniform Matrices { mat4 view; @@ -34,7 +28,6 @@ vec4 unpackABGR(uint packedABGR) { void main() { gl_Position = proj * view * vec4(aPos, 1.0); - texCoord = aTexCoord; - norm = aNorm; - color = unpackABGR(aColor); + + color = vec4(normalize(aPos), 1.0); } \ No newline at end of file diff --git a/pléascach.cpp b/pléascach.cpp index 7257199..47b87be 100644 --- a/pléascach.cpp +++ b/pléascach.cpp @@ -22,9 +22,8 @@ int main(int argc, char* argv[]) { Renderer ren(win); in->setCursor(false); - bool should_close = false; - while (!in->shouldClose() || ren.should_close) { + while (!in->shouldClose() && !ren.should_close) { Timer frame_timer; in->poll(); in->handleMovementKeys(ren); @@ -88,5 +87,5 @@ int main(int argc, char* argv[]) { } quit: - Log::info("Quitting"); + Log::info("Quitting\n"); }