Added Camera
Set up uniform buffers for the camera. The camera still lacks a proper controller on the lisp side, but you can create the matrix data in lisp. The projection matrices use the "reverse-z" trick. When setting up depth buffering in the (near) future, this needs to be considered.
This commit is contained in:
parent
207de345f7
commit
29b7e4b50b
@ -4,15 +4,23 @@
|
||||
layout(location = 0) in vec2 inPos;
|
||||
|
||||
// instance data
|
||||
layout(location = 1) in vec2 inInstancePos;
|
||||
layout(location = 2) in vec2 inInstanceScale;
|
||||
layout(location = 1) in vec3 inInstancePos;
|
||||
layout(location = 2) in vec3 inInstanceScale;
|
||||
layout(location = 3) in vec4 inInstanceColor;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 0) uniform Camera
|
||||
{
|
||||
mat4 view;
|
||||
mat4 perspective;
|
||||
mat4 orthographic;
|
||||
|
||||
} camera;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pos = inPos * inInstanceScale + inInstancePos;
|
||||
gl_Position = vec4(pos, 0.0, 1.0);
|
||||
vec3 pos = vec3(inPos, 0.0) * inInstanceScale + inInstancePos;
|
||||
gl_Position = camera.orthographic * vec4(pos, 1.0);
|
||||
fragColor = inInstanceColor;
|
||||
}
|
||||
|
@ -44,6 +44,14 @@ typedef struct vulkan_buffer
|
||||
|
||||
} vulkan_buffer;
|
||||
|
||||
typedef struct renderer_camera
|
||||
{
|
||||
f32 view[16];
|
||||
f32 perspective[16];
|
||||
f32 orthographic[16];
|
||||
|
||||
} renderer_camera;
|
||||
|
||||
typedef struct mesh
|
||||
{
|
||||
vulkan_buffer vertex_buffer;
|
||||
@ -116,6 +124,13 @@ typedef struct vulkan_context
|
||||
|
||||
} single_submit_context;
|
||||
|
||||
renderer_camera camera;
|
||||
vulkan_buffer camera_uniform_buffers[MAX_FRAMES_IN_FLIGHT];
|
||||
u8 update_camera_uniform_counter;
|
||||
VkDescriptorSetLayout camera_descriptor_set_layout;
|
||||
VkDescriptorPool camera_descriptor_pool;
|
||||
VkDescriptorSet camera_descriptor_sets[MAX_FRAMES_IN_FLIGHT];
|
||||
|
||||
hash_table mesh_pipelines;
|
||||
|
||||
} vulkan_context;
|
||||
@ -1326,12 +1341,10 @@ static u8 init_vulkan_staging_buffer(vulkan_buffer* buffer, VkDeviceSize byte_si
|
||||
}
|
||||
|
||||
// uniform buffer, CPU accessible memory
|
||||
/*
|
||||
static u8 init_vulkan_uniform_buffer(vulkan_buffer* buffer, VkDeviceSize byte_size)
|
||||
{
|
||||
return init_vulkan_buffer(buffer, byte_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
}
|
||||
*/
|
||||
|
||||
// vertex buffer, device memory
|
||||
static u8 init_vulkan_vertex_buffer(vulkan_buffer* buffer, VkDeviceSize byte_size)
|
||||
@ -1400,6 +1413,148 @@ static u8 copy_vulkan_buffer(vulkan_buffer* dst, vulkan_buffer* src, VkDeviceSiz
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void shutdown_camera()
|
||||
{
|
||||
vkDestroyDescriptorPool(context.device.logical, context.camera_descriptor_pool, context.allocator);
|
||||
|
||||
vkDestroyDescriptorSetLayout(context.device.logical, context.camera_descriptor_set_layout, context.allocator);
|
||||
|
||||
for (u8 i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
shutdown_vulkan_buffer(context.camera_uniform_buffers + i);
|
||||
}
|
||||
|
||||
static u8 init_camera()
|
||||
{
|
||||
// camera data
|
||||
const f32 id_mat4[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
|
||||
memcpy(context.camera.view, id_mat4, sizeof(f32) * 16);
|
||||
memcpy(context.camera.perspective, id_mat4, sizeof(f32) * 16);
|
||||
memcpy(context.camera.orthographic, id_mat4, sizeof(f32) * 16);
|
||||
context.update_camera_uniform_counter = 0;
|
||||
|
||||
// uniform buffers
|
||||
for (u8 i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
vulkan_buffer* uniform_buffer = context.camera_uniform_buffers + i;
|
||||
if (!init_vulkan_uniform_buffer(uniform_buffer, sizeof(renderer_camera)) ||
|
||||
!map_vulkan_buffer(uniform_buffer, 0, sizeof(renderer_camera), 0)) // persistent mapping
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to create Vulkan camera; failed to setup the uniform buffers.");
|
||||
return 0;
|
||||
}
|
||||
memcpy(uniform_buffer->mapped, &context.camera, sizeof(renderer_camera));
|
||||
}
|
||||
|
||||
// descriptor set layout
|
||||
const VkDescriptorSetLayoutBinding camera_layout_binding =
|
||||
{
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.pImmutableSamplers = NULL
|
||||
};
|
||||
const VkDescriptorSetLayoutCreateInfo descriptor_layout_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = 1,
|
||||
.pBindings = &camera_layout_binding,
|
||||
.flags = 0,
|
||||
.pNext = NULL
|
||||
};
|
||||
if (vkCreateDescriptorSetLayout(context.device.logical, &descriptor_layout_info, context.allocator, &context.camera_descriptor_set_layout) != VK_SUCCESS)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to create Vulkan camera; failed to create descriptor set layout.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// descriptor pool
|
||||
const VkDescriptorPoolSize pool_size =
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = MAX_FRAMES_IN_FLIGHT
|
||||
};
|
||||
const VkDescriptorPoolCreateInfo descriptor_pool_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = &pool_size,
|
||||
.maxSets = MAX_FRAMES_IN_FLIGHT,
|
||||
.flags = 0,
|
||||
.pNext = NULL
|
||||
};
|
||||
if (vkCreateDescriptorPool(context.device.logical, &descriptor_pool_info, context.allocator, &context.camera_descriptor_pool) != VK_SUCCESS)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to create Vulkan camera; failed to create descriptor pool.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// descriptor sets
|
||||
VkDescriptorSetLayout* descriptor_set_layouts = malloc(MAX_FRAMES_IN_FLIGHT * sizeof(VkDescriptorSetLayout));
|
||||
for (u8 i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
descriptor_set_layouts[i] = context.camera_descriptor_set_layout;
|
||||
const VkDescriptorSetAllocateInfo alloc_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = context.camera_descriptor_pool,
|
||||
.descriptorSetCount = MAX_FRAMES_IN_FLIGHT,
|
||||
.pSetLayouts = descriptor_set_layouts,
|
||||
.pNext = NULL
|
||||
};
|
||||
if (vkAllocateDescriptorSets(context.device.logical, &alloc_info, context.camera_descriptor_sets) != VK_SUCCESS)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to create Vulkan camera; failed to allocated descriptor sets");
|
||||
return 0;
|
||||
}
|
||||
for (u8 i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
const VkDescriptorBufferInfo buffer_info =
|
||||
{
|
||||
.buffer = context.camera_uniform_buffers[i].handle,
|
||||
.offset = 0,
|
||||
.range = sizeof(renderer_camera)
|
||||
};
|
||||
const VkWriteDescriptorSet write =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = context.camera_descriptor_sets[i],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.pBufferInfo = &buffer_info,
|
||||
.pImageInfo = NULL,
|
||||
.pTexelBufferView = NULL,
|
||||
.pNext = NULL
|
||||
};
|
||||
vkUpdateDescriptorSets(context.device.logical, 1, &write, 0, NULL);
|
||||
}
|
||||
|
||||
free(descriptor_set_layouts);
|
||||
trace_log(LOG_DEBUG, "Successfully created Vulkan camera.");
|
||||
signal_for_shutdown(shutdown_camera);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void set_camera_view(const f32* view)
|
||||
{
|
||||
memcpy(context.camera.view, view, sizeof(f32) * 16);
|
||||
context.update_camera_uniform_counter= MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
void set_camera_perspective_projection(const f32* perspective)
|
||||
{
|
||||
memcpy(context.camera.perspective, perspective, sizeof(f32) * 16);
|
||||
context.update_camera_uniform_counter = MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
void set_camera_orthographic_projection(const f32* orthographic)
|
||||
{
|
||||
memcpy(context.camera.orthographic, orthographic, sizeof(f32) * 16);
|
||||
context.update_camera_uniform_counter = MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
static u8 init_mesh(mesh* msh, const mesh_geometry* geometry, vertex_input_type geometry_type, const mesh_instance_data* instance_data, vertex_input_type instance_type)
|
||||
{
|
||||
VkDeviceSize geometry_vertices_byte_size = 0, instance_data_byte_size = 0;
|
||||
@ -1426,8 +1581,8 @@ static u8 init_mesh(mesh* msh, const mesh_geometry* geometry, vertex_input_type
|
||||
case VERTEX_INPUT_TYPE_POS2:
|
||||
*ds = count * sizeof(pos2);
|
||||
break;
|
||||
case VERTEX_INPUT_TYPE_POS2_POS2_COLOR4:
|
||||
*ds = count * sizeof(pos2_pos2_color4);
|
||||
case VERTEX_INPUT_TYPE_POS3_POS3_COLOR4:
|
||||
*ds = count * sizeof(pos3_pos3_color4);
|
||||
break;
|
||||
default:
|
||||
trace_log(LOG_ERROR, "Failed to create mesh; invalid vertex type (binding = %d).", i);
|
||||
@ -1575,17 +1730,17 @@ static u8 init_mesh_pipeline(mesh_pipeline* pipeline, const mesh_pipeline_templa
|
||||
attribute_descriptions = darray_pushback(attribute_descriptions, attributes, 1);
|
||||
}
|
||||
break;
|
||||
case VERTEX_INPUT_TYPE_POS2_POS2_COLOR4:
|
||||
case VERTEX_INPUT_TYPE_POS3_POS3_COLOR4:
|
||||
{
|
||||
const VkVertexInputBindingDescription binding =
|
||||
{
|
||||
.binding = i, .stride = sizeof(pos2_pos2_color4), .inputRate = input_rate
|
||||
.binding = i, .stride = sizeof(pos3_pos3_color4), .inputRate = input_rate
|
||||
};
|
||||
const VkVertexInputAttributeDescription attributes[] =
|
||||
{
|
||||
(VkVertexInputAttributeDescription){ .location = idx, .binding = i, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(pos2_pos2_color4, posa) },
|
||||
(VkVertexInputAttributeDescription){ .location = idx + 1, .binding = i, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(pos2_pos2_color4, posb) },
|
||||
(VkVertexInputAttributeDescription){ .location = idx + 2, .binding = i, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(pos2_pos2_color4, color) }
|
||||
(VkVertexInputAttributeDescription){ .location = idx, .binding = i, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(pos3_pos3_color4, posa) },
|
||||
(VkVertexInputAttributeDescription){ .location = idx + 1, .binding = i, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(pos3_pos3_color4, posb) },
|
||||
(VkVertexInputAttributeDescription){ .location = idx + 2, .binding = i, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(pos3_pos3_color4, color) }
|
||||
};
|
||||
binding_descriptions = darray_pushback(binding_descriptions, &binding, 1);
|
||||
attribute_descriptions = darray_pushback(attribute_descriptions, attributes, 3);
|
||||
@ -1631,7 +1786,7 @@ static u8 init_mesh_pipeline(mesh_pipeline* pipeline, const mesh_pipeline_templa
|
||||
.polygonMode = VK_POLYGON_MODE_FILL,
|
||||
.lineWidth = 1.0f,
|
||||
.cullMode = VK_CULL_MODE_BACK_BIT,
|
||||
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
||||
.rasterizerDiscardEnable = VK_FALSE,
|
||||
.depthClampEnable = VK_FALSE,
|
||||
.depthBiasEnable = VK_FALSE,
|
||||
@ -1691,12 +1846,12 @@ static u8 init_mesh_pipeline(mesh_pipeline* pipeline, const mesh_pipeline_templa
|
||||
.pNext = NULL
|
||||
};
|
||||
|
||||
// layout
|
||||
// layout; TO DO probably need something in the pipeline template to make this better
|
||||
const VkPipelineLayoutCreateInfo layout_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 0,
|
||||
.pSetLayouts = NULL,
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &context.camera_descriptor_set_layout,
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = NULL,
|
||||
.flags = 0,
|
||||
@ -1786,18 +1941,21 @@ static void shutdown_mesh_pipeline(mesh_pipeline* pipeline)
|
||||
}
|
||||
|
||||
u8 draw_mesh_pipeline(const char* name)
|
||||
{
|
||||
{
|
||||
// bind pipeline
|
||||
VkCommandBuffer command_buffer = context.frames[context.current_frame].command_buffer;
|
||||
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, name);
|
||||
if (!pipeline)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to draw mesh pipeline '%s'; lookup failed." , name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
VkCommandBuffer command_buffer = context.frames[context.current_frame].command_buffer;
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
|
||||
|
||||
for (u32 i = 0; i < pipeline->meshes.slot_count; i++)
|
||||
// bind camera descriptor set (set 0)
|
||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, 0, 1, context.camera_descriptor_sets + context.current_frame, 0, NULL);
|
||||
|
||||
for (u32 i = 0; i < pipeline->meshes.slot_count; i++)
|
||||
for (hash_table_entry* entry = pipeline->meshes.entries[i]; entry != NULL; entry = entry->next)
|
||||
{
|
||||
mesh* msh = entry->data;
|
||||
@ -1927,6 +2085,7 @@ u8 init_vulkan()
|
||||
if (!init_command_pool()) return 0;
|
||||
if (!init_frame_data()) return 0;
|
||||
if (!init_single_submit_context()) return 0;
|
||||
if (!init_camera()) return 0;
|
||||
|
||||
init_hash_table(&context.mesh_pipelines, 8, sizeof(mesh_pipeline), basic_hash);
|
||||
|
||||
@ -1978,6 +2137,14 @@ u8 begin_render_frame()
|
||||
}
|
||||
else if (acquire_next_image_result != VK_SUCCESS && acquire_next_image_result != VK_SUBOPTIMAL_KHR)
|
||||
return 0;
|
||||
|
||||
// update camera uniform buffer
|
||||
if (context.update_camera_uniform_counter)
|
||||
{
|
||||
vulkan_buffer* uniform_buffer = context.camera_uniform_buffers + context.current_frame;
|
||||
memcpy(uniform_buffer->mapped, &context.camera, sizeof(renderer_camera));
|
||||
context.update_camera_uniform_counter--;
|
||||
}
|
||||
|
||||
vkResetFences(context.device.logical, 1, &frame->in_flight_fence);
|
||||
|
||||
|
@ -43,7 +43,7 @@ typedef struct window_event
|
||||
typedef enum
|
||||
{
|
||||
VERTEX_INPUT_TYPE_POS2,
|
||||
VERTEX_INPUT_TYPE_POS2_POS2_COLOR4
|
||||
VERTEX_INPUT_TYPE_POS3_POS3_COLOR4
|
||||
|
||||
} vertex_input_type;
|
||||
|
||||
@ -53,13 +53,13 @@ typedef struct pos2
|
||||
|
||||
} pos2;
|
||||
|
||||
typedef struct pos2_pos2_color4
|
||||
typedef struct pos3_pos3_color4
|
||||
{
|
||||
f32 posa[2];
|
||||
f32 posb[2];
|
||||
f32 posa[3];
|
||||
f32 posb[3];
|
||||
f32 color[4];
|
||||
|
||||
} pos2_pos2_color4;
|
||||
} pos3_pos3_color4;
|
||||
|
||||
typedef struct mesh_geometry
|
||||
{
|
||||
@ -105,6 +105,10 @@ void shutdown_window();
|
||||
u8 is_window_open();
|
||||
void poll_window_input();
|
||||
|
||||
void set_camera_view(const f32* view);
|
||||
void set_camera_perspective_projection(const f32* perspective);
|
||||
void set_camera_orthographic_projection(const f32* orthographic);
|
||||
|
||||
u8 draw_mesh_pipeline(const char* name);
|
||||
u8 insert_mesh_pipeline(const mesh_pipeline_template* template);
|
||||
u8 remove_mesh_pipeline(const char* name);
|
||||
|
5
sof.asd
5
sof.asd
@ -15,8 +15,9 @@
|
||||
((:module "src"
|
||||
:components
|
||||
((:file "package")
|
||||
(:file "main")
|
||||
(:module "math"
|
||||
:components
|
||||
((:file "vec")
|
||||
(:file "quat")))))))
|
||||
(:file "quat")
|
||||
(:file "mat")))
|
||||
(:file "main")))))
|
||||
|
147
src/main.lisp
147
src/main.lisp
@ -41,7 +41,7 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
|
||||
(cffi:defcenum vertex-input-type
|
||||
:vertex-input-type-pos2
|
||||
:vertex-input-type-pos2-pos2-color4)
|
||||
:vertex-input-type-pos3-pos3-color4)
|
||||
|
||||
(cffi:defcstruct (%pos2 :class c-pos2)
|
||||
(pos :float :count 2))
|
||||
@ -73,64 +73,72 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(cffi:mem-aref pos :float 0) (aref (pos2-pos ,value) 0)
|
||||
(cffi:mem-aref pos :float 1) (aref (pos2-pos ,value) 1))))
|
||||
|
||||
(cffi:defcstruct (%pos2-pos2-color4 :class c-pos2-pos2-color4)
|
||||
(posa :float :count 2)
|
||||
(posb :float :count 2)
|
||||
(cffi:defcstruct (%pos3-pos3-color4 :class c-pos3-pos3-color4)
|
||||
(posa :float :count 3)
|
||||
(posb :float :count 3)
|
||||
(color :float :count 4))
|
||||
|
||||
(defstruct pos2-pos2-color4
|
||||
(posa (vector 0.0 0.0))
|
||||
(posb (vector 0.0 0.0))
|
||||
(defstruct pos3-pos3-color4
|
||||
(posa (vector 0.0 0.0 0.0))
|
||||
(posb (vector 0.0 0.0 0.0))
|
||||
(color (vector 0.0 0.0 0.0 0.0)))
|
||||
|
||||
(defmethod cffi:translate-from-foreign (ptr (type c-pos2-pos2-color4))
|
||||
(cffi:with-foreign-slots ((posa posb color) ptr (:struct %pos2-pos2-color4))
|
||||
(make-pos2-pos2-color4
|
||||
(defmethod cffi:translate-from-foreign (ptr (type c-pos3-pos3-color4))
|
||||
(cffi:with-foreign-slots ((posa posb color) ptr (:struct %pos3-pos3-color4))
|
||||
(make-pos3-pos3-color4
|
||||
:posa (vector (cffi:mem-aref posa :float 0)
|
||||
(cffi:mem-aref posa :float 1))
|
||||
(cffi:mem-aref posa :float 1)
|
||||
(cffi:mem-aref posa :float 2))
|
||||
:posb (vector (cffi:mem-aref posb :float 0)
|
||||
(cffi:mem-aref posb :float 1))
|
||||
(cffi:mem-aref posb :float 1)
|
||||
(cffi:mem-aref posb :float 2))
|
||||
:color (vector (cffi:mem-aref color :float 0)
|
||||
(cffi:mem-aref color :float 1)
|
||||
(cffi:mem-aref color :float 2)
|
||||
(cffi:mem-aref color :float 4)))))
|
||||
(cffi:mem-aref color :float 3)))))
|
||||
|
||||
(defmethod cffi:expand-from-foreign (ptr (type c-pos2-pos2-color4))
|
||||
`(cffi:with-foreign-slots ((posa posb color) ,ptr (:struct %pos2-pos2-color4))
|
||||
(make-pos2-pos2-color4
|
||||
(defmethod cffi:expand-from-foreign (ptr (type c-pos3-pos3-color4))
|
||||
`(cffi:with-foreign-slots ((posa posb color) ,ptr (:struct %pos3-pos3-color4))
|
||||
(make-pos3-pos3-color4
|
||||
:posa (vector (cffi:mem-aref posa :float 0)
|
||||
(cffi:mem-aref posa :float 1))
|
||||
(cffi:mem-aref posa :float 1)
|
||||
(cffi:mem-aref posa :float 2))
|
||||
:posb (vector (cffi:mem-aref posb :float 0)
|
||||
(cffi:mem-aref posb :float 1))
|
||||
(cffi:mem-aref posb :float 1)
|
||||
(cffi:mem-aref posb :float 2))
|
||||
:color (vector (cffi:mem-aref color :float 0)
|
||||
(cffi:mem-aref color :float 1)
|
||||
(cffi:mem-aref color :float 2)
|
||||
(cffi:mem-aref color :float 4)))))
|
||||
(cffi:mem-aref color :float 3)))))
|
||||
|
||||
(defmethod cffi:translate-into-foreign-memory (value (type c-pos2-pos2-color4) ptr)
|
||||
(cffi:with-foreign-slots ((posa posb color) ptr (:struct %pos2-pos2-color4))
|
||||
(defmethod cffi:translate-into-foreign-memory (value (type c-pos3-pos3-color4) ptr)
|
||||
(cffi:with-foreign-slots ((posa posb color) ptr (:struct %pos3-pos3-color4))
|
||||
(setf
|
||||
(cffi:mem-aref posa :float 0) (aref (pos2-pos2-color4-posa value) 0)
|
||||
(cffi:mem-aref posa :float 1) (aref (pos2-pos2-color4-posa value) 1)
|
||||
(cffi:mem-aref posb :float 0) (aref (pos2-pos2-color4-posb value) 0)
|
||||
(cffi:mem-aref posb :float 1) (aref (pos2-pos2-color4-posb value) 1)
|
||||
(cffi:mem-aref color :float 0) (aref (pos2-pos2-color4-color value) 0)
|
||||
(cffi:mem-aref color :float 1) (aref (pos2-pos2-color4-color value) 1)
|
||||
(cffi:mem-aref color :float 2) (aref (pos2-pos2-color4-color value) 2)
|
||||
(cffi:mem-aref color :float 3) (aref (pos2-pos2-color4-color value) 3))))
|
||||
(cffi:mem-aref posa :float 0) (aref (pos3-pos3-color4-posa value) 0)
|
||||
(cffi:mem-aref posa :float 1) (aref (pos3-pos3-color4-posa value) 1)
|
||||
(cffi:mem-aref posa :float 2) (aref (pos3-pos3-color4-posa value) 2)
|
||||
(cffi:mem-aref posb :float 0) (aref (pos3-pos3-color4-posb value) 0)
|
||||
(cffi:mem-aref posb :float 1) (aref (pos3-pos3-color4-posb value) 1)
|
||||
(cffi:mem-aref posb :float 2) (aref (pos3-pos3-color4-posb value) 2)
|
||||
(cffi:mem-aref color :float 0) (aref (pos3-pos3-color4-color value) 0)
|
||||
(cffi:mem-aref color :float 1) (aref (pos3-pos3-color4-color value) 1)
|
||||
(cffi:mem-aref color :float 2) (aref (pos3-pos3-color4-color value) 2)
|
||||
(cffi:mem-aref color :float 3) (aref (pos3-pos3-color4-color value) 3))))
|
||||
|
||||
(defmethod cffi:expand-into-foreign-memory (value (type c-pos2-pos2-color4) ptr)
|
||||
`(cffi:with-foreign-slots ((posa posb color) ,ptr (:struct %pos2-pos2-color4))
|
||||
(defmethod cffi:expand-into-foreign-memory (value (type c-pos3-pos3-color4) ptr)
|
||||
`(cffi:with-foreign-slots ((posa posb color) ,ptr (:struct %pos3-pos3-color4))
|
||||
(setf
|
||||
|
||||
(cffi:mem-aref posa :float 0) (aref (pos2-pos2-color4-posa ,value) 0)
|
||||
(cffi:mem-aref posa :float 1) (aref (pos2-pos2-color4-posa ,value) 1)
|
||||
(cffi:mem-aref posb :float 0) (aref (pos2-pos2-color4-posb ,value) 0)
|
||||
(cffi:mem-aref posb :float 1) (aref (pos2-pos2-color4-posb ,value) 1)
|
||||
(cffi:mem-aref color :float 0) (aref (pos2-pos2-color4-color ,value) 0)
|
||||
(cffi:mem-aref color :float 1) (aref (pos2-pos2-color4-color ,value) 1)
|
||||
(cffi:mem-aref color :float 2) (aref (pos2-pos2-color4-color ,value) 2)
|
||||
(cffi:mem-aref color :float 3) (aref (pos2-pos2-color4-color ,value) 3))))
|
||||
(cffi:mem-aref posa :float 0) (aref (pos3-pos3-color4-posa ,value) 0)
|
||||
(cffi:mem-aref posa :float 1) (aref (pos3-pos3-color4-posa ,value) 1)
|
||||
(cffi:mem-aref posa :float 2) (aref (pos3-pos3-color4-posa ,value) 2)
|
||||
(cffi:mem-aref posb :float 0) (aref (pos3-pos3-color4-posb ,value) 0)
|
||||
(cffi:mem-aref posb :float 1) (aref (pos3-pos3-color4-posb ,value) 1)
|
||||
(cffi:mem-aref posb :float 2) (aref (pos3-pos3-color4-posb ,value) 2)
|
||||
(cffi:mem-aref color :float 0) (aref (pos3-pos3-color4-color ,value) 0)
|
||||
(cffi:mem-aref color :float 1) (aref (pos3-pos3-color4-color ,value) 1)
|
||||
(cffi:mem-aref color :float 2) (aref (pos3-pos3-color4-color ,value) 2)
|
||||
(cffi:mem-aref color :float 3) (aref (pos3-pos3-color4-color ,value) 3))))
|
||||
|
||||
(cffi:defcstruct %mesh-geometry
|
||||
(vertices :pointer)
|
||||
@ -200,6 +208,32 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
|
||||
(cffi:defcfun ("poll_window_input" poll-window-input) :void)
|
||||
|
||||
(cffi:defcfun ("set_camera_view" %set-camera-view) :void
|
||||
(view :pointer))
|
||||
|
||||
(cffi:defcfun ("set_camera_perspective_projection" %set-camera-perspective-projection) :void
|
||||
(perspective :pointer))
|
||||
|
||||
(cffi:defcfun ("set_camera_orthographic_projection" %set-camera-orthographic-projection) :void
|
||||
(orthographic :pointer))
|
||||
|
||||
(defmacro set-camera-helper (camera-mat4 camera-setter)
|
||||
`(cffi:with-foreign-object (c-mat4 :float 16)
|
||||
(dotimes (i 4)
|
||||
(dotimes (j 4)
|
||||
(setf (cffi:mem-aref c-mat4 :float (+ j (* i 4)))
|
||||
(float (aref (aref ,camera-mat4 i) j) 1.0))))
|
||||
(funcall ,camera-setter c-mat4)))
|
||||
|
||||
(defun set-camera-view (view)
|
||||
(set-camera-helper view #'%set-camera-view))
|
||||
|
||||
(defun set-camera-perspective-projection (perspective)
|
||||
(set-camera-helper perspective #'%set-camera-perspective-projection))
|
||||
|
||||
(defun set-camera-orthographic-projection (orthographic)
|
||||
(set-camera-helper orthographic #'%set-camera-orthographic-projection))
|
||||
|
||||
(cffi:defcfun ("draw_mesh_pipeline" draw-mesh-pipeline) :boolean
|
||||
(name :string))
|
||||
|
||||
@ -245,15 +279,29 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(defparameter *frame-time* 0.016)
|
||||
(defparameter *max-frame-time* 0.250)
|
||||
|
||||
(defparameter *view-mat4* *id-mat4*)
|
||||
(defparameter *perspective-mat4* *id-mat4*)
|
||||
(defparameter *orthographic-mat4* *id-mat4*)
|
||||
(defparameter *perspective-near-plane* 0.1)
|
||||
(defparameter *perspective-far-plane* 10.0)
|
||||
(defparameter *orthographic-near-plane* 0.1)
|
||||
(defparameter *orthographic-far-plane* 10.0)
|
||||
|
||||
(defun init-game (name width height)
|
||||
(setf *game-running?*
|
||||
(when (init-window name width height)
|
||||
(when (init-vulkan) t)))
|
||||
|
||||
(setf
|
||||
*perspective-mat4* (perspective-projection (/ pi 4) (/ width height) *perspective-near-plane* *perspective-far-plane*)
|
||||
*orthographic-mat4* (orthographic-projection width height *orthographic-near-plane* *orthographic-far-plane*))
|
||||
(set-camera-perspective-projection *perspective-mat4*)
|
||||
(set-camera-orthographic-projection *orthographic-mat4*)
|
||||
|
||||
(insert-mesh-pipeline
|
||||
"ui-pane"
|
||||
(cffi:foreign-enum-value 'vertex-input-type :vertex-input-type-pos2)
|
||||
(cffi:foreign-enum-value 'vertex-input-type :vertex-input-type-pos2-pos2-color4))
|
||||
(cffi:foreign-enum-value 'vertex-input-type :vertex-input-type-pos3-pos3-color4))
|
||||
|
||||
(cffi:with-foreign-object (quad-vertices '(:struct %pos2) 4)
|
||||
(setf
|
||||
@ -276,12 +324,12 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
vertex-count 4
|
||||
indices quad-indices
|
||||
index-count 6)
|
||||
(cffi:with-foreign-object (quad-instances '(:struct %pos2-pos2-color4) 2)
|
||||
(cffi:with-foreign-object (quad-instances '(:struct %pos3-pos3-color4) 2)
|
||||
(setf
|
||||
(cffi:mem-aref quad-instances '(:struct %pos2-pos2-color4) 0)
|
||||
(make-pos2-pos2-color4 :posa (vector -0.5 0.5) :posb (vector 0.25 0.25) :color (vector 0.7 0.0 0.0 1.0))
|
||||
(cffi:mem-aref quad-instances '(:struct %pos2-pos2-color4) 1)
|
||||
(make-pos2-pos2-color4 :posa (vector 0.5 0.5) :posb (vector 0.4 0.4) :color (vector 0.0 0.5 0.5 0.6)))
|
||||
(cffi:mem-aref quad-instances '(:struct %pos3-pos3-color4) 0)
|
||||
(make-pos3-pos3-color4 :posa (vector 10.0 10.0 1.0) :posb (vector 100.0 100.0 10.0) :color (vector 0.7 0.0 0.0 1.0))
|
||||
(cffi:mem-aref quad-instances '(:struct %pos3-pos3-color4) 1)
|
||||
(make-pos3-pos3-color4 :posa (vector 200.0 200.0 1.0) :posb (vector 100.0 100.0 10.0) :color (vector 1.0 0.4 0.4 0.6)))
|
||||
(cffi:with-foreign-object (instance-data '(:struct %mesh-instance-data))
|
||||
(cffi:with-foreign-slots ((instances instance-count) instance-data (:struct %mesh-instance-data))
|
||||
(setf
|
||||
@ -295,7 +343,12 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
|
||||
(defun process-window-resize (handle)
|
||||
(cffi:with-foreign-slots ((window-resize) handle (:union %window-event-handle))
|
||||
(format t "~a, ~a" (second window-resize) (fourth window-resize))))
|
||||
(let ((width (second window-resize)) (height (fourth window-resize)))
|
||||
(setf
|
||||
*perspective-mat4* (perspective-projection (/ pi 4) (/ width height) *perspective-near-plane* *perspective-far-plane*)
|
||||
*orthographic-mat4* (orthographic-projection width height *orthographic-near-plane* *orthographic-far-plane*))
|
||||
(set-camera-perspective-projection *perspective-mat4*)
|
||||
(set-camera-orthographic-projection *orthographic-mat4*))))
|
||||
|
||||
(defun process-window-input ()
|
||||
(poll-window-input)
|
||||
@ -323,7 +376,7 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
#+slynk
|
||||
(with-simple-restart (continue-game "Continue")
|
||||
(let ((connection (or slynk::*emacs-connection* (slynk::default-connection))))
|
||||
(when connection (slynk::handle-requests connection t))))
|
||||
(when connection (slynk::process-requests t))))
|
||||
|
||||
(let ((dt (/ (float (- curr-time prev-time)) internal-time-units-per-second)))
|
||||
|
||||
|
@ -43,9 +43,10 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(defun diag->mat2 (d) (diag->mat d 2))
|
||||
(defun diag->mat3 (d) (diag->mat d 3))
|
||||
(defun diag->mat4 (d) (diag->mat d 4))
|
||||
(defconstant +id-mat2+ (diag->mat2 #(1 1)))
|
||||
(defconstant +id-mat3+ (diag->mat3 #(1 1 1)))
|
||||
(defconstant +id-mat4+ (diag->mat4 #(1 1 1 1)))
|
||||
|
||||
(defparameter *id-mat2* (diag->mat2 #(1 1)))
|
||||
(defparameter *id-mat3* (diag->mat3 #(1 1 1)))
|
||||
(defparameter *id-mat4* (diag->mat4 #(1 1 1 1)))
|
||||
|
||||
(defmacro transpose-mat (m dim)
|
||||
`(vector
|
||||
@ -73,11 +74,11 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(defmacro mult-mat-diag (m d dim)
|
||||
`(vector
|
||||
,@(loop for i from 0 below dim
|
||||
collect `(scaled-vec3 (aref ,m ,i) (aref ,d ,i)))))
|
||||
collect `(scale-vec3 (aref ,m ,i) (aref ,d ,i)))))
|
||||
|
||||
(defun mult-mat2-diag (m d) (mult-mat-diag m d 2))
|
||||
(defun mult-mat3-diag (m d) (mult-mat-diag m d 3))
|
||||
(defun mult-mat3-diag (m d) (mult-mat-diag m d 4))
|
||||
(defun mult-mat4-diag (m d) (mult-mat-diag m d 4))
|
||||
|
||||
(defmacro mult-mat-vec (m v dim)
|
||||
`(vector
|
||||
@ -115,10 +116,10 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(left (normalize-vec3 (cross-vec3 world-up-dir forward)))
|
||||
(up (cross-vec3 forward left)))
|
||||
(vector
|
||||
(vector 1 (- (dot-vec3 left camera-pos)) (- (dot-vec3 up camera-pos)) (- (dot-vec3 forward camera-pos)))
|
||||
(vector 0 (aref left 0) (aref up 0) (aref forward 0))
|
||||
(vector 0 (aref left 1) (aref up 1) (aref forward 1))
|
||||
(vector 0 (aref left 2) (aref up 2) (aref forward 2)))))
|
||||
(vector (aref left 0) (aref up 0) (aref forward 0) 0)
|
||||
(vector (aref left 1) (aref up 1) (aref forward 1) 0)
|
||||
(vector (aref left 2) (aref up 2) (aref forward 2) 0)
|
||||
(vector (- (dot-vec3 left camera-pos)) (- (dot-vec3 up camera-pos)) (- (dot-vec3 forward camera-pos)) 1))))
|
||||
|
||||
|
||||
(defun perspective-projection (fov ratio near far)
|
||||
@ -126,16 +127,16 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
We are projecting onto the near plane and choosing a reverse-z convention: higher depth values correspond to closer positions."
|
||||
(let ((cot-fov (/ 1 (tan (/ fov 2)))))
|
||||
(vector
|
||||
(vector 0 0 0 (/ (* near far) (- far near)))
|
||||
(vector 0 cot-fov 0 0)
|
||||
(vector 0 0 (- (/ cot-fov ratio)) 0)
|
||||
(vector 1 0 0 (/ near (- near far))))))
|
||||
(vector cot-fov 0 0 0)
|
||||
(vector 0 (- (/ cot-fov ratio)) 0 0)
|
||||
(vector 0 0 (/ near (- near far)) 1)
|
||||
(vector 0 0 (/ (* near far) (- far near)) 0))))
|
||||
|
||||
(defun orthographic-projecion (width height near far)
|
||||
(defun orthographic-projection (width height near far)
|
||||
"This maps a rectangular prism [0, width]x[0, height]x[near, far] to the rectangular prism [-1, 1]x[1, -1]x[1, 0] (Vulkan clip space).
|
||||
We are choosing a reverse-z convention: higher depth values correspond to closer positions."
|
||||
(vector
|
||||
(vector 1 -1 1 (/ far (- far near)))
|
||||
(vector 0 (/ 2 width) 0 0)
|
||||
(vector 0 0 (- (/ 2 height)) 0)
|
||||
(vector 0 0 0 (/ 1 (- near far)))))
|
||||
(vector (/ 2 width) 0 0 0)
|
||||
(vector 0 (- (/ 2 height)) 0 0)
|
||||
(vector 0 0 (/ 1 (- near far)) 0)
|
||||
(vector -1 1 (/ far (- far near)) 1)))
|
||||
|
@ -20,20 +20,20 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
|
||||
(defun mult-quat (q1 q2)
|
||||
(vector
|
||||
(- (* (aref q1 0) (aref q2 0))
|
||||
(+ (* (aref q1 1) (aref q2 1)) (* (aref q1 2) (aref q2 2)) (* (aref q1 3) (aref q2 3))))
|
||||
(-
|
||||
(+ (* (aref q1 0) (aref q2 1)) (* (aref q1 1) (aref q2 0)) (* (aref q1 2) (aref q2 3)))
|
||||
(* (aref q1 3) (aref q2 2)))
|
||||
(+ (* (aref q1 3) (aref q2 0)) (* (aref q1 0) (aref q2 3)) (* (aref q1 1) (aref q2 2)))
|
||||
(* (aref q1 2) (aref q2 1)))
|
||||
(-
|
||||
(+ (* (aref q1 0) (aref q2 2)) (* (aref q1 2) (aref q2 0)) (* (aref q1 3) (aref q2 1)))
|
||||
(* (aref q1 1) (aref q2 3)))
|
||||
(+ (* (aref q1 3) (aref q2 1)) (* (aref q1 1) (aref q2 3)) (* (aref q1 2) (aref q2 0)))
|
||||
(* (aref q1 0) (aref q2 2)))
|
||||
(-
|
||||
(+ (* (aref q1 0) (aref q2 3)) (* (aref q1 3) (aref q2 0)) (* (aref q1 1) (aref q2 2)))
|
||||
(* (aref q1 2) (aref q2 1)))))
|
||||
(+ (* (aref q1 3) (aref q2 2)) (* (aref q1 2) (aref q2 3)) (* (aref q1 0) (aref q2 1)))
|
||||
(* (aref q1 1) (aref q2 0)))
|
||||
(- (* (aref q1 3) (aref q2 3))
|
||||
(+ (* (aref q1 0) (aref q2 0)) (* (aref q1 1) (aref q2 1)) (* (aref q1 2) (aref q2 2))))))
|
||||
|
||||
(defun conjugate-quat (q)
|
||||
(vector (aref q 0) (- (aref q 1)) (- (aref q 2)) (- (aref q 3))))
|
||||
(vector (- (aref q 0)) (- (aref q 1)) (- (aref q 2) (aref q 3))))
|
||||
|
||||
(defmacro quat->versor (q)
|
||||
"Normalize a quaternion. A unit quaternion is also called a versor."
|
||||
@ -44,12 +44,12 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(let* ((sine-angle (sin angle))
|
||||
(cosine-angle (cos angle))
|
||||
(v (scale-vec3 (normalize-vec3 axis) sine-angle)))
|
||||
(concatenate 'vector (vector cosine-angle) v)))
|
||||
(concatenate 'vector v (vector cosine-angle))))
|
||||
|
||||
(defconstant +id-versor+ (vector 1 0 0 0))
|
||||
(defparameter *id-versor* (vector 0 0 0 1))
|
||||
|
||||
(defun slerp-versor (vrs1 vrs2 l)
|
||||
"Spherical interpolation along the shortest path. If the inputs are versors, the output is a versor."
|
||||
"Spherical interpolation of two versors along the shortest path. If the inputs are versors, the output is a versor."
|
||||
(let ((cosine-angle (dot-vec4 vrs1 vrs2)) (vrs vrs2))
|
||||
(when (< cosine-angle 0)
|
||||
(setf
|
||||
|
@ -39,7 +39,7 @@
|
||||
#:conjugate-quat
|
||||
#:quat->versor
|
||||
#:axis-angle->versor
|
||||
#:+id-versor+
|
||||
#:*id-versor*
|
||||
#:slerp-versor))
|
||||
|
||||
(defpackage #:sof-mat
|
||||
@ -54,9 +54,9 @@
|
||||
#:diag->mat2
|
||||
#:diag->mat3
|
||||
#:diag->mat4
|
||||
#:+id-mat2+
|
||||
#:+id-mat3+
|
||||
#:+id-mat4+
|
||||
#:*id-mat2*
|
||||
#:*id-mat3*
|
||||
#:*id-mat4*
|
||||
#:transpose-mat2
|
||||
#:transpose-mat3
|
||||
#:transpose-mat4
|
||||
@ -85,6 +85,9 @@
|
||||
(:use
|
||||
#:cl
|
||||
#:cffi
|
||||
#:sof-vec
|
||||
#:sof-quat
|
||||
#:sof-mat
|
||||
#:sof-transform)
|
||||
(:export
|
||||
#:main))
|
||||
|
Loading…
Reference in New Issue
Block a user