Vulkan中SMAA抗锯齿效果不完整,权重混合纹理模糊问题求助
Vulkan中SMAA抗锯齿效果不完整,权重混合纹理模糊问题求助
各位大佬好,我在Vulkan环境下实现SMAA抗锯齿时遇到了棘手的问题:最终输出的图像抗锯齿效果不完整,观察中间渲染结果发现边缘检测纹理(edgesTex)是正常的,但权重混合纹理(blendTex)和官方SMAA Demo里的权重图像相比模糊很多。我反复排查了权重混合阶段的代码,但一直找不到问题根因,希望大家能帮忙看看。
以下是我的最小复现代码:
一、SMAA通用定义与公共着色器
SMAA_define.h
// SMAA common header file // push constant, use for smaa render target metrics layout(push_constant) uniform PushConstant { vec4 smaa_rt_metrics; } pc; #define SMAA_RT_METRICS pc.smaa_rt_metrics #define SMAA_GLSL_4 #define SMAA_PRESET_ULTRA
SMAA_vert.h(顶点着色器公共部分)
// SMAA vertex shader common define #include "SMAA_define.h" #define SMAA_INCLUDE_PS 0 #include "SMAA.hlsl" layout(location = 0) out vec2 texture_coord; layout(location = 1) out vec2 pixel_coord; layout(location = 2) out vec4 offset[3]; // fullscreen triangle vec2 vertices[] = { { -1, -1 }, { 3, -1 }, { -1, 3 }, }; vec2 texture_coords[] = { { 0, 0 }, { 2, 0 }, { 0, 2 }, }; void set_gl_Position_and_texture_coord() { gl_Position = vec4(vertices[gl_VertexIndex], 0, 1); texture_coord = texture_coords[gl_VertexIndex]; }
SMAA_frag.h(片段着色器公共部分)
// SMAA fragment shader common define #include "SMAA_define.h" #define SMAA_INCLUDE_VS 0 #include "SMAA.hlsl" layout(location = 0) in vec2 texture_coord; layout(location = 1) in vec2 pixel_coord; layout(location = 2) in vec4 offset[3]; layout(location = 0) out vec4 color;
二、SMAA各阶段着色器
1. 边缘检测阶段
SMAA_edge_detection.vert
#version 460 #include "SMAA_vert.h" void main() { set_gl_Position_and_texture_coord(); SMAAEdgeDetectionVS(texture_coord, offset); }
SMAA_edge_detection.frag
#version 460 #include "SMAA_frag.h" layout(binding = 0) uniform sampler2D original_image; void main() { color = vec4(SMAAColorEdgeDetectionPS(texture_coord, offset, original_image), 0.0, 0.0); }
2. 权重混合阶段
SMAA_blend_weight.vert
#version 460 #include "SMAA_vert.h" void main() { set_gl_Position_and_texture_coord(); SMAABlendingWeightCalculationVS(texture_coord, pixel_coord, offset); }
SMAA_blend_weight.frag
#version 460 #include "SMAA_frag.h" layout(binding = 1) uniform sampler2D edges_texture; layout(binding = 2) uniform sampler2D area_texture; layout(binding = 3) uniform sampler2D search_texture; void main() { color = SMAABlendingWeightCalculationPS(texture_coord, pixel_coord, offset, edges_texture, area_texture, search_texture, vec4(0.f)); }
3. 邻域混合阶段
SMAA_neighbor.vert
#version 460 #include "SMAA_vert.h" void main() { set_gl_Position_and_texture_coord(); SMAANeighborhoodBlendingVS(texture_coord, offset[0]); }
SMAA_neighbor.frag
#version 460 #include "SMAA_frag.h" layout(location = 0) in vec2 texture_coord; layout(location = 1) in vec2 pixel_coord; layout(location = 2) in vec4 offset[3]; layout(location = 0) out vec4 color; layout(binding = 0) uniform sampler2D original_image; layout(binding = 4) uniform sampler2D blend_texture; void main() { color = SMAANeighborhoodBlendingPS(texture_coord, offset[0], original_image, blend_texture); }
三、测试用着色器(旋转三角形)
triangle.vert
#version 460 vec2 vertices[] = { { 0, -.5 }, { .5, .5 }, { -.5, .5 }, }; mat2 rotate(float degree) { return mat2 ( cos(degree), sin(degree), -sin(degree), cos(degree) ); } void main() { gl_Position = vec4(rotate(45) * vertices[gl_VertexIndex], 0, 1); }
triangle.frag
#version 460 layout(location = 0) out vec4 color; void main() { color = vec4(1, 1, 1, 1); }
四、Core结构定义(main.cpp核心部分)
// structure struct Image { VkImage handle; VkImageView view; VmaAllocation allocation; VkFormat format; VkExtent3D extent; }; struct Buffer { VkBuffer handle; VmaAllocation allocation; }; struct PushConstant { glm::vec4 smaa_rt_metrics; }; struct Frame { VkCommandBuffer cmd; VkFence fence; VkSemaphore image_available; VkSemaphore render_finished; }; // global variables std::vector<Frame> g_frames; uint32_t g_frame_index = 0; VmaAllocator g_allocator; VkDevice g_device; VkFormat g_swapchain_image_format; VkExtent2D g_swapchain_extent; VkCommandPool g_command_pool; // every pass output image Image g_source_image; // original image Image g_edges_image; // edge detection Image g_blend_image; // weight blend Image g_output_image; // neighbor VkSampler g_sampler; // linear sampler VkDescriptorPool g_descriptor_pool; VkDescriptorSetLayout g_descriptor_set_layout; VkDescriptorSet g_descriptor_set; // use for blend weight pass // SMAA lookup textures Image g_area_texture; Image g_search_texture; std::vector<VkPipeline> g_pipelines(4); // 0 : triangle, 1 : edge detection, 2 : blend weight, 3 : neighbor
我目前的排查方向和疑问
- 我当前给所有纹理用的是线性采样器(g_sampler),但SMAA的area和search纹理是离散查找表,是不是应该强制用最近邻采样?线性过滤会不会直接导致blendTex的计算结果模糊?
- g_blend_image我用的是RGBA8格式,会不会因为精度不足导致权重信息丢失?有没有必要换成更高精度的格式?
- Push Constant里的SMAA_RT_METRICS我是按
glm::vec4(1.0f / width, 1.0f / height, width, height)计算的,这个参数的顺序有没有搞反? - 着色器里定义的
SMAA_GLSL_4宏,和我使用的GLSL 460版本会不会存在兼容性冲突? - Vulkan的纹理布局转换有没有遗漏?比如blend weight pass中,edgesTex、area、search纹理是不是正确设置为
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,g_blend_image是不是设置为VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL?
希望有经验的大佬能帮忙指出问题所在,感激不尽!
内容来源于stack exchange




