remove color vertex data, mipmapping
This commit is contained in:
parent
29e2d9db80
commit
ee3a4d6073
15 changed files with 158 additions and 86 deletions
|
@ -121,6 +121,7 @@ void Device::pickPhysicalDevice() {
|
||||||
for (const auto &device : devices) {
|
for (const auto &device : devices) {
|
||||||
if (isDeviceSuitable(device)) {
|
if (isDeviceSuitable(device)) {
|
||||||
physicalDevice = device;
|
physicalDevice = device;
|
||||||
|
msaaSamples = getMaxUsableSampleCount();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +134,21 @@ void Device::pickPhysicalDevice() {
|
||||||
std::cout << "Physical device: " << properties.deviceName << std::endl;
|
std::cout << "Physical device: " << properties.deviceName << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkSampleCountFlagBits Device::getMaxUsableSampleCount() {
|
||||||
|
VkPhysicalDeviceProperties physicalDeviceProperties;
|
||||||
|
vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
|
||||||
|
|
||||||
|
VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
|
||||||
|
if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
|
||||||
|
if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
|
||||||
|
if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
|
||||||
|
if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
|
||||||
|
if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
|
||||||
|
if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
|
||||||
|
|
||||||
|
return VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
void Device::createLogicalDevice() {
|
void Device::createLogicalDevice() {
|
||||||
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
|
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ class Device {
|
||||||
VkSurfaceKHR surface() { return surface_; }
|
VkSurfaceKHR surface() { return surface_; }
|
||||||
VkQueue graphicsQueue() { return graphicsQueue_; }
|
VkQueue graphicsQueue() { return graphicsQueue_; }
|
||||||
VkQueue presentQueue() { return presentQueue_; }
|
VkQueue presentQueue() { return presentQueue_; }
|
||||||
|
VkPhysicalDeviceProperties getProperties() { return properties; }
|
||||||
|
|
||||||
SwapChainSupportDetails getSwapChainSupport() { return querySwapChainSupport(physicalDevice); }
|
SwapChainSupportDetails getSwapChainSupport() { return querySwapChainSupport(physicalDevice); }
|
||||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||||
|
@ -56,11 +57,11 @@ class Device {
|
||||||
VkMemoryPropertyFlags properties,
|
VkMemoryPropertyFlags properties,
|
||||||
VkBuffer &buffer,
|
VkBuffer &buffer,
|
||||||
VkDeviceMemory &bufferMemory);
|
VkDeviceMemory &bufferMemory);
|
||||||
|
|
||||||
VkCommandBuffer beginSingleTimeCommands();
|
VkCommandBuffer beginSingleTimeCommands();
|
||||||
void endSingleTimeCommands(VkCommandBuffer commandBuffer);
|
void endSingleTimeCommands(VkCommandBuffer commandBuffer);
|
||||||
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
|
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
|
||||||
void copyBufferToImage(
|
void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t layerCount);
|
||||||
VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t layerCount);
|
|
||||||
|
|
||||||
void createImageWithInfo(
|
void createImageWithInfo(
|
||||||
const VkImageCreateInfo &imageInfo,
|
const VkImageCreateInfo &imageInfo,
|
||||||
|
@ -86,6 +87,7 @@ class Device {
|
||||||
void hasGflwRequiredInstanceExtensions();
|
void hasGflwRequiredInstanceExtensions();
|
||||||
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
|
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
|
||||||
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
|
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
|
||||||
|
VkSampleCountFlagBits getMaxUsableSampleCount();
|
||||||
|
|
||||||
VkInstance instance;
|
VkInstance instance;
|
||||||
VkDebugUtilsMessengerEXT debugMessenger;
|
VkDebugUtilsMessengerEXT debugMessenger;
|
||||||
|
@ -98,6 +100,8 @@ class Device {
|
||||||
VkQueue graphicsQueue_;
|
VkQueue graphicsQueue_;
|
||||||
VkQueue presentQueue_;
|
VkQueue presentQueue_;
|
||||||
|
|
||||||
|
VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
const std::vector<const char *> validationLayers = {"VK_LAYER_KHRONOS_validation"};
|
const std::vector<const char *> validationLayers = {"VK_LAYER_KHRONOS_validation"};
|
||||||
const std::vector<const char *> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_MAINTENANCE1_EXTENSION_NAME};
|
const std::vector<const char *> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_MAINTENANCE1_EXTENSION_NAME};
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,9 +13,11 @@ namespace xe {
|
||||||
Image::Image(Device &xeDevice, const std::string &filename) : xeDevice{xeDevice} {
|
Image::Image(Device &xeDevice, const std::string &filename) : xeDevice{xeDevice} {
|
||||||
createTextureImage(filename);
|
createTextureImage(filename);
|
||||||
createTextureImageView();
|
createTextureImageView();
|
||||||
|
createTextureSampler();
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::~Image() {
|
Image::~Image() {
|
||||||
|
vkDestroySampler(xeDevice.device(), textureSampler, nullptr);
|
||||||
vkDestroyImage(xeDevice.device(), textureImage, nullptr);
|
vkDestroyImage(xeDevice.device(), textureImage, nullptr);
|
||||||
vkFreeMemory(xeDevice.device(), textureImageMemory, nullptr);
|
vkFreeMemory(xeDevice.device(), textureImageMemory, nullptr);
|
||||||
vkDestroyImageView(xeDevice.device(), textureImageView, nullptr);
|
vkDestroyImageView(xeDevice.device(), textureImageView, nullptr);
|
||||||
|
@ -25,6 +27,7 @@ void Image::createTextureImage(const std::string &filename) {
|
||||||
int texWidth, texHeight, texChannels;
|
int texWidth, texHeight, texChannels;
|
||||||
stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
|
stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
|
||||||
VkDeviceSize imageSize = texWidth * texHeight * 4;
|
VkDeviceSize imageSize = texWidth * texHeight * 4;
|
||||||
|
mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1;
|
||||||
|
|
||||||
if (!pixels) {
|
if (!pixels) {
|
||||||
throw std::runtime_error("failed to load texture: " + filename);
|
throw std::runtime_error("failed to load texture: " + filename);
|
||||||
|
@ -48,15 +51,17 @@ void Image::createTextureImage(const std::string &filename) {
|
||||||
|
|
||||||
stbi_image_free(pixels);
|
stbi_image_free(pixels);
|
||||||
|
|
||||||
createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);
|
createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);
|
||||||
|
|
||||||
transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
copyBufferToImage(stagingBuffer, textureImage, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));
|
copyBufferToImage(stagingBuffer, textureImage, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));
|
||||||
transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
// transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
vkDestroyBuffer(xeDevice.device(), stagingBuffer, nullptr);
|
vkDestroyBuffer(xeDevice.device(), stagingBuffer, nullptr);
|
||||||
vkFreeMemory(xeDevice.device(), stagingBufferMemory, nullptr);
|
vkFreeMemory(xeDevice.device(), stagingBufferMemory, nullptr);
|
||||||
|
|
||||||
|
generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_SRGB, texWidth, texHeight, mipLevels);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
|
void Image::createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
|
||||||
|
@ -67,7 +72,7 @@ void Image::createImage(uint32_t width, uint32_t height, VkFormat format, VkImag
|
||||||
imageInfo.extent.width = width;
|
imageInfo.extent.width = width;
|
||||||
imageInfo.extent.height = height;
|
imageInfo.extent.height = height;
|
||||||
imageInfo.extent.depth = 1;
|
imageInfo.extent.depth = 1;
|
||||||
imageInfo.mipLevels = 1;
|
imageInfo.mipLevels = mipLevels;
|
||||||
imageInfo.arrayLayers = 1;
|
imageInfo.arrayLayers = 1;
|
||||||
imageInfo.format = format;
|
imageInfo.format = format;
|
||||||
imageInfo.tiling = tiling;
|
imageInfo.tiling = tiling;
|
||||||
|
@ -107,7 +112,7 @@ void Image::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout
|
||||||
barrier.image = image;
|
barrier.image = image;
|
||||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
barrier.subresourceRange.baseMipLevel = 0;
|
barrier.subresourceRange.baseMipLevel = 0;
|
||||||
barrier.subresourceRange.levelCount = 1;
|
barrier.subresourceRange.levelCount = mipLevels;
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
barrier.subresourceRange.layerCount = 1;
|
barrier.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
@ -142,6 +147,86 @@ void Image::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout
|
||||||
xeDevice.endSingleTimeCommands(commandBuffer);
|
xeDevice.endSingleTimeCommands(commandBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Image::generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {
|
||||||
|
|
||||||
|
VkCommandBuffer commandBuffer = xeDevice.beginSingleTimeCommands();
|
||||||
|
|
||||||
|
VkImageMemoryBarrier barrier{};
|
||||||
|
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, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
1, &barrier);
|
||||||
|
|
||||||
|
VkImageBlit blit{};
|
||||||
|
blit.srcOffsets[0] = {0, 0, 0};
|
||||||
|
blit.srcOffsets[1] = {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] = {0, 0, 0};
|
||||||
|
blit.dstOffsets[1] = { 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_SHADER_READ_ONLY_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, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
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_SHADER_READ_ONLY_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, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
1, &barrier);
|
||||||
|
|
||||||
|
xeDevice.endSingleTimeCommands(commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
void Image::copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height) {
|
void Image::copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height) {
|
||||||
VkCommandBuffer commandBuffer = xeDevice.beginSingleTimeCommands();
|
VkCommandBuffer commandBuffer = xeDevice.beginSingleTimeCommands();
|
||||||
|
|
||||||
|
@ -173,7 +258,7 @@ void Image::createTextureImageView() {
|
||||||
viewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
viewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||||
viewInfo.subresourceRange.levelCount = 1;
|
viewInfo.subresourceRange.levelCount = mipLevels;
|
||||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
viewInfo.subresourceRange.layerCount = 1;
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
@ -182,4 +267,29 @@ void Image::createTextureImageView() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Image::createTextureSampler() {
|
||||||
|
|
||||||
|
VkSamplerCreateInfo samplerInfo{};
|
||||||
|
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||||
|
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
||||||
|
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||||
|
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerInfo.anisotropyEnable = VK_TRUE;
|
||||||
|
samplerInfo.maxAnisotropy = xeDevice.getProperties().limits.maxSamplerAnisotropy;
|
||||||
|
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||||
|
samplerInfo.unnormalizedCoordinates = VK_FALSE;
|
||||||
|
samplerInfo.compareEnable = VK_FALSE;
|
||||||
|
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||||
|
samplerInfo.minLod = 0.0f;
|
||||||
|
samplerInfo.maxLod = static_cast<float>(mipLevels);
|
||||||
|
samplerInfo.mipLodBias = 0.0f;
|
||||||
|
|
||||||
|
if (vkCreateSampler(xeDevice.device(), &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to create texture sampler!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -21,12 +21,16 @@ class Image {
|
||||||
void createTextureImage(const std::string &filename);
|
void createTextureImage(const std::string &filename);
|
||||||
void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory);
|
void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory);
|
||||||
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout);
|
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout);
|
||||||
|
void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels);
|
||||||
void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height);
|
void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height);
|
||||||
void createTextureImageView();
|
void createTextureImageView();
|
||||||
|
void createTextureSampler();
|
||||||
|
|
||||||
Device &xeDevice;
|
Device &xeDevice;
|
||||||
|
|
||||||
|
uint32_t mipLevels;
|
||||||
VkImage textureImage;
|
VkImage textureImage;
|
||||||
|
VkSampler textureSampler;
|
||||||
VkImageView textureImageView;
|
VkImageView textureImageView;
|
||||||
VkDeviceMemory textureImageMemory;
|
VkDeviceMemory textureImageMemory;
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ void Model::Builder::loadModel(const std::string &filepath) {
|
||||||
indices.clear();
|
indices.clear();
|
||||||
vertexSize = 0;
|
vertexSize = 0;
|
||||||
|
|
||||||
bool vertex, color, normal, uvs;
|
bool vertex, normal, uvs;
|
||||||
|
|
||||||
for (const auto &shape : shapes) {
|
for (const auto &shape : shapes) {
|
||||||
for (const auto &index : shape.mesh.indices) {
|
for (const auto &index : shape.mesh.indices) {
|
||||||
|
@ -127,11 +127,6 @@ void Model::Builder::loadModel(const std::string &filepath) {
|
||||||
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 1]);
|
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 1]);
|
||||||
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 2]);
|
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 2]);
|
||||||
vertex = true;
|
vertex = true;
|
||||||
|
|
||||||
vertexData.push_back(attrib.colors[3 * index.vertex_index + 0]);
|
|
||||||
vertexData.push_back(attrib.colors[3 * index.vertex_index + 1]);
|
|
||||||
vertexData.push_back(attrib.colors[3 * index.vertex_index + 2]);
|
|
||||||
color = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index.normal_index >= 0) {
|
if(index.normal_index >= 0) {
|
||||||
|
@ -152,8 +147,6 @@ void Model::Builder::loadModel(const std::string &filepath) {
|
||||||
|
|
||||||
if(vertex)
|
if(vertex)
|
||||||
vertexSize += 12;
|
vertexSize += 12;
|
||||||
if(color)
|
|
||||||
vertexSize += 12;
|
|
||||||
if(normal)
|
if(normal)
|
||||||
vertexSize += 12;
|
vertexSize += 12;
|
||||||
if(uvs)
|
if(uvs)
|
||||||
|
|
|
@ -18,7 +18,6 @@ RenderSystem::RenderSystem(
|
||||||
pushCunstantDataSize{pushCunstantDataSize},
|
pushCunstantDataSize{pushCunstantDataSize},
|
||||||
uniformBindings{uniformBindings},
|
uniformBindings{uniformBindings},
|
||||||
imageBindings{imageBindings} {
|
imageBindings{imageBindings} {
|
||||||
createTextureSampler();
|
|
||||||
createDescriptorSetLayout();
|
createDescriptorSetLayout();
|
||||||
createUniformBuffers();
|
createUniformBuffers();
|
||||||
createDescriptorSets();
|
createDescriptorSets();
|
||||||
|
@ -28,32 +27,8 @@ RenderSystem::RenderSystem(
|
||||||
|
|
||||||
RenderSystem::~RenderSystem() {
|
RenderSystem::~RenderSystem() {
|
||||||
vkDestroyPipelineLayout(xeDevice.device(), pipelineLayout, nullptr);
|
vkDestroyPipelineLayout(xeDevice.device(), pipelineLayout, nullptr);
|
||||||
vkDestroySampler(xeDevice.device(), textureSampler, nullptr);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void RenderSystem::createTextureSampler() {
|
|
||||||
VkSamplerCreateInfo samplerInfo{};
|
|
||||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
|
||||||
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
|
||||||
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
|
||||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
samplerInfo.anisotropyEnable = VK_FALSE;
|
|
||||||
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
|
||||||
samplerInfo.unnormalizedCoordinates = VK_FALSE;
|
|
||||||
samplerInfo.compareEnable = VK_FALSE;
|
|
||||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
|
||||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
|
||||||
samplerInfo.mipLodBias = 0.0f;
|
|
||||||
samplerInfo.minLod = 0.0f;
|
|
||||||
samplerInfo.maxLod = 0.0f;
|
|
||||||
|
|
||||||
if (vkCreateSampler(xeDevice.device(), &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) {
|
|
||||||
throw std::runtime_error("failed to create texture sampler!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderSystem::createDescriptorSetLayout() {
|
void RenderSystem::createDescriptorSetLayout() {
|
||||||
DescriptorSetLayout::Builder builder{xeDevice};
|
DescriptorSetLayout::Builder builder{xeDevice};
|
||||||
|
|
||||||
|
@ -62,7 +37,7 @@ void RenderSystem::createDescriptorSetLayout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( const auto &[binding, image]: imageBindings) {
|
for ( const auto &[binding, image]: imageBindings) {
|
||||||
builder.addBinding(binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &textureSampler);
|
builder.addBinding(binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &(image->textureSampler));
|
||||||
}
|
}
|
||||||
|
|
||||||
xeDescriptorSetLayout = builder.build();
|
xeDescriptorSetLayout = builder.build();
|
||||||
|
@ -109,7 +84,7 @@ void RenderSystem::updateDescriptorSet(int frameIndex, bool allocate) {
|
||||||
VkDescriptorImageInfo imageInfo{};
|
VkDescriptorImageInfo imageInfo{};
|
||||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
imageInfo.imageView = image->textureImageView;
|
imageInfo.imageView = image->textureImageView;
|
||||||
imageInfo.sampler = textureSampler;
|
imageInfo.sampler = image->textureSampler;
|
||||||
writer.writeImage(binding, &imageInfo);
|
writer.writeImage(binding, &imageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,6 @@ class RenderSystem {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void createTextureSampler();
|
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
void createUniformBuffers();
|
void createUniformBuffers();
|
||||||
void createDescriptorSets();
|
void createDescriptorSets();
|
||||||
|
@ -128,8 +127,6 @@ class RenderSystem {
|
||||||
|
|
||||||
uint32_t pushCunstantDataSize;
|
uint32_t pushCunstantDataSize;
|
||||||
|
|
||||||
VkSampler textureSampler;
|
|
||||||
|
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
std::unique_ptr<Pipeline> xePipeline;
|
std::unique_ptr<Pipeline> xePipeline;
|
||||||
std::unique_ptr<DescriptorPool> &xeDescriptorPool;
|
std::unique_ptr<DescriptorPool> &xeDescriptorPool;
|
||||||
|
|
BIN
res/image/dirt.jpg
Normal file
BIN
res/image/dirt.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
|
@ -23,5 +23,5 @@ layout(push_constant) uniform Push {
|
||||||
} push;
|
} push;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
outColor = mix(texture(texSampler, fragUv), vec4(fragColor, 1.0), .5);
|
outColor = mix(texture(texSampler, fragUv), vec4(fragColor, 1.0), .1);
|
||||||
}
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout (location = 0) in vec3 position;
|
layout (location = 0) in vec3 position;
|
||||||
layout (location = 1) in vec3 color;
|
layout (location = 1) in vec3 normal;
|
||||||
layout (location = 2) in vec3 normal;
|
layout (location = 2) in vec2 uv;
|
||||||
layout (location = 3) in vec2 uv;
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 fragColor;
|
layout (location = 0) out vec3 fragColor;
|
||||||
layout (location = 1) out vec2 fragUv;
|
layout (location = 1) out vec2 fragUv;
|
||||||
|
@ -32,6 +31,6 @@ void main() {
|
||||||
|
|
||||||
float lightIntensity = AMBIENT + max(dot(normalWorldSpace, ubo.directionToLight), 0);
|
float lightIntensity = AMBIENT + max(dot(normalWorldSpace, ubo.directionToLight), 0);
|
||||||
|
|
||||||
fragColor = lightIntensity * vec3(1/position.y,position.y,clamp(sin(position.x - position.z), 0, 1));
|
fragColor = lightIntensity * vec3(1);
|
||||||
fragUv = uv;
|
fragUv = uv;
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ std::shared_ptr<xe::Model> Chunk::getMesh() {
|
||||||
delete chunkMesh.get();
|
delete chunkMesh.get();
|
||||||
xe::Model::Builder builder{};
|
xe::Model::Builder builder{};
|
||||||
builder.vertexData = vertexData;
|
builder.vertexData = vertexData;
|
||||||
builder.vertexSize = 44;
|
builder.vertexSize = 32;
|
||||||
chunkMesh = std::make_shared<xe::Model>(xe::Engine::getInstance()->getDevice(), builder);
|
chunkMesh = std::make_shared<xe::Model>(xe::Engine::getInstance()->getDevice(), builder);
|
||||||
}
|
}
|
||||||
return chunkMesh;
|
return chunkMesh;
|
||||||
|
@ -123,9 +123,6 @@ void Chunk::addVerticies(uint32_t side, uint32_t x, uint32_t y, uint32_t z) {
|
||||||
vertexData.push_back(px[side * 6 + i][0] + x);
|
vertexData.push_back(px[side * 6 + i][0] + x);
|
||||||
vertexData.push_back(px[side * 6 + i][1] + y);
|
vertexData.push_back(px[side * 6 + i][1] + y);
|
||||||
vertexData.push_back(px[side * 6 + i][2] + z);
|
vertexData.push_back(px[side * 6 + i][2] + z);
|
||||||
vertexData.push_back(1.f);
|
|
||||||
vertexData.push_back(1.f);
|
|
||||||
vertexData.push_back(1.f);
|
|
||||||
vertexData.push_back(nm[side][0]);
|
vertexData.push_back(nm[side][0]);
|
||||||
vertexData.push_back(nm[side][1]);
|
vertexData.push_back(nm[side][1]);
|
||||||
vertexData.push_back(nm[side][2]);
|
vertexData.push_back(nm[side][2]);
|
||||||
|
|
|
@ -108,10 +108,10 @@ const float nm[6][3] = {
|
||||||
|
|
||||||
|
|
||||||
const float uv[6][2] = {
|
const float uv[6][2] = {
|
||||||
|
{1.f,1.f},
|
||||||
|
{0.f,1.f},
|
||||||
|
{0.f,0.f},
|
||||||
{0.f,0.f},
|
{0.f,0.f},
|
||||||
{1.f,0.f},
|
|
||||||
{0.f,1.f},
|
|
||||||
{0.f,1.f},
|
|
||||||
{1.f,0.f},
|
{1.f,0.f},
|
||||||
{1.f,1.f}
|
{1.f,1.f}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,8 +11,7 @@ FirstApp::~FirstApp() {}
|
||||||
|
|
||||||
void FirstApp::run() {
|
void FirstApp::run() {
|
||||||
|
|
||||||
std::shared_ptr<xe::Image> image = xeEngine.loadImageFromFile("res/image/texture.png");
|
std::shared_ptr<xe::Image> image = xeEngine.loadImageFromFile("res/image/dirt.jpg");
|
||||||
std::shared_ptr<xe::Image> image2 = xeEngine.loadImageFromFile("res/image/scaly.png");
|
|
||||||
|
|
||||||
SimpleRenderer renderer{xeEngine, image.get()};
|
SimpleRenderer renderer{xeEngine, image.get()};
|
||||||
|
|
||||||
|
@ -33,7 +32,7 @@ void FirstApp::run() {
|
||||||
xeEngine.getCamera().setViewYXZ(viewerObject.transform.translation, viewerObject.transform.rotation);
|
xeEngine.getCamera().setViewYXZ(viewerObject.transform.translation, viewerObject.transform.rotation);
|
||||||
|
|
||||||
if(xeEngine.beginFrame()) {
|
if(xeEngine.beginFrame()) {
|
||||||
renderer.render(gameObjects, xeEngine.getCamera(), image2.get());
|
renderer.render(gameObjects, xeEngine.getCamera(), image.get());
|
||||||
xeEngine.endFrame();
|
xeEngine.endFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,27 +45,13 @@ void FirstApp::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FirstApp::loadGameObjects() {
|
void FirstApp::loadGameObjects() {
|
||||||
std::shared_ptr<xe::Model> xeModel = xeEngine.loadModelFromFile("res/models/stanford-dragon.obj");
|
|
||||||
|
|
||||||
auto dragon = xe::GameObject::createGameObject();
|
|
||||||
dragon.model = xeModel;
|
|
||||||
dragon.transform.translation = {.0f, .0f, 2.5f};
|
|
||||||
dragon.transform.scale = {.5f, .5f, .5f};
|
|
||||||
gameObjects.push_back(std::move(dragon));
|
|
||||||
|
|
||||||
auto dragon2 = xe::GameObject::createGameObject();
|
|
||||||
dragon2.model = xeModel;
|
|
||||||
dragon2.transform.translation = {5.0f, .0f, -1.5f};
|
|
||||||
dragon2.transform.rotation.y = glm::radians(90.f);
|
|
||||||
dragon2.transform.scale = {.35f, .35f, .35f};
|
|
||||||
gameObjects.push_back(std::move(dragon2));
|
|
||||||
|
|
||||||
Chunk* chunk = Chunk::newChunk(0, 0, 123);
|
Chunk* chunk = Chunk::newChunk(0, 0, 123);
|
||||||
chunk->createMesh();
|
chunk->createMesh();
|
||||||
|
|
||||||
auto chunkObject = xe::GameObject::createGameObject();
|
auto chunkObject = xe::GameObject::createGameObject();
|
||||||
chunkObject.model = chunk->getMesh();
|
chunkObject.model = chunk->getMesh();
|
||||||
chunkObject.transform.translation = {5.f, 5.f, 5.f};
|
chunkObject.transform.translation = {0.f, 0.f, 0.f};
|
||||||
gameObjects.push_back(std::move(chunkObject));
|
gameObjects.push_back(std::move(chunkObject));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,9 @@ namespace app {
|
||||||
SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, xe::Image *xeImage) {
|
SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, xe::Image *xeImage) {
|
||||||
xeRenderSystem = xe::RenderSystem::Builder(xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv")
|
xeRenderSystem = xe::RenderSystem::Builder(xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv")
|
||||||
.addVertexBinding(0, 3, 0) // position
|
.addVertexBinding(0, 3, 0) // position
|
||||||
.addVertexBinding(1, 3, 12) // color
|
.addVertexBinding(1, 3, 12) // normal
|
||||||
.addVertexBinding(2, 3, 24) // normal
|
.addVertexBinding(2, 2, 24) // uvs
|
||||||
.addVertexBinding(3, 2, 36) // uvs
|
.setVertexSize(32)
|
||||||
.setVertexSize(sizeof(Vertex))
|
|
||||||
.addPushConstant(sizeof(PushConstant))
|
.addPushConstant(sizeof(PushConstant))
|
||||||
.addUniformBinding(0, sizeof(UniformBuffer))
|
.addUniformBinding(0, sizeof(UniformBuffer))
|
||||||
.addTextureBinding(1, xeImage)
|
.addTextureBinding(1, xeImage)
|
||||||
|
|
|
@ -16,13 +16,6 @@ struct PushConstant {
|
||||||
alignas(16) glm::mat4 normalMatrix{1.f};
|
alignas(16) glm::mat4 normalMatrix{1.f};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vertex {
|
|
||||||
glm::vec3 position;
|
|
||||||
glm::vec3 color;
|
|
||||||
glm::vec3 normal;
|
|
||||||
glm::vec2 uv;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SimpleRenderer {
|
class SimpleRenderer {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue