Added textured material with per-vertex UV, but no texture images yet

main
noah metz 2024-01-08 20:32:47 -07:00
parent b603af2f89
commit e5842f3ef5
3 changed files with 191 additions and 45 deletions

@ -0,0 +1,10 @@
#version 450
layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTex;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragTex, 0.0f, 1.0);
}

@ -0,0 +1,19 @@
#version 450
layout(binding = 0) uniform UniformBufferObject {
mat4 view;
mat4 proj;
} ubo;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTex;
layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTex;
void main() {
gl_Position = ubo.proj * ubo.view * vec4(inPosition, 1.0);
fragColor = inColor;
fragTex = inTex;
}

@ -112,12 +112,20 @@ typedef struct VulkanContextStruct {
void** scene_ubo_ptrs;
Mesh triangle_mesh;
Mesh triangle_mesh_textured;
Material simple_mesh_material;
Material texture_mesh_material;
uint32_t current_frame;
} VulkanContext;
struct Vertex{
struct TextureVertex {
vec3 pos;
vec3 color;
vec2 tex;
};
struct Vertex {
vec3 pos;
vec3 color;
};
@ -132,12 +140,17 @@ const struct Vertex vertices[] = {
{.pos = { 0.5f, -0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}},
{.pos = { 0.5f, 0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}},
{.pos = {-0.5f, 0.5f, 0.5f}, .color = {1.0f, 1.0f, 1.0f}},
{.pos = { 0.5f, 0.5f, 1.0f}, .color = {0.0f, 0.0f, 1.0f}},
{.pos = {-0.5f, 0.5f, 1.0f}, .color = {1.0f, 1.0f, 1.0f}},
};
const struct TextureVertex texture_vertices[] = {
{.pos = {-0.5f, -0.5f, 0.5f}, .color = {1.0f, 0.0f, 0.0f}, .tex = {0.0f, 1.0f}},
{.pos = { 0.5f, -0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}, .tex = {1.0f, 0.0f}},
{.pos = { 0.5f, 0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}, .tex = {1.0f, 1.0f}},
{.pos = {-0.5f, 0.5f, 0.5f}, .color = {1.0f, 1.0f, 1.0f}, .tex = {0.5f, 0.5f}},
};
const uint16_t indices[] = {
2, 1, 0, 0, 3, 2, 5, 4, 3,
2, 1, 0, 0, 3, 2,
};
const char * validation_layers[] = {
@ -1363,7 +1376,36 @@ VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count
return fences;
}
Mesh load_mesh(VkPhysicalDevice physical_device, VkDevice device, struct Vertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) {
Mesh load_texture_mesh(VkPhysicalDevice physical_device, VkDevice device, struct TextureVertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) {
Mesh mesh = {};
mesh.vertex_buffer.buffer = VK_NULL_HANDLE;
mesh.vertex_buffer.memory = VK_NULL_HANDLE;
mesh.index_buffer.buffer = VK_NULL_HANDLE;
mesh.index_buffer.memory = VK_NULL_HANDLE;
AllocatedBuffer vertex_buffer = create_populated_buffer(physical_device, device, (void*)vertices, sizeof(struct TextureVertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
if(vertex_buffer.memory == VK_NULL_HANDLE) {
return mesh;
}
mesh.vertex_buffer = vertex_buffer;
mesh.vertex_count = vertex_count;
AllocatedBuffer index_buffer = create_populated_buffer(physical_device, device, (void*)indices, sizeof(uint16_t) * index_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
if(index_buffer.memory == VK_NULL_HANDLE) {
deallocate_buffer(device, vertex_buffer);
AllocatedBuffer tmp = { .memory = VK_NULL_HANDLE, .buffer = VK_NULL_HANDLE};
mesh.vertex_buffer = tmp;
return mesh;
}
mesh.index_buffer = index_buffer;
mesh.index_count = index_count;
return mesh;
}
Mesh load_simple_mesh(VkPhysicalDevice physical_device, VkDevice device, struct Vertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) {
Mesh mesh = {};
mesh.vertex_buffer.buffer = VK_NULL_HANDLE;
mesh.vertex_buffer.memory = VK_NULL_HANDLE;
@ -1452,6 +1494,100 @@ Material create_material(
return material;
}
Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout) {
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device);
VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device);
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
shader_stages[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shader_stages[0].module = vert_shader;
shader_stages[0].pName = "main";
shader_stages[1].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shader_stages[1].module = frag_shader;
shader_stages[1].pName = "main";
VkVertexInputBindingDescription bindings[1] = {
{
.binding = 0,
.stride = sizeof(struct Vertex),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
},
};
VkVertexInputAttributeDescription attributes[2] = {
{
.binding = 0,
.location = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(struct Vertex, pos),
},
{
.binding = 0,
.location = 1,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(struct Vertex, color),
},
};
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, 0, 0, 0, 0, 1, bindings, 2, attributes);
}
Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout) {
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/texture.vert.spv", device);
if(vert_shader == VK_NULL_HANDLE) {
Material tmp = {};
return tmp;
}
VkShaderModule frag_shader = load_shader_file(2048, "shader_src/texture.frag.spv", device);
if(frag_shader == VK_NULL_HANDLE) {
Material tmp = {};
return tmp;
}
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
shader_stages[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shader_stages[0].module = vert_shader;
shader_stages[0].pName = "main";
shader_stages[1].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shader_stages[1].module = frag_shader;
shader_stages[1].pName = "main";
VkVertexInputBindingDescription bindings[1] = {
{
.binding = 0,
.stride = sizeof(struct TextureVertex),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
},
};
VkVertexInputAttributeDescription attributes[3] = {
{
.binding = 0,
.location = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(struct TextureVertex, pos),
},
{
.binding = 0,
.location = 1,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(struct TextureVertex, color),
},
{
.binding = 0,
.location = 2,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(struct TextureVertex, tex),
},
};
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, 0, 0, 0, 0, 1, bindings, 3, attributes);
}
VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
VulkanContext* context = (VulkanContext*)malloc(sizeof(VulkanContext));
@ -1688,43 +1824,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0);
}
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device);
VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device);
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
shader_stages[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shader_stages[0].module = vert_shader;
shader_stages[0].pName = "main";
shader_stages[1].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shader_stages[1].module = frag_shader;
shader_stages[1].pName = "main";
VkVertexInputBindingDescription bindings[1] = {
{
.binding = 0,
.stride = sizeof(struct Vertex),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
},
};
VkVertexInputAttributeDescription attributes[2] = {
{
.binding = 0,
.location = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(struct Vertex, pos),
},
{
.binding = 0,
.location = 1,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(struct Vertex, color),
},
};
Material simple_mesh_material = create_material(context->device, context->swapchain_extent, context->render_pass, 2, shader_stages, context->scene_ubo_layout, 0, 0, 0, 0, 1, bindings, 2, attributes);
Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, context->scene_ubo_layout);
if(simple_mesh_material.pipeline == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create simple mesh material\n");
return 0;
@ -1732,13 +1832,30 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->simple_mesh_material = simple_mesh_material;
}
Mesh triangle_mesh = load_mesh(context->physical_device, context->device, (struct Vertex*)vertices, 6, (uint16_t*)indices, 9, context->transfer_command_pool, context->queues.transfer);
Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, context->scene_ubo_layout);
if(texture_mesh_material.pipeline == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create texture mesh material\n");
return 0;
} else {
context->texture_mesh_material = texture_mesh_material;
}
Mesh triangle_mesh = load_simple_mesh(context->physical_device, context->device, (struct Vertex*)vertices, 4, (uint16_t*)indices, 6, context->transfer_command_pool, context->queues.transfer);
if(triangle_mesh.vertex_buffer.buffer == VK_NULL_HANDLE) {
fprintf(stderr, "failed to load triangle mesh\n");
return 0;
} else {
context->triangle_mesh = triangle_mesh;
}
Mesh triangle_mesh_textured = load_texture_mesh(context->physical_device, context->device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, context->transfer_command_pool, context->queues.transfer);
if(triangle_mesh_textured.vertex_buffer.buffer == VK_NULL_HANDLE) {
fprintf(stderr, "failed to load textured triangle mesh\n");
return 0;
} else {
context->triangle_mesh_textured = triangle_mesh_textured;
}
return context;
}
@ -1937,8 +2054,8 @@ VkResult draw_frame(VulkanContext* context) {
}
uint32_t mesh_counts[] = {1};
Mesh* meshes[] = {&context->triangle_mesh};
result = record_command_buffer_scene(1, &context->simple_mesh_material, (uint32_t*)&mesh_counts, (Mesh**)meshes, context->scene_ubo_descriptors[context->current_frame], context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent);
Mesh* meshes[] = {&context->triangle_mesh_textured};
result = record_command_buffer_scene(1, &context->texture_mesh_material, (uint32_t*)&mesh_counts, (Mesh**)meshes, context->scene_ubo_descriptors[context->current_frame], context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent);
if(result != VK_SUCCESS) {
return result;
}