vulkan 實現的forward 和 deferred 下的 Multisampling

一 前言
1.鋸齒

也叫 走樣(Aliasing),產生原因 ,我們屏幕的分辨率有限,在光柵插值時三角形的邊會從像素裏穿過,被穿過的像素,無論着色 還是不着色,都會產生鋸齒。
圖片來自 learnopengl插值在這裏插入圖片描述

2. msaa的原理

原理比較簡單,光柵化時在一個像素裏生成更多的樣本,計算覆蓋率,片元着色器結束後 用覆蓋率 乘以像素的顏色,使之顯得平滑,不管生成多少樣點,shading sample 還是一個樣點 shading。
在這裏插入圖片描述在這裏插入圖片描述
二 . 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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章