diff --git a/client/include/draw.h b/client/include/draw.h index 7faf535..c915e63 100644 --- a/client/include/draw.h +++ b/client/include/draw.h @@ -3,12 +3,12 @@ #include "gpu.h" #include "ui.h" +#include "hex.h" VkResult draw_frame( RenderContext* context, UIContext* ui, - GraphicsPipeline* hex_graphics, - VkDeviceAddress world, + HexContext* hex, double time); #endif diff --git a/client/include/hex.h b/client/include/hex.h index e5d85e7..554ea8d 100644 --- a/client/include/hex.h +++ b/client/include/hex.h @@ -3,20 +3,59 @@ #include "gpu.h" -typedef struct GPUHexContextStruct { - mat4 proj; - mat4 view; -} GPUHexContext; +#define REGION_SIZE 6 +#define REGION_HEX_COUNT 3*REGION_SIZE*(REGION_SIZE-1)+1 typedef struct HexPushConstantStruct { VkDeviceAddress context; double time; } HexPushConstant; -VkResult create_hex_pipeline( - VkDevice device, - VkRenderPass render_pass, - GraphicsPipeline* graphics, - ComputePipeline* compute); +typedef struct GPUHexContextStruct { + mat4 proj; + mat4 view; + VkDeviceAddress regions; +} GPUHexContext; + +typedef struct HexContextStruct { + VkDeviceAddress address; + VkBuffer context; + VmaAllocation context_memory; + + GraphicsPipeline graphics; + ComputePipeline compute; + + GPUHexContext data; +} HexContext; + +typedef struct GPUHexStruct { + float height[6]; + uint32_t color[6]; +} GPUHex; + +typedef struct GPUHexRegionStruct { + uint32_t x; + uint32_t y; + + GPUHex hexes[REGION_HEX_COUNT]; +} GPUHexRegion; + +typedef struct HexRegionStruct { + uint32_t x; + uint32_t y; + + VkDeviceAddress address; + VkBuffer region; + VmaAllocation region_memory; +} HexRegion; + +VkResult create_hex_context( + RenderContext* gpu, + HexContext* context); + +VkResult create_hex_region( + uint32_t x, uint32_t y, + HexRegion* region, + RenderContext* gpu); #endif diff --git a/client/shader/hex.vert b/client/shader/hex.vert index 879b574..e4d0b88 100644 --- a/client/shader/hex.vert +++ b/client/shader/hex.vert @@ -4,9 +4,11 @@ #include "hex_common.glsl" #define PI 3.1415926535897932384626433832795 -float w = 0.5; +const float w = 0.5; +const float x = 0.75; +const float z = sqrt(3.0)/4.0; -vec4 vertices[] = { +const vec4 vertices[] = { vec4(0, 0, 0, 1), vec4(w*cos(0*PI/3), 0, w*sin(0*PI/3), 1), vec4(w*cos(1*PI/3), 0, w*sin(1*PI/3), 1), @@ -16,7 +18,7 @@ vec4 vertices[] = { vec4(w*cos(5*PI/3), 0, w*sin(5*PI/3), 1), }; -uint indices[] = { +const uint indices[] = { 0, 2, 1, 0, 3, 2, 0, 4, 3, @@ -25,6 +27,38 @@ uint indices[] = { 0, 1, 6, }; +const vec4 starts[] = { + vec4( 0, 0, 2*z, 0), + vec4(-x, 0, z, 0), + vec4(-x, 0, -z, 0), + vec4( 0, 0, -2*z, 0), + vec4( x, 0, -z, 0), + vec4( x, 0, z, 0), +}; + +const vec4 direction[] = { + vec4(-x, 0, -z, 0), + vec4( 0, 0, -2*z, 0), + vec4( x, 0, -z, 0), + vec4( x, 0, z, 0), + vec4( 0, 0, 2*z, 0), + vec4(-x, 0, z, 0), +}; + void main() { - gl_Position = pc.context.proj * pc.context.view * vertices[indices[gl_VertexIndex]]; + uint radius = 0; + uint ring = 0; + uint side = 0; + uint hex = 0; + if(gl_InstanceIndex != 0) { + radius = uint(floor(0.5 + sqrt(12*gl_InstanceIndex-3)/6)); + ring = gl_InstanceIndex - (3*radius*radius - 3*radius + 1); + side = uint(floor(ring/(radius))); + hex = ring - (radius*side); + } + + // Calculate position based on radius/ring/side/hex + vec4 position = vertices[indices[gl_VertexIndex]] + (starts[side]*radius) + (direction[side]*hex); + + gl_Position = pc.context.proj * pc.context.view * position; } diff --git a/client/shader/hex_common.glsl b/client/shader/hex_common.glsl index 39abf2e..383fe4d 100644 --- a/client/shader/hex_common.glsl +++ b/client/shader/hex_common.glsl @@ -1,6 +1,26 @@ +struct Hex { + float heights[6]; + uint colors[6]; +}; + +layout(std430, buffer_reference) readonly buffer HexList { + Hex h[]; +}; + +struct Region { + uint x; + uint y; + HexList hexes; +}; + +layout(std430, buffer_reference) readonly buffer RegionList { + Region r[]; +}; + layout(std430, buffer_reference) readonly buffer HexContext { mat4 proj; mat4 view; + RegionList regions; }; layout(std430, push_constant) uniform PushConstant { diff --git a/client/src/draw.c b/client/src/draw.c index bc19aa8..55fff02 100644 --- a/client/src/draw.c +++ b/client/src/draw.c @@ -1,6 +1,4 @@ #include "draw.h" -#include "gpu.h" -#include "hex.h" #include "vulkan/vulkan_core.h" void record_ui_draw(VkCommandBuffer command_buffer, UIContext* ui_context, double time, uint32_t frame) { @@ -24,14 +22,14 @@ void record_ui_draw(VkCommandBuffer command_buffer, UIContext* ui_context, doubl } } -void record_hex_draw(VkCommandBuffer command_buffer, GraphicsPipeline* graphics, VkDeviceAddress context, double time) { +void record_hex_draw(VkCommandBuffer command_buffer, HexContext* hex, double time, uint32_t frame) { HexPushConstant push = { - .context = context, + .context = hex->address, .time = time, }; - vkCmdPushConstants(command_buffer, graphics->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(HexPushConstant), &push); - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphics->pipeline); - vkCmdDraw(command_buffer, 18, 1, 0, 0); + vkCmdPushConstants(command_buffer, hex->graphics.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(HexPushConstant), &push); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, hex->graphics.pipeline); + vkCmdDraw(command_buffer, 18, REGION_HEX_COUNT, 0, 0); } void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui, uint32_t frame) { @@ -65,8 +63,7 @@ void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui, uint32_t f VkResult draw_frame( RenderContext* context, UIContext* ui, - GraphicsPipeline* hex_graphics, - VkDeviceAddress hex_context, + HexContext* hex, double time) { VkResult result; @@ -186,7 +183,7 @@ VkResult draw_frame( }; vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); - record_hex_draw(command_buffer, hex_graphics, hex_context, time); + record_hex_draw(command_buffer, hex, time, context->current_frame); vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); record_ui_draw(command_buffer, ui, time, context->current_frame); vkCmdEndRenderPass(command_buffer); diff --git a/client/src/hex.c b/client/src/hex.c index c752342..2bf7ca3 100644 --- a/client/src/hex.c +++ b/client/src/hex.c @@ -2,16 +2,14 @@ #include "gpu.h" #include "vulkan/vulkan_core.h" -VkResult create_hex_pipeline( - VkDevice device, - VkRenderPass render_pass, - GraphicsPipeline* graphics, - ComputePipeline* compute) { +VkResult create_hex_context( + RenderContext* gpu, + HexContext* context) { VkResult result; // Compute Pipeline - VkShaderModule compute_shader = load_shader_file("shader/hex.comp.spv", device); + VkShaderModule compute_shader = load_shader_file("shader/hex.comp.spv", gpu->device); if(compute_shader == VK_NULL_HANDLE) { return VK_ERROR_UNKNOWN; } @@ -35,20 +33,20 @@ VkResult create_hex_pipeline( .pushConstantRangeCount = 1, }; - VK_RESULT(vkCreatePipelineLayout(device, &compute_layout_info, NULL, &compute->layout)); + VK_RESULT(vkCreatePipelineLayout(gpu->device, &compute_layout_info, NULL, &context->compute.layout)); VkComputePipelineCreateInfo compute_pipeline_info = { .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, .stage = compute_shader_stage, - .layout = compute->layout, + .layout = context->compute.layout, }; - VK_RESULT(vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_info, NULL, &compute->pipeline)); + VK_RESULT(vkCreateComputePipelines(gpu->device, VK_NULL_HANDLE, 1, &compute_pipeline_info, NULL, &context->compute.pipeline)); // Graphics Pipeline - VkShaderModule vert_shader = load_shader_file("shader/hex.vert.spv", device); - VkShaderModule frag_shader = load_shader_file("shader/hex.frag.spv", device); + VkShaderModule vert_shader = load_shader_file("shader/hex.vert.spv", gpu->device); + VkShaderModule frag_shader = load_shader_file("shader/hex.frag.spv", gpu->device); VkPipelineShaderStageCreateInfo graphics_stages[] = { { @@ -77,7 +75,7 @@ VkResult create_hex_pipeline( .pushConstantRangeCount = 1, }; - VK_RESULT(vkCreatePipelineLayout(device, &graphics_layout_info, NULL, &graphics->layout)); + VK_RESULT(vkCreatePipelineLayout(gpu->device, &graphics_layout_info, NULL, &context->graphics.layout)); VkPipelineVertexInputStateCreateInfo vertex_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, @@ -180,7 +178,7 @@ VkResult create_hex_pipeline( VkGraphicsPipelineCreateInfo graphics_pipeline_info = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .layout = graphics->layout, + .layout = context->graphics.layout, .stageCount = sizeof(graphics_stages)/sizeof(VkPipelineShaderStageCreateInfo), .pStages = graphics_stages, .pVertexInputState = &vertex_info, @@ -191,13 +189,42 @@ VkResult create_hex_pipeline( .pDynamicState = &dynamic_info, .pMultisampleState = &multisample_info, .pDepthStencilState = &depth_info, - .renderPass = render_pass, + .renderPass = gpu->render_pass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = -1, }; - VK_RESULT(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphics_pipeline_info, NULL, &graphics->pipeline)); + VK_RESULT(vkCreateGraphicsPipelines(gpu->device, VK_NULL_HANDLE, 1, &graphics_pipeline_info, NULL, &context->graphics.pipeline)); + + glm_perspective(30.0, (float)gpu->swapchain_extent.width/(float)gpu->swapchain_extent.height, 0.01, 99.9, context->data.proj); + glm_mat4_identity(context->data.view); + VK_RESULT(create_storage_buffer( + gpu->allocator, + 0, + sizeof(GPUHexContext), + &context->context, + &context->context_memory)); + context->address = buffer_address(gpu->device, context->context); + VK_RESULT(add_transfer(&context->data, context->context, 0, sizeof(GPUHexContext), gpu->current_frame, gpu)); + + return VK_SUCCESS; +} + +VkResult create_hex_region(uint32_t x, uint32_t y, HexRegion* region, RenderContext* gpu) { + VkResult result; + + region->x = x; + region->y = y; + VK_RESULT(create_storage_buffer( + gpu->allocator, + 0, + sizeof(GPUHexRegion), + ®ion->region, + ®ion->region_memory)); + VK_RESULT(add_transfer(®ion->x, region->region, offsetof(GPUHexRegion, x), sizeof(uint32_t)*2, 0, gpu)); + region->address = buffer_address(gpu->device, region->region); + return VK_SUCCESS; } diff --git a/client/src/main.c b/client/src/main.c index d3af58b..9316527 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -17,6 +17,7 @@ typedef struct ClientContextStruct { GLFWwindow* window; RenderContext render; UIContext ui; + HexContext hex; uint32_t clicked_container; uint32_t clicked_element; @@ -51,9 +52,6 @@ vec3 up = {0, 1, 0}; VkResult main_thread(ClientContext* context) { VkResult result; - GraphicsPipeline graphics; - ComputePipeline compute; - VK_RESULT(create_hex_pipeline(context->render.device, context->render.render_pass, &graphics, &compute)); GPUString strings[] = { { @@ -124,17 +122,13 @@ VkResult main_thread(ClientContext* context) { 4*sizeof(uint32_t), &context->render)); - VkBuffer hex_context; - VmaAllocation hex_context_memory; - GPUHexContext hex; - VK_RESULT(create_storage_buffer(context->render.allocator, 0, sizeof(GPUHexContext), &hex_context, &hex_context_memory)); - VkDeviceAddress hex_context_address = buffer_address(context->render.device, hex_context); - glm_perspective(30.0, (float)context->render.swapchain_extent.width/(float)context->render.swapchain_extent.height, 0.01, 99.9, hex.proj); + HexRegion region; + VK_RESULT(create_hex_region(0, 0, ®ion, &context->render)); context->position[0] = 0; context->position[1] = 0; context->position[2] = 0; - context->rotation[0] = 0; + context->rotation[0] = 3*M_PI/2; context->rotation[1] = 0; context->cur_spin[0] = 0; context->cur_spin[1] = 0; @@ -143,7 +137,7 @@ VkResult main_thread(ClientContext* context) { context->key_spin[1] = 0; context->cur_spin[0] = 0; context->cur_spin[1] = 0; - context->distance = 1; + context->distance = 10; context->zoom = 0; context->camera_mode = false; context->key_spin_speed = 1.0; @@ -154,7 +148,6 @@ VkResult main_thread(ClientContext* context) { uint32_t* mapped_codes = context->ui.containers[0].layers[0].codes_buffer; GPUString* mapped_string = context->ui.containers[0].layers[0].strings_buffer; char str[21]; - // double last_frame_time = glfwGetTime(); while(glfwWindowShouldClose(context->window) == 0) { @@ -183,8 +176,8 @@ VkResult main_thread(ClientContext* context) { context->rotation[1] += (float)context->key_spin[1]*delta_time*context->key_spin_speed; context->rotation[1] += (float)context->cur_spin[1]*delta_time*context->cur_spin_speed; - if(context->rotation[1] > M_PI/2) { - context->rotation[1] = M_PI/2; + if(context->rotation[1] > (M_PI/2 - 0.1)) { + context->rotation[1] = (M_PI/2 - 0.1); } else if(context->rotation[1] < 0) { context->rotation[1] = 0; } @@ -198,9 +191,9 @@ VkResult main_thread(ClientContext* context) { camera[0] = context->position[0] + context->distance*cos(context->rotation[1])*cos(context->rotation[0]); camera[1] = context->position[1] + context->distance*sin(context->rotation[1]); camera[2] = context->position[2] + context->distance*cos(context->rotation[1])*sin(context->rotation[0]); - glm_lookat(camera, context->position, up, hex.view); - - add_transfer(&hex, hex_context, 0, sizeof(GPUHexContext), (context->render.current_frame + 1) % MAX_FRAMES_IN_FLIGHT, &context->render); + glm_lookat(camera, context->position, up, context->hex.data.view); + add_transfer(&context->hex.data, context->hex.context, 0, sizeof(GPUHexContext), 0, &context->render); + add_transfer(&context->hex.data, context->hex.context, 0, sizeof(GPUHexContext), 1, &context->render); } if(context->clicked_container != 0) { @@ -223,7 +216,7 @@ VkResult main_thread(ClientContext* context) { } // - VkResult result = draw_frame(&context->render, &context->ui, &graphics, hex_context_address, frame_time); + VkResult result = draw_frame(&context->render, &context->ui, &context->hex, frame_time); if(result != VK_SUCCESS) { fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result)); glfwDestroyWindow(context->window); @@ -365,6 +358,7 @@ int main() { // TODO: make # of fonts/textures/containers scaling, recreate GPU buffers as necessary VK_RESULT(create_ui_context(10, 10, 10, &context.render, &context.ui)); + VK_RESULT(create_hex_context(&context.render, &context.hex)); pthread_t network_thread_handle;