fix: video without UI + correct colors

1. No UI in video: end render pass before ImGui, capture, start new
   render pass with loadOp=LOAD for ImGui, end again. Video captures
   only the 3D scene.

2. Acid colors fixed: swapchain format changed from B8G8R8A8_SRGB to
   B8G8R8A8_UNORM. SRGB format stores gamma-compressed values that
   vkCmdCopyImageToBuffer reads raw — FFmpeg treated them as linear
   causing acid colors. UNORM stores linear values, copy gives linear
   data, FFmpeg bgra→yuv420p conversion is correct.
This commit is contained in:
emil28092005
2026-06-19 09:13:04 +03:00
parent 2daf10b3b1
commit d6939e9efa
3 changed files with 34 additions and 10 deletions
+31 -7
View File
@@ -521,17 +521,41 @@ public sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreensh
Vk.vkCmdDrawIndexed(cmd, dc.indexCount, 1, 0, 0, 0);
}
// Capture BEFORE ImGui — video without UI
if (IsRecording)
{
// End rendering temporarily to do copy outside render pass
Vk.vkCmdEndRendering(cmd);
CaptureFrame(cmd, imageIndex);
// Start new render pass for ImGui
var imgClearValue = new VkClearValue
{
Color = new VkClearColorValue { Float0 = 0, Float1 = 0, Float2 = 0, Float3 = 0 },
};
var imgLoadAttachment = new VkRenderingAttachmentInfo
{
sType = VkStructureType.RenderingAttachmentInfo,
imageView = _swapchain.ImageViews[imageIndex],
imageLayout = VkImageLayout.ColorAttachmentOptimal,
loadOp = VkAttachmentLoadOp.Load, // Keep existing content
storeOp = VkAttachmentStoreOp.Store,
};
var imgRenderingInfo = new VkRenderingInfo
{
sType = VkStructureType.RenderingInfo,
renderArea = new VkRect2D { Offset = new VkOffset2D { X = 0, Y = 0 }, Extent = _swapchain.Extent },
layerCount = 1,
colorAttachmentCount = 1,
pColorAttachments = &imgLoadAttachment,
};
Vk.vkCmdBeginRendering(cmd, &imgRenderingInfo);
}
_imGui?.Render(cmd, _swapchain.Extent.Width, _swapchain.Extent.Height);
Vk.vkCmdEndRendering(cmd);
// Capture frame for video recording — AFTER render pass, BEFORE present
// This captures scene + ImGui. To capture without UI, we'd need separate render pass.
if (IsRecording)
{
CaptureFrame(cmd, imageIndex);
}
TransitionImageLayout(cmd, _swapchain.Images[imageIndex],
VkImageLayout.ColorAttachmentOptimal, VkImageLayout.PresentSrcKHR,
0x400, 0x100,