在 Vulkan 中使用 SDL_image 作为纹理时的意外行为
unexpected behavior while using SDL_image for texture in Vulkan
我设法加载了 jpg 图像并将它们用作 vulkan 中的纹理,但是不同的图像会产生不同的结果,有些图像效果很好,有些图像映射得不好。
这里是图片加载和格式转换相关的代码块:-
void Vulkan::createTextureImage()
{
SDL_Surface *tempImg;
SDL_RWops *rwop;
rwop = SDL_RWFromFile("Textures/img1.jpg", "rb");
tempImg = IMG_LoadJPG_RW(rwop);
SDL_Surface *image = SDL_ConvertSurfaceFormat(tempImg, SDL_PIXELFORMAT_ABGR8888, 0);
VkDeviceSize imageSize = image->format->BytesPerPixel * image->h * image->w;
if (!image)
{
throw std::runtime_error("failed to load texture image!");
}
VkImage stagingImage;
VkDeviceMemory staingImageMemory;
createImage(
image->w, image->h,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
stagingImage,
staingImageMemory);
std::cout << "the image size is " << imageSize << std::endl;
void * data;
vkMapMemory(device, staingImageMemory, 0, imageSize, 0, &data);
memcpy(data, image->pixels, (size_t)imageSize);
vkUnmapMemory(device, staingImageMemory);
createImage(
image->w, image->h,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
textureImage,
textureImageMemory);
transitionImageLayout(stagingImage, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
copyImage(stagingImage, textureImage, image->w, image->h);
transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
我所做的唯一修改是翻转纹理的 V 分量以修复镜像图像
图像结果:
这张贴图不好
虽然它应该显示这样的东西
看起来sdl的行间距和vulkan想要的行间距不匹配
相反,您可以使用缓冲区从暂存内存中使用 vkCmdCopyBufferToImage
进行图像复制,而不是图像到图像位块传输,您可以在 VkBufferImageCopy
结构中显式传递行间距。
我设法加载了 jpg 图像并将它们用作 vulkan 中的纹理,但是不同的图像会产生不同的结果,有些图像效果很好,有些图像映射得不好。
这里是图片加载和格式转换相关的代码块:-
void Vulkan::createTextureImage()
{
SDL_Surface *tempImg;
SDL_RWops *rwop;
rwop = SDL_RWFromFile("Textures/img1.jpg", "rb");
tempImg = IMG_LoadJPG_RW(rwop);
SDL_Surface *image = SDL_ConvertSurfaceFormat(tempImg, SDL_PIXELFORMAT_ABGR8888, 0);
VkDeviceSize imageSize = image->format->BytesPerPixel * image->h * image->w;
if (!image)
{
throw std::runtime_error("failed to load texture image!");
}
VkImage stagingImage;
VkDeviceMemory staingImageMemory;
createImage(
image->w, image->h,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
stagingImage,
staingImageMemory);
std::cout << "the image size is " << imageSize << std::endl;
void * data;
vkMapMemory(device, staingImageMemory, 0, imageSize, 0, &data);
memcpy(data, image->pixels, (size_t)imageSize);
vkUnmapMemory(device, staingImageMemory);
createImage(
image->w, image->h,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
textureImage,
textureImageMemory);
transitionImageLayout(stagingImage, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
copyImage(stagingImage, textureImage, image->w, image->h);
transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
我所做的唯一修改是翻转纹理的 V 分量以修复镜像图像
图像结果:
这张贴图不好
虽然它应该显示这样的东西
看起来sdl的行间距和vulkan想要的行间距不匹配
相反,您可以使用缓冲区从暂存内存中使用 vkCmdCopyBufferToImage
进行图像复制,而不是图像到图像位块传输,您可以在 VkBufferImageCopy
结构中显式传递行间距。