Added pipeline to visualize click ray, and added calculation of click ray

main
noah metz 2024-11-04 00:24:42 -07:00
parent 6b0c1f11c1
commit 6b999ebbde
8 changed files with 263 additions and 15 deletions

@ -60,10 +60,10 @@ debug: roleplay $(EXTRA_DEBUG_REQUIREMENTS) $(SPV_FILES)
$(GDB) roleplay $(GDB) roleplay
%.vert.spv: %.vert %.vert.spv: %.vert
glslc -O -o $@ $< glslc -o $@ $<
%.frag.spv: %.frag %.frag.spv: %.frag
glslc -O -o $@ $< glslc -o $@ $<
%.comp.spv: %.comp %.comp.spv: %.comp
glslc -O -o $@ $< glslc -o $@ $<

@ -9,6 +9,8 @@ VkResult draw_frame(
RenderContext* context, RenderContext* context,
UIContext* ui, UIContext* ui,
HexContext* hex, HexContext* hex,
GraphicsPipeline ray_pipeline,
VkDeviceAddress ray_address,
double time); double time);
#endif #endif

@ -25,9 +25,14 @@
#include <cglm/quat.h> #include <cglm/quat.h>
#include <cglm/cam.h> #include <cglm/cam.h>
#include <math.h>
#define MAX_FRAMES_IN_FLIGHT 2 #define MAX_FRAMES_IN_FLIGHT 2
#define WINDOW_MIN_WIDTH 800 #define WINDOW_MIN_WIDTH 800
#define WINDOW_MIN_HEIGHT 600 #define WINDOW_MIN_HEIGHT 600
#define PERSPECTIVE_FOVY (-M_PI/3)
#define PERSPECTIVE_NEARZ 0.01
#define PERSPECTIVE_FARZ 1000
#define VK_RESULT(x) {\ #define VK_RESULT(x) {\
result = x;\ result = x;\

@ -111,12 +111,7 @@ void main() {
} }
color = int2color(region.hexes[hex_index].colors[indices[gl_VertexIndex]]); color = int2color(region.hexes[hex_index].colors[indices[gl_VertexIndex]]);
/*
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;
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);
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;
@ -125,6 +120,14 @@ 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;
color = vec4(world_pos.x/10+0.5, 0, world_pos.z/10+0.5, 1);
/*
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);

@ -0,0 +1,7 @@
#version 450
layout(location = 0) out vec4 color;
void main() {
color = vec4(1, 1, 1, 1);
}

@ -0,0 +1,25 @@
#version 450
#extension GL_EXT_buffer_reference : require
layout(std430, buffer_reference) readonly buffer Ray {
vec4 a;
vec4 b;
};
layout(std430, buffer_reference) readonly buffer HexContext {
mat4 proj;
mat4 view;
};
layout(push_constant, std430) uniform PushConstant {
Ray ray;
HexContext context;
} pc;
void main() {
if(gl_VertexIndex == 0) {
gl_Position = pc.context.proj * pc.context.view * pc.ray.a;
} else {
gl_Position = pc.context.proj * pc.context.view * pc.ray.b;
}
}

@ -31,7 +31,7 @@ void record_hex_draw(VkCommandBuffer command_buffer, HexContext* hex, double tim
}; };
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, 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) {
@ -66,6 +66,8 @@ VkResult draw_frame(
RenderContext* context, RenderContext* context,
UIContext* ui, UIContext* ui,
HexContext* hex, HexContext* hex,
GraphicsPipeline ray_pipeline,
VkDeviceAddress ray_address,
double time) { double time) {
VkResult result; VkResult result;
@ -191,6 +193,10 @@ VkResult draw_frame(
vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
record_hex_draw(command_buffer, hex, time, context->current_frame); record_hex_draw(command_buffer, hex, time, context->current_frame);
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ray_pipeline.pipeline);
VkDeviceAddress push[2] = {ray_address, hex->address};
vkCmdPushConstants(command_buffer, ray_pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 2*sizeof(VkDeviceAddress), &push);
vkCmdDraw(command_buffer, 2, 1, 0, 0);
vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE);
record_ui_draw(command_buffer, ui, time, context->current_frame); record_ui_draw(command_buffer, ui, time, context->current_frame);
vkCmdEndRenderPass(command_buffer); vkCmdEndRenderPass(command_buffer);

@ -1,6 +1,9 @@
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#define CGLM_PRINT_PRECISION 10
#define CGLM_DEFINE_PRINTS 1
#include "cglm/cam.h" #include "cglm/cam.h"
#include "cglm/mat4.h" #include "cglm/mat4.h"
#include "cglm/io.h"
#include "ui.h" #include "ui.h"
#include "gpu.h" #include "gpu.h"
#include "draw.h" #include "draw.h"
@ -16,6 +19,11 @@
#define max(a, b) ((a > b) ? a : b) #define max(a, b) ((a > b) ? a : b)
typedef struct GPURayStruct {
vec4 a;
vec4 b;
} GPURay;
typedef struct ClientContextStruct { typedef struct ClientContextStruct {
GLFWwindow* window; GLFWwindow* window;
RenderContext* render; RenderContext* render;
@ -41,6 +49,14 @@ typedef struct ClientContextStruct {
float key_spin_speed; float key_spin_speed;
float cur_spin_speed; float cur_spin_speed;
float zoom_speed; float zoom_speed;
mat4 inverse;
GraphicsPipeline ray_pipeline;
VkBuffer ray;
VkDeviceAddress ray_address;
VmaAllocation ray_memory;
} ClientContext; } ClientContext;
void* network_thread(void* data) { void* network_thread(void* data) {
@ -53,9 +69,169 @@ void* network_thread(void* data) {
vec3 zero = {0, 0, 0}; vec3 zero = {0, 0, 0};
vec3 up = {0, 1, 0}; vec3 up = {0, 1, 0};
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 = 2*sizeof(VkDeviceAddress),
.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 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,
};
return vkCreateGraphicsPipelines(gpu->device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &pipeline->pipeline);
}
VkResult main_thread(ClientContext* context) { VkResult main_thread(ClientContext* context) {
VkResult result; VkResult result;
VK_RESULT(create_ray_pipeline(context->render, &context->ray_pipeline));
VK_RESULT(create_storage_buffer(
context->render->allocator,
0,
sizeof(GPURay),
&context->ray,
&context->ray_memory));
context->ray_address = buffer_address(context->render->device, context->ray);
GPUString strings[] = { GPUString strings[] = {
{ {
@ -96,8 +272,8 @@ VkResult main_thread(ClientContext* context) {
}; };
uint32_t region = 0; uint32_t region = 0;
for(int32_t q = -10; q < 10; q++) { for(int32_t q = 0; q < 1; q++) {
for(int32_t r = -10; r < 10; r++) { for(int32_t r = 0; r < 1; r++) {
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++) {
@ -159,10 +335,10 @@ VkResult main_thread(ClientContext* context) {
if(context->render->framebuffer_recreated == true) { if(context->render->framebuffer_recreated == true) {
context->render->framebuffer_recreated = false; context->render->framebuffer_recreated = false;
glm_perspective( glm_perspective(
-M_PI*1/8, PERSPECTIVE_FOVY,
(float)context->render->swapchain_extent.width/(float)context->render->swapchain_extent.height, (float)context->render->swapchain_extent.width/(float)context->render->swapchain_extent.height,
0.01, PERSPECTIVE_NEARZ,
1000, PERSPECTIVE_FARZ,
context->hex->data.proj); context->hex->data.proj);
VK_RESULT(add_transfer( VK_RESULT(add_transfer(
&context->hex->data.proj, &context->hex->data.proj,
@ -208,6 +384,11 @@ VkResult main_thread(ClientContext* context) {
hex_forward[1] = 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;
glm_mat4_mul(context->hex->data.proj, context->hex->data.view, regular);
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_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); add_transfer(hex_forward, context->hex->context, offsetof(GPUHexContext, forward), sizeof(vec2), context->render->current_frame, context->render);
@ -233,7 +414,7 @@ VkResult main_thread(ClientContext* context) {
} }
// //
VkResult result = draw_frame(context->render, context->ui, context->hex, frame_time); VkResult result = draw_frame(context->render, context->ui, context->hex, context->ray_pipeline, context->ray_address, frame_time);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result)); fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result));
glfwDestroyWindow(context->window); glfwDestroyWindow(context->window);
@ -314,6 +495,25 @@ 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) {
vec4 start = {
cursor[0]*context->render->window_scale[0]*2/context->render->swapchain_extent.width - 1,
cursor[1]*context->render->window_scale[1]*2/context->render->swapchain_extent.height - 1,
0,
1.0
};
vec4 end = {
PERSPECTIVE_FARZ*(cursor[0]*context->render->window_scale[0]*2/context->render->swapchain_extent.width - 1),
PERSPECTIVE_FARZ*(cursor[1]*context->render->window_scale[1]*2/context->render->swapchain_extent.height - 1),
PERSPECTIVE_FARZ,
PERSPECTIVE_FARZ,
};
vec4 rays[2] = {};
glm_mat4_mulv(context->inverse, start, rays[0]);
glm_mat4_mulv(context->inverse, end, rays[1]);
add_transfer(rays, context->ray, 0, 2*sizeof(vec4), 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) {
continue; continue;