vulkan 下实现forward 和 deferred 下的MSAA

一 前言
1.锯齿

也叫 走样(Aliasing),产生直接原因 ,我们屏幕的分辨率有限,在光栅插值时三角形的边会从像素里穿过,被穿过的像素,着色后会产生锯齿,本质原因和信号采样有关。
图片来自 learnopengl插值在这里插入图片描述

2. msaa的原理

原理比较简单,光栅化时在一个像素里生成更多的样本,计算覆盖率,片元着色器结束后 用覆盖率 乘以像素的颜色,边缘颜色变淡,使之显得平滑,不管生成多少样点,如果没有设置pre sample shading, fragment或者ps shader里还是只计算一次 shading。vulkan 和dx 设置pre sample shading时不同的,vulkan 在c++ 设置采样器里设置,dx 在shader 设置采样器时设置。
在这里插入图片描述在这里插入图片描述

二 . forward msaa 的核心步骤
1. 设置 setupMultisampleTarget

创建 颜色 和 深度的 image buffer ,设置 下面结构体VkImageCreateInfo 的VkSampleCountFlagBits ,样本数量取决于具体的硬件,一般是4倍样本,VkSampleCountFlagBits = 4;

2. 设置 setupFrameBuffer

一个framebuffer 关联 4 个 附件的视图,两个是上面的Multisample的附件,两个是单样本的附件。

3. 设置渲染通道

关键是 subpass 的 这个
typedef struct VkSubpassDescription {
VkSubpassDescriptionFlags flags;
VkPipelineBindPoint pipelineBindPoint;
uint32_t inputAttachmentCount;
const VkAttachmentReference* pInputAttachments;
uint32_t colorAttachmentCount;
const VkAttachmentReference* pColorAttachments;
const VkAttachmentReference* pResolveAttachments;
const VkAttachmentReference* pDepthStencilAttachment;
uint32_t preserveAttachmentCount;
const uint32_t* pPreserveAttachments;
} VkSubpassDescription;

这个 结构 会在 片元着色器计算后,framebuffer 阶段 把 pColorAttachments 的附件 解析到 pResolveAttachments 这个附件上,把多样本的image 解析给交换链一个样本的image. 这是自动解析多样本。

三. deferred msaa 的核心步骤

在 deferred 时 光栅化时 只输出 outPosition outNormal outAlbedo ,并没有做shading,而是转移到 下一个 pass 处理 shading, 所以会有 msaa 和 deferred 冲突。
解决办法 就是 给 输出 outPosition outNormal outAlbedo depth的 image 都设置成 超样本,这个和 forward 时一样。
在fs 做 shading 我们采样在这些保存着多样本的 gbuffer ,手动解析多样本。
sampler2DMS 表示 这是一个多样本纹理 ,要用 texelFetch 去采样。

layout (binding = 1) uniform sampler2DMS samplerPosition;
layout (binding = 2) uniform sampler2DMS samplerNormal;
layout (binding = 3) uniform sampler2DMS samplerAlbedo;
vec4 resolve(sampler2DMS tex, ivec2 uv)
{
	vec4 result = vec4(0.0);	   
	for (int i = 0; i < NUM_SAMPLES; i++)
	{
	//  i 就是每个样本
		vec4 val = texelFetch(tex, uv, i); 
		result += val;
	}    
	// Average resolved samples
	return result / float(NUM_SAMPLES);
}
	// Calualte lighting for every MSAA sample
	for (int i = 0; i < NUM_SAMPLES; i++)
	{ 
		vec3 pos = texelFetch(samplerPosition, UV, i).rgb;
		vec3 normal = texelFetch(samplerNormal, UV, i).rgb;
		vec4 albedo = texelFetch(samplerAlbedo, UV, i);
		fragColor += calculateLighting(pos, normal, albedo);
	}
	fragColor = (alb.rgb * ambient) + fragColor / float(NUM_SAMPLES);
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值