Vulkan Tutorial 10 重采样

news2024/11/25 8:16:03

目录

30 多重采样

获得可用的样本数

设置一个渲染目标

添加新的附件


30 多重采样

我们的程序现在可以为纹理加载多层次的细节,这修复了在渲染离观众较远的物体时出现的假象。现在的图像平滑了许多,然而仔细观察,你会发现在绘制的几何图形的边缘有锯齿状的图案。在我们早期的一个程序中,当我们渲染一个四边形时,这一点尤其明显:

在普通的渲染中,像素的颜色是根据单个采样点确定的,在大多数情况下,这个采样点就是屏幕上目标像素的中心。如果绘制的线条有一部分穿过某个像素点,但没有覆盖到采样点,那么这个像素点就会留下空白,导致锯齿状的 “阶梯”效果。

MSAA所做的是,它使用每个像素的多个采样点(因此而得名)来确定其最终颜色。正如人们所期望的那样,更多的样本会带来更好的结果,但是它的计算成本也更高。

获得可用的样本数

让我们首先确定我们的硬件可以使用多少个样本。大多数现代GPU至少支持8个样本,但这个数字不能保证在任何地方都是一样的。我们将通过添加一个新的类成员来跟踪它:

...
VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
...


//。准确的最大样本数可以从与我们选定的物理设备相关的VkPhysicalDeviceProperties中提取。
//我们必须考虑到颜色和深度的样本数。两者都支持的最高采样数将是我们能支持的最大限度。
//添加一个函数,为我们获取这些信息:

VkSampleCountFlagBits getMaxUsableSampleCount() {
    VkPhysicalDeviceProperties physicalDeviceProperties;
    vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);

    VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
    if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
    if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
    if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
    if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
    if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
    if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }

    return VK_SAMPLE_COUNT_1_BIT;
}

现在我们将在物理设备选择过程中使用这个函数来设置msaaSamples变量。为此,我们必须稍微修改pickPhysicalDevice函数:

void pickPhysicalDevice() {
    ...
    for (const auto& device : devices) {
        if (isDeviceSuitable(device)) {
            physicalDevice = device;
            msaaSamples = getMaxUsableSampleCount();
            break;
        }
    }
    ...
}

设置一个渲染目标

在MSAA中,每个像素在屏幕外的缓冲区中被采样,然后被渲染到屏幕上。这个新的缓冲区与我们一直在渲染的普通图像略有不同–它们必须能够存储每个像素的一个以上的样本。一旦多采样缓冲区被创建,它就必须被解析为默认的帧缓冲区(每个像素只存储一个样本)。

//必须创建一个额外的渲染目标并修改我们当前的绘图过程。我们只需要一个渲染目标,因为每次只有一个绘制操作是活动的,就像深度缓冲器一样。添加以下类成员:

...
VkImage colorImage;
VkDeviceMemory colorImageMemory;
VkImageView colorImageView;
...

//这个新图像将必须存储每个像素所需的样本数,所以我们需要在图像创建过程中把这个数字传给VkImageCreateInfo。修改createImage函数,增加一个numSamples参数:

void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCountFlagBits numSamples, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
    ...
    imageInfo.samples = numSamples;
    ...

//使用`VK_SAMPLE_COUNT_1_BIT’更新对该函数的所有调用 - 我们将在实施过程中用适当的值替换它:

createImage(swapChainExtent.width, swapChainExtent.height, 1, VK_SAMPLE_COUNT_1_BIT, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
...
createImage(texWidth, texHeight, mipLevels, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);

我们现在将创建一个多采样的颜色缓冲区。添加一个createColorResources函数,注意我们在这里使用msaaSamples作为createImage的一个函数参数。我们也只使用一个mip级别,因为这是Vulkan规范在每个像素有一个以上的样本的情况下强制执行的。另外,这个颜色缓冲区不需要mipmaps,因为它不会被用作纹理:

void createColorResources() {
    VkFormat colorFormat = swapChainImageFormat;

    createImage(swapChainExtent.width, swapChainExtent.height, 1, msaaSamples, colorFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, colorImage, colorImageMemory);
    colorImageView = createImageView(colorImage, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}//在createDepthResources之前调用该函数:

//我们现在已经创建了几个新的Vulkan资源,所以我们不要忘记在必要时释放它们:

void cleanupSwapChain() {
    vkDestroyImageView(device, colorImageView, nullptr);
    vkDestroyImage(device, colorImage, nullptr);
    vkFreeMemory(device, colorImageMemory, nullptr);
    ...
}

添加新的附件

让我们先来处理一下渲染通道的问题。修改createRenderPass并更新颜色和深度附件创建信息结构:

void createRenderPass() {
    ...
    colorAttachment.samples = msaaSamples;
    colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
//你会注意到,我们把最终布局从VK_IMAGE_LAYOUT_PRESENT_SRC_KHR改为VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL。
//这是因为多采样图像不能直接呈现。我们首先需要将它们解析为普通图像。
//这个要求并不适用于深度缓冲区,因为它不会在任何时候被呈现。
//因此,我们将不得不为颜色添加一个新的附件,这是一个所谓的解析附件:
    ...
    depthAttachment.samples = msaaSamples;
    ...

 VkAttachmentDescription colorAttachmentResolve{};
    colorAttachmentResolve.format = swapChainImageFormat;
    colorAttachmentResolve.samples = VK_SAMPLE_COUNT_1_BIT;
    colorAttachmentResolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    colorAttachmentResolve.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    colorAttachmentResolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    colorAttachmentResolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    colorAttachmentResolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    colorAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
    ...

//现在必须指示渲染通道将多采样的彩色图像解析为常规附件。
//创建一个新的附件引用,它将指向作为解析目标的颜色缓冲区:

    ...
 VkAttachmentReference colorAttachmentResolveRef{};
    colorAttachmentResolveRef.attachment = 2;
    colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

//设置pResolveAttachments子通道结构成员,指向新创建的附件引用。

    subpass.pResolveAttachments = &colorAttachmentResolveRef;


    ...

现在用新的颜色附件更新渲染通道信息结构:

    ...
    std::array<VkAttachmentDescription, 3> attachments = {colorAttachment, depthAttachment, colorAttachmentResolve};
    ...

//渲染通道到位后,修改createFramebuffers并将新的图像视图添加到列表中:
std::array<VkImageView, 3> attachments = {
            colorImageView,
            depthImageView,
            swapChainImageViews[i]
        };

//修改createGraphicsPipeline,告诉新创建的管道使用一个以上的样本:

void createGraphicsPipeline() {
    ...
    multisampling.rasterizationSamples = msaaSamples;
    ...
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/718869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP8266 RTOS SDK开发 windows开发

https://blog.csdn.net/qq_36347513/article/details/105066905 文件下载路径 https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/get-started/windows-setup.html 下载编译环境MSYS2 下载完成后解压到根目录 双击mingw32.exe打开&#xff0c;ls看一下是在什么…

青岛大学_王卓老师【数据结构与算法】Week04_04_双向链表的插入_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c;另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础–…

微信小程序实现抖音视频效果

当我们进行开发的时候可能会遇到需要实现抖音视频效果的需求&#xff0c;并且网上该效果的开源代码少&#xff0c;找到的开源代码代码量大&#xff0c;很难进行二次开发 对此我将自己的代码进行简化&#xff0c;仅留下可动性高的代码模块 以上是实现效果与此处demo的模板 wx…

c++的输入与输出

c中的各种流 文件输入流ifstream 读数据 #include <iostream> #include <iostream> #include <fstream> int main(int const argc, char const *const *argv) {std::ifstream is{"hello.txt"};if (is.good()){std::string s;while (is >> s)…

如何给没有坐标的栅格数据添加坐标信息

在进行NETCDF和HDF格式转换时&#xff0c;经常会出现数据转出来了。但没有任何坐标信息的情况。这如下图转出来的数据就完全不带坐标信息&#xff0c;就好像一副图片一样。但数据的值和像素信息保存完好。如下边一个NC数转出的TIFF栅格数据&#xff1a; 这是我用GIS数据转换器-…

【Matlab】神经网络遗传算法(BP-GA)函数极值寻优——非线性函数求极值

目前关于神经网络遗传算法函数极值寻优——非线性函数求极值的博客资源已经不少了&#xff0c;我看了下来源&#xff0c;最初的应该是来自于Matlab中文论坛&#xff0c;论坛出版的《MATLAB神经网络30个案例分析》第4章就是《神经网络遗传算法函数极值寻优——非线性函数极值寻优…

Ubuntu 添加新用户并配额

背景&#xff1a;在配置工作站或者服务器时&#xff0c;需要为多个用户提供服务&#xff0c;但是需要各个用户之间操作互不干扰&#xff0c;自己所安装的各种环境不会对其他人或root账号下的主系统环境有影响&#xff0c;并且各用户每个用户需要分配额定的内存空间。 安装 quo…

紫光展锐联合罗德与施瓦茨在MWC上海共同展示RedCap测试方案

在6月28日-30日举办的2023上海世界移动大会上&#xff08;MWC上海&#xff09;&#xff0c;紫光展锐联合罗德与施瓦茨共同演示RedCap射频与吞吐量测试&#xff0c;确保RedCap终端功能和性能达到预期。在本次联合测试中&#xff0c;RedCap下行吞吐量可达220Mbps&#xff0c;上行…

大模型加速学科升级,飞桨赋能北邮“X+大模型”特色小学期

在人工智能时代&#xff0c;设计师与产品经理比以往更加需要关注一个事实&#xff1a;那就是如何利用人工智能和数据分析技术&#xff0c;打造让用户心动的信息交互产品和用户体验&#xff0c;释放人-机协同共创的巨大潜能&#xff0c;是决定设计产能和竞争力的关键。 在产业的…

港科夜闻|叶玉如校长出席香港创科 砥砺前行主题论坛

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大校长叶玉如教授出席「香港创科 砥砺前行」主题论坛。该论坛为中华人民共和国香港特别行政区成立26周年庆祝活动之一&#xff0c;叶玉如校长在论坛上分享了她对香港创新科技及研究发展未来的见解。论坛亦包括国际…

Cmder最新版--打开慢 删除字符残留问题

标题Cmder最新版–打开慢 删除字符残留问题 1 打开慢 打开后左下角跳动显示findstr.exe cmd.exe git.exe&#xff0c;很久后才能正常输入。 解决方案&#xff1a; 关闭更新检查及运行dll注入&#xff08;如下二图&#xff09; 2 删除后有字符残留 像这样很烦 解决方案有…

wireshark学习

抓包原理 哪种网络情况可以抓到包&#xff1f;&#xff08;1&#xff09;本机环境&#xff08;2&#xff09;集线器环境&#xff08;3&#xff09;交换机环境 交换机环境目前较为常用&#xff0c;这也分为三种情况&#xff08;1&#xff09;端口镜像&#xff08;2&#xff09…

vue项目使用自定义域名开启本地服务(ip地址和域名映射)

前言 有的时候&#xff0c;我们直接用script请求需要在同一个顶级&#xff08;一级&#xff09;域名下才可以拿到数据。 本地服务在开启时一般都是localhost&#xff0c;或者带ip。如果想要自定义域名访问本地服务&#xff0c;需要做以下配置。 ip地址和域名映射 在域名请求…

六轴机械臂搬运仿真(机器人工具箱)

1、建立机械臂模型 工作台、货物 clear close all clc L(1)Link(d, 0.33, a,0 , alpha, pi/2,offset,pi); L(2)Link(d, 0, a, 0.26, alpha,0,offset,pi/2); L(3)Link(d, 0, a, 0.02, alpha,pi/2,offset,0); L(4)Link(d, -0.29, a, 0, alpha,pi/2,offset,0); L(5)Link(d, 0, a,…

问诊住院医疗业务数仓建模实操案例

一、数仓建模实超案例 &#xff08;一&#xff09;前言 医疗业务系统比较复杂&#xff0c;有HIS&#xff1a;医院信息管理系统&#xff08; Hospital Information System&#xff09;、CIS&#xff1a;临床信息系统&#xff08;Clinical Information System&#xff09;、LIS&…

临床数据 1. 临床基因突变数据如何发高分?

桓峰基因公众号的粉丝中医学类科研偏多&#xff0c;因此对于临床数据的分析需求还是很多的&#xff0c;因此我们再次推出临床数据相关的一些文献以及对应的分析方法&#xff0c;那么临床数据大概哪几类呢&#xff1f; 临床信息 患者的个人信息包括性别、年龄、家族遗传史、吸烟…

微众区块链开源分布式数据协作管理解决方案,建数据要素高效流通桥梁

数据要素已成为数字经济时代最核心的生产要素&#xff0c;为助力全行业伙伴提升区块链数据协作管理效率、保障数据要素高效有序流通&#xff0c;微众区块链在多年技术研究和应用实践的基础上&#xff0c;积极分析总结行业需求&#xff0c;研发了分布式数据协作管理解决方案DDCM…

css文字图标(阿里图标)使用及引入方式

首先打开 iconfont图标 网页 选择素材库中的单色图标库 选择自己需要用的图标 这里简绍四种类型的引入方式&#xff0c;其中是网页上的三种引入方式&#xff1a; 1. Unicode 使用方式 复制代码 引入样式 (这里是线上引入 通过网址引入的) 引入样式注意路径完整性 标签中间放入…

如何在Forlinx OK3588-C EVK上安装OpenCV?

OpenCV&#xff08;开源计算机视觉库&#xff09;是一个开源计算机视觉和机器学习软件库。 OpenCV 广泛应用于计算机视觉、机器人、智能交通、医学成像、安全等领域。 Forlinx RK3588 EVK 是一款高性能嵌入式计算机&#xff0c;结合 OpenCV&#xff0c;可进行高效的图像和视频处…

七牛云面试复盘-实习后端Java开发 一面复盘 【已通过】

💪💪💪欢迎订阅本专栏,持续更新,本专栏内容为我参加的各个公司面试的复盘专栏。将完整记录面试细节问题。 七牛云面试 实习后端Java开发 一面 [视频面试] 首先自我介绍 我是XXX,来自XXX,XXXX。 面试官提问: 1.先问几个基础题,循序渐进的来哈,谈谈Java⾃动装箱…