summaryrefslogtreecommitdiffstats
path: root/src/render.c
diff options
context:
space:
mode:
authorgramanas <anastasis.gramm2@gmail.com>2024-05-31 21:00:57 +0300
committergramanas <anastasis.gramm2@gmail.com>2024-05-31 21:00:57 +0300
commita5a82709028c475d0ff6cd54f6d07f16375e156e (patch)
treedb1386b3e5af7075ee6e5c45c3a4964cdecdc9d2 /src/render.c
parent1f6538bcaf379cb3fe257a0053e4e7567f8ddb98 (diff)
downloadcgame-a5a82709028c475d0ff6cd54f6d07f16375e156e.tar.gz
cgame-a5a82709028c475d0ff6cd54f6d07f16375e156e.tar.bz2
cgame-a5a82709028c475d0ff6cd54f6d07f16375e156e.zip
Allaboard
Diffstat (limited to 'src/render.c')
-rw-r--r--src/render.c518
1 files changed, 435 insertions, 83 deletions
diff --git a/src/render.c b/src/render.c
index b6383c4..db3c168 100644
--- a/src/render.c
+++ b/src/render.c
@@ -1,4 +1,7 @@
+
+#include <emmintrin.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
#include <time.h>
@@ -22,48 +25,25 @@
#define VKSETUP_IMPLEMENTATION
#include "vksetup.h"
+#define FAST_OBJ_IMPLEMENTATION
+#include "../lib/fast_obj.h"
+
+#define CGLTF_IMPLEMENTATION
+#include "../lib/cgltf.h"
+
//#include "cplusplus.h"
-#include "vkutil.h"
+//#include "vkutil.h"
#include "state.h"
+#define MODEL_PATH "assets/human.obj"
+#define TEXTURE_PATH "assets/viking_room.png"
+
+void load_model_obj();
+
// embedded clgm library
uint32_t currentFrame = 0;
state_t s;
-const char *const validation_layers[] = {
- "VK_LAYER_KHRONOS_validation"
-};
-const uint32_t validation_layer_count = VK_ARRAY_LEN(validation_layers);
-
-const char *const device_extensions[] = {
- VK_KHR_SWAPCHAIN_EXTENSION_NAME,
-};
-const uint32_t deviceExtensionCount = VK_ARRAY_LEN(device_extensions);
-
-
-#ifdef VKDEBUG
- const bool enableValidationLayers = true;
-#else
- const bool enableValidationLayers = false;
-#endif
-
-typedef struct {
- float x;
- float y;
-} V2;
-
-typedef struct {
- float x;
- float y;
- float z;
-} V3;
-
-typedef struct {
- V3 pos;
- V3 color;
- V2 texCoord;
-} Vertex;
-
/* Vertex vertices[] = { */
/* (Vertex) { (V2) {-0.2f, -0.5f}, (V3) {0.0f, 1.0f, 0.0f}}, */
/* (Vertex) { (V2) {0.5f, 0.3f}, (V3) {0.0f, 0.0f, 1.0f}}, */
@@ -97,7 +77,7 @@ Vertex vertices[] = {
};
const int VERTICES_SIZE = VK_ARRAY_LEN(vertices);
-const uint16_t indices[] = {
+const uint32_t indices[] = {
0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 5, 4
};
const int INDICES_SIZE = VK_ARRAY_LEN(indices);
@@ -117,7 +97,8 @@ const int INDICES_SIZE = VK_ARRAY_LEN(indices);
/* }; */
/* const int INDICES_SIZE = VK_ARRAY_LEN(indices); */
-static int resizing_event_watcher(void* data, SDL_Event* event) {
+static int resizing_event_watcher(void *data, SDL_Event *event) {
+ (void) data;
if (event->type == SDL_WINDOWEVENT &&
event->window.event == SDL_WINDOWEVENT_RESIZED) {
s.sdl_window_resized = 1;
@@ -180,6 +161,9 @@ debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
{
+ (void) messageSeverity;
+ (void) messageType;
+ (void) pUserData;
vk_log(VK_ERROR, "validation layer: %s\n", pCallbackData->pMessage);
return VK_FALSE;
}
@@ -527,7 +511,6 @@ void
mouseCallback(SDL_Event *event)
{
if (event->type != SDL_MOUSEMOTION) return;
- if (!s.mouse_pressed) return;
float xoffset = event->motion.xrel;
float yoffset = -event->motion.yrel; // Reversed since y-coordinates range from bottom to top
@@ -535,7 +518,20 @@ mouseCallback(SDL_Event *event)
xoffset *= sensitivity;
yoffset *= sensitivity;
- update_camera(xoffset, yoffset);
+ if (s.mouse_pressed) {
+ update_camera(xoffset, yoffset);
+ } else if (s.middle_click) {
+ vec4 _up = {0, 1, 0, 0};
+ vec4 _right = {1, 0, 0, 0};
+
+ vec4 up, right;
+ glm_mat4_mulv(s.ubo.model, _up, up);
+ glm_mat4_mulv(s.ubo.model, _right, right);
+
+ glm_rotate(s.ubo.model, glm_rad(xoffset * glm_rad(90.0f)), GLM_ZUP);
+ glm_rotate(s.ubo.model, glm_rad(yoffset * glm_rad(90.0f)), GLM_XUP);
+ }
+ return;
}
void
@@ -612,7 +608,7 @@ vulkan_create_swap_chain()
VkImageView
-create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
+create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels)
{
VkImageViewCreateInfo viewInfo = {0};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -621,7 +617,7 @@ create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags
viewInfo.format = format;
viewInfo.subresourceRange.aspectMask = aspectFlags;
viewInfo.subresourceRange.baseMipLevel = 0;
- viewInfo.subresourceRange.levelCount = 1;
+ viewInfo.subresourceRange.levelCount = mipLevels;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
@@ -635,7 +631,7 @@ void
vulkan_create_image_views()
{
for (size_t i = 0; i < s.vk_swap_chain_image_count; i++) {
- s.vk_swap_chain_image_views[i] = create_image_view(s.vk_swap_chain_images[i], s.vk_swap_chain_image_format, VK_IMAGE_ASPECT_COLOR_BIT);
+ s.vk_swap_chain_image_views[i] = create_image_view(s.vk_swap_chain_images[i], s.vk_swap_chain_image_format, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}
vk_log(VK_INFO, "Vulkan image views created!\n");
}
@@ -725,7 +721,7 @@ findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
}
void
-createImage(uint32_t width, uint32_t height, VkFormat format,
+createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkFormat format,
VkImageTiling tiling, VkImageUsageFlags usage,
VkMemoryPropertyFlags properties, VkImage *image,
VkDeviceMemory *imageMemory)
@@ -736,7 +732,7 @@ createImage(uint32_t width, uint32_t height, VkFormat format,
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
- imageInfo.mipLevels = 1;
+ imageInfo.mipLevels = mipLevels;
imageInfo.arrayLayers = 1;
imageInfo.format = format;
imageInfo.tiling = tiling;
@@ -807,7 +803,7 @@ void
transitionImageLayout(VkImage image, VkFormat format,
VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
- VkImageLayout oldLayout, VkImageLayout newLayout)
+ VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels)
{
VkCommandBuffer commandBuffer = beginSingleTimeCommands();
@@ -833,7 +829,7 @@ transitionImageLayout(VkImage image, VkFormat format,
}
barrier.subresourceRange.baseMipLevel = 0;
- barrier.subresourceRange.levelCount = 1;
+ barrier.subresourceRange.levelCount = mipLevels;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
@@ -880,18 +876,18 @@ void
vulkan_create_depth_resources()
{
VkFormat depthFormat = findDepthFormat();
- createImage(s.vk_swap_chain_extent.width, s.vk_swap_chain_extent.height,
+ createImage(s.vk_swap_chain_extent.width, s.vk_swap_chain_extent.height, 1,
depthFormat, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&s.vk_depth_image, &s.vk_depth_image_memory);
s.vk_depth_image_view = create_image_view(s.vk_depth_image, depthFormat,
- VK_IMAGE_ASPECT_DEPTH_BIT);
+ VK_IMAGE_ASPECT_DEPTH_BIT, 1);
transitionImageLayout(s.vk_depth_image, depthFormat,
VK_ACCESS_NONE, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1);
}
void
@@ -1013,7 +1009,7 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode)
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_NONE;
//rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
- //rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
@@ -1159,7 +1155,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex)
s.vk_swap_chain_images[imageIndex], VK_FORMAT_R8G8B8A8_SRGB, 0,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1);
VkRenderingAttachmentInfo colorAttachment = {0};
colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
@@ -1168,7 +1164,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex)
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.clearValue.color =
- (VkClearColorValue){0.0f, 0.0f, 0.0f, 1.0f};
+ (VkClearColorValue){{0.0f, 0.0f, 0.0f, 1.0f}};
VkRenderingAttachmentInfo depthAttachment = {0};
depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
@@ -1210,13 +1206,13 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex)
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, s.vk_index_buffer, 0,
- VK_INDEX_TYPE_UINT16);
+ VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
s.vk_pipeline_layout, 0, 1,
&s.frames[currentFrame].vk_descriptor_set, 0, NULL);
- vkCmdDrawIndexed(commandBuffer, INDICES_SIZE, 1, 0, 0, 0);
+ vkCmdDrawIndexed(commandBuffer, s.indices_count, 1, 0, 0, 0);
vkCmdEndRendering(commandBuffer);
transitionImageLayout(s.vk_swap_chain_images[imageIndex],
@@ -1225,7 +1221,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex)
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 1);
VK_CHECK(vkEndCommandBuffer(commandBuffer));
}
@@ -1288,7 +1284,8 @@ void copy_buffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
void
vulkan_create_vertex_buffer()
{
- VkDeviceSize bufferSize = sizeof(vertices[0]) * VERTICES_SIZE;
+ VkDeviceSize bufferSize = sizeof(s.vertices[0]) * s.vertices_count;
+ /* VkDeviceSize bufferSize = sizeof(vertices[0]) * VERTICES_SIZE; */
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
@@ -1300,7 +1297,8 @@ vulkan_create_vertex_buffer()
void* data;
VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data));
- memcpy(data, vertices, (size_t) bufferSize);
+ // memcpy(data, vertices, (size_t) bufferSize);
+ memcpy(data, s.vertices, (size_t) bufferSize);
vkUnmapMemory(s.vk_device, stagingBufferMemory);
createBuffer(bufferSize,
@@ -1317,7 +1315,8 @@ vulkan_create_vertex_buffer()
void
vulkan_create_index_buffer()
{
- VkDeviceSize bufferSize = sizeof(indices[0]) * INDICES_SIZE;
+ VkDeviceSize bufferSize = sizeof(s.indices[0]) * s.indices_count;
+ /* VkDeviceSize bufferSize = sizeof(indices[0]) * INDICES_SIZE; */
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
@@ -1329,7 +1328,8 @@ vulkan_create_index_buffer()
void* data;
VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data));
- memcpy(data, indices, (size_t) bufferSize);
+ memcpy(data, s.indices, (size_t) bufferSize);
+ /* memcpy(data, indices, (size_t) bufferSize); */
vkUnmapMemory(s.vk_device, stagingBufferMemory);
createBuffer(bufferSize,
@@ -1544,6 +1544,25 @@ handle_input(bool * quit)
case SDLK_l:
s.rotate = s.rotate ? 0 : 1;
break;
+ case SDLK_m:
+ vkDeviceWaitIdle(s.vk_device);
+ free(s.vertices);
+ free(s.indices);
+ if (!strcmp(s.model_path, "assets/human.obj"))
+ strcpy(s.model_path, "assets/viking_room.obj");
+ else if (!strcmp(s.model_path, "assets/viking_room.obj"))
+ strcpy(s.model_path, "assets/test.obj");
+ else
+ strcpy(s.model_path, "assets/human.obj");
+ load_model_obj();
+ vkDestroyBuffer(s.vk_device, s.vk_vertex_buffer, NULL);
+ vkFreeMemory(s.vk_device, s.vk_vertex_buffer_memory, NULL);
+
+ vkDestroyBuffer(s.vk_device, s.vk_index_buffer, NULL);
+ vkFreeMemory(s.vk_device, s.vk_index_buffer_memory, NULL);
+ vulkan_create_vertex_buffer();
+ vulkan_create_index_buffer();
+ break;
case SDLK_r:
s.camera.pos[0] = 1.0f;
s.camera.pos[1] = 1.0f;
@@ -1562,6 +1581,10 @@ handle_input(bool * quit)
s.camera.lastX = 400.0f;
s.camera.lastY = 300.0f;
s.camera.fov = 45.0f;
+
+ glm_mat4_identity(s.ubo.model);
+
+ s.zoom = 10;
update_camera(0,0);
break;
}
@@ -1569,19 +1592,28 @@ handle_input(bool * quit)
else if (e.type == SDL_MOUSEWHEEL) {
if(e.wheel.y > 0) // scroll up
{
- s.zoom += 1;
+ s.zoom -= 1;
}
else if(e.wheel.y < 0) // scroll down
{
- s.zoom -= 1;
+ s.zoom += 1;
if (s.zoom == -100) s.zoom = 1;
}
}
else if (e.type == SDL_MOUSEBUTTONDOWN) {
- s.mouse_pressed = 1;
+ if (e.button.button != 2) {
+ s.mouse_pressed = 1;
+ } else {
+ s.middle_click = 1;
+ }
+
}
else if (e.type == SDL_MOUSEBUTTONUP) {
- s.mouse_pressed = 0;
+ if (e.button.button != 2) {
+ s.mouse_pressed = 0;
+ } else {
+ s.middle_click = 0;
+ }
}
mouseCallback(&e);
}
@@ -1617,13 +1649,88 @@ copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width,
endSingleTimeCommands(commandBuffer);
}
+void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {
+ VkCommandBuffer commandBuffer = beginSingleTimeCommands();
+
+ VkImageMemoryBarrier barrier = {0};
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.image = image;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = 1;
+ barrier.subresourceRange.levelCount = 1;
+
+ int32_t mipWidth = texWidth;
+ int32_t mipHeight = texHeight;
+
+ for (uint32_t i = 1; i < mipLevels; i++) {
+ barrier.subresourceRange.baseMipLevel = i - 1;
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+
+ vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1,
+ &barrier);
+
+ VkImageBlit blit = {0};
+ blit.srcOffsets[0] = (VkOffset3D){ 0, 0, 0 };
+ blit.srcOffsets[1] = (VkOffset3D){ mipWidth, mipHeight, 1 };
+ blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ blit.srcSubresource.mipLevel = i - 1;
+ blit.srcSubresource.baseArrayLayer = 0;
+ blit.srcSubresource.layerCount = 1;
+ blit.dstOffsets[0] = (VkOffset3D){ 0, 0, 0 };
+ blit.dstOffsets[1] = (VkOffset3D){ mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 };
+ blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ blit.dstSubresource.mipLevel = i;
+ blit.dstSubresource.baseArrayLayer = 0;
+ blit.dstSubresource.layerCount = 1;
+
+ vkCmdBlitImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
+ VK_FILTER_LINEAR);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+ vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0,
+ NULL, 1, &barrier);
+
+ if (mipWidth > 1) mipWidth /= 2;
+ if (mipHeight > 1) mipHeight /= 2;
+ }
+
+ /* barrier.subresourceRange.baseMipLevel = mipLevels - 1; */
+ /* barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; */
+ /* barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; */
+ /* barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; */
+ /* barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; */
+
+ /* vkCmdPipelineBarrier(commandBuffer, */
+ /* VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, */
+ /* 0, NULL, */
+ /* 0, NULL, */
+ /* 1, &barrier); */
+
+ endSingleTimeCommands(commandBuffer);
+}
+
void
vulkan_create_texture_image()
{
int texWidth, texHeight, texChannels;
- stbi_uc* pixels = stbi_load("assets/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
+ stbi_uc* pixels = stbi_load(TEXTURE_PATH, &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
VkDeviceSize imageSize = texWidth * texHeight * 4;
+ s.vk_mip_levels = (uint32_t)floor(log2(fmax(texWidth, texHeight))) + 1;
+
if (!pixels) {
vk_log(VK_ERROR, "failed to load texture image!\n");
}
@@ -1639,9 +1746,9 @@ vulkan_create_texture_image()
stbi_image_free(pixels);
- createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB,
+ createImage(texWidth, texHeight, s.vk_mip_levels, VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vk_texture_image,
&s.vk_texture_image_memory);
@@ -1649,15 +1756,16 @@ vulkan_create_texture_image()
s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, s.vk_mip_levels);
copyBufferToImage(stagingBuffer, s.vk_texture_image, (uint32_t)texWidth,
(uint32_t)texHeight);
+ generateMipmaps(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, texWidth, texHeight, s.vk_mip_levels);
transitionImageLayout(
s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, s.vk_mip_levels);
vkDestroyBuffer(s.vk_device, stagingBuffer, NULL);
vkFreeMemory(s.vk_device, stagingBufferMemory, NULL);
@@ -1666,7 +1774,7 @@ vulkan_create_texture_image()
void
vulkan_create_texture_image_view()
{
- s.vk_texture_image_view = create_image_view(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
+ s.vk_texture_image_view = create_image_view(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, s.vk_mip_levels);
}
void vulkan_create_texture_sampler() {
@@ -1690,12 +1798,235 @@ void vulkan_create_texture_sampler() {
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
- samplerInfo.maxLod = 0.0f;
+ samplerInfo.maxLod = VK_LOD_CLAMP_NONE;
VK_CHECK(vkCreateSampler(s.vk_device, &samplerInfo, NULL, &s.vk_texture_sampler));
}
void
+load_model_obj()
+{
+ fastObjMesh *m = fast_obj_read(s.model_path);
+
+ if (!m) {
+ vk_log(VK_ERROR, "Can't load object\n");
+ }
+
+ s.indices_count = m->index_count;
+ s.indices = (uint32_t *)malloc(s.indices_count * sizeof(uint32_t));
+ s.vertices_count = 0;
+
+ if (m->group_count > 1) {
+ vk_log(VK_WARN, "fast_obj Mesh with groups > 1 not supported.");
+ }
+
+ /*
+ Since blender exports objs indexed we use those same indices for our
+ indexed draw call.
+ */
+
+ /* Count indexs and vertices */
+ size_t c = 0;
+ for (size_t ii = 0; ii < m->group_count; ii++) {
+ const fastObjGroup *grp = &m->groups[ii];
+ for (unsigned int jj = 0; jj < grp->face_count; jj++) {
+ unsigned int fv = m->face_vertices[grp->face_offset + jj];
+ for (unsigned int kk = 0; kk < fv; kk++) {
+ /* position index */
+ uint32_t mip = m->indices[grp->index_offset + c].p - 1; /* make index start from zero */
+
+ /* flag if we've seen the index*/
+ int index_seen = 0;
+ for (size_t i = 0; i < c; i++) {
+ if (mip == s.indices[i]) {
+ index_seen = 1;
+ break;
+ }
+ }
+ s.indices[c] = mip;
+ if (!index_seen) {
+ /* If not seen, incremet vertices */
+ s.vertices_count++;
+ }
+ c++;
+ }
+ }
+ }
+
+ printf("vertex count %ld!!!!!!!!!!!!!!!!!!\n", s.vertices_count);
+ s.vertices = (Vertex *)malloc(s.vertices_count * sizeof(Vertex));
+
+ /* for (size_t i = 0; i < s.indices_count; i++) { */
+ /* uint32_t mip = s.indices[i]; */
+ /* int index_seen = 0; */
+ /* for (size_t j = 0; j < i; j++) { */
+ /* if (mip == s.indices[j]) { */
+ /* index_seen = 1; */
+ /* break; */
+ /* } */
+ /* } */
+ /* if (!index_seen) { */
+ /* s.vertices[mip].pos.x = m->positions[3 * (mip + 1) + 0]; */
+ /* s.vertices[mip].pos.y = m->positions[3 * (mip + 1) + 1]; */
+ /* s.vertices[mip].pos.z = m->positions[3 * (mip + 1) + 2]; */
+ /* } */
+ /* } */
+
+ for (size_t ii = 0; ii < m->group_count; ii++) {
+ const fastObjGroup *grp = &m->groups[ii];
+ size_t idx = 0;
+ for (unsigned int jj = 0; jj < grp->face_count; jj++) {
+ unsigned int fv = m->face_vertices[grp->face_offset + jj];
+ for (unsigned int kk = 0; kk < fv; kk++) {
+ fastObjIndex mi = m->indices[grp->index_offset + idx];
+
+ int flag = 0;
+ for (size_t i = 0; i < idx; i++) {
+ /* if it exists */
+ if (mi.p - 1 == s.indices[i]) {
+ flag = 1;
+ break;
+ }
+ }
+ if (!flag) {
+ int index = mi.p - 1; /* zero indexed */
+ if (mi.p) {
+ s.vertices[index].pos.x = m->positions[3 * mi.p + 0];
+ s.vertices[index].pos.y = m->positions[3 * mi.p + 1];
+ s.vertices[index].pos.z = m->positions[3 * mi.p + 2];
+ }
+ if (mi.t) {
+ s.vertices[index].texCoord.x = m->texcoords[2 * mi.t + 0];
+ s.vertices[index].texCoord.y = 1.0f - m->texcoords[2 * mi.t + 1];
+ }
+ if (mi.n) {
+ s.vertices[index].color.x = m->normals[3 * mi.n + 0];
+ s.vertices[index].color.y = m->normals[3 * mi.n + 1];
+ s.vertices[index].color.z = m->normals[3 * mi.n + 2];
+ }
+ }
+ idx++;
+ }
+ }
+ }
+
+ fast_obj_destroy(m);
+}
+
+void load_model_gltf() {
+ // TODO maybe copy the raylib implemenetation
+ /*
+ RESTRICTIONS:
+ - Only triangle meshes supported
+ - Vertex attribute types and formats supported:
+ > Vertices (position): vec3: float
+ > Normals: vec3: float
+ > Texcoords: vec2: float
+ > Colors: vec4: u8, u16, f32 (normalized)
+ > Indices: u16, u32 (truncated to u16)
+ - Node hierarchies or transforms not supported
+ */
+
+ /* cgltf_options options; */
+ /* memset(&options, 0, sizeof(cgltf_options)); */
+ /* cgltf_data* data = NULL; */
+ /* cgltf_result result = cgltf_parse_file(&options, MODEL_PATH, &data); */
+
+ /* if (result == cgltf_result_success) */
+ /* result = cgltf_load_buffers(&options, data, MODEL_PATH); */
+
+ /* if (result == cgltf_result_success) */
+ /* result = cgltf_validate(data); */
+
+ /* if (data->meshes_count < 1) { */
+ /* cgltf_free(data); */
+ /* return; */
+ /* } */
+
+ /* int idx = 0; */
+ /* int meshIndex = 0; */
+ /* for (unsigned int i = 0, meshIndex = 0; i < data->meshes_count; i++) { */
+ /* for (unsigned int p = 0; p < data->meshes[i].primitives_count; p++) { */
+ /* // NOTE: We only support primitives defined by triangles */
+ /* // Other alternatives: points, lines, line_strip, triangle_strip */
+ /* if (data->meshes[i].primitives[p].type != cgltf_primitive_type_triangles) continue; */
+
+ /* // NOTE: Attributes data could be provided in several data formats (8, 8u, 16u, 32...), */
+ /* // Only some formats for each attribute type are supported, read info at the top of this function! */
+
+ /* for (unsigned int j = 0; j < data->meshes[i].primitives[p].attributes_count; j++) { */
+ /* // Check the different attributes for every primitive */
+ /* if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_position) { // POSITION, vec3, float */
+ /* cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data; */
+
+ /* // WARNING: SPECS: POSITION accessor MUST have its min and max properties defined */
+
+ /* if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f)) { */
+ /* // Init raylib mesh vertices to copy glTF attribute data */
+ /* s.vertices_count = attribute->count / 3; */
+ /* s.vertices = calloc(attribute->count, attribute->count*sizeof(Vertex)); */
+
+ /* size_t float_count = cgltf_accessor_unpack_floats(attribute, NULL, 0); */
+ /* printf("This many floats: %ld\n", float_count); */
+ /* float floats[float_count] = {}; */
+ /* cgltf_accessor_unpack_floats(attribute, floats, float_count); */
+
+ /* for (unsigned int k = 0; k < attribute->count + 3; k+=3) { */
+ /* s.vertices[idx].pos.x = floats[k + 0]; */
+ /* s.vertices[idx].pos.y = floats[k + 1]; */
+ /* s.vertices[idx].pos.z = floats[k + 2]; */
+ /* //s.indices[idx] = idx; */
+ /* idx++; */
+ /* } */
+ /* // Load 3 components of float data type into mesh.vertices */
+ /* } */
+ /* } */
+ /* } */
+ /* if (data->meshes[i].primitives[p].indices != NULL) { */
+ /* printf("THERE ARE INDIXCES!!!\n"); */
+ /* cgltf_accessor *attribute = data->meshes[i].primitives[p].indices; */
+
+ /* s.indices_count = attribute->count / 3; */
+ /* s.indices = calloc(attribute->count, attribute->count*sizeof(uint32_t)); */
+
+ /* if (attribute->component_type == cgltf_component_type_r_16u) { */
+ /* size_t float_count = cgltf_accessor_unpack_indices(attribute, NULL, 0, 0); */
+ /* printf("This many floats: %ld\n", float_count); */
+ /* uint16_t floats[float_count] = {}; */
+ /* cgltf_accessor_unpack_indices(attribute, floats, float_count, */
+ /* float_count); */
+
+ /* for (int x = 0; x < float_count; x++) { */
+ /* printf("%d \n", floats[x]); */
+ /* } */
+
+ /* } */
+ /* else if (attribute->component_type == cgltf_component_type_r_32u) { */
+ /* printf("ASDASDASDAS2222222!\n"); */
+ /* // Init raylib mesh indices to copy glTF attribute data */
+ /* /\* model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short)); *\/ */
+
+ /* /\* // Load data into a temp buffer to be converted to raylib data type *\/ */
+ /* /\* unsigned int *temp = malloc(attribute->count*sizeof(unsigned int)); *\/ */
+ /* /\* LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp); *\/ */
+
+ /* /\* // Convert data to raylib indices data type (unsigned short) *\/ */
+ /* /\* for (unsigned int d = 0; d < attribute->count; d++) model.meshes[meshIndex].indices[d] = (unsigned short)temp[d]; *\/ */
+
+ /* //free(temp); */
+ /* } */
+ /* } */
+ /* } */
+ /* } */
+
+ /* for (int i = 0; i < s.vertices_count; i++) { */
+ /* printf("%d: %f %f %f\n",i, s.vertices[i].pos.x, s.vertices[i].pos.y, s.vertices[i].pos.z); */
+ /* } */
+
+ /* cgltf_free(data); */
+}
+
+void
init_vulkan()
{
vk_log(VK_WARN, "====================================\n");
@@ -1704,8 +2035,8 @@ init_vulkan()
//vulkan_create_instance();
s.vk_instance =
- vksetup_create_instance(enableValidationLayers, validation_layers,
- validation_layer_count, s.sdl_window);
+ vks_create_instance(enableValidationLayers, validation_layers,
+ validation_layer_count, s.sdl_window);
// vulkan_setup_debug_messenger();
vulkan_create_surface();
vulkan_pick_physical_device();
@@ -1719,6 +2050,8 @@ init_vulkan()
vulkan_create_texture_image();
vulkan_create_texture_image_view();
vulkan_create_texture_sampler();
+ load_model_obj();
+ //load_model_gltf();
vulkan_create_vertex_buffer();
vulkan_create_index_buffer();
vulkan_create_uniform_buffers();
@@ -1777,6 +2110,9 @@ close_vulkan()
if (s.prev_frag_result) {
shaderc_result_release(s.prev_frag_result);
}
+
+ free(s.vertices);
+ free(s.indices);
}
float
@@ -1798,24 +2134,28 @@ current_time()
}
void
-updateUniformBuffer(uint32_t currentImage)
+updateUniformBuffer(uint32_t currentImage, float dt)
{
- float time = current_time();
-
UniformBufferObject ubo = {0};
+ ubo.time = current_time();
+ ubo.dt = dt;
+
ubo.resolution[0] = s.vk_swap_chain_extent.width;
ubo.resolution[1] = s.vk_swap_chain_extent.height;
- glm_mat4_identity(ubo.model);
+ //glm_mat4_identity(ubo.model);
+ glm_mat4_dup(s.ubo.model, ubo.model);
+
+ if (s.rotate)
+ glm_rotate(ubo.model, glm_rad(30 * dt * glm_rad(90.0f)), GLM_ZUP);
- if (!s.rotate)
- glm_rotate(ubo.model, glm_rad(50 * time * glm_rad(90.0f)), GLM_ZUP);
+ glm_mat4_dup(ubo.model, s.ubo.model);
- vec3 eye = GLM_VEC3_ONE_INIT;
- vec3 center = GLM_VEC3_ZERO_INIT;
+ /* vec3 eye = GLM_VEC3_ONE_INIT; */
+ /* vec3 center = GLM_VEC3_ZERO_INIT; */
-// vk_log(VK_INFO, "{%.2f, %.2f, %.2f}\n", s.camera.front[0], s.camera.front[1], s.camera.front[2]);
+ // vk_log(VK_INFO, "{%.2f, %.2f, %.2f}\n", s.camera.front[0], s.camera.front[1], s.camera.front[2]);
/* glm_vec3_add(s.camera.pos, s.camera.front, center); */
glm_lookat(s.camera.pos, s.camera.front, s.camera.up, ubo.view);
@@ -1830,8 +2170,15 @@ updateUniformBuffer(uint32_t currentImage)
memcpy(s.frames[currentImage].vk_uniform_buffer_mapped, &ubo, sizeof(ubo));
}
+float prev_time = 0;
+
void
draw_frame() {
+ float time = current_time();
+
+ float dt = time - prev_time;
+
+
vkWaitForFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence, VK_TRUE, UINT64_MAX);
uint32_t imageIndex;
@@ -1844,7 +2191,7 @@ draw_frame() {
vk_log(VK_ERROR, "failed to acquire swap chain image!\n");
}
- updateUniformBuffer(currentFrame);
+ updateUniformBuffer(currentFrame, dt);
vkResetFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence);
@@ -1892,11 +2239,16 @@ draw_frame() {
}
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
+
+ prev_time = time;
}
int
-main(int argc, char* args[])
+main(int argc, char* argv[])
{
+ (void) argc;
+ (void)argv;
+
init_state(&s);
if (!init()) {
vk_log(VK_INFO, "Failed to initialize!\n");