Shifted to Half Life BSPs, learned how to unwind their really weird triangle fans
This commit is contained in:
parent
0bba09a055
commit
4433d34e32
@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CMAKE_CXX_FLAGS "-D_DEBUG")
|
set(CMAKE_CXX_FLAGS "-D_DEBUG")
|
||||||
else()
|
else()
|
||||||
set(CMAKE_CXX_FLAGS "-D_DEBUG -Wall -O3")
|
set(CMAKE_CXX_FLAGS "-D_DEBUG -Wall")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Pleascach)
|
project(Pleascach)
|
||||||
|
|||||||
@ -82,7 +82,7 @@ void CommandBuffer::bind(Terrain* terrain) {
|
|||||||
command_buffer.bindIndexBuffer(*terrain->index_buffer, 0, vk::IndexType::eUint32);
|
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->pipeline);
|
||||||
bind(*bsp->vertex_buffer);
|
bind(*bsp->vertex_buffer);
|
||||||
command_buffer.bindIndexBuffer(*bsp->index_buffer, 0, vk::IndexType::eUint32);
|
command_buffer.bindIndexBuffer(*bsp->index_buffer, 0, vk::IndexType::eUint32);
|
||||||
|
|||||||
@ -43,7 +43,7 @@ struct CommandBuffer {
|
|||||||
|
|
||||||
void bind(std::shared_ptr<Model> model);
|
void bind(std::shared_ptr<Model> model);
|
||||||
void bind(Terrain* terrain);
|
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);
|
void draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex = 0, uint32_t first_instance = 0);
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,8 @@
|
|||||||
#include <util/log.hpp>
|
#include <util/log.hpp>
|
||||||
|
|
||||||
|
|
||||||
GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& shaders, const vk::Extent2D& extent, const RenderPass& render_pass, vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings, const vk::VertexInputBindingDescription& vertex_binding, const std::vector<vk::VertexInputAttributeDescription>& vertex_attrs, enum Type type) : dev(dev) {
|
GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& shaders, const vk::Extent2D& extent, const RenderPass& render_pass, vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings, const vk::VertexInputBindingDescription& vertex_binding, const std::vector<vk::VertexInputAttributeDescription>& 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
|
/* create layout
|
||||||
* Eventually add a graphicspipline constructor that allows specification of layouts etc
|
* Eventually add a graphicspipline constructor that allows specification of layouts etc
|
||||||
* kinda like how Image::Image has all those versions
|
* kinda like how Image::Image has all those versions
|
||||||
@ -56,24 +57,23 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
|
|||||||
})[0];
|
})[0];
|
||||||
|
|
||||||
/* shader setup */
|
/* shader setup */
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> shader_info;
|
|
||||||
shader_info.reserve(shaders.size());
|
shader_info.reserve(shaders.size());
|
||||||
for (const auto& shader : shaders)
|
for (const auto& shader : shaders)
|
||||||
shader_info.push_back(shader.info());
|
shader_info.push_back(shader.info());
|
||||||
|
|
||||||
/* vertex input setup */
|
/* vertex input setup */
|
||||||
const std::vector<vk::VertexInputBindingDescription> vertex_bindings = {
|
vertex_bindings = {
|
||||||
vertex_binding,
|
vertex_binding,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto vertex_input_info = vk::PipelineVertexInputStateCreateInfo{
|
vertex_input_info = vk::PipelineVertexInputStateCreateInfo {
|
||||||
.vertexBindingDescriptionCount = static_cast<uint32_t>(vertex_bindings.size()),
|
.vertexBindingDescriptionCount = static_cast<uint32_t>(vertex_bindings.size()),
|
||||||
.pVertexBindingDescriptions = vertex_bindings.data(),
|
.pVertexBindingDescriptions = vertex_bindings.data(),
|
||||||
.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_attrs.size()),
|
.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_attrs.size()),
|
||||||
.pVertexAttributeDescriptions = vertex_attrs.data(),
|
.pVertexAttributeDescriptions = vertex_attrs.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
auto input_asm_info = vk::PipelineInputAssemblyStateCreateInfo {
|
input_asm_info = vk::PipelineInputAssemblyStateCreateInfo {
|
||||||
/* matters later if we use strip primitives */
|
/* matters later if we use strip primitives */
|
||||||
.primitiveRestartEnable = vk::False,
|
.primitiveRestartEnable = vk::False,
|
||||||
};
|
};
|
||||||
@ -94,7 +94,7 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
|
|||||||
|
|
||||||
const vk::PipelineTessellationStateCreateInfo* ptesselation_info = nullptr;
|
const vk::PipelineTessellationStateCreateInfo* ptesselation_info = nullptr;
|
||||||
|
|
||||||
const auto tess_info = vk::PipelineTessellationStateCreateInfo {
|
tess_info = vk::PipelineTessellationStateCreateInfo {
|
||||||
/* quads*/
|
/* quads*/
|
||||||
.patchControlPoints = 4,
|
.patchControlPoints = 4,
|
||||||
};
|
};
|
||||||
@ -103,22 +103,22 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
|
|||||||
ptesselation_info = &tess_info;
|
ptesselation_info = &tess_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto raster_info = vk::PipelineRasterizationStateCreateInfo {
|
raster_info = vk::PipelineRasterizationStateCreateInfo {
|
||||||
.depthClampEnable = vk::False,
|
.depthClampEnable = vk::False,
|
||||||
.polygonMode = type == eBOX ? vk::PolygonMode::eLine : vk::PolygonMode::eFill,
|
.polygonMode = (type == eBOX || wireframe) ? vk::PolygonMode::eLine : vk::PolygonMode::eFill,
|
||||||
.cullMode = type == eBOX ? vk::CullModeFlagBits::eNone : vk::CullModeFlagBits::eBack,
|
.cullMode = type == eBOX ? vk::CullModeFlagBits::eNone : vk::CullModeFlagBits::eNone,
|
||||||
.frontFace = vk::FrontFace::eCounterClockwise,
|
.frontFace = vk::FrontFace::eCounterClockwise,
|
||||||
.depthBiasEnable = type == eBOX,
|
.depthBiasEnable = type == eBOX,
|
||||||
.depthBiasConstantFactor = 0.01,
|
.depthBiasConstantFactor = 0.01,
|
||||||
.lineWidth = 1.0,
|
.lineWidth = 1.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto multisample_info = vk::PipelineMultisampleStateCreateInfo {
|
multisample_info = vk::PipelineMultisampleStateCreateInfo {
|
||||||
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
||||||
.sampleShadingEnable = vk::False,
|
.sampleShadingEnable = vk::False,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto depth_stencil_info = vk::PipelineDepthStencilStateCreateInfo{
|
depth_stencil_info = vk::PipelineDepthStencilStateCreateInfo{
|
||||||
.depthTestEnable = vk::True,
|
.depthTestEnable = vk::True,
|
||||||
.depthWriteEnable = type != eBOX,
|
.depthWriteEnable = type != eBOX,
|
||||||
.depthCompareOp = vk::CompareOp::eLess,
|
.depthCompareOp = vk::CompareOp::eLess,
|
||||||
@ -128,7 +128,7 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
|
|||||||
.maxDepthBounds = 1.0,
|
.maxDepthBounds = 1.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto color_blend_attachment = vk::PipelineColorBlendAttachmentState {
|
color_blend_attachment = vk::PipelineColorBlendAttachmentState {
|
||||||
/* only the box has blending */
|
/* only the box has blending */
|
||||||
.blendEnable = type == eBOX,
|
.blendEnable = type == eBOX,
|
||||||
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
|
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
|
||||||
@ -142,8 +142,8 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<float, 4> blend_constants = {0.0f, 0.0f, 0.0f, 0.0f };
|
blend_constants = {0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
auto color_blend_info = vk::PipelineColorBlendStateCreateInfo{
|
color_blend_info = vk::PipelineColorBlendStateCreateInfo{
|
||||||
.logicOpEnable = vk::False,
|
.logicOpEnable = vk::False,
|
||||||
.logicOp = vk::LogicOp::eCopy,
|
.logicOp = vk::LogicOp::eCopy,
|
||||||
.attachmentCount = 1,
|
.attachmentCount = 1,
|
||||||
@ -152,36 +152,34 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* temporary viewport and scissor, since it is a dynamic state due to the existence of window resizing */
|
/* 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,
|
.x = 0.0,
|
||||||
.y = static_cast<float>(extent.height),
|
.y = static_cast<float>(extent.height),
|
||||||
.width = static_cast<float>(extent.width),
|
.width = static_cast<float>(extent.width),
|
||||||
.height = -static_cast<float>(extent.height),
|
.height = -static_cast<float>(extent.height),
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto scissor = vk::Rect2D {
|
scissor = vk::Rect2D {
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.extent = extent,
|
.extent = extent,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto viewport_info = vk::PipelineViewportStateCreateInfo {
|
viewport_info = vk::PipelineViewportStateCreateInfo {
|
||||||
.viewportCount = 1,
|
.viewportCount = 1,
|
||||||
.pViewports = &viewport,
|
.pViewports = &viewport,
|
||||||
.scissorCount = 1,
|
.scissorCount = 1,
|
||||||
.pScissors = &scissor,
|
.pScissors = &scissor,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::DynamicState dyn_states[] = {
|
dyn_states[0] = vk::DynamicState::eScissor;
|
||||||
vk::DynamicState::eScissor,
|
dyn_states[1] = vk::DynamicState::eViewport;
|
||||||
vk::DynamicState::eViewport,
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto dyn_info = vk::PipelineDynamicStateCreateInfo{
|
dyn_info = vk::PipelineDynamicStateCreateInfo {
|
||||||
.dynamicStateCount = std::size(dyn_states),
|
.dynamicStateCount = (uint32_t)std::size(dyn_states),
|
||||||
.pDynamicStates = dyn_states,
|
.pDynamicStates = dyn_states,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto pipeline_info = vk::GraphicsPipelineCreateInfo {
|
pipeline_info = vk::GraphicsPipelineCreateInfo {
|
||||||
.stageCount = static_cast<uint32_t>(shaders.size()),
|
.stageCount = static_cast<uint32_t>(shaders.size()),
|
||||||
.pStages = shader_info.data(),
|
.pStages = shader_info.data(),
|
||||||
.pVertexInputState = &vertex_input_info,
|
.pVertexInputState = &vertex_input_info,
|
||||||
@ -237,7 +235,29 @@ void GraphicsPipeline::update(uint32_t binding, const Texture& tex) {
|
|||||||
}, nullptr);
|
}, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsPipeline::rebuild(bool wireframe) {
|
||||||
|
vertex_input_info = vk::PipelineVertexInputStateCreateInfo {
|
||||||
|
.vertexBindingDescriptionCount = static_cast<uint32_t>(vertex_bindings.size()),
|
||||||
|
.pVertexBindingDescriptions = vertex_bindings.data(),
|
||||||
|
.vertexAttributeDescriptionCount = static_cast<uint32_t>(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() {
|
GraphicsPipeline::~GraphicsPipeline() {
|
||||||
|
for(auto& p : defunct_pipelines) {
|
||||||
|
dev.destroyPipeline(p);
|
||||||
|
}
|
||||||
dev.destroyDescriptorSetLayout(desc_layout);
|
dev.destroyDescriptorSetLayout(desc_layout);
|
||||||
dev.destroyPipelineLayout(layout);
|
dev.destroyPipelineLayout(layout);
|
||||||
dev.destroyDescriptorPool(desc_pool);
|
dev.destroyDescriptorPool(desc_pool);
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
#include <util/log.hpp>
|
||||||
|
|
||||||
#include <Renderer/VertexBuffer.hpp>
|
#include <Renderer/VertexBuffer.hpp>
|
||||||
|
|
||||||
struct Shader;
|
struct Shader;
|
||||||
@ -22,14 +24,49 @@ struct GraphicsPipeline {
|
|||||||
GraphicsPipeline(vk::Device dev, const std::vector<Shader>& shaders,
|
GraphicsPipeline(vk::Device dev, const std::vector<Shader>& shaders,
|
||||||
const vk::Extent2D& extent, const RenderPass& render_pass,
|
const vk::Extent2D& extent, const RenderPass& render_pass,
|
||||||
vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings,
|
vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings,
|
||||||
const vk::VertexInputBindingDescription& vertex_binding, const std::vector<vk::VertexInputAttributeDescription>& vertex_attrs, enum Type type = Type::eVERTEX);
|
const vk::VertexInputBindingDescription& vertex_binding,
|
||||||
|
const std::vector<vk::VertexInputAttributeDescription>& vertex_attrs,
|
||||||
|
enum Type type = Type::eVERTEX, bool wireframe = false);
|
||||||
|
|
||||||
|
/* everything needed for recreation */
|
||||||
vk::Device dev;
|
vk::Device dev;
|
||||||
|
const std::vector<Shader> shaders;
|
||||||
|
const vk::Extent2D extent;
|
||||||
|
const RenderPass& render_pass;
|
||||||
|
const vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings;
|
||||||
|
const vk::VertexInputBindingDescription vertex_binding;
|
||||||
|
const std::vector<vk::VertexInputAttributeDescription> vertex_attrs;
|
||||||
|
const Type type;
|
||||||
|
|
||||||
|
|
||||||
vk::Pipeline pipeline;
|
vk::Pipeline pipeline;
|
||||||
vk::PipelineLayout layout;
|
vk::PipelineLayout layout;
|
||||||
vk::DescriptorSetLayout desc_layout;
|
vk::DescriptorSetLayout desc_layout;
|
||||||
vk::DescriptorPool desc_pool;
|
vk::DescriptorPool desc_pool;
|
||||||
vk::DescriptorSet desc_set;
|
vk::DescriptorSet desc_set;
|
||||||
|
|
||||||
|
/* pipeline creation info cached for rebuilding */
|
||||||
|
std::vector<vk::PipelineShaderStageCreateInfo> shader_info;
|
||||||
|
std::vector<vk::VertexInputBindingDescription> 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<float, 4> 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<vk::Pipeline> defunct_pipelines;
|
||||||
|
|
||||||
inline operator vk::Pipeline&() {
|
inline operator vk::Pipeline&() {
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
@ -38,6 +75,9 @@ struct GraphicsPipeline {
|
|||||||
void update(uint32_t binding, const UniformBuffer& uni);
|
void update(uint32_t binding, const UniformBuffer& uni);
|
||||||
void update(uint32_t binding, const Texture& tex);
|
void update(uint32_t binding, const Texture& tex);
|
||||||
|
|
||||||
|
|
||||||
|
void rebuild(bool wireframe);
|
||||||
|
|
||||||
~GraphicsPipeline();
|
~GraphicsPipeline();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -199,24 +199,25 @@ Renderer::Renderer(Window& win) : win(win) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* BSP loader */
|
/* BSP loader */
|
||||||
bsp = std::make_unique<Q3BSP::BSP>(phys_dev, dev, "assets/maps/git.bsp");
|
bsp = std::make_unique<HLBSP::BSP>(phys_dev, dev, "assets/maps/hl1.bsp");
|
||||||
std::vector<Shader> bsp_shaders = {
|
bsp_shaders = {
|
||||||
{ dev, "assets/shaders/bin/bsp.vert.spv", vk::ShaderStageFlagBits::eVertex },
|
{ dev, "assets/shaders/bin/bsp.vert.spv", vk::ShaderStageFlagBits::eVertex },
|
||||||
{ dev, "assets/shaders/bin/bsp.frag.spv", vk::ShaderStageFlagBits::eFragment },
|
{ dev, "assets/shaders/bin/bsp.frag.spv", vk::ShaderStageFlagBits::eFragment },
|
||||||
};
|
};
|
||||||
|
|
||||||
bsp->pipeline = std::make_unique<GraphicsPipeline>(dev, bsp_shaders, swapchain->extent, *render_pass, bindings, bsp->vertex_buffer->binding(0), bsp->vertex_buffer->attrs(0));
|
bsp->pipeline = std::make_unique<GraphicsPipeline>(dev, bsp_shaders, swapchain->extent, *render_pass, bindings, bsp->vertex_buffer->binding(0), bsp->vertex_buffer->attrs(0));
|
||||||
bsp->pipeline->update(0, *uniform_buffer);
|
bsp->pipeline->update(0, *uniform_buffer);
|
||||||
|
|
||||||
/* bounding and hitboxs */
|
/* bounding and hitboxs */
|
||||||
std::vector<Shader> box_shaders = {
|
box_shaders = {
|
||||||
{ dev, "assets/shaders/bin/box.vert.spv", vk::ShaderStageFlagBits::eVertex },
|
{ 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.geom.spv", vk::ShaderStageFlagBits::eGeometry },
|
||||||
{ dev, "assets/shaders/bin/box.frag.spv", vk::ShaderStageFlagBits::eFragment },
|
{ dev, "assets/shaders/bin/box.frag.spv", vk::ShaderStageFlagBits::eFragment },
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<BoxVertex> boxes;
|
std::vector<BoxVertex> boxes;
|
||||||
boxes.reserve(bsp->leafs.size());
|
boxes.reserve(bsp->leaves.size());
|
||||||
for (auto& leaf : bsp->leafs) {
|
for (auto& leaf : bsp->leaves) {
|
||||||
boxes.push_back(BoxVertex{
|
boxes.push_back(BoxVertex{
|
||||||
.mins = leaf.bb_mins,
|
.mins = leaf.bb_mins,
|
||||||
.maxes = leaf.bb_maxes,
|
.maxes = leaf.bb_maxes,
|
||||||
@ -228,11 +229,6 @@ Renderer::Renderer(Window& win) : win(win) {
|
|||||||
box_pipeline = std::make_unique<GraphicsPipeline>(dev, box_shaders, swapchain->extent, *render_pass, bindings, box_buffer->binding(0), box_buffer->attrs(0), GraphicsPipeline::Type::eBOX);
|
box_pipeline = std::make_unique<GraphicsPipeline>(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);
|
box_pipeline->update(0, *uniform_buffer);
|
||||||
|
|
||||||
for (auto& shader : box_shaders)
|
|
||||||
shader.cleanup();
|
|
||||||
for (auto& shader : bsp_shaders)
|
|
||||||
shader.cleanup();
|
|
||||||
|
|
||||||
ui = std::make_unique<UI>(this);
|
ui = std::make_unique<UI>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,6 +347,7 @@ void Renderer::draw() {
|
|||||||
|
|
||||||
bsp->load_indices(cam.pos, visibility_testing, p * uni.view);
|
bsp->load_indices(cam.pos, visibility_testing, p * uni.view);
|
||||||
command_buffer->bind(bsp.get());
|
command_buffer->bind(bsp.get());
|
||||||
|
/*command_buffer->draw(bsp->vertices.size(), 1);*/
|
||||||
command_buffer->command_buffer.drawIndexed(bsp->indices.size(), 1, 0, 0, 0);
|
command_buffer->command_buffer.drawIndexed(bsp->indices.size(), 1, 0, 0, 0);
|
||||||
|
|
||||||
n_indices = bsp->indices.size();
|
n_indices = bsp->indices.size();
|
||||||
@ -422,6 +419,10 @@ Renderer::~Renderer() {
|
|||||||
box_pipeline.reset();
|
box_pipeline.reset();
|
||||||
uniform_buffer.reset();
|
uniform_buffer.reset();
|
||||||
|
|
||||||
|
for (auto& shader : box_shaders)
|
||||||
|
shader.cleanup();
|
||||||
|
for (auto& shader : bsp_shaders)
|
||||||
|
shader.cleanup();
|
||||||
|
|
||||||
for (auto& tex : textures) {
|
for (auto& tex : textures) {
|
||||||
tex.cleanup();
|
tex.cleanup();
|
||||||
|
|||||||
@ -51,11 +51,13 @@ struct Renderer {
|
|||||||
std::unique_ptr<CommandBuffer> command_buffer;
|
std::unique_ptr<CommandBuffer> command_buffer;
|
||||||
std::unique_ptr<RenderPass> render_pass;
|
std::unique_ptr<RenderPass> render_pass;
|
||||||
|
|
||||||
|
std::vector<Shader> box_shaders;
|
||||||
std::unique_ptr<GraphicsPipeline> box_pipeline;
|
std::unique_ptr<GraphicsPipeline> box_pipeline;
|
||||||
std::unique_ptr<GeneralVertexBuffer<BoxVertex>> box_buffer;
|
std::unique_ptr<GeneralVertexBuffer<BoxVertex>> box_buffer;
|
||||||
std::unique_ptr<UniformBuffer> uniform_buffer;
|
std::unique_ptr<UniformBuffer> uniform_buffer;
|
||||||
|
|
||||||
std::unique_ptr<Q3BSP::BSP> bsp;
|
std::vector<Shader> bsp_shaders;
|
||||||
|
std::unique_ptr<HLBSP::BSP> bsp;
|
||||||
|
|
||||||
std::vector<Texture> textures;
|
std::vector<Texture> textures;
|
||||||
|
|
||||||
@ -77,6 +79,7 @@ struct Renderer {
|
|||||||
bool visibility_testing = false;
|
bool visibility_testing = false;
|
||||||
bool show_bboxes = false;
|
bool show_bboxes = false;
|
||||||
bool should_close = false;
|
bool should_close = false;
|
||||||
|
bool wireframe_mode = false;
|
||||||
|
|
||||||
size_t n_indices;
|
size_t n_indices;
|
||||||
|
|
||||||
|
|||||||
154
Scene/BSP.cpp
154
Scene/BSP.cpp
@ -11,7 +11,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
using namespace Q3BSP;
|
using namespace HLBSP;
|
||||||
|
|
||||||
static inline void copy_data(void* file_data, std::string& dst, Lump& lump) {
|
static inline void copy_data(void* file_data, std::string& dst, Lump& lump) {
|
||||||
dst.resize(lump.len);
|
dst.resize(lump.len);
|
||||||
@ -20,6 +20,7 @@ static inline void copy_data(void* file_data, std::string& dst, Lump& lump) {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline void copy_data(void* file_data, std::vector<T>& dst, Lump& lump) {
|
static inline void copy_data(void* file_data, std::vector<T>& dst, Lump& lump) {
|
||||||
|
Log::debug("%zu items\n", lump.len / sizeof(T));
|
||||||
dst.resize(lump.len / sizeof(T));
|
dst.resize(lump.len / sizeof(T));
|
||||||
std::memcpy(dst.data(), ((u8*)file_data) + lump.offset, lump.len);
|
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<T>& dst, Lump& lump) {
|
|||||||
void BSP::load_indices(const glm::vec3& cam_pos, bool visibility_test, const glm::mat4& view) {
|
void BSP::load_indices(const glm::vec3& cam_pos, bool visibility_test, const glm::mat4& view) {
|
||||||
std::set<int> present_faces;
|
std::set<int> present_faces;
|
||||||
std::vector<Face> visible_faces;
|
std::vector<Face> visible_faces;
|
||||||
if (visibility_test) {
|
// if (visibility_test) {
|
||||||
|
if(false) {
|
||||||
auto leaf_idx = determine_leaf(cam_pos);
|
auto leaf_idx = determine_leaf(cam_pos);
|
||||||
|
|
||||||
auto fr_planes = frustum(view);
|
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);
|
index_buffer->upload(indices);
|
||||||
|
|
||||||
last_leaf = leaf_idx;
|
last_leaf = leaf_idx;
|
||||||
auto& cam_leaf = leafs[leaf_idx];
|
auto& cam_leaf = leaves[leaf_idx];
|
||||||
|
|
||||||
|
|
||||||
std::vector<Leaf> visible_leafs;
|
std::vector<Leaf> visible_leafs;
|
||||||
for (auto& leaf : leafs) {
|
for (auto& leaf : leaves) {
|
||||||
|
|
||||||
const auto min = leaf.bb_mins;
|
const auto min = leaf.bb_mins;
|
||||||
const auto max = leaf.bb_maxes;
|
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 (const auto& leaf : visible_leafs) {
|
||||||
for (size_t i = 0; i < leaf.n_leaf_faces; i++) {
|
for (size_t i = 0; i < leaf.n_mark_surfaces; i++) {
|
||||||
auto idx = leaf_faces[leaf.first_leaf_face_idx + i].face_idx;
|
auto idx = mark_surfaces[leaf.first_mark_surface_idx + i];
|
||||||
if (present_faces.contains(idx))
|
if (present_faces.contains(idx))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -77,22 +79,27 @@ void BSP::load_indices(const glm::vec3& cam_pos, bool visibility_test, const glm
|
|||||||
indices.clear();
|
indices.clear();
|
||||||
|
|
||||||
for (auto& face : visible_faces) {
|
for (auto& face : visible_faces) {
|
||||||
switch (face.type) {
|
for (i16 i = 1, j = 2; j < face.n_surf_edges; i++, j++) {
|
||||||
case Face::ePATCH:
|
indices.push_back(face.first_surf_edge_idx);
|
||||||
break;
|
indices.push_back(face.first_surf_edge_idx+i);
|
||||||
case Face::ePOLYGON:
|
indices.push_back(face.first_surf_edge_idx+j);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
// indices.push_back(get_index_from_surfedge(face.first_surf_edge_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(indices.size() % 3 == 0);
|
|
||||||
|
|
||||||
index_buffer->upload(indices);
|
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) {
|
int BSP::determine_leaf(glm::vec3 cam_pos) {
|
||||||
/* use SDF of planes to determine relative position with respect to partitioning planes */
|
/* use SDF of planes to determine relative position with respect to partitioning planes */
|
||||||
int idx = 0;
|
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<glm::vec4, 6>& frustum, const glm::vec3 box_verts[8]) {
|
bool BSP::determine_visibility(const Leaf& cam_leaf, const Leaf& leaf, const std::array<glm::vec4, 6>& 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 */
|
/* perform fustrum culling */
|
||||||
return box_in_frustum(frustum, box_verts);
|
return box_in_frustum(frustum, box_verts);
|
||||||
}
|
}
|
||||||
@ -134,64 +131,109 @@ static inline void change_swizzle(T& v) {
|
|||||||
v.z = tmp;
|
v.z = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<std::map<std::string, std::string>> load_entities(const std::string& in) {
|
||||||
|
/* TODO */
|
||||||
|
return {
|
||||||
|
{{"test", "this"}},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<MipTexture> load_mip_textures(const u8* data, u32 offset) {
|
||||||
|
const TextureLump* lump = reinterpret_cast<const TextureLump*>(data + offset);
|
||||||
|
std::vector<MipTexture> ret;
|
||||||
|
ret.resize(lump->n_mip_textures);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < ret.size(); i++) {
|
||||||
|
ret[i] = *reinterpret_cast<const MipTexture*>(data + lump->offsets[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
BSP::BSP(vk::PhysicalDevice phys_dev, vk::Device dev, const std::string& fname) : dev(dev), filename(fname) {
|
BSP::BSP(vk::PhysicalDevice phys_dev, vk::Device dev, const std::string& fname) : dev(dev), filename(fname) {
|
||||||
file_data = file::slurpb(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<Header*>(file_data.data());
|
header = reinterpret_cast<Header*>(file_data.data());
|
||||||
|
|
||||||
Log::info("Loading BSP: %s\n", fname.c_str());
|
Log::info("Loading BSP: %s\n", fname.c_str());
|
||||||
|
|
||||||
if(header->magic != BSP_MAGIC) {
|
if(header->version != 30) {
|
||||||
Log::error("BSP file missing magic!\n");
|
Log::error("BSP file not expected version (Half Life has version 30)!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_data(file_data.data(), entities, header->entities);
|
Log::debug("Loading entities\n");
|
||||||
copy_data(file_data.data(), textures, header->textures);
|
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);
|
copy_data(file_data.data(), planes, header->planes);
|
||||||
/* change swizzle */
|
/* change swizzle */
|
||||||
for (auto& plane : planes) {
|
for (auto& plane : planes) {
|
||||||
change_swizzle(plane.norm);
|
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);
|
copy_data(file_data.data(), nodes, header->nodes);
|
||||||
for (auto& node : nodes) {
|
for (auto& node : nodes) {
|
||||||
change_swizzle(node.bb_mins);
|
change_swizzle(node.bb_mins);
|
||||||
change_swizzle(node.bb_maxes);
|
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<rgb*>(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_mins);
|
||||||
change_swizzle(leaf.bb_maxes);
|
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);
|
copy_data(file_data.data(), models, header->models);
|
||||||
for (auto& model : models) {
|
for (auto& model : models) {
|
||||||
change_swizzle(model.bb_mins);
|
change_swizzle(model.bb_mins);
|
||||||
change_swizzle(model.bb_maxes);
|
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);
|
Log::debug("Creating vertex buffer of size %zu\n", vertices.size());
|
||||||
copy_data(file_data.data(), effects, header->effects);
|
vertex_buffer = std::make_unique<GeneralVertexBuffer<Vertex>>(phys_dev, dev, vertices_prime.size());
|
||||||
copy_data(file_data.data(), faces, header->faces);
|
vertex_buffer->upload(vertices_prime);
|
||||||
copy_data(file_data.data(), lightmaps, header->lightmaps);
|
|
||||||
copy_data(file_data.data(), lightvols, header->lightvols);
|
|
||||||
|
|
||||||
vis_info.sz_vectors = reinterpret_cast<u32*>(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<GeneralVertexBuffer<Vertex>>(phys_dev, dev, vertices.size());
|
|
||||||
vertex_buffer->upload(vertices);
|
|
||||||
|
|
||||||
|
Log::debug("Creating index buffer\n");
|
||||||
/* set limit at 256Mi indices */
|
/* set limit at 256Mi indices */
|
||||||
index_buffer = std::make_unique<Buffer>(phys_dev, dev, 100000 * sizeof(u32),
|
index_buffer = std::make_unique<Buffer>(phys_dev, dev, 100000 * sizeof(u32),
|
||||||
vk::BufferUsageFlagBits::eIndexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible
|
vk::BufferUsageFlagBits::eIndexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible
|
||||||
|
|||||||
292
Scene/BSP.hpp
292
Scene/BSP.hpp
@ -12,8 +12,14 @@
|
|||||||
#include <Renderer/VertexBuffer.hpp>
|
#include <Renderer/VertexBuffer.hpp>
|
||||||
#include <Renderer/Pipeline.hpp>
|
#include <Renderer/Pipeline.hpp>
|
||||||
|
|
||||||
/* 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 {
|
struct Lump {
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 len;
|
u32 len;
|
||||||
@ -21,105 +27,62 @@ namespace Q3BSP {
|
|||||||
using rgb = glm::u8vec3;
|
using rgb = glm::u8vec3;
|
||||||
using rgba = glm::u8vec4;
|
using rgba = glm::u8vec4;
|
||||||
|
|
||||||
/* "IBSP" */
|
using vec3 = glm::vec3;
|
||||||
const uint32_t BSP_MAGIC = 0x50534249U;
|
using ivec3 = glm::vec<3, i16>;
|
||||||
|
|
||||||
struct Header {
|
struct Header {
|
||||||
u32 magic;
|
|
||||||
u32 version;
|
u32 version;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
Lump lumps[17];
|
Lump lumps[15];
|
||||||
struct {
|
struct {
|
||||||
Lump entities,
|
Lump entities,
|
||||||
textures,
|
|
||||||
planes,
|
planes,
|
||||||
nodes,
|
textures,
|
||||||
leafs,
|
|
||||||
leaf_faces,
|
|
||||||
leaf_brushes,
|
|
||||||
models,
|
|
||||||
brushes,
|
|
||||||
brush_sides,
|
|
||||||
vertices,
|
vertices,
|
||||||
mesh_vertices,
|
visibility,
|
||||||
effects,
|
nodes,
|
||||||
|
texinfo,
|
||||||
faces,
|
faces,
|
||||||
lightmaps,
|
lighting,
|
||||||
lightvols,
|
clip_nodes,
|
||||||
vis_info;
|
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 {
|
struct Plane {
|
||||||
glm::vec3 norm;
|
vec3 norm;
|
||||||
float dist;
|
float dist;
|
||||||
|
/* exists for certain optimizations (swaped y and z) */
|
||||||
|
enum PlaneType {
|
||||||
|
eX,
|
||||||
|
eZ,
|
||||||
|
eY,
|
||||||
|
eAnyX,
|
||||||
|
eAnyZ,
|
||||||
|
eAnyY,
|
||||||
|
} type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Node {
|
struct TextureLump {
|
||||||
u32 plane;
|
u32 n_mip_textures;
|
||||||
/* negative numbers are leaf indices */
|
i32 offsets[];
|
||||||
i32 children[2];
|
|
||||||
|
|
||||||
/* bounding box coords (integer) */
|
|
||||||
glm::ivec3 bb_mins;
|
|
||||||
glm::ivec3 bb_maxes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Leaf {
|
struct MipTexture {
|
||||||
i32 cluster_idx;
|
char name[MAX_TEXTURE_NAME];
|
||||||
u32 area;
|
u32 width, height;
|
||||||
glm::ivec3 bb_mins;
|
/* is 0 if stored in WAD, otherwise, offset is from beginning of this struct */
|
||||||
glm::ivec3 bb_maxes;
|
u32 mip_offsets[MIP_LEVELS];
|
||||||
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 Vertex {
|
struct Vertex {
|
||||||
glm::vec3 pos;
|
vec3 pos;
|
||||||
glm::vec2 uv;
|
|
||||||
glm::vec2 lightmap_coords;
|
|
||||||
glm::vec3 norm;
|
|
||||||
glm::u8vec4 color;
|
|
||||||
|
|
||||||
static inline std::vector<vk::VertexInputAttributeDescription> attrs(uint32_t binding) {
|
static inline std::vector<vk::VertexInputAttributeDescription> attrs(uint32_t binding) {
|
||||||
return std::vector<vk::VertexInputAttributeDescription> {
|
return std::vector<vk::VertexInputAttributeDescription> {
|
||||||
@ -128,109 +91,132 @@ namespace Q3BSP {
|
|||||||
.binding = binding,
|
.binding = binding,
|
||||||
.format = vk::Format::eR32G32B32Sfloat,
|
.format = vk::Format::eR32G32B32Sfloat,
|
||||||
.offset = offsetof(Vertex, pos),
|
.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 {
|
struct Vis {};
|
||||||
i32 idx;
|
|
||||||
|
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 {
|
struct TexInfo {
|
||||||
char name[64];
|
vec3 shift_s_dir;
|
||||||
i32 brush_idx;
|
float shift_s;
|
||||||
/* almost always 5 for some reason */
|
vec3 shift_t_dir;
|
||||||
i32 unknown;
|
float shift_t;
|
||||||
|
u32 mip_tex_idx;
|
||||||
|
/* seems to always be 0 */
|
||||||
|
u32 flags;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Face {
|
struct Face {
|
||||||
i32 texture_idx;
|
u16 plane_idx;
|
||||||
/* -1 if no effect */
|
/* set if different normals orientation */
|
||||||
i32 effect_idx;
|
u16 plane_side;
|
||||||
enum FaceType {
|
u32 first_surf_edge_idx;
|
||||||
ePOLYGON = 1,
|
i16 n_surf_edges;
|
||||||
ePATCH = 2,
|
i16 tex_info_idx;
|
||||||
eMESH = 3,
|
u8 lighting_styles[4];
|
||||||
eBILLBOARD = 4,
|
u32 lightmap_offset;
|
||||||
} 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Lightmap {
|
struct Lightmap {
|
||||||
u8 map[128][128][3];
|
rgb* lights;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Lightvol {
|
struct ClipNode {
|
||||||
rgb ambient;
|
i32 plane_idx;
|
||||||
rgb directional;
|
/* negative numbers are contents */
|
||||||
/* spherical coordinates */
|
i16 children[2];
|
||||||
glm::u8vec2 direction;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VisibilityInfo {
|
struct Leaf {
|
||||||
u32 sz_vectors;
|
enum {
|
||||||
std::vector<u8> vectors;
|
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 {
|
struct BSP {
|
||||||
BSP(vk::PhysicalDevice phys_dev, vk::Device dev, const std::string& fname);
|
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);
|
void load_indices(const vec3& cam_pos, bool visibility_testing, const glm::mat4& view);
|
||||||
int determine_leaf(glm::vec3 cam_pos);
|
int determine_leaf(vec3 cam_pos);
|
||||||
bool determine_visibility(const Leaf& cam_leaf, const Leaf& leaf, const std::array<glm::vec4, 6>& frustum, const glm::vec3 box_verts[8]);
|
bool determine_visibility(const Leaf& cam_leaf, const Leaf& leaf, const std::array<glm::vec4, 6>& frustum, const vec3 box_verts[8]);
|
||||||
|
int get_index_from_surfedge(int surfedge);
|
||||||
|
|
||||||
|
|
||||||
vk::Device dev;
|
vk::Device dev;
|
||||||
Header* header;
|
Header* header;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::vector<u8> file_data;
|
std::vector<u8> file_data;
|
||||||
std::string entities;
|
|
||||||
std::vector<Texture> textures;
|
std::vector<::std::map<::std::string, std::string>> entities;
|
||||||
std::vector<Plane> planes;
|
std::vector<Plane> planes;
|
||||||
std::vector<Node> nodes;
|
std::vector<MipTexture> textures;
|
||||||
std::vector<Leaf> leafs;
|
|
||||||
std::vector<LeafBrush> leaf_brushes;
|
|
||||||
std::vector<LeafFaces> leaf_faces;
|
|
||||||
std::vector<Model> models;
|
|
||||||
std::vector<Brush> brushes;
|
|
||||||
std::vector<BrushSide> brush_sides;
|
|
||||||
std::vector<Vertex> vertices;
|
std::vector<Vertex> vertices;
|
||||||
std::vector<MeshVertex> mesh_vertices;
|
std::vector<Vertex> vertices_prime;
|
||||||
std::vector<Effect> effects;
|
/* skipping vis for now */
|
||||||
|
std::vector<Node> nodes;
|
||||||
|
std::vector<TexInfo> tex_infos;
|
||||||
std::vector<Face> faces;
|
std::vector<Face> faces;
|
||||||
std::vector<Lightmap> lightmaps;
|
Lightmap lightmap;
|
||||||
std::vector<Lightvol> lightvols;
|
std::vector<ClipNode> clip_nodes;
|
||||||
VisibilityInfo vis_info;
|
std::vector<Leaf> leaves;
|
||||||
|
std::vector<MarkSurface> mark_surfaces;
|
||||||
|
std::vector<Edge> edges;
|
||||||
|
std::vector<Surfedge> surfedges;
|
||||||
|
std::vector<Model> models;
|
||||||
|
|
||||||
std::vector<u32> indices;
|
std::vector<u32> indices;
|
||||||
std::unique_ptr<Buffer> index_buffer;
|
std::unique_ptr<Buffer> index_buffer;
|
||||||
|
|||||||
20
UI/UI.cpp
20
UI/UI.cpp
@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
#include <Scene/Camera.hpp>
|
#include <Scene/Camera.hpp>
|
||||||
|
|
||||||
|
/* this pains me to do, but its the only way :( */
|
||||||
|
Renderer* __ren;
|
||||||
|
|
||||||
static csys::ItemLog& operator<<(csys::ItemLog& log, ImVector<float>& vec) {
|
static csys::ItemLog& operator<<(csys::ItemLog& log, ImVector<float>& vec) {
|
||||||
if (!vec.size())
|
if (!vec.size())
|
||||||
return log << "vector<f32> {}";
|
return log << "vector<f32> {}";
|
||||||
@ -21,12 +24,15 @@ static csys::ItemLog& operator<<(csys::ItemLog& log, ImVector<float>& vec) {
|
|||||||
return log << vec[vec.size() - 1] << " }";
|
return log << vec[vec.size() - 1] << " }";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static void vec_setter(ImVector<float>& v, std::vector<float> in) {
|
static void wireframe_setter(bool& v, bool in) {
|
||||||
v.reserve(in.size());
|
if(v == in)
|
||||||
std::memcpy(v.Data, in.data(), sizeof(float) * in.size());
|
return;
|
||||||
}*/
|
v = in;
|
||||||
|
__ren->bsp->pipeline->rebuild(in);
|
||||||
|
}
|
||||||
|
|
||||||
UI::UI(Renderer* ren) : ren(ren), dev(ren->dev) {
|
UI::UI(Renderer* ren) : ren(ren), dev(ren->dev) {
|
||||||
|
__ren = ren;
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
|
|
||||||
@ -117,6 +123,7 @@ UI::UI(Renderer* ren) : ren(ren), dev(ren->dev) {
|
|||||||
"flycam",
|
"flycam",
|
||||||
"speed",
|
"speed",
|
||||||
"max_fps",
|
"max_fps",
|
||||||
|
"wireframe",
|
||||||
};
|
};
|
||||||
|
|
||||||
for(const auto& name : names)
|
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<float>("value"));
|
console->System().RegisterVariable("speed", ren->speed, csys::Arg<float>("value"));
|
||||||
console->System().RegisterVariable("max_fps", ren->max_fps, csys::Arg<float>("value"));
|
console->System().RegisterVariable("max_fps", ren->max_fps, csys::Arg<float>("value"));
|
||||||
|
|
||||||
|
console->System().RegisterVariable("wireframe", ren->wireframe_mode, wireframe_setter);
|
||||||
|
|
||||||
console->System().Log(csys::ItemType::eINFO) << "Welcome to Pleascach!" << csys::endl;
|
console->System().Log(csys::ItemType::eINFO) << "Welcome to Pleascach!" << csys::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,9 +166,8 @@ void UI::render(vk::CommandBuffer cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UI::~UI() {
|
UI::~UI() {
|
||||||
dev.destroyDescriptorPool(desc_pool);
|
|
||||||
|
|
||||||
console.reset();
|
console.reset();
|
||||||
|
dev.destroyDescriptorPool(desc_pool);
|
||||||
ImGui_ImplVulkan_Shutdown();
|
ImGui_ImplVulkan_Shutdown();
|
||||||
ImGui_ImplGlfw_Shutdown();
|
ImGui_ImplGlfw_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
#version 460 core
|
#version 460 core
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm;
|
layout (location = 0) in vec4 color;
|
||||||
layout (location = 1) in vec2 texCoord;
|
|
||||||
layout (location = 2) in vec4 color;
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
layout (location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
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;
|
layout (set = 0, binding = 1) uniform sampler2D tex;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
FragColor = color;
|
FragColor = (color + vec4(1.0)) / 2.0;
|
||||||
}
|
}
|
||||||
@ -1,13 +1,7 @@
|
|||||||
#version 460 core
|
#version 460 core
|
||||||
layout (location = 0) in vec3 aPos;
|
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 = 0) out vec4 color;
|
||||||
layout (location = 1) out vec2 texCoord;
|
|
||||||
layout (location = 2) out vec4 color;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
layout (set = 0, binding = 0) uniform Matrices {
|
||||||
mat4 view;
|
mat4 view;
|
||||||
@ -34,7 +28,6 @@ vec4 unpackABGR(uint packedABGR) {
|
|||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
gl_Position = proj * view * vec4(aPos, 1.0);
|
gl_Position = proj * view * vec4(aPos, 1.0);
|
||||||
texCoord = aTexCoord;
|
|
||||||
norm = aNorm;
|
color = vec4(normalize(aPos), 1.0);
|
||||||
color = unpackABGR(aColor);
|
|
||||||
}
|
}
|
||||||
@ -22,9 +22,8 @@ int main(int argc, char* argv[]) {
|
|||||||
Renderer ren(win);
|
Renderer ren(win);
|
||||||
in->setCursor(false);
|
in->setCursor(false);
|
||||||
|
|
||||||
bool should_close = false;
|
|
||||||
|
|
||||||
while (!in->shouldClose() || ren.should_close) {
|
while (!in->shouldClose() && !ren.should_close) {
|
||||||
Timer frame_timer;
|
Timer frame_timer;
|
||||||
in->poll();
|
in->poll();
|
||||||
in->handleMovementKeys(ren);
|
in->handleMovementKeys(ren);
|
||||||
@ -88,5 +87,5 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
Log::info("Quitting");
|
Log::info("Quitting\n");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user