tacraft/main.cpp

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;
};