Added click and hover ray and display with pipeline

main
noah metz 2024-11-04 17:51:10 -07:00
parent 797b44d6a4
commit 9abfd82cab
7 changed files with 231 additions and 41 deletions

@ -20,30 +20,30 @@ typedef struct GPUHexRegionStruct {
} GPUHexRegion; } GPUHexRegion;
typedef struct HexRegionStruct { typedef struct HexRegionStruct {
int32_t q;
int32_t r;
VkDeviceAddress address; VkDeviceAddress address;
VkBuffer region; VkBuffer region;
VmaAllocation region_memory; VmaAllocation region_memory;
GPUHex data[REGION_HEX_COUNT]; GPUHexRegion data;
} HexRegion; } HexRegion;
typedef struct GPUHexContextStruct { typedef struct GPUHexContextStruct {
mat4 proj; mat4 proj;
mat4 view; mat4 view;
vec2 camera; vec4 click_start;
vec2 forward; vec4 click_end;
vec4 hover_start;
vec4 hover_end;
VkDeviceAddress regions[MAX_LOADED_REGIONS]; VkDeviceAddress regions[MAX_LOADED_REGIONS];
} GPUHexContext; } GPUHexContext;
typedef struct HexContextStruct { typedef struct HexContextStruct {
VkDeviceAddress address; VkDeviceAddress address;
VkBuffer context; VkBuffer context;
VmaAllocation context_memory; VmaAllocation context_memory;
GraphicsPipeline graphics; GraphicsPipeline graphics;
GraphicsPipeline ray_pipeline;
HexRegion regions[MAX_LOADED_REGIONS]; HexRegion regions[MAX_LOADED_REGIONS];
@ -52,7 +52,6 @@ typedef struct HexContextStruct {
typedef struct HexPushConstantStruct { typedef struct HexPushConstantStruct {
VkDeviceAddress context; VkDeviceAddress context;
uint32_t region;
double time; double time;
} HexPushConstant; } HexPushConstant;

@ -12,13 +12,14 @@ layout(std430, buffer_reference) readonly buffer Region {
layout(std430, buffer_reference) readonly buffer HexContext { layout(std430, buffer_reference) readonly buffer HexContext {
mat4 proj; mat4 proj;
mat4 view; mat4 view;
vec2 camera; vec4 click_start;
vec2 forward; vec4 click_end;
vec4 hover_start;
vec4 hover_end;
Region regions[]; Region regions[];
}; };
layout(std430, push_constant) uniform PushConstant { layout(std430, push_constant) uniform PushConstant {
HexContext context; HexContext context;
uint region;
float time; float time;
} pc; } pc;

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

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

@ -27,11 +27,14 @@ void record_hex_draw(VkCommandBuffer command_buffer, HexContext* hex, double tim
HexPushConstant push = { HexPushConstant push = {
.context = hex->address, .context = hex->address,
.time = (float)time, .time = (float)time,
.region = 0,
}; };
vkCmdPushConstants(command_buffer, hex->graphics.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(HexPushConstant), &push); 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); vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, hex->graphics.pipeline);
vkCmdDraw(command_buffer, 18, REGION_HEX_COUNT*MAX_LOADED_REGIONS, 0, 0); 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) { void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui, uint32_t frame) {

@ -4,11 +4,166 @@
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
VkResult create_hex_context( VkResult create_ray_pipeline(
RenderContext* gpu, RenderContext* gpu,
HexContext* context) { GraphicsPipeline* pipeline) {
VkResult result; 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 vert_shader = load_shader_file("shader/hex.vert.spv", gpu->device);
VkShaderModule frag_shader = load_shader_file("shader/hex.frag.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, .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 = { VkPipelineVertexInputStateCreateInfo vertex_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
@ -138,7 +293,7 @@ VkResult create_hex_context(
VkGraphicsPipelineCreateInfo graphics_pipeline_info = { VkGraphicsPipelineCreateInfo graphics_pipeline_info = {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.layout = context->graphics.layout, .layout = pipeline->layout,
.stageCount = sizeof(stages)/sizeof(VkPipelineShaderStageCreateInfo), .stageCount = sizeof(stages)/sizeof(VkPipelineShaderStageCreateInfo),
.pStages = stages, .pStages = stages,
.pVertexInputState = &vertex_info, .pVertexInputState = &vertex_info,
@ -155,10 +310,20 @@ VkResult create_hex_context(
.basePipelineIndex = -1, .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)); 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); glm_mat4_identity(context->data.view);
VK_RESULT(create_storage_buffer( VK_RESULT(create_storage_buffer(
gpu->allocator, 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; return VK_ERROR_OUT_OF_HOST_MEMORY;
} }
(*region)->q = q; (*region)->data.q = q;
(*region)->r = r; (*region)->data.r = r;
VK_RESULT(create_storage_buffer( VK_RESULT(create_storage_buffer(
gpu->allocator, gpu->allocator,
0, 0,
sizeof(GPUHexRegion), sizeof(GPUHexRegion),
&(*region)->region, &(*region)->region,
&(*region)->region_memory)); &(*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); (*region)->address = buffer_address(gpu->device, (*region)->region);

@ -46,8 +46,6 @@ typedef struct ClientContextStruct {
float zoom_speed; float zoom_speed;
mat4 inverse; mat4 inverse;
vec4 cursor_ray[2];
vec4 click_ray[2];
} ClientContext; } ClientContext;
void* network_thread(void* data) { void* network_thread(void* data) {
@ -107,12 +105,12 @@ VkResult main_thread(ClientContext* context) {
VK_RESULT(create_hex_region(q, r, &regions[region], context->hex, context->render)); VK_RESULT(create_hex_region(q, r, &regions[region], context->hex, context->render));
for(uint32_t i = 0; i < REGION_HEX_COUNT; i++) { for(uint32_t i = 0; i < REGION_HEX_COUNT; i++) {
for(uint32_t h = 0; h < 6; h++) { 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.hexes[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].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(&regions[region]->data, regions[region]->region, offsetof(GPUHexRegion, hexes), sizeof(GPUHex)*REGION_HEX_COUNT, 0, context->render)); VK_RESULT(add_transfer(&regions[region]->data.hexes, regions[region]->region, offsetof(GPUHexRegion, hexes), sizeof(GPUHex)*REGION_HEX_COUNT, 0, context->render));
region++; region++;
} }
} }
@ -186,14 +184,6 @@ VkResult main_thread(ClientContext* context) {
camera[1] = context->position[1] + context->distance*sin(context->rotation[1]); 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]); 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); glm_lookat(camera, context->position, up, context->hex->data.view);
mat4 regular; mat4 regular;
@ -201,8 +191,6 @@ VkResult main_thread(ClientContext* context) {
glm_mat4_inv(regular, context->inverse); 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(&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) { 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; break;
case GLFW_MOUSE_BUTTON_LEFT: case GLFW_MOUSE_BUTTON_LEFT:
if(action == GLFW_PRESS) { 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--) { for(int32_t c = context->ui->max_containers - 1; c >= 0; c--) {
if(context->ui->containers[c].id == 0x00000000) { 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[0] = xpos;
context->cursor[1] = ypos; 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() { int main() {