对 srgb 格式使用 VK_IMAGE_TILING_LINEAR?
Using VK_IMAGE_TILING_LINEAR for srgb formats?
所以我仍在尝试找出渲染纹理的色彩空间,以及如何创建没有色带的图像。在我的 gbuffer 中,我将 VK_FORMAT_R8G8B8A8_UNORM 和 VK_IMAGE_TILING 用于我的反照率纹理,并将 VK_FORMAT_A2B10G10R10_UNORM_PACK32 和 VK_IMAGE_TILING_OPTIMAL 用于我的法线和发射渲染纹理。对于我的亮度纹理(包含在场景中被视为 "bright" 的像素值)和辉光渲染纹理(用于稍后添加到最终场景的光晕效果的最终纹理),我使用 VK_FORMAT_R8G8B8A8_SRGB 和VK_IMAGE_TILING_OPTIMAL(虽然看着这个,我可能应该将我的明亮和最终纹理改为 R16G16B16A16 浮点格式)。我得到的绝对不是我想要的:
然而,将我的法线、发射、发光和亮度纹理的平铺更改为 VK_IMAGE_TILING_LINEAR,却得到了不错的结果,但以牺牲性能为代价:
不过它的好处(对于左上角的奇怪边框感到抱歉,在 MS 画图上被裁剪了...),图像没有色带,例如 when 相反为了将这些格式用于我的纹理,我使用 VK_FORMAT_R8G8B8A8_UNORM 和 VK_IMAGE_TILING_OPTIMAL:
您是否可以看到头盔左上角和头盔下方(黑管所在的位置)出现条纹。当然,我听说过从 post
中避免 VK_IMAGE_TILING_LINEAR
一般来说,我无法确定在使用 srgb 纹理时避免使用 VK_IMAGE_TILING_LINEAR 的最佳方法是什么?我仍然想保留 srgb 给我的漂亮清晰的图像,但我不确定如何解决这个问题。 link 可能确实有解决方案,但我不太确定是否有办法将它应用到我的 gbuffer。
我还想澄清一下 VK_IMAGE_TILING_OPTIMAL 适用于基于 Nvidia 的 GPU(好吧,在 GTX 870M 上测试过),但抱怨对 srgb 格式使用 VK_IMAGE_TILING_LINEAR,然而,intel基于 gpus 的 VK_IMAGE_TILING_LINEAR 可以很好地工作,当使用 VK_IMAGE_TILING_OPTIMAL.
时,有点像 post 上面的第一张图片
该引擎是定制的,请随时在此查看 link
如果你喜欢一些代码,我在 Engine/Renderer/Private/Renderer.cpp 文件中使用了一个名为 SetUpRenderTextures() 的函数,在第 1396 行下:
VkImageCreateInfo cImageInfo = { };
VkImageViewCreateInfo cViewInfo = { };
// TODO(): Need to make this more adaptable, as intel chips have trouble with srgb optimal tiling.
cImageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
cImageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
cImageInfo.imageType = VK_IMAGE_TYPE_2D;
cImageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
cImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
cImageInfo.mipLevels = 1;
cImageInfo.extent.depth = 1;
cImageInfo.arrayLayers = 1;
cImageInfo.extent.width = m_pWindow->Width();
cImageInfo.extent.height = m_pWindow->Height();
cImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
cImageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
cViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
cViewInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
cViewInfo.image = nullptr; // No need to set the image, texture->Initialize() handles this for us.
cViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
cViewInfo.subresourceRange = { };
cViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
cViewInfo.subresourceRange.baseArrayLayer = 0;
cViewInfo.subresourceRange.baseMipLevel = 0;
cViewInfo.subresourceRange.layerCount = 1;
cViewInfo.subresourceRange.levelCount = 1;
gbuffer_Albedo->Initialize(cImageInfo, cViewInfo);
gbuffer_Emission->Initialize(cImageInfo, cViewInfo);
cImageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
cViewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
GlowTarget->Initialize(cImageInfo, cViewInfo);
// It's probably best that these be 64bit float formats as well...
pbr_Bright->Initialize(cImageInfo, cViewInfo);
pbr_Final->Initialize(cImageInfo, cViewInfo);
cImageInfo.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
cViewInfo.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
gbuffer_Normal->Initialize(cImageInfo, cViewInfo);
gbuffer_Position->Initialize(cImageInfo, cViewInfo);
所以是的,破败。如何避免对 srgb 纹理使用线性图像平铺?这是硬件特定的东西吗,是强制性的吗?另外,对于我在这个问题上的任何形式的无知,我深表歉意。
谢谢:3
必须支持此组合,因此您第一张图片中的损坏是应用程序错误或驱动程序错误。
所以 VK_FORMAT_R8G8B8A8_SRGB
在您的 Nvidia GPU 上使用 VK_IMAGE_TILING_OPTIMAL
而不是在您的 Intel GPU 上?但是 VK_FORMAT_R8G8B8A8_SRGB
可以在 Intel GPU 上与 VK_IMAGE_TILING_LINEAR
一起使用吗?
如果是这样,这听起来像是您缺少或不正确的图像布局过渡。与 Nvidia 相比,Intel 对正确处理这些问题更为敏感。验证层会抱怨什么吗?您需要确保图像在渲染时为 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
,在从中采样时为 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
。
所以我仍在尝试找出渲染纹理的色彩空间,以及如何创建没有色带的图像。在我的 gbuffer 中,我将 VK_FORMAT_R8G8B8A8_UNORM 和 VK_IMAGE_TILING 用于我的反照率纹理,并将 VK_FORMAT_A2B10G10R10_UNORM_PACK32 和 VK_IMAGE_TILING_OPTIMAL 用于我的法线和发射渲染纹理。对于我的亮度纹理(包含在场景中被视为 "bright" 的像素值)和辉光渲染纹理(用于稍后添加到最终场景的光晕效果的最终纹理),我使用 VK_FORMAT_R8G8B8A8_SRGB 和VK_IMAGE_TILING_OPTIMAL(虽然看着这个,我可能应该将我的明亮和最终纹理改为 R16G16B16A16 浮点格式)。我得到的绝对不是我想要的:
然而,将我的法线、发射、发光和亮度纹理的平铺更改为 VK_IMAGE_TILING_LINEAR,却得到了不错的结果,但以牺牲性能为代价:
不过它的好处(对于左上角的奇怪边框感到抱歉,在 MS 画图上被裁剪了...),图像没有色带,例如 when 相反为了将这些格式用于我的纹理,我使用 VK_FORMAT_R8G8B8A8_UNORM 和 VK_IMAGE_TILING_OPTIMAL:
您是否可以看到头盔左上角和头盔下方(黑管所在的位置)出现条纹。当然,我听说过从 post
中避免 VK_IMAGE_TILING_LINEAR一般来说,我无法确定在使用 srgb 纹理时避免使用 VK_IMAGE_TILING_LINEAR 的最佳方法是什么?我仍然想保留 srgb 给我的漂亮清晰的图像,但我不确定如何解决这个问题。 link 可能确实有解决方案,但我不太确定是否有办法将它应用到我的 gbuffer。
我还想澄清一下 VK_IMAGE_TILING_OPTIMAL 适用于基于 Nvidia 的 GPU(好吧,在 GTX 870M 上测试过),但抱怨对 srgb 格式使用 VK_IMAGE_TILING_LINEAR,然而,intel基于 gpus 的 VK_IMAGE_TILING_LINEAR 可以很好地工作,当使用 VK_IMAGE_TILING_OPTIMAL.
时,有点像 post 上面的第一张图片该引擎是定制的,请随时在此查看 link
如果你喜欢一些代码,我在 Engine/Renderer/Private/Renderer.cpp 文件中使用了一个名为 SetUpRenderTextures() 的函数,在第 1396 行下:
VkImageCreateInfo cImageInfo = { };
VkImageViewCreateInfo cViewInfo = { };
// TODO(): Need to make this more adaptable, as intel chips have trouble with srgb optimal tiling.
cImageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
cImageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
cImageInfo.imageType = VK_IMAGE_TYPE_2D;
cImageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
cImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
cImageInfo.mipLevels = 1;
cImageInfo.extent.depth = 1;
cImageInfo.arrayLayers = 1;
cImageInfo.extent.width = m_pWindow->Width();
cImageInfo.extent.height = m_pWindow->Height();
cImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
cImageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
cViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
cViewInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
cViewInfo.image = nullptr; // No need to set the image, texture->Initialize() handles this for us.
cViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
cViewInfo.subresourceRange = { };
cViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
cViewInfo.subresourceRange.baseArrayLayer = 0;
cViewInfo.subresourceRange.baseMipLevel = 0;
cViewInfo.subresourceRange.layerCount = 1;
cViewInfo.subresourceRange.levelCount = 1;
gbuffer_Albedo->Initialize(cImageInfo, cViewInfo);
gbuffer_Emission->Initialize(cImageInfo, cViewInfo);
cImageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
cViewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
GlowTarget->Initialize(cImageInfo, cViewInfo);
// It's probably best that these be 64bit float formats as well...
pbr_Bright->Initialize(cImageInfo, cViewInfo);
pbr_Final->Initialize(cImageInfo, cViewInfo);
cImageInfo.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
cViewInfo.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
gbuffer_Normal->Initialize(cImageInfo, cViewInfo);
gbuffer_Position->Initialize(cImageInfo, cViewInfo);
所以是的,破败。如何避免对 srgb 纹理使用线性图像平铺?这是硬件特定的东西吗,是强制性的吗?另外,对于我在这个问题上的任何形式的无知,我深表歉意。
谢谢:3
必须支持此组合,因此您第一张图片中的损坏是应用程序错误或驱动程序错误。
所以 VK_FORMAT_R8G8B8A8_SRGB
在您的 Nvidia GPU 上使用 VK_IMAGE_TILING_OPTIMAL
而不是在您的 Intel GPU 上?但是 VK_FORMAT_R8G8B8A8_SRGB
可以在 Intel GPU 上与 VK_IMAGE_TILING_LINEAR
一起使用吗?
如果是这样,这听起来像是您缺少或不正确的图像布局过渡。与 Nvidia 相比,Intel 对正确处理这些问题更为敏感。验证层会抱怨什么吗?您需要确保图像在渲染时为 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
,在从中采样时为 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
。