Added hexagon highlight pipeline

main
noah metz 2024-11-04 20:42:58 -07:00
parent 9abfd82cab
commit 56f686273a
8 changed files with 323 additions and 71 deletions

@ -34,6 +34,10 @@ typedef struct GPUHexContextStruct {
vec4 click_end; vec4 click_end;
vec4 hover_start; vec4 hover_start;
vec4 hover_end; vec4 hover_end;
uint32_t clicked_region;
int32_t clicked_hex;
uint32_t hovered_region;
int32_t hovered_hex;
VkDeviceAddress regions[MAX_LOADED_REGIONS]; VkDeviceAddress regions[MAX_LOADED_REGIONS];
} GPUHexContext; } GPUHexContext;
@ -44,6 +48,7 @@ typedef struct HexContextStruct {
GraphicsPipeline graphics; GraphicsPipeline graphics;
GraphicsPipeline ray_pipeline; GraphicsPipeline ray_pipeline;
GraphicsPipeline highlight_pipeline;
HexRegion regions[MAX_LOADED_REGIONS]; HexRegion regions[MAX_LOADED_REGIONS];

@ -3,66 +3,6 @@
#include "hex_common.glsl" #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; layout(location=0) out vec4 color;
vec4 int2color(uint color_int) { vec4 int2color(uint color_int) {
@ -73,11 +13,6 @@ vec4 int2color(uint color_int) {
return vec4(r, g, b, a)/255.0; 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() { void main() {
int region_index = gl_InstanceIndex/region_hex_count; int region_index = gl_InstanceIndex/region_hex_count;
int hex_index = gl_InstanceIndex - (region_index*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 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); vec4 hex_pos = vec4(0, 0, 0, 1);
hex_pos.x = x*hex_qr.x; hex_pos.x = x*hex_qr.x;
hex_pos.z = -z*hex_qr.y - z*hex_qr.x/2; 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.x = hex_pos.x + region_pos.x;
world_pos.z = hex_pos.z + region_pos.z; 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); vec2 world_qr = vec2(0, 0);
world_qr.x = world_pos.x/x; world_qr.x = world_pos.x/x;
world_qr.y = -world_pos.z/z - world_pos.x/(2*x); world_qr.y = -world_pos.z/z - world_pos.x/(2*x);

@ -16,6 +16,10 @@ layout(std430, buffer_reference) readonly buffer HexContext {
vec4 click_end; vec4 click_end;
vec4 hover_start; vec4 hover_start;
vec4 hover_end; vec4 hover_end;
uint clicked_region;
int clicked_hex;
uint hovered_region;
int hovered_hex;
Region regions[]; Region regions[];
}; };
@ -23,3 +27,69 @@ layout(std430, push_constant) uniform PushConstant {
HexContext context; HexContext context;
float time; float time;
} pc; } 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),
};

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

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

@ -35,6 +35,10 @@ void record_hex_draw(VkCommandBuffer command_buffer, HexContext* hex, double tim
// Draw rays // Draw rays
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, hex->ray_pipeline.pipeline); vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, hex->ray_pipeline.pipeline);
vkCmdDraw(command_buffer, 2, 2, 0, 0); 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) { void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui, uint32_t frame) {

@ -1,7 +1,6 @@
#include "hex.h" #include "hex.h"
#include "gpu.h" #include "gpu.h"
#include "vulkan/vulkan_core.h" #include "vulkan/vulkan_core.h"
#include <math.h>
#include <stdio.h> #include <stdio.h>
VkResult create_ray_pipeline( VkResult create_ray_pipeline(
@ -159,6 +158,161 @@ VkResult create_ray_pipeline(
return VK_SUCCESS; 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( VkResult create_hex_pipeline(
RenderContext* gpu, RenderContext* gpu,
GraphicsPipeline* pipeline) { GraphicsPipeline* pipeline) {
@ -321,6 +475,7 @@ VkResult create_hex_context(
VK_RESULT(create_hex_pipeline(gpu, &context->graphics)); VK_RESULT(create_hex_pipeline(gpu, &context->graphics));
VK_RESULT(create_ray_pipeline(gpu, &context->ray_pipeline)); 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)); 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); glm_perspective(PERSPECTIVE_FOVY, (float)gpu->swapchain_extent.width/(float)gpu->swapchain_extent.height, PERSPECTIVE_NEARZ, PERSPECTIVE_FARZ, context->data.proj);

@ -122,6 +122,7 @@ VkResult main_thread(ClientContext* context) {
int frame = 0; int frame = 0;
double last_frame_time = 0; double last_frame_time = 0;
double test = glfwGetTime();
while(glfwWindowShouldClose(context->window) == 0) { while(glfwWindowShouldClose(context->window) == 0) {
double frame_time = glfwGetTime(); double frame_time = glfwGetTime();
double delta_time = (frame_time - last_frame_time); double delta_time = (frame_time - last_frame_time);
@ -136,6 +137,17 @@ VkResult main_thread(ClientContext* context) {
context->cur_spin[1] = 0; context->cur_spin[1] = 0;
glfwPollEvents(); 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 || if((context->key_spin[0] != 0 || context->key_spin[1] != 0 ||
context->zoom != 0 || context->zoom != 0 ||