You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

我目前的排查方向和疑问

  1. 我当前给所有纹理用的是线性采样器(g_sampler),但SMAA的area和search纹理是离散查找表,是不是应该强制用最近邻采样?线性过滤会不会直接导致blendTex的计算结果模糊?
  2. g_blend_image我用的是RGBA8格式,会不会因为精度不足导致权重信息丢失?有没有必要换成更高精度的格式?
  3. Push Constant里的SMAA_RT_METRICS我是按glm::vec4(1.0f / width, 1.0f / height, width, height)计算的,这个参数的顺序有没有搞反?
  4. 着色器里定义的SMAA_GLSL_4宏,和我使用的GLSL 460版本会不会存在兼容性冲突?
  5. 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

火山引擎 最新活动