Skip to content

vulkan: fix washed-out and blurry 2D UI rendering (minimap, bigmap)#4

Open
Rakete175 wants to merge 1 commit into
Fran6nd:vulkan-2from
Rakete175:vulkan-2
Open

vulkan: fix washed-out and blurry 2D UI rendering (minimap, bigmap)#4
Rakete175 wants to merge 1 commit into
Fran6nd:vulkan-2from
Rakete175:vulkan-2

Conversation

@Rakete175

Copy link
Copy Markdown

The swapchain uses VK_FORMAT_B8G8R8A8_SRGB, which means the hardware automatically sRGB-encodes all fragment shader output before display. UI textures are uploaded as UNORM (raw sRGB-encoded bytes, sampled verbatim), matching the GL renderer's non-sRGB framebuffer behavior.

In the GL renderer, UI bytes are written directly to a linear framebuffer and displayed as-is. In Vulkan, those same bytes get sRGB-encoded a second time by the swapchain attachment, causing a perceptual washed-out appearance on the minimap, bigmap, and other 2D elements.

Fix by performing all color math in sRGB space (matching GL semantics), then decoding the final result to linear before output. The swapchain's automatic sRGB encoding then restores the original byte values, ensuring bit-identical output to GL.

Semi-transparent blends now occur in linear space rather than sRGB space. This is visually imperceptible on soft edges and text; the alternative (byte-exact blending) would require VK_KHR_swapchain_mutable_format and a UNORM view, which is overkill for marginal gain.

Separately, the flat map (minimap) texture was being rendered with linear filtering in Vulkan, causing a blurry appearance when magnified. The OpenGL renderer uses GL_NEAREST for both MIN and MAG filters on the minimap texture, producing crisp pixel-perfect rendering. This mismatch occurred because VulkanFlatMapRenderer did not configure a sampler for the map image, leaving it with the default linear sampler from VulkanRenderer::CreateImage. The bigmap was unaffected because it is typically rendered at or near 1:1 scale, where filtering artifacts are less visible.

Fix by explicitly creating a nearest-neighbor sampler for the flat map texture immediately after image creation. The VulkanImageRenderer already respects per-image samplers via GetSampler(), so this change takes effect automatically without modifications to the 2D rendering pipeline. Also add a safeguard in VulkanImage::CreateSampler to destroy any existing sampler before creating a new one, preventing potential resource leaks on resampling.

Fixes: minimap/bigmap rendering appearing desaturated under Vulkan
Fixes: minimap appearing blurry/soft-edged under Vulkan

The swapchain uses VK_FORMAT_B8G8R8A8_SRGB, which means the hardware
automatically sRGB-encodes all fragment shader output before display.
UI textures are uploaded as UNORM (raw sRGB-encoded bytes, sampled
verbatim), matching the GL renderer's non-sRGB framebuffer behavior.

In the GL renderer, UI bytes are written directly to a linear framebuffer
and displayed as-is. In Vulkan, those same bytes get sRGB-encoded a second
time by the swapchain attachment, causing a perceptual washed-out
appearance on the minimap, bigmap, and other 2D elements.

Fix by performing all color math in sRGB space (matching GL semantics),
then decoding the final result to linear before output. The swapchain's
automatic sRGB encoding then restores the original byte values, ensuring
bit-identical output to GL.

Semi-transparent blends now occur in linear space rather than sRGB
space. This is visually imperceptible on soft edges and text; the
alternative (byte-exact blending) would require VK_KHR_swapchain_mutable_format
and a UNORM view, which is overkill for marginal gain.

Separately, the flat map (minimap) texture was being rendered with
linear filtering in Vulkan, causing a blurry appearance when magnified.
The OpenGL renderer uses GL_NEAREST for both MIN and MAG filters on the
minimap texture, producing crisp pixel-perfect rendering. This mismatch
occurred because VulkanFlatMapRenderer did not configure a sampler for
the map image, leaving it with the default linear sampler from
VulkanRenderer::CreateImage. The bigmap was unaffected because it is
typically rendered at or near 1:1 scale, where filtering artifacts are
less visible.

Fix by explicitly creating a nearest-neighbor sampler for the flat map
texture immediately after image creation. The VulkanImageRenderer already
respects per-image samplers via GetSampler(), so this change takes effect
automatically without modifications to the 2D rendering pipeline. Also
add a safeguard in VulkanImage::CreateSampler to destroy any existing
sampler before creating a new one, preventing potential resource leaks
on resampling.

Fixes: minimap/bigmap rendering appearing desaturated under Vulkan
Fixes: minimap appearing blurry/soft-edged under Vulkan
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant