From 9abfd82cabadab88f352742cf4a3559768aef96b Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Mon, 4 Nov 2024 17:51:10 -0700 Subject: [PATCH] Added click and hover ray and display with pipeline --- client/include/hex.h | 15 ++- client/shader/hex_common.glsl | 7 +- client/shader/ray.frag | 8 ++ client/shader/ray.vert | 24 +++++ client/src/draw.c | 5 +- client/src/hex.c | 187 ++++++++++++++++++++++++++++++++-- client/src/main.c | 26 ++--- 7 files changed, 231 insertions(+), 41 deletions(-) create mode 100644 client/shader/ray.frag create mode 100644 client/shader/ray.vert diff --git a/client/include/hex.h b/client/include/hex.h index 8293911..99a1d2b 100644 --- a/client/include/hex.h +++ b/client/include/hex.h @@ -20,30 +20,30 @@ typedef struct GPUHexRegionStruct { } GPUHexRegion; typedef struct HexRegionStruct { - int32_t q; - int32_t r; - VkDeviceAddress address; VkBuffer region; VmaAllocation region_memory; - GPUHex data[REGION_HEX_COUNT]; + GPUHexRegion data; } HexRegion; typedef struct GPUHexContextStruct { mat4 proj; mat4 view; - vec2 camera; - vec2 forward; + vec4 click_start; + vec4 click_end; + vec4 hover_start; + vec4 hover_end; VkDeviceAddress regions[MAX_LOADED_REGIONS]; } GPUHexContext; typedef struct HexContextStruct { VkDeviceAddress address; VkBuffer context; - VmaAllocation context_memory; + VmaAllocation context_memory; GraphicsPipeline graphics; + GraphicsPipeline ray_pipeline; HexRegion regions[MAX_LOADED_REGIONS]; @@ -52,7 +52,6 @@ typedef struct HexContextStruct { typedef struct HexPushConstantStruct { VkDeviceAddress context; - uint32_t region; double time; } HexPushConstant; diff --git a/client/shader/hex_common.glsl b/client/shader/hex_common.glsl index 362a3b7..bb71e7f 100644 --- a/client/shader/hex_common.glsl +++ b/client/shader/hex_common.glsl @@ -12,13 +12,14 @@ layout(std430, buffer_reference) readonly buffer Region { layout(std430, buffer_reference) readonly buffer HexContext { mat4 proj; mat4 view; - vec2 camera; - vec2 forward; + vec4 click_start; + vec4 click_end; + vec4 hover_start; + vec4 hover_end; Region regions[]; }; layout(std430, push_constant) uniform PushConstant { HexContext context; - uint region; float time; } pc; diff --git a/client/shader/ray.frag b/client/shader/ray.frag new file mode 100644 index 0000000..c617b79 --- /dev/null +++ b/client/shader/ray.frag @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) out vec4 color; +layout(location = 0) flat in vec4 in_color; + +void main() { + color = in_color; +} diff --git a/client/shader/ray.vert b/client/shader/ray.vert new file mode 100644 index 0000000..2d15a22 --- /dev/null +++ b/client/shader/ray.vert @@ -0,0 +1,24 @@ +#version 450 +#extension GL_EXT_buffer_reference : require + +#include "hex_common.glsl" + +layout(location = 0) flat out vec4 color; + +void main() { + if(gl_InstanceIndex == 0) { + color = vec4(1, 0, 0, 1); + if(gl_VertexIndex == 0) { + gl_Position = pc.context.proj * pc.context.view * pc.context.click_start; + } else { + gl_Position = pc.context.proj * pc.context.view * pc.context.click_end; + } + } else { + color = vec4(0, 1, 0, 1); + if(gl_VertexIndex == 0) { + gl_Position = pc.context.proj * pc.context.view * pc.context.hover_start; + } else { + gl_Position = pc.context.proj * pc.context.view * pc.context.hover_end; + } + } +} diff --git a/client/src/draw.c b/client/src/draw.c index 2c91c4f..0d3c30b 100644 --- a/client/src/draw.c +++ b/client/src/draw.c @@ -27,11 +27,14 @@ void record_hex_draw(VkCommandBuffer command_buffer, HexContext* hex, double tim HexPushConstant push = { .context = hex->address, .time = (float)time, - .region = 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*MAX_LOADED_REGIONS, 0, 0); + + // Draw rays + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, hex->ray_pipeline.pipeline); + vkCmdDraw(command_buffer, 2, 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 eeb251e..e14ec75 100644 --- a/client/src/hex.c +++ b/client/src/hex.c @@ -4,11 +4,166 @@ #include #include -VkResult create_hex_context( - RenderContext* gpu, - HexContext* context) { +VkResult create_ray_pipeline( + RenderContext* gpu, + GraphicsPipeline* pipeline) { VkResult result; - + + VkShaderModule vert_shader = load_shader_file("shader/ray.vert.spv", gpu->device); + VkShaderModule frag_shader = load_shader_file("shader/ray.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_LINE_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) { + VkResult result; + VkShaderModule vert_shader = load_shader_file("shader/hex.vert.spv", gpu->device); VkShaderModule frag_shader = load_shader_file("shader/hex.frag.spv", gpu->device); @@ -39,7 +194,7 @@ VkResult create_hex_context( .pushConstantRangeCount = 1, }; - VK_RESULT(vkCreatePipelineLayout(gpu->device, &layout_info, NULL, &context->graphics.layout)); + VK_RESULT(vkCreatePipelineLayout(gpu->device, &layout_info, NULL, &pipeline->layout)); VkPipelineVertexInputStateCreateInfo vertex_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, @@ -138,7 +293,7 @@ VkResult create_hex_context( VkGraphicsPipelineCreateInfo graphics_pipeline_info = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .layout = context->graphics.layout, + .layout = pipeline->layout, .stageCount = sizeof(stages)/sizeof(VkPipelineShaderStageCreateInfo), .pStages = stages, .pVertexInputState = &vertex_info, @@ -155,10 +310,20 @@ VkResult create_hex_context( .basePipelineIndex = -1, }; - VK_RESULT(vkCreateGraphicsPipelines(gpu->device, VK_NULL_HANDLE, 1, &graphics_pipeline_info, NULL, &context->graphics.pipeline)); + VK_RESULT(vkCreateGraphicsPipelines(gpu->device, VK_NULL_HANDLE, 1, &graphics_pipeline_info, NULL, &pipeline->pipeline)); + return VK_SUCCESS; +} + +VkResult create_hex_context( + RenderContext* gpu, + HexContext* context) { + VkResult result; + + VK_RESULT(create_hex_pipeline(gpu, &context->graphics)); + VK_RESULT(create_ray_pipeline(gpu, &context->ray_pipeline)); memset(&context->data, 0, sizeof(GPUHexContext)); - glm_perspective(-M_PI*1/8, (float)gpu->swapchain_extent.width/(float)gpu->swapchain_extent.height, 0.01, 1000, context->data.proj); + glm_perspective(PERSPECTIVE_FOVY, (float)gpu->swapchain_extent.width/(float)gpu->swapchain_extent.height, PERSPECTIVE_NEARZ, PERSPECTIVE_FARZ, context->data.proj); glm_mat4_identity(context->data.view); VK_RESULT(create_storage_buffer( gpu->allocator, @@ -187,15 +352,15 @@ VkResult create_hex_region(int32_t q, int32_t r, HexRegion** region, HexContext* return VK_ERROR_OUT_OF_HOST_MEMORY; } - (*region)->q = q; - (*region)->r = r; + (*region)->data.q = q; + (*region)->data.r = r; VK_RESULT(create_storage_buffer( gpu->allocator, 0, sizeof(GPUHexRegion), &(*region)->region, &(*region)->region_memory)); - VK_RESULT(add_transfer(&(*region)->q, (*region)->region, offsetof(GPUHexRegion, q), sizeof(uint32_t)*2, gpu->current_frame, gpu)); + VK_RESULT(add_transfer(&(*region)->data.q, (*region)->region, offsetof(GPUHexRegion, q), sizeof(uint32_t)*2, gpu->current_frame, gpu)); (*region)->address = buffer_address(gpu->device, (*region)->region); diff --git a/client/src/main.c b/client/src/main.c index cc8f007..bca31b0 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -46,8 +46,6 @@ typedef struct ClientContextStruct { float zoom_speed; mat4 inverse; - vec4 cursor_ray[2]; - vec4 click_ray[2]; } ClientContext; void* network_thread(void* data) { @@ -107,12 +105,12 @@ VkResult main_thread(ClientContext* context) { VK_RESULT(create_hex_region(q, r, ®ions[region], context->hex, context->render)); for(uint32_t i = 0; i < REGION_HEX_COUNT; i++) { for(uint32_t h = 0; h < 6; h++) { - regions[region]->data[i].color[h] = colors[(q+r+50) % (sizeof(colors)/sizeof(uint32_t))]; - regions[region]->data[i].height[h] = (float)i/REGION_HEX_COUNT; + regions[region]->data.hexes[i].color[h] = colors[(q+r+50) % (sizeof(colors)/sizeof(uint32_t))]; + regions[region]->data.hexes[i].height[h] = (float)i/REGION_HEX_COUNT; } - regions[region]->data[i].color[6] = colors[(q+r+50) % (sizeof(colors)/sizeof(uint32_t))]; + regions[region]->data.hexes[i].color[6] = colors[(q+r+50) % (sizeof(colors)/sizeof(uint32_t))]; } - VK_RESULT(add_transfer(®ions[region]->data, regions[region]->region, offsetof(GPUHexRegion, hexes), sizeof(GPUHex)*REGION_HEX_COUNT, 0, context->render)); + VK_RESULT(add_transfer(®ions[region]->data.hexes, regions[region]->region, offsetof(GPUHexRegion, hexes), sizeof(GPUHex)*REGION_HEX_COUNT, 0, context->render)); region++; } } @@ -186,14 +184,6 @@ VkResult main_thread(ClientContext* context) { 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]); - vec2 hex_pos = {}; - vec2 hex_forward = {}; - - hex_pos[0] = camera[0]; - hex_pos[1] = -camera[2] + camera[0]/2; - hex_forward[0] = 0; - hex_forward[1] = 0; - glm_lookat(camera, context->position, up, context->hex->data.view); mat4 regular; @@ -201,8 +191,6 @@ VkResult main_thread(ClientContext* context) { glm_mat4_inv(regular, context->inverse); add_transfer(&context->hex->data, context->hex->context, 0, 2*sizeof(mat4), context->render->current_frame, context->render); - add_transfer(hex_pos, context->hex->context, offsetof(GPUHexContext, camera), sizeof(vec2), context->render->current_frame, context->render); - add_transfer(hex_forward, context->hex->context, offsetof(GPUHexContext, forward), sizeof(vec2), context->render->current_frame, context->render); } if(context->clicked_hex[0] != 0 || context->clicked_hex[1] != 0) { @@ -325,7 +313,8 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) break; case GLFW_MOUSE_BUTTON_LEFT: if(action == GLFW_PRESS) { - cursor_to_world_ray(context, cursor, context->click_ray[0], context->click_ray[1]); + cursor_to_world_ray(context, cursor, context->hex->data.click_start, context->hex->data.click_end); + add_transfer(&context->hex->data.click_start, context->hex->context, offsetof(GPUHexContext, click_start), sizeof(vec4)*2, context->render->current_frame, context->render); for(int32_t c = context->ui->max_containers - 1; c >= 0; c--) { if(context->ui->containers[c].id == 0x00000000) { @@ -367,7 +356,8 @@ void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { } context->cursor[0] = xpos; context->cursor[1] = ypos; - cursor_to_world_ray(context, context->cursor, context->cursor_ray[0], context->cursor_ray[1]); + cursor_to_world_ray(context, context->cursor, context->hex->data.hover_start, context->hex->data.hover_end); + add_transfer(&context->hex->data.hover_start, context->hex->context, offsetof(GPUHexContext, hover_start), sizeof(vec4)*2, context->render->current_frame, context->render); } int main() {