diff --git a/client/include/hex.h b/client/include/hex.h index 99a1d2b..17d44f5 100644 --- a/client/include/hex.h +++ b/client/include/hex.h @@ -34,6 +34,10 @@ typedef struct GPUHexContextStruct { vec4 click_end; vec4 hover_start; vec4 hover_end; + uint32_t clicked_region; + int32_t clicked_hex; + uint32_t hovered_region; + int32_t hovered_hex; VkDeviceAddress regions[MAX_LOADED_REGIONS]; } GPUHexContext; @@ -44,6 +48,7 @@ typedef struct HexContextStruct { GraphicsPipeline graphics; GraphicsPipeline ray_pipeline; + GraphicsPipeline highlight_pipeline; HexRegion regions[MAX_LOADED_REGIONS]; diff --git a/client/shader/hex.vert b/client/shader/hex.vert index 16ee3ba..e1e27ba 100644 --- a/client/shader/hex.vert +++ b/client/shader/hex.vert @@ -3,66 +3,6 @@ #include "hex_common.glsl" -#define PI 3.1415926535897932384626433832795 -const float w = 0.5; -const float x = 0.75; -const float z = sqrt(3.0)/2.0; - -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), - vec4(w*cos(2*PI/3), 0, w*sin(2*PI/3), 1), - vec4(w*cos(3*PI/3), 0, w*sin(3*PI/3), 1), - vec4(w*cos(4*PI/3), 0, w*sin(4*PI/3), 1), - vec4(w*cos(5*PI/3), 0, w*sin(5*PI/3), 1), -}; - -const uint indices[] = { - 0, 2, 1, - 0, 3, 2, - 0, 4, 3, - 0, 5, 4, - 0, 6, 5, - 0, 1, 6, -}; - -const vec4 starts[] = { - vec4( 0, 0, z, 0), // 0, -1 - vec4(-x, 0, z/2, 0), // -1, 0 - vec4(-x, 0, -z/2, 0), // -1, +1 - vec4( 0, 0, -z, 0), // 0, +1 - vec4( x, 0, -z/2, 0), // +1, 0 - vec4( x, 0, z/2, 0), // +1, -1 -}; - -const vec2 start_coords[] = { - vec2(0, -1), - vec2(-1, 0), - vec2(-1, 1), - vec2(0, 1), - vec2(1, 0), - vec2(1, -1), -}; - -const vec4 direction[] = { - vec4(-x, 0, -z/2, 0), - vec4( 0, 0, -z, 0), - vec4( x, 0, -z/2, 0), - vec4( x, 0, z/2, 0), - vec4( 0, 0, z, 0), - vec4(-x, 0, z/2, 0), -}; - -const vec2 direction_coords[] = { - vec2(-1, 1), - vec2(0, 1), - vec2(1, 0), - vec2(1, -1), - vec2(0, -1), - vec2(-1, 0), -}; - layout(location=0) out vec4 color; vec4 int2color(uint color_int) { @@ -73,11 +13,6 @@ vec4 int2color(uint color_int) { return vec4(r, g, b, a)/255.0; } -const int region_size = 10; -const float region_width = x*(2*region_size-1); -const float region_height = z*(2*region_size-1); -const int region_hex_count = 3*region_size*(region_size-1)+1; - void main() { int region_index = gl_InstanceIndex/region_hex_count; int hex_index = gl_InstanceIndex - (region_index*region_hex_count); @@ -113,6 +48,16 @@ void main() { /* vec2 hex_qr = start_coords[side]*radius + direction_coords[side]*(ring-(radius*side)); + vec2 world_qr = vec2(0, 0); + world_qr.y = hex_qr.y + - region_qr.x*(region_size + 0.5) + - region_qr.y*(region_size*2 + 1.0); + + world_qr.x = hex_qr.x + + region_qr.x*(region_size*2 + 1.0) + + region_qr.y*(region_size + 0.0); + color = vec4(world_qr/100, 0, 1); + vec4 hex_pos = vec4(0, 0, 0, 1); hex_pos.x = x*hex_qr.x; hex_pos.z = -z*hex_qr.y - z*hex_qr.x/2; @@ -121,11 +66,6 @@ void main() { world_pos.x = hex_pos.x + region_pos.x; world_pos.z = hex_pos.z + region_pos.z; - vec2 world_qr; - world_qr.x = (x*hex_qr.x + (region_qr.x+region_qr.y/2)*region_width - region_qr.y*x/2)/x; - world_qr.y = -(-z*hex_qr.y - z*hex_qr.x/2 + 0.75*region_qr.y*region_height + 0.25*region_qr.y*z + 0.5*region_qr.x*z)/z - (x*hex_qr.x + (region_qr.x+region_qr.y/2)*region_width - region_qr.y*x/2)/(2*x); - - vec2 world_qr = vec2(0, 0); world_qr.x = world_pos.x/x; world_qr.y = -world_pos.z/z - world_pos.x/(2*x); diff --git a/client/shader/hex_common.glsl b/client/shader/hex_common.glsl index bb71e7f..03df02c 100644 --- a/client/shader/hex_common.glsl +++ b/client/shader/hex_common.glsl @@ -16,6 +16,10 @@ layout(std430, buffer_reference) readonly buffer HexContext { vec4 click_end; vec4 hover_start; vec4 hover_end; + uint clicked_region; + int clicked_hex; + uint hovered_region; + int hovered_hex; Region regions[]; }; @@ -23,3 +27,69 @@ layout(std430, push_constant) uniform PushConstant { HexContext context; float time; } pc; + +#define PI 3.1415926535897932384626433832795 +const float w = 0.5; +const float x = 0.75; +const float z = sqrt(3.0)/2.0; + +const int region_size = 10; +const float region_diameter = 2*region_size-1; +const float region_width = x*region_diameter; +const float region_height = z*region_diameter; +const int region_hex_count = 3*region_size*(region_size-1)+1; + +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), + vec4(w*cos(2*PI/3), 0, w*sin(2*PI/3), 1), + vec4(w*cos(3*PI/3), 0, w*sin(3*PI/3), 1), + vec4(w*cos(4*PI/3), 0, w*sin(4*PI/3), 1), + vec4(w*cos(5*PI/3), 0, w*sin(5*PI/3), 1), +}; + +const uint indices[] = { + 0, 2, 1, + 0, 3, 2, + 0, 4, 3, + 0, 5, 4, + 0, 6, 5, + 0, 1, 6, +}; + +const vec4 starts[] = { + vec4( 0, 0, z, 0), // 0, -1 + vec4(-x, 0, z/2, 0), // -1, 0 + vec4(-x, 0, -z/2, 0), // -1, +1 + vec4( 0, 0, -z, 0), // 0, +1 + vec4( x, 0, -z/2, 0), // +1, 0 + vec4( x, 0, z/2, 0), // +1, -1 +}; + +const vec2 start_coords[] = { + vec2(0, -1), + vec2(-1, 0), + vec2(-1, 1), + vec2(0, 1), + vec2(1, 0), + vec2(1, -1), +}; + +const vec4 direction[] = { + vec4(-x, 0, -z/2, 0), + vec4( 0, 0, -z, 0), + vec4( x, 0, -z/2, 0), + vec4( x, 0, z/2, 0), + vec4( 0, 0, z, 0), + vec4(-x, 0, z/2, 0), +}; + +const vec2 direction_coords[] = { + vec2(-1, 1), + vec2(0, 1), + vec2(1, 0), + vec2(1, -1), + vec2(0, -1), + vec2(-1, 0), +}; diff --git a/client/shader/hex_highlight.frag b/client/shader/hex_highlight.frag new file mode 100644 index 0000000..08aba96 --- /dev/null +++ b/client/shader/hex_highlight.frag @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) out vec4 color; +layout(location = 0) flat in vec4 color_in; + +void main() { + color = color_in; +} diff --git a/client/shader/hex_highlight.vert b/client/shader/hex_highlight.vert new file mode 100644 index 0000000..40dec01 --- /dev/null +++ b/client/shader/hex_highlight.vert @@ -0,0 +1,58 @@ +#version 450 +#extension GL_EXT_buffer_reference : require + +#include "hex_common.glsl" + +layout(location = 0) flat out vec4 color; + +void main() { + int hex_index; + Region region; + float raise; + if(gl_InstanceIndex == 0) { + hex_index = pc.context.clicked_hex; + region = pc.context.regions[pc.context.clicked_region]; + color = vec4(0.3, 0.3, 0.3, 0.3); + raise = 0.015; + } else { + hex_index = pc.context.hovered_hex; + region = pc.context.regions[pc.context.hovered_region]; + color = vec4(0.8, 0.8, 0.8, 0.3); + raise = 0.01; + } + + vec2 region_qr = vec2(region.q, region.r); + + vec4 region_pos = vec4(0, 0, 0, 0); + region_pos.x = (region_qr.x+region_qr.y/2)*region_width - region_qr.y*x/2; + region_pos.z = 0.75*region_qr.y*region_height + 0.25*region_qr.y*z + 0.5*region_qr.x*z; + + float radius = 0; + float ring = 0; + int side = 0; + if(hex_index != 0) { + radius = floor(0.5 + sqrt(12*hex_index-3)/6); + ring = hex_index - (3*radius*radius - 3*radius + 1); + side = int(floor(ring/(radius))); + } + + vec4 position = vertices[indices[gl_VertexIndex]] + + (starts[side]*radius) + + (direction[side]*(ring-(radius*side))) + + region_pos; + + if(gl_VertexIndex % 3 == 0) { + position.y = (region.hexes[hex_index].heights[0] + + region.hexes[hex_index].heights[1] + + region.hexes[hex_index].heights[2] + + region.hexes[hex_index].heights[3] + + region.hexes[hex_index].heights[4] + + region.hexes[hex_index].heights[5])/6; + } else { + position.y = region.hexes[hex_index].heights[indices[gl_VertexIndex]-1]; + } + + position.y += raise; + + gl_Position = pc.context.proj * pc.context.view * position; +} diff --git a/client/src/draw.c b/client/src/draw.c index 0d3c30b..2e486d5 100644 --- a/client/src/draw.c +++ b/client/src/draw.c @@ -35,6 +35,10 @@ void record_hex_draw(VkCommandBuffer command_buffer, HexContext* hex, double tim // Draw rays vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, hex->ray_pipeline.pipeline); vkCmdDraw(command_buffer, 2, 2, 0, 0); + + // Draw Highlights + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, hex->highlight_pipeline.pipeline); + vkCmdDraw(command_buffer, 18, 2, 0, 0); } void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui, uint32_t frame) { diff --git a/client/src/hex.c b/client/src/hex.c index e14ec75..9d1bfb2 100644 --- a/client/src/hex.c +++ b/client/src/hex.c @@ -1,7 +1,6 @@ #include "hex.h" #include "gpu.h" #include "vulkan/vulkan_core.h" -#include #include VkResult create_ray_pipeline( @@ -159,6 +158,161 @@ VkResult create_ray_pipeline( return VK_SUCCESS; } +VkResult create_hex_highlight_pipeline( + RenderContext* gpu, + GraphicsPipeline* pipeline) { + VkResult result; + + VkShaderModule vert_shader = load_shader_file("shader/hex_highlight.vert.spv", gpu->device); + VkShaderModule frag_shader = load_shader_file("shader/hex_highlight.frag.spv", gpu->device); + + VkPipelineShaderStageCreateInfo stages[] = { + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .pName = "main", + .module = vert_shader, + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .pName = "main", + .module = frag_shader, + }, + }; + + VkPushConstantRange push = { + .size = sizeof(HexPushConstant), + .offset = 0, + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + }; + + VkPipelineLayoutCreateInfo layout_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pPushConstantRanges = &push, + .pushConstantRangeCount = 1, + }; + + VK_RESULT(vkCreatePipelineLayout(gpu->device, &layout_info, NULL, &pipeline->layout)); + + VkPipelineVertexInputStateCreateInfo vertex_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + }; + + VkPipelineInputAssemblyStateCreateInfo input_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; + + VkViewport viewport = { + .x = 0.0f, + .y = 0.0f, + .width = (float)(100), + .height = (float)(100), + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + + VkRect2D scissor = { + .offset = { + .x = 0, + .y = 0, + }, + .extent = { + .width = 100, + .height = 100, + }, + }; + + VkPipelineViewportStateCreateInfo viewport_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .viewportCount = 1, + .pViewports = &viewport, + .scissorCount = 1, + .pScissors = &scissor, + }; + + VkPipelineRasterizationStateCreateInfo raster_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .depthClampEnable = VK_FALSE, + .rasterizerDiscardEnable = VK_FALSE, + .polygonMode = VK_POLYGON_MODE_FILL, + .lineWidth = 1.0f, + .cullMode = VK_CULL_MODE_BACK_BIT, + .frontFace = VK_FRONT_FACE_CLOCKWISE, + }; + + VkPipelineColorBlendAttachmentState blend_attachments = { + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + .blendEnable = VK_TRUE, + .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA, + .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + .colorBlendOp = VK_BLEND_OP_ADD, + .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, + .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, + .alphaBlendOp = VK_BLEND_OP_ADD, + }; + + VkPipelineColorBlendStateCreateInfo blend_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_COPY, + .attachmentCount = 1, + .pAttachments = &blend_attachments, + }; + + VkDynamicState dynamic_states[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + + VkPipelineDynamicStateCreateInfo dynamic_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = sizeof(dynamic_states)/sizeof(VkDynamicState), + .pDynamicStates = dynamic_states, + }; + + VkPipelineMultisampleStateCreateInfo multisample_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .sampleShadingEnable = VK_FALSE, + .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, + .minSampleShading = 1.0f, + .pSampleMask = 0, + .alphaToCoverageEnable = VK_FALSE, + .alphaToOneEnable = VK_FALSE, + }; + + VkPipelineDepthStencilStateCreateInfo depth_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .depthTestEnable = VK_TRUE, + .depthWriteEnable = VK_TRUE, + .depthCompareOp = VK_COMPARE_OP_LESS, + }; + + VkGraphicsPipelineCreateInfo graphics_pipeline_info = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .layout = pipeline->layout, + .stageCount = sizeof(stages)/sizeof(VkPipelineShaderStageCreateInfo), + .pStages = stages, + .pVertexInputState = &vertex_info, + .pInputAssemblyState = &input_info, + .pViewportState = &viewport_info, + .pRasterizationState = &raster_info, + .pColorBlendState = &blend_info, + .pDynamicState = &dynamic_info, + .pMultisampleState = &multisample_info, + .pDepthStencilState = &depth_info, + .renderPass = gpu->render_pass, + .subpass = 0, + .basePipelineHandle = VK_NULL_HANDLE, + .basePipelineIndex = -1, + }; + + VK_RESULT(vkCreateGraphicsPipelines(gpu->device, VK_NULL_HANDLE, 1, &graphics_pipeline_info, NULL, &pipeline->pipeline)); + return VK_SUCCESS; +} + VkResult create_hex_pipeline( RenderContext* gpu, GraphicsPipeline* pipeline) { @@ -321,6 +475,7 @@ VkResult create_hex_context( VK_RESULT(create_hex_pipeline(gpu, &context->graphics)); VK_RESULT(create_ray_pipeline(gpu, &context->ray_pipeline)); + VK_RESULT(create_hex_highlight_pipeline(gpu, &context->highlight_pipeline)); memset(&context->data, 0, sizeof(GPUHexContext)); glm_perspective(PERSPECTIVE_FOVY, (float)gpu->swapchain_extent.width/(float)gpu->swapchain_extent.height, PERSPECTIVE_NEARZ, PERSPECTIVE_FARZ, context->data.proj); diff --git a/client/src/main.c b/client/src/main.c index bca31b0..75cb0c7 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -122,6 +122,7 @@ VkResult main_thread(ClientContext* context) { int frame = 0; double last_frame_time = 0; + double test = glfwGetTime(); while(glfwWindowShouldClose(context->window) == 0) { double frame_time = glfwGetTime(); double delta_time = (frame_time - last_frame_time); @@ -136,6 +137,17 @@ VkResult main_thread(ClientContext* context) { context->cur_spin[1] = 0; glfwPollEvents(); + if((frame_time - test) > 0.05) { + test = frame_time; + context->hex->data.clicked_region = 210; + context->hex->data.hovered_region = 210; + context->hex->data.hovered_hex = context->hex->data.clicked_hex; + context->hex->data.clicked_hex += 1; + if(context->hex->data.clicked_hex >= REGION_HEX_COUNT) { + context->hex->data.clicked_hex = 0; + } + add_transfer(&context->hex->data.clicked_region, context->hex->context, offsetof(GPUHexContext, clicked_region), 2*sizeof(uint32_t) + 2*sizeof(int32_t), context->render->current_frame, context->render); + } if((context->key_spin[0] != 0 || context->key_spin[1] != 0 || context->zoom != 0 ||