511 lines
24 KiB
C++
511 lines
24 KiB
C++
|
#include <iostream>
|
||
|
#include <cstdio>
|
||
|
|
||
|
#define GLFW_INCLUDE_NONE
|
||
|
#define GLFW_INCLUDE_VULKAN
|
||
|
#include <GLFW/glfw3.h>
|
||
|
|
||
|
#include "rusty.hpp"
|
||
|
#include "vulkan.hpp"
|
||
|
#include "tmath.hpp"
|
||
|
#include "image.hpp"
|
||
|
#include "model_object.hpp"
|
||
|
|
||
|
const uint32_t object_matrix_count = 2048;
|
||
|
|
||
|
struct GlobalVars {
|
||
|
tmath::fmat4 proj_view;
|
||
|
alignas(16) tmath::fvec3 light;
|
||
|
alignas(16) tmath::fvec3 eye;
|
||
|
};
|
||
|
|
||
|
class Application {
|
||
|
public:
|
||
|
~Application() {
|
||
|
if(device)
|
||
|
device->wait_idle();
|
||
|
swapchain.reset();
|
||
|
}
|
||
|
void init(GLFWwindow* window) {
|
||
|
mdl_objects.push_back(std::make_shared<mdo::MDLAxis>(verts));
|
||
|
field = std::make_shared<mdo::MDLField>(verts);
|
||
|
mdl_objects.push_back(field);
|
||
|
auto u1 = std::make_shared<mdo::MDLUnit1>(verts);
|
||
|
u1->set_pos(0, 0);
|
||
|
mdl_objects.push_back(u1);
|
||
|
auto u4 = std::make_shared<mdo::MDLUnit1>(verts);
|
||
|
u4->set_pos(4, 0);
|
||
|
u1->attack(*u4, 0.4f);
|
||
|
mdl_objects.push_back(u4);
|
||
|
this->window = window;
|
||
|
uint32_t ext_count;
|
||
|
const char** ext_names = glfwGetRequiredInstanceExtensions(&ext_count);
|
||
|
instance = vk::Instance::begin_build().set_application_name("Tacraft").set_enging_name("tacraft")
|
||
|
.set_layers({"VK_LAYER_LUNARG_standard_validation"})
|
||
|
.set_extensions(rs::vector<const char*>(ext_names, ext_names + ext_count))
|
||
|
.end();
|
||
|
physical_device = instance->enumerate_physical_device().nth(0).value();
|
||
|
auto maxsample = std::min(physical_device->properties()->limits.framebufferColorSampleCounts,
|
||
|
physical_device->properties()->limits.framebufferDepthSampleCounts);
|
||
|
|
||
|
VkSurfaceKHR raw_surface;
|
||
|
glfwCreateWindowSurface(instance->handle(), window, nullptr, &raw_surface);
|
||
|
surface = vk::Surface::from_raw_surface(raw_surface, *instance, *physical_device);
|
||
|
auto findex = physical_device->enumerate_queue_families().enumerate().filter([&](size_t idx, const VkQueueFamilyProperties* p) -> bool {
|
||
|
VkBool32 support_present = false;
|
||
|
vkGetPhysicalDeviceSurfaceSupportKHR(physical_device->handle(), idx, raw_surface, &support_present);
|
||
|
return (p->queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 && support_present
|
||
|
&& glfwGetPhysicalDevicePresentationSupport(instance->handle(), physical_device->handle(), idx);
|
||
|
}).unzip().first.nth(0).value();
|
||
|
|
||
|
device = vk::Device::begin_build(*physical_device).set_extensions({"VK_KHR_swapchain"})
|
||
|
.add_queue_family(findex, 1.0f).add_queue_family(findex, 1.0f)
|
||
|
.enable_features(*physical_device->supported_features())
|
||
|
.end();
|
||
|
auto gqueue = device->enumerate_queues().next().value();
|
||
|
auto pqueue = device->enumerate_queues().next().value_or(gqueue);
|
||
|
graphic_queue = *gqueue;
|
||
|
present_queue = *pqueue;
|
||
|
|
||
|
vert_shader = vk::ShaderModule::load_from_src(*device, "./shader/shader.vert", vk::ShaderModule::shader_type_vertex);
|
||
|
if(!vert_shader) {
|
||
|
std::cout << "vertex shader null!" << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
frag_shader = vk::ShaderModule::load_from_src(*device, "./shader/shader.frag", vk::ShaderModule::shader_type_fragment);
|
||
|
if(!frag_shader) {
|
||
|
std::cout << "fragment shader null!" << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
render_pass = vk::RenderPass::begin_build(*device)
|
||
|
.set_samples(sample_count)
|
||
|
.end();
|
||
|
if(!render_pass) {
|
||
|
std::cout << "renderpass null!" << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
auto& vertices = verts.all_vertices();
|
||
|
auto& vert_indices = verts.all_indices();
|
||
|
vertex_buffer = vk::Buffer::begin_build(*device, *physical_device).alloc_size(vertices.size() * sizeof(Vertex))
|
||
|
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||
|
.set_sharing_mode(VK_SHARING_MODE_EXCLUSIVE)
|
||
|
.set_cpu_accessible()
|
||
|
.end();
|
||
|
vertex_buffer->update_buffer(vertices.data(), vertices.size() * sizeof(Vertex));
|
||
|
index_buffer = vk::Buffer::begin_build(*device, *physical_device).alloc_size(vert_indices.size() * sizeof(uint32_t))
|
||
|
.set_usage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
|
||
|
.set_sharing_mode(VK_SHARING_MODE_EXCLUSIVE)
|
||
|
.set_cpu_accessible()
|
||
|
.end();
|
||
|
index_buffer->update_buffer(vert_indices.data(), vert_indices.size() * sizeof(uint32_t));
|
||
|
|
||
|
auto image = Image::load_from_file("res/snow.tga");
|
||
|
auto [imgx, imgy] = image->img_size();
|
||
|
img_buffer = vk::Buffer::begin_build(*device, *physical_device).alloc_size(imgx * imgy * 4 + 64)
|
||
|
.set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
|
||
|
.set_sharing_mode(VK_SHARING_MODE_EXCLUSIVE)
|
||
|
.set_cpu_accessible()
|
||
|
.end();
|
||
|
img_buffer->update_buffer(image->img_data(), imgx * imgy * 4);
|
||
|
memset(img_buffer->map(imgx * imgy * 4, 64), 0xff, 64);
|
||
|
img_buffer->unmap();
|
||
|
teximage = vk::Image::begin_build(*device, *physical_device)
|
||
|
.set_device_local()
|
||
|
.set_format(VK_FORMAT_R8G8B8A8_UNORM)
|
||
|
.set_extent({(uint32_t)imgx, (uint32_t)imgy, 1})
|
||
|
.end();
|
||
|
teximage_view = teximage->create_view(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
|
||
|
whiteimage = vk::Image::begin_build(*device, *physical_device)
|
||
|
.set_device_local()
|
||
|
.set_format(VK_FORMAT_R8G8B8A8_UNORM)
|
||
|
.set_extent({(uint32_t)4, (uint32_t)4, 1})
|
||
|
.end();
|
||
|
whiteimage_view = whiteimage->create_view(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
|
||
|
|
||
|
sampler = vk::Sampler::begin_build(*device).set_anisotrophy(16.0f).end();
|
||
|
descriptor_set_layout = vk::DescriptorSetLayout::begin_build(*device)
|
||
|
.add_binding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER).set_count(1).set_stage(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||
|
.add_binding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER).set_count(1).set_stage(VK_SHADER_STAGE_VERTEX_BIT)
|
||
|
.add_binding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER).set_count(2).set_stage(VK_SHADER_STAGE_FRAGMENT_BIT)
|
||
|
.end();
|
||
|
descriptor_pool = vk::DescriptorPool::begin_build(*device).set_max_sets(2)
|
||
|
.add_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 16)
|
||
|
.add_pool_size(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 16)
|
||
|
.add_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 16)
|
||
|
.end();
|
||
|
descriptor_sets = descriptor_pool->alloc_descriptor_set(*descriptor_set_layout, 2);
|
||
|
uint32_t buffer_size = 0x100 + sizeof(VertexAttribute) * object_matrix_count;
|
||
|
for(uint32_t i = 0; i < 2; ++i) {
|
||
|
uniform_buffers.emplace_back(vk::Buffer::begin_build(*device, *physical_device).alloc_size(buffer_size)
|
||
|
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||
|
.set_sharing_mode(VK_SHARING_MODE_EXCLUSIVE)
|
||
|
.set_cpu_accessible()
|
||
|
.end());
|
||
|
for(auto& ds : descriptor_sets) {
|
||
|
ds->update_write(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, 0)
|
||
|
.update_write_buffer_info(*uniform_buffers.back(), 0, sizeof(GlobalVars), 1)
|
||
|
.update_end();
|
||
|
ds->update_write(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, 0)
|
||
|
.update_write_buffer_info(*uniform_buffers.back(), 0x100, sizeof(VertexAttribute) * object_matrix_count, 1)
|
||
|
.update_write(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, 0)
|
||
|
.update_write_image_info(*whiteimage_view, *sampler)
|
||
|
.update_write_image_info(*teximage_view, *sampler)
|
||
|
.update_end();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
draw_command_pool = vk::CommandPool::begin_build(*device)
|
||
|
.set_queue_family_index(graphic_queue.queue_family_index)
|
||
|
.set_pool_flag(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
|
||
|
.end();
|
||
|
onetime_command_pool = vk::CommandPool::begin_build(*device)
|
||
|
.set_queue_family_index(graphic_queue.queue_family_index)
|
||
|
.set_pool_flag(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT)
|
||
|
.end();
|
||
|
draw_command_pool->alloc_command_buffer(command_buffers, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 2);
|
||
|
renderer = vk::Renderer::create_renderer(*device, 2);
|
||
|
|
||
|
onetime_command_pool->alloc_command_buffer(onetime_commands, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 2);
|
||
|
onetime_commands[0]->begin_command(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
|
||
|
.begin_pipeline_barrior(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT)
|
||
|
.add_image_memory_barrior(*teximage)
|
||
|
.image_set_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||
|
.image_set_aspect_mask(VK_IMAGE_ASPECT_COLOR_BIT)
|
||
|
.image_set_access_mask(0, VK_ACCESS_TRANSFER_WRITE_BIT)
|
||
|
.end_pipeline_barrior()
|
||
|
.begin_copy_buffer_to_image(*img_buffer, *teximage)
|
||
|
.add_region(0, {0, 0, 0}, {(uint32_t)imgx, (uint32_t)imgy, 1u})
|
||
|
.end_buffer_image_copy()
|
||
|
.begin_pipeline_barrior(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
|
||
|
.add_image_memory_barrior(*teximage)
|
||
|
.image_set_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||
|
.image_set_aspect_mask(VK_IMAGE_ASPECT_COLOR_BIT)
|
||
|
.image_set_access_mask(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||
|
.end_pipeline_barrior()
|
||
|
.end_command();
|
||
|
onetime_commands[1]->begin_command(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
|
||
|
.begin_pipeline_barrior(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT)
|
||
|
.add_image_memory_barrior(*whiteimage)
|
||
|
.image_set_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||
|
.image_set_aspect_mask(VK_IMAGE_ASPECT_COLOR_BIT)
|
||
|
.image_set_access_mask(0, VK_ACCESS_TRANSFER_WRITE_BIT)
|
||
|
.end_pipeline_barrior()
|
||
|
.begin_copy_buffer_to_image(*img_buffer, *whiteimage)
|
||
|
.add_region(imgx * imgy * 4, {0, 0, 0}, {4u, 4u, 1u})
|
||
|
.end_buffer_image_copy()
|
||
|
.begin_pipeline_barrior(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
|
||
|
.add_image_memory_barrior(*whiteimage)
|
||
|
.image_set_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||
|
.image_set_aspect_mask(VK_IMAGE_ASPECT_COLOR_BIT)
|
||
|
.image_set_access_mask(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||
|
.end_pipeline_barrior()
|
||
|
.end_command();
|
||
|
recreate_sized_object();
|
||
|
}
|
||
|
|
||
|
void draw_frame() {
|
||
|
if(skipdraw)
|
||
|
return;
|
||
|
if(recreate || renderer->out_of_date()) {
|
||
|
recreate_sized_object();
|
||
|
recreate = false;
|
||
|
}
|
||
|
uint32_t frame_index = renderer->prepare_for_next_frame();
|
||
|
uint32_t image_index = renderer->accquire_next_image(*swapchain);
|
||
|
if(renderer->out_of_date())
|
||
|
return;
|
||
|
// update attributes
|
||
|
// global_vars.light = tmath::fmat4::identity().translate(5.0f, 0.0f, 8.0f).rotatex(glfwGetTime() * 0.5f).rotatez(pi * 0.25f) * tmath::fvec3{0.0f, 0.0f, 0.0f};
|
||
|
for(auto& mdo : mdl_objects)
|
||
|
mdo->update(glfwGetTime());
|
||
|
auto ptr = uniform_buffers[frame_index]->map(0, 0x100 + sizeof(VertexAttribute) * object_matrix_count);
|
||
|
memcpy(ptr, &global_vars, sizeof(GlobalVars));
|
||
|
auto att_ptr = reinterpret_cast<VertexAttribute*>((uintptr_t)ptr + 0x100);
|
||
|
memcpy(att_ptr, verts.all_attributes().data(), verts.all_attributes().size() * sizeof(VertexAttribute));
|
||
|
uniform_buffers[frame_index]->unmap();
|
||
|
|
||
|
if(!onetime_commands.empty()) {
|
||
|
renderer->submit_onetime_command(graphic_queue, onetime_commands).wait_idle(graphic_queue);
|
||
|
onetime_commands.clear();
|
||
|
}
|
||
|
command_buffers[frame_index]->begin_command(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
|
||
|
.begin_render_pass(*render_pass, *framebuffers[image_index], VkClearValue{0.0, 0.0, 0.0, 0.8})
|
||
|
.bind_pipeline_and_descriptor_sets(*pipeline, *descriptor_sets[frame_index])
|
||
|
.draw_indexed(*vertex_buffer, *index_buffer, verts.all_indices().size())
|
||
|
.end_render_pass()
|
||
|
.end_command();
|
||
|
renderer->submit_draw_command(graphic_queue, *command_buffers[frame_index]);
|
||
|
renderer->present(present_queue, *swapchain, image_index);
|
||
|
}
|
||
|
|
||
|
void recreate_sized_object() {
|
||
|
device->wait_idle();
|
||
|
swapchain = nullptr;
|
||
|
framebuffers.clear();
|
||
|
glfwGetFramebufferSize(window, &width, &height);
|
||
|
surface->refresh();
|
||
|
const VkSurfaceFormatKHR* format = surface->default_format();
|
||
|
auto caps = surface->capabilities();
|
||
|
swapchain = vk::Swapchain::begin_build(*device)
|
||
|
.set_surface(*surface)
|
||
|
.set_min_image_count(caps->maxImageCount)
|
||
|
.set_format(format->format)
|
||
|
.set_extent({(uint32_t)width, (uint32_t)height})
|
||
|
.set_image_usage(caps->supportedUsageFlags)
|
||
|
.set_queue_family_indices(device->queue_family_in_use())
|
||
|
.set_transform(caps->currentTransform)
|
||
|
.end();
|
||
|
auto swapchain_images = swapchain->get_swapchain_images();
|
||
|
|
||
|
depthimage = vk::Image::begin_build(*device, *physical_device)
|
||
|
.set_device_local()
|
||
|
.set_samples(sample_count)
|
||
|
.set_usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||
|
.set_format(VK_FORMAT_D24_UNORM_S8_UINT)
|
||
|
.set_tilling(VK_IMAGE_TILING_OPTIMAL)
|
||
|
.set_extent({(uint32_t)width, (uint32_t)height, 1u})
|
||
|
.end();
|
||
|
depthimage_view = depthimage->create_view(VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||
|
onetime_command_pool->alloc_command_buffer(onetime_commands, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1);
|
||
|
onetime_commands.back()->begin_command(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
|
||
|
.begin_pipeline_barrior(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT)
|
||
|
.add_image_memory_barrior(*depthimage)
|
||
|
.image_set_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
|
||
|
.image_set_aspect_mask(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)
|
||
|
.image_set_access_mask(0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)
|
||
|
.end_pipeline_barrior()
|
||
|
.end_command();
|
||
|
|
||
|
if(sample_count != VK_SAMPLE_COUNT_1_BIT) {
|
||
|
msaaimage = vk::Image::begin_build(*device, *physical_device)
|
||
|
.set_device_local()
|
||
|
.set_usage(VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
|
||
|
.set_samples(sample_count)
|
||
|
.set_format(format->format)
|
||
|
.set_tilling(VK_IMAGE_TILING_OPTIMAL)
|
||
|
.set_extent({(uint32_t)width, (uint32_t)height, 1u})
|
||
|
.end();
|
||
|
msaaimage_view = msaaimage->create_view(format->format, VK_IMAGE_ASPECT_COLOR_BIT);
|
||
|
onetime_command_pool->alloc_command_buffer(onetime_commands, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1);
|
||
|
onetime_commands.back()->begin_command(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
|
||
|
.begin_pipeline_barrior(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
|
||
|
.add_image_memory_barrior(*msaaimage)
|
||
|
.image_set_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
|
||
|
.image_set_aspect_mask(VK_IMAGE_ASPECT_COLOR_BIT)
|
||
|
.image_set_access_mask(0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
|
||
|
.end_pipeline_barrior()
|
||
|
.end_command();
|
||
|
}
|
||
|
|
||
|
framebuffers.clear();
|
||
|
for(auto view : swapchain_images) {
|
||
|
if(sample_count == VK_SAMPLE_COUNT_1_BIT) {
|
||
|
framebuffers.emplace_back(vk::Framebuffer::begin_build(*device)
|
||
|
.set_render_pass(*render_pass)
|
||
|
.set_framebuffer_size(width, height)
|
||
|
.add_image_view(*view)
|
||
|
.add_image_view(*depthimage_view)
|
||
|
.end()
|
||
|
);
|
||
|
} else {
|
||
|
framebuffers.emplace_back(vk::Framebuffer::begin_build(*device)
|
||
|
.set_render_pass(*render_pass)
|
||
|
.set_framebuffer_size(width, height)
|
||
|
.add_image_view(*msaaimage_view)
|
||
|
.add_image_view(*depthimage_view)
|
||
|
.add_image_view(*view)
|
||
|
.end()
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
pipeline = vk::Pipeline::begin_build(*device)
|
||
|
.set_render_pass(*render_pass)
|
||
|
.set_vertex_shader(*vert_shader)
|
||
|
.set_fragment_shader(*frag_shader)
|
||
|
.set_cull_mode(VK_CULL_MODE_BACK_BIT)
|
||
|
.normal_viewport((float)width, (float)height)
|
||
|
.normal_scissor((uint32_t)width, (uint32_t)height)
|
||
|
.add_descriptor_set_layout(*descriptor_set_layout)
|
||
|
.set_samples(sample_count)
|
||
|
.bind_vertex_size(sizeof(Vertex))
|
||
|
.add_binding_attribute(VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position))
|
||
|
.add_binding_attribute(VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal))
|
||
|
.add_binding_attribute(VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texcoord))
|
||
|
.add_binding_attribute(VK_FORMAT_R32G32_SINT, offsetof(Vertex, index))
|
||
|
.end();
|
||
|
global_vars.proj_view = tmath::fmat4::perspective_fov(3.1415926f / 3.0f, (float)width / (float)height, 0.1f, 100.0f).scale(1.0f, -1.0f, 1.0f)
|
||
|
* tmath::fmat4::look_at({8.0f, 20.0f, 10.0f}, {8.0f, 10.0f, 0.0f}, {0.0f, 0.0f, 1.0f});
|
||
|
global_vars.light = {8.0f, 24.0f, 20.0f};
|
||
|
global_vars.eye = {8.0f, 20.0f, 10.0f};
|
||
|
}
|
||
|
|
||
|
void copy_buffer_to_image() {
|
||
|
|
||
|
}
|
||
|
void post_window_resized(bool skip = false) { skipdraw = skip; recreate = true; }
|
||
|
void mouse_move(float x, float y) {
|
||
|
auto& m = global_vars.proj_view;
|
||
|
float w = x * 2.0f / width - 1.0f;
|
||
|
float h = y * 2.0f / height - 1.0f;
|
||
|
float a1 = m[0] - w * m[3];
|
||
|
float b1 = m[4] - w * m[7];
|
||
|
float c1 = m[12] - w * m[15];
|
||
|
float a2 = m[1] - h * m[3];
|
||
|
float b2 = m[5] - h * m[7];
|
||
|
float c2 = m[13] - h * m[15];
|
||
|
float d = a1 * b2 - a2 * b1;
|
||
|
float zx = (b1 * c2 - b2 * c1) / d;
|
||
|
float zy = (c1 * a2 - c2 * a1) / d;
|
||
|
|
||
|
field->mouse_point(zx, zy);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
bool recreate = false;
|
||
|
bool skipdraw = false;
|
||
|
GLFWwindow* window = nullptr;
|
||
|
std::shared_ptr<vk::Instance> instance;
|
||
|
const vk::PhysicalDevice* physical_device;
|
||
|
std::shared_ptr<vk::Device> device;
|
||
|
std::shared_ptr<vk::Swapchain> swapchain;
|
||
|
std::shared_ptr<vk::Surface> surface;
|
||
|
rs::vector<std::shared_ptr<vk::Framebuffer>> framebuffers;
|
||
|
std::shared_ptr<vk::ShaderModule> vert_shader;
|
||
|
std::shared_ptr<vk::ShaderModule> frag_shader;
|
||
|
std::shared_ptr<vk::RenderPass> render_pass;
|
||
|
std::shared_ptr<vk::Pipeline> pipeline;
|
||
|
std::shared_ptr<vk::CommandPool> draw_command_pool;
|
||
|
std::shared_ptr<vk::CommandPool> onetime_command_pool;
|
||
|
rs::vector<std::shared_ptr<vk::CommandBuffer>> command_buffers;
|
||
|
rs::vector<std::shared_ptr<vk::CommandBuffer>> onetime_commands;
|
||
|
std::shared_ptr<vk::Renderer> renderer;
|
||
|
vk::Queue graphic_queue;
|
||
|
vk::Queue present_queue;
|
||
|
std::shared_ptr<vk::Buffer> vertex_buffer;
|
||
|
std::shared_ptr<vk::Buffer> index_buffer;
|
||
|
rs::vector<std::shared_ptr<vk::Buffer>> uniform_buffers;
|
||
|
std::shared_ptr<vk::DescriptorSetLayout> descriptor_set_layout;
|
||
|
std::shared_ptr<vk::DescriptorPool> descriptor_pool;
|
||
|
rs::vector<std::shared_ptr<vk::DescriptorSet>> descriptor_sets;
|
||
|
std::shared_ptr<vk::Buffer> img_buffer;
|
||
|
std::shared_ptr<vk::Image> teximage;
|
||
|
std::shared_ptr<vk::Image> whiteimage;
|
||
|
std::shared_ptr<vk::Image> depthimage;
|
||
|
std::shared_ptr<vk::Image> msaaimage;
|
||
|
std::shared_ptr<vk::ImageView> teximage_view;
|
||
|
std::shared_ptr<vk::ImageView> whiteimage_view;
|
||
|
std::shared_ptr<vk::ImageView> depthimage_view;
|
||
|
std::shared_ptr<vk::ImageView> msaaimage_view;
|
||
|
std::shared_ptr<vk::Sampler> sampler;
|
||
|
GlobalVars global_vars;
|
||
|
VkSampleCountFlagBits sample_count = VK_SAMPLE_COUNT_4_BIT;
|
||
|
VertCollection verts;
|
||
|
rs::vector<std::shared_ptr<ModelObject>> mdl_objects;
|
||
|
std::shared_ptr<mdo::MDLField> field;
|
||
|
int32_t width;
|
||
|
int32_t height;
|
||
|
};
|
||
|
|
||
|
Application app;
|
||
|
|
||
|
void show_mat4(tmath::fmat4& m) {
|
||
|
printf("| %f %f %f %f |\n", m[0], m[4], m[8], m[12]);
|
||
|
printf("| %f %f %f %f |\n", m[1], m[5], m[9], m[13]);
|
||
|
printf("| %f %f %f %f |\n", m[2], m[6], m[10], m[14]);
|
||
|
printf("| %f %f %f %f |\n", m[3], m[7], m[11], m[15]);
|
||
|
}
|
||
|
|
||
|
GLFWwindow* window;
|
||
|
int dx, dy, dwx, dwy;
|
||
|
bool window_moving = false;
|
||
|
|
||
|
int main(int argc, char *argv[]) {
|
||
|
if (!glfwInit())
|
||
|
exit(EXIT_FAILURE);
|
||
|
if (!glfwVulkanSupported()) {
|
||
|
std::cout << "Vulkan not supported" << std::endl;
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||
|
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
|
||
|
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
|
||
|
window = glfwCreateWindow(1280, 800, "Tacraft!", NULL, NULL);
|
||
|
if (!window) {
|
||
|
glfwTerminate();
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||
|
int monitorX, monitorY;
|
||
|
glfwGetMonitorPos(monitor, &monitorX, &monitorY);
|
||
|
int windowWidth, windowHeight;
|
||
|
glfwGetWindowSize(window, &windowWidth, &windowHeight);
|
||
|
glfwSetWindowPos(window, monitorX + (mode->width - windowWidth) / 2, monitorY + (mode->height - windowHeight) / 2);
|
||
|
float xscale, yscale;
|
||
|
glfwGetWindowContentScale(window, &xscale, &yscale);
|
||
|
|
||
|
app.init(window);
|
||
|
|
||
|
glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||
|
if(action == GLFW_PRESS) {
|
||
|
if(key == GLFW_KEY_ESCAPE)
|
||
|
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||
|
} else {
|
||
|
|
||
|
}
|
||
|
});
|
||
|
glfwSetWindowSizeCallback(window, [](GLFWwindow* window, int x, int y) {
|
||
|
app.post_window_resized(x == 0 && y == 0);
|
||
|
});
|
||
|
glfwSetMouseButtonCallback(window, [](GLFWwindow*,int button,int action,int mods){
|
||
|
if(action == GLFW_PRESS) {
|
||
|
if(button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||
|
double mx, my;
|
||
|
glfwGetWindowPos(window, &dwx, &dwy);
|
||
|
glfwGetCursorPos(window, &mx, &my);
|
||
|
dx = dwx + (int)mx;
|
||
|
dy = dwy + (int)my;
|
||
|
window_moving = true;
|
||
|
}
|
||
|
} else {
|
||
|
if(button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||
|
window_moving = false;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
glfwSetCursorPosCallback(window, [](GLFWwindow*,double x,double y) {
|
||
|
if(window_moving) {
|
||
|
int wx, wy, delx, dely;
|
||
|
glfwGetWindowPos(window, &wx, &wy);
|
||
|
delx = wx + (int)x - dx;
|
||
|
dely = wy + (int)y - dy;
|
||
|
glfwSetWindowPos(window, dwx + delx, dwy + dely);
|
||
|
}
|
||
|
app.mouse_move(x, y);
|
||
|
});
|
||
|
glfwSetTime(0.0);
|
||
|
double prev_time = 0.0;
|
||
|
double time_check= 0.0;
|
||
|
uint32_t frame = 0;
|
||
|
while (!glfwWindowShouldClose(window)) {
|
||
|
glfwPollEvents();
|
||
|
app.draw_frame();
|
||
|
frame++;
|
||
|
double curtime = glfwGetTime();
|
||
|
time_check += (curtime - prev_time);
|
||
|
prev_time = curtime;
|
||
|
if(time_check > 1.0) {
|
||
|
time_check -= 1.0;
|
||
|
char buffer[50];
|
||
|
sprintf(buffer, "Tacraft! %d", frame);
|
||
|
glfwSetWindowTitle(window, buffer);
|
||
|
frame = 0;
|
||
|
}
|
||
|
}
|
||
|
glfwDestroyWindow(window);
|
||
|
glfwTerminate();
|
||
|
exit(EXIT_SUCCESS);
|
||
|
|
||
|
return 0;
|
||
|
};
|