時(shí)光追降噪的自適應(yīng)時(shí)間抗鋸齒技術(shù)解析)
上篇聊完光追降噪里的空間濾波之后評(píng)論區(qū)問(wèn)得最多的一個(gè)問(wèn)題出奇一致光源也追了、反射也追了、陰影也追了為什么畫(huà)面還是花的一句話就能解釋——實(shí)時(shí)光追里絕大多數(shù)場(chǎng)景的預(yù)算只有每像素1到2個(gè)樣本蒙特卡洛估計(jì)在這種樣本量下壓根來(lái)不及收斂。挨個(gè)像素堆樣本不現(xiàn)實(shí)GPU會(huì)在幾幀內(nèi)燒穿性能預(yù)算。所以業(yè)界的實(shí)際套路就是低成本采樣出帶噪圖再用降噪把噪聲磨平。時(shí)間維度是最容易被忽視的一塊富礦。同一個(gè)像素上一幀的樣本和這一幀的樣本如果放在一起用等效樣本數(shù)就能不知不覺(jué)堆上去。傳統(tǒng)TAA做的就是這個(gè)事但光追場(chǎng)景下簡(jiǎn)單混合經(jīng)常翻車。這篇文章我繼續(xù)聊一種新的解決方案——ATAA我按 Adaptive Temporal Anti-Aliasing 來(lái)理解也就是自適應(yīng)時(shí)間抗鋸齒/自適應(yīng)時(shí)間降噪。它不把時(shí)間濾波當(dāng)成用或不用的開(kāi)關(guān)而是做成能用多少用多少的動(dòng)態(tài)調(diào)節(jié)器。如果你正在手寫(xiě)延遲渲染器、在引擎里接入光追或者被鬼影和閃爍折磨得頭疼這篇文章應(yīng)該能給你一些可以直接落地的思路。全文不涉及具體引擎源碼但所有偽代碼和參數(shù)都是我實(shí)際驗(yàn)證過(guò)、可以直接抄進(jìn)自己管線里的版本。1. 為什么光追跑完還要降噪噪聲特性與時(shí)間復(fù)用的破局點(diǎn)1.1 蒙特卡洛收斂的數(shù)學(xué)直覺(jué)1spp的圖為什么必然花光追渲染本質(zhì)上在做蒙特卡洛積分。每個(gè)像素的最終顏色是成千上萬(wàn)條可能光路的期望值但我們只采樣了其中極少數(shù)幾條。誤差收斂速度有個(gè)硬約束誤差和樣本數(shù)的平方根成反比。這意味著想把噪聲降低一半需要把樣本數(shù)提高到四倍想降低到原來(lái)的十分之一需要一百倍的樣本。這是個(gè)非常殘酷的數(shù)學(xué)現(xiàn)實(shí)。實(shí)時(shí)路徑追蹤里很多場(chǎng)景只能給1spp寬裕一點(diǎn)給2spp。1spp的圖是什么概念直接光照可能勉強(qiáng)能看但間接光照、軟陰影、鏡面反射這幾個(gè)區(qū)域基本是雪花屏。就算硬堆到16spp噪點(diǎn)也只是從完全沒(méi)法看變成仔細(xì)看還是臟而采樣成本已經(jīng)翻了十六倍。1.2 空間濾波的局限與時(shí)間復(fù)用的機(jī)會(huì)既然樣本不夠就只能靠后期處理。空間濾波的思路是用周圍像素的樣本幫我補(bǔ)像SVGF、BMFR這類方案就是在顏色、深度、法線三個(gè)維度上做保邊權(quán)重把鄰域樣本加權(quán)平均??臻g濾波的問(wèn)題也很明顯它是拿鄰居的信息來(lái)猜當(dāng)前像素本質(zhì)上是在用空間分辨率換噪聲降低。反射邊緣、細(xì)幾何結(jié)構(gòu)、遠(yuǎn)處的高頻紋理一旦濾波核開(kāi)大細(xì)節(jié)就糊了。時(shí)間濾波則完全不同。它的思路是用過(guò)去幀的樣本來(lái)補(bǔ)當(dāng)前幀同一個(gè)像素在不同幀里采樣的光路不同但統(tǒng)計(jì)上都來(lái)自同一個(gè)真實(shí)值。把過(guò)去16幀的樣本累積起來(lái)等效于每幀16spp而代價(jià)只多了一次全屏混合和一張歷史緩沖。這個(gè)對(duì)比在工程上非常誘人時(shí)間復(fù)用的成本幾乎是恒定的不管你累積了多少幀每幀開(kāi)銷不變。這也是為什么所有現(xiàn)代渲染器都會(huì)把時(shí)間濾波放在核心位置。1.3 時(shí)間復(fù)用為什么需要重投影歷史信息不是隨便拿來(lái)用的但時(shí)間累積有一個(gè)前提不同幀之間的樣本必須對(duì)應(yīng)場(chǎng)景中同一個(gè)點(diǎn)。相機(jī)在動(dòng)、物體在動(dòng)上一幀的像素坐標(biāo)和這一幀的像素坐標(biāo)已經(jīng)對(duì)不上了必須通過(guò)運(yùn)動(dòng)向量velocity buffer找到這個(gè)物體上一幀在屏幕哪個(gè)位置然后把歷史顏色拿過(guò)來(lái)這叫重投影reprojection。問(wèn)題也恰好出在這里。運(yùn)動(dòng)向量是根據(jù)幾何信息算出來(lái)的但光照效果不一定跟幾何同步移動(dòng)。鏡面反射里的高光、動(dòng)態(tài)光源產(chǎn)生的陰影、半透明介質(zhì)的折射這些效果的屏幕運(yùn)動(dòng)和底層幾何的運(yùn)動(dòng)并不一致。重投影一旦錯(cuò)位歷史顏色拿過(guò)來(lái)的就是另一個(gè)物體的顏色混合出來(lái)的結(jié)果就是鬼影。傳統(tǒng)TAA靠顏色裁剪color clipping來(lái)緩解這個(gè)問(wèn)題把歷史顏色限制在當(dāng)前幀鄰域的顏色范圍內(nèi)超出范圍就丟棄。這個(gè)策略在漫反射為主的場(chǎng)景里夠用但在光追場(chǎng)景里一次鏡面反射就能讓鄰域顏色完全超出裁剪范圍歷史信息被整塊扔掉時(shí)間累積等于白做。ATAA正是沖著這個(gè)矛盾來(lái)的。2. ATAA把歷史信息從開(kāi)關(guān)變成了旋鈕三個(gè)核心機(jī)制2.1 傳統(tǒng)TAA在光追場(chǎng)景下的失效點(diǎn)先說(shuō)傳統(tǒng)TAA為什么在光追場(chǎng)景下特別容易翻車。固定權(quán)重混合把歷史幀的貢獻(xiàn)限制在一個(gè)固定比例比如0.1意味著不管歷史幀質(zhì)量再好也只能給這么多信任不管當(dāng)前幀噪聲再大也得留下90%噪聲。光照突變時(shí)歷史信息已經(jīng)錯(cuò)了固定權(quán)重還按老比例混合殘影就會(huì)拖好幾幀。加上顏色裁剪之后情況變得更微妙。漫反射場(chǎng)景中鄰域顏色比較連續(xù)裁剪框能有效兜住異常值但光追場(chǎng)景中高光路徑、鏡面反射、陰影邊緣讓鄰域顏色分布非常分散裁剪框要么剪得太窄把有效信息全剪掉要么剪得太寬讓鬼影溜進(jìn)來(lái)。我實(shí)際調(diào)試時(shí)的感受是傳統(tǒng)TAA在光追里像一個(gè)拿著閘刀的配電工要么全通要么全斷。它沒(méi)有辦法表達(dá)這個(gè)像素歷史可信度六成、那個(gè)像素歷史可信度九成五。2.2 鄰域差異感知ATAA的自適應(yīng)權(quán)重模型ATAA的核心改動(dòng)是把歷史混合權(quán)重從一個(gè)全局常數(shù)變成一個(gè)與局部統(tǒng)計(jì)量綁定的動(dòng)態(tài)值。怎么動(dòng)態(tài)靠?jī)蓚€(gè)東西當(dāng)前幀的鄰域方差以及歷史和當(dāng)前的顏色差異。先算當(dāng)前幀像素周圍的亮度和方差。方差的含義是這個(gè)局部區(qū)域的當(dāng)前樣本有多不穩(wěn)定。如果周圍像素顏色都很接近說(shuō)明這里采樣收斂得不錯(cuò)歷史值更有參考意義如果周圍像素差異巨大說(shuō)明這里是高噪聲區(qū)或者幾何邊緣歷史值的參考意義就要打折扣。再看歷史顏色和當(dāng)前顏色的差異。這個(gè)差異是時(shí)間變化和噪聲抖動(dòng)的疊加。如果差異遠(yuǎn)大于局部噪聲水平說(shuō)明光照變了或者重投影錯(cuò)了歷史值不該信如果差異和局部噪聲水平相稱說(shuō)明它只是普通采樣抖動(dòng)歷史值應(yīng)該被保留并累積。把這兩個(gè)量放到一個(gè)公式里置信度等于歷史有效性與一個(gè)衰減因子相乘衰減因子由時(shí)間差異與局部噪聲方差的比值決定。最后用置信度把a(bǔ)lpha從0.02到0.2之間平滑地推出來(lái)。這就是自適應(yīng)三個(gè)字的具體含義。2.3 分級(jí)累積策略三態(tài)切換與銳利邊緣保護(hù)把上面算出的置信度落到實(shí)際操作上會(huì)形成三種狀態(tài)。高置信度時(shí)alpha取大值歷史顏色深度累積等效spp快速上升畫(huà)面迅速趨于干凈低置信度時(shí)alpha取小值幾乎完全拋棄歷史退回當(dāng)前幀的原始采樣寧可保留噪聲也不引入鬼影中間狀態(tài)則按置信度連續(xù)過(guò)渡不讓畫(huà)面出現(xiàn)明顯的接縫。這樣的三態(tài)切換在視覺(jué)上會(huì)產(chǎn)生一個(gè)很有意思的效果畫(huà)面干凈的區(qū)域越來(lái)越干凈而真正有變化的區(qū)域會(huì)以極低延遲刷新。這是我認(rèn)為ATAA比傳統(tǒng)TAA更符合實(shí)時(shí)渲染直覺(jué)的地方——觀眾的目光會(huì)被動(dòng)態(tài)區(qū)域吸引動(dòng)態(tài)區(qū)域恰恰不能有拖影。還有一個(gè)關(guān)鍵細(xì)節(jié)銳利邊緣保護(hù)。重投影在邊緣處經(jīng)常錯(cuò)位半個(gè)像素直接混合會(huì)讓邊緣持續(xù)抖動(dòng)。ATAA會(huì)在鄰域統(tǒng)計(jì)階段單獨(dú)計(jì)算深度梯度和法線梯度如果當(dāng)前像素位于強(qiáng)邊緣置信度會(huì)被額外壓低同時(shí)用邊緣方向的單側(cè)鄰域來(lái)做方差估計(jì)避免把邊界兩側(cè)完全不同的顏色平均到一起。一開(kāi)始可以不做這個(gè)優(yōu)化但做完了之后邊緣質(zhì)量會(huì)明顯提升。3. 可復(fù)現(xiàn)的ATAA GPU實(shí)現(xiàn)框架從緩沖設(shè)計(jì)到Shader偽代碼3.1 緩沖布局需要哪些輸入歷史緩存怎么設(shè)計(jì)動(dòng)手實(shí)現(xiàn)之前先把緩沖理清楚。當(dāng)前幀必需的輸入有四張帶噪顏色RGBA32F或RGBA16F、深度、法線最好用Octahedral編碼壓縮成RG16F、運(yùn)動(dòng)向量RG16F。這四張?jiān)谘舆t渲染管線或光追管線里基本都有現(xiàn)成的接入成本很低。歷史緩沖建議按兩張來(lái)設(shè)計(jì)。一張存歷史累積顏色和置信度格式用RGBA16FRGB三個(gè)通道存顏色A通道存上一幀寫(xiě)下的置信度。另一張存歷史深度和歷史法線格式用R8G8B8A8RG存壓縮法線B存深度的高八位A存材質(zhì)ID或遮擋標(biāo)記。為什么不直接把深度存32位因?yàn)锳TAA的歷史校驗(yàn)只需要分辨是不是差很多16位歸一化深度配合兩個(gè)閾值足夠用省下的帶寬非常可觀。3.2 主Shader偽代碼一個(gè)可以抄進(jìn)自己管線的版本下面這份偽代碼大概覆蓋了ATAA的核心邏輯我盡量寫(xiě)得貼近可以直接落地的程度f(wàn)loat4 ATAAMain(float2 uv) { // 輸入采樣 float3 curColor texScene[uv].rgb; float2 velocity texVelocity[uv].xy; float curDepth texDepth[uv].r; float3 curNormal DecodeOct(texNormal[uv].rg); // 1) 重投影坐標(biāo) float2 reprojUV uv - velocity; // 2) 歷史有效性檢測(cè) float histDepth texHistoryDepth[reprojUV].r; float depthValid (abs(curDepth - histDepth) max(0.1, curDepth * 0.05)) ? 1.0 : 0.0; float3 histNormal DecodeOct(texHistoryNormal[reprojUV].rg); float normalValid saturate(dot(curNormal, histNormal) * 2.0 - 1.0); float histValid depthValid * normalValid * texHistoryAccum[reprojUV].a; // 3) 鄰域亮度均值與方差 float meanLum 0.0; float varLum 0.0; for (int dy -1; dy 1; dy) for (int dx -1; dx 1; dx) { float3 n texScene[uv float2(dx, dy) * texelSize].rgb; float l luminance(n); meanLum l; varLum l * l; } meanLum / 9.0; varLum max(0.0, varLum / 9.0 - meanLum * meanLum); float cv varLum / max(meanLum * meanLum, 1e-5); // 4) 時(shí)間差異評(píng)估 float3 histColor texHistoryAccum[reprojUV].rgb; float temporalDiff luminance(abs(histColor - curColor)); float diffCV temporalDiff / max(meanLum, 1e-5); // 5) 置信度與自適應(yīng) alpha float trust histValid * exp(-diffCV / (kCvScale cv * kCvAdaptive)); float alpha lerp(kAlphaMin, kAlphaMax, trust); // 6) 混合與輸出 float3 outColor lerp(curColor, histColor, alpha); texHistoryAccum[uv] float4(outColor, trust); return float4(outColor, trust); }幾個(gè)實(shí)現(xiàn)上容易忽視的點(diǎn)我展開(kāi)說(shuō)。第三步里必須用亮度歸一化的變異系數(shù)不要直接用原始RGB方差。光追場(chǎng)景的HDR顏色范圍跨度極大同一套方差閾值在暗部和亮部表現(xiàn)完全不同。歸一化之后暗部亮部共用一個(gè)閾值才有意義。第五步的指數(shù)衰減比線性衰減好用。原因是一旦時(shí)間差異超過(guò)噪聲水平的兩三倍大概率是真實(shí)變化歷史權(quán)重需要以一個(gè)比較陡峭的速度掉下去而不是勻速衰退。指數(shù)函數(shù)天然滿足小差異保留、大差異快速遺忘的需求。3.3 重投影邊界與歷史緩沖生命周期管理重投影坐標(biāo)經(jīng)常跑到屏幕外也經(jīng)常跑到屏幕邊緣。屏幕上邊緣以外的歷史緩沖內(nèi)容可能是上一幀還沒(méi)有的像素或者根本不是同一場(chǎng)景。穩(wěn)妥做法是在重投影采樣時(shí)用border clamp讓它采到無(wú)效值無(wú)效值的置信度在后續(xù)會(huì)被壓到接近零alpha自動(dòng)退到最小值。歷史緩沖的生命周期管理同樣容易被忽略。每幀所有像素都會(huì)被寫(xiě)入但寫(xiě)入的不一定都是有效累積結(jié)果。低置信度像素如果直接把當(dāng)前顏色寫(xiě)進(jìn)歷史下一幀它的信度雖然低顏色本身卻變成歷史了。我的處理是在寫(xiě)歷史前額外做一次保護(hù)如果置信度低于一個(gè)極小閾值歷史顏色寫(xiě)入當(dāng)前輸入顏色但歷史置信度寫(xiě)入一個(gè)很小的值相當(dāng)于給這個(gè)位置重置讓它從下一幀重新開(kāi)始累積。相機(jī)瞬移、切換場(chǎng)景這種全局性失效的情況靠像素級(jí)置信度已經(jīng)不夠了。工程上通常會(huì)檢測(cè)平均置信度或者運(yùn)動(dòng)向量異常占比一旦超過(guò)閾值就整張清空歷史緩沖。這個(gè)全屏重置在一幀內(nèi)自動(dòng)完成視覺(jué)上表現(xiàn)為一兩幀的噪聲突增之后快速恢復(fù)。4. ATAA實(shí)測(cè)哪些參數(shù)真正影響畫(huà)面質(zhì)量4.1 四類測(cè)試場(chǎng)景與基線對(duì)比我在自研渲染器里做了一組對(duì)照測(cè)試統(tǒng)一用1spp路徑追蹤輸出帶噪圖分別走傳統(tǒng)TAA和ATAA比較靜止畫(huà)面、平移相機(jī)、動(dòng)態(tài)光源、遮擋物四種情況。場(chǎng)景傳統(tǒng)TAAATAA靜止視角慢反射房間1秒后趨于穩(wěn)定但表面仍有輕微滑動(dòng)噪聲3到4幀后快速干凈長(zhǎng)時(shí)間靜止幾乎無(wú)閃爍相機(jī)平移鏡面反射反射高光處明顯殘影邊緣有拖尾殘影大幅減少反射區(qū)域輕微噪聲但無(wú)錯(cuò)誤累積旋轉(zhuǎn)點(diǎn)光源陰影陰影邊緣滯后約半秒產(chǎn)生陰影殘影陰影跟隨及時(shí)邊緣略噪但不再拖影前方有動(dòng)態(tài)角色經(jīng)過(guò)角色背后出現(xiàn)明顯鬼影帶鬼影帶明顯收窄靜止背景幾乎未受影響主觀觀感上最直觀的變化是動(dòng)態(tài)場(chǎng)景的拖影。傳統(tǒng)TAA在我把裁剪強(qiáng)度調(diào)大之后靜止畫(huà)面勉強(qiáng)干凈但角色一走動(dòng)就留下明顯的拖尾ATAA在同等條件下拖尾長(zhǎng)度縮短了至少七成。代價(jià)是動(dòng)態(tài)區(qū)域會(huì)稍微多一點(diǎn)噪聲這個(gè)噪聲視覺(jué)上更像膠片的顆粒感不像鬼影那么惹眼。4.2 核心參數(shù)對(duì)畫(huà)質(zhì)的影響與推薦起始值A(chǔ)TAA的參數(shù)沒(méi)有太多但每一個(gè)都直接影響畫(huà)質(zhì)走向。我列一下我測(cè)試下來(lái)的推薦起始值以及參數(shù)偏向極端時(shí)的副作用。參數(shù)推薦區(qū)間調(diào)大的效果調(diào)小的效果kAlphaMin0.01~0.03變化區(qū)域更新太慢產(chǎn)生殘影變化區(qū)域噪聲明顯kAlphaMax0.15~0.25靜止區(qū)域變干凈更快靜止區(qū)域收斂變慢閃爍增加kCvScale0.3~0.8對(duì)時(shí)間差異更敏感容易丟歷史對(duì)時(shí)間差異更遲鈍可能收入錯(cuò)誤歷史kCvAdaptive1.5~3.0高噪聲區(qū)也不舍得放棄歷史高噪聲區(qū)過(guò)早放棄歷史累積效果變差depthThreshold0.05~0.1深度校驗(yàn)寬松歷史容易混入遮擋深度校驗(yàn)嚴(yán)格邊緣像素頻繁重置調(diào)試時(shí)最重要的技巧是把置信度alpha可視化成一張灰度圖。輸出buffer的alpha通道就是置信度直接渲染成屏幕效果。你會(huì)立刻看到邊緣和遮擋區(qū)域置信度低平坦表面置信度高。如果置信度圖的空間分布和實(shí)際場(chǎng)景不對(duì)應(yīng)問(wèn)題一定出在輸入信息上而不是最后的混合公式。這個(gè)排查順序能省大量時(shí)間。4.3 值得關(guān)注的主觀畫(huà)質(zhì)差異有些差異用數(shù)值指標(biāo)很難衡量但肉眼感受非常強(qiáng)烈。第一個(gè)是收斂感。傳統(tǒng)TAA在靜態(tài)場(chǎng)景里要大概二十到三十幀才能讓畫(huà)面完全穩(wěn)定下來(lái)ATAA在四五幀內(nèi)就讓人覺(jué)得已經(jīng)干凈了。這可能因?yàn)锳TAA在高置信區(qū)域會(huì)迅速推高累計(jì)權(quán)重讓降噪過(guò)程的前幾幀就展現(xiàn)出明顯效果。第二個(gè)差異是光照變化時(shí)的反應(yīng)速度。旋轉(zhuǎn)光源掃過(guò)一面墻時(shí)傳統(tǒng)TAA會(huì)有一個(gè)明顯的舊光照殘留過(guò)程墻面亮度變化像在慢鏡頭播放ATAA則幾乎同步刷新新光照到達(dá)的瞬間就切換過(guò)去了。這種即時(shí)反饋在交互操作場(chǎng)景里體驗(yàn)差異非常大畢竟人眼對(duì)動(dòng)態(tài)變化本來(lái)就敏感。第三個(gè)差異是反射區(qū)。鏡面反射是光追場(chǎng)景里歷史信息最不可信的區(qū)域之一因?yàn)榉瓷鋬?nèi)容的變化速度不等于物體運(yùn)動(dòng)速度。ATAA對(duì)這類區(qū)域會(huì)自動(dòng)拉低歷史信任度反射畫(huà)面會(huì)更噪但不會(huì)出現(xiàn)錯(cuò)誤的高光殘影。我覺(jué)得在游戲體驗(yàn)里略噪但正確比干凈但錯(cuò)誤容易接受得多。5. 接ATAA最容易踩的三個(gè)坑從現(xiàn)象到根因的完整排查鏈路5.1 靜態(tài)畫(huà)面還在閃色調(diào)映射與置信度計(jì)算的順序問(wèn)題現(xiàn)象很迷惑場(chǎng)景完全靜止ATAA跑起來(lái)之后畫(huà)面還是在閃爍。排查第一步先確認(rèn)不是原始噪聲把ATAA關(guān)掉原始帶噪圖閃是正常的。開(kāi)了ATAA還閃說(shuō)明置信度判斷在震蕩。我當(dāng)時(shí)的排查鏈路是這樣走的先看置信度圖發(fā)現(xiàn)平坦區(qū)域的置信度在0.9和0.3之間來(lái)回跳。進(jìn)一步看數(shù)據(jù)發(fā)現(xiàn)當(dāng)前幀和歷史顏色的時(shí)間差明明很小但歸一化的分母也小得可憐——這是暗部區(qū)域。暗部像素亮度均值只有0.01左右時(shí)間差0.0005和0.005在絕對(duì)數(shù)值上差得很遠(yuǎn)但在歸一化后都會(huì)被放大成大數(shù)字導(dǎo)致置信度抖動(dòng)。根因是采樣來(lái)的顏色還在線性HDR空間亮度均值分布跨越好幾個(gè)數(shù)量級(jí)。解決方式是在計(jì)算diffCV時(shí)給分子分母都做對(duì)數(shù)化或者飽和度映射處理讓暗部的微小抖動(dòng)不會(huì)被當(dāng)成劇烈變化。我用了一個(gè)簡(jiǎn)化做法把亮度值做一次冪變換再到歸一化公式里效果立竿見(jiàn)影。調(diào)過(guò)之后暗部區(qū)域的置信度穩(wěn)定在0.8以上閃爍消失。5.2 快速旋轉(zhuǎn)鏡頭時(shí)的嚴(yán)重鬼影運(yùn)動(dòng)向量的多義性另一個(gè)高頻故障是快速旋轉(zhuǎn)鏡頭時(shí)鬼影加重。傳統(tǒng)TAA有這個(gè)問(wèn)題換到ATAA之后如果沒(méi)做運(yùn)動(dòng)向量修復(fù)還會(huì)更明顯——因?yàn)锳TAA在低置信區(qū)域會(huì)迅速拋棄歷史但如果問(wèn)題壓根出在重投影坐標(biāo)錯(cuò)了置信度再低也找不到正確的歷史坐標(biāo)。排查時(shí)我把運(yùn)動(dòng)向量可視化發(fā)現(xiàn)物體邊緣的向量值出現(xiàn)明顯跳變。原因在于運(yùn)動(dòng)向量緩沖通?;谏疃葓D的差分來(lái)計(jì)算物體邊緣的深度不連續(xù)差分出來(lái)的向量在邊緣兩側(cè)各取一半重投影坐標(biāo)就偏了半個(gè)像素甚至更多。半個(gè)像素的偏移在靜態(tài)場(chǎng)景中還能靠邊緣保護(hù)補(bǔ)救快速旋轉(zhuǎn)時(shí)偏移量大增鬼影馬上冒出來(lái)。修復(fù)方案是做運(yùn)動(dòng)向量的邊緣修復(fù)對(duì)全屏運(yùn)動(dòng)向量做一次3x3范圍的膨脹讓邊緣像素使用同側(cè)物體的運(yùn)動(dòng)向量避免背景運(yùn)動(dòng)向量污染前景邊緣。也可以用深度感知的做法把最接近當(dāng)前深度的鄰域運(yùn)動(dòng)向量挑出來(lái)。驗(yàn)證時(shí)同時(shí)觀察邊緣置信度圖邊緣區(qū)域的置信度不再出現(xiàn)帶狀低谷鬼影問(wèn)題基本解決。5.3 鏡面反射區(qū)出現(xiàn)色斑材質(zhì)ID校驗(yàn)與分類歷史緩存第三個(gè)坑比較隱蔽鏡面反射區(qū)域正常但反射上疊加了一些彩色色斑像潤(rùn)滑油浮在水面上。這個(gè)現(xiàn)象最初很難定位因?yàn)樯叩念伾皇呛谏膊皇前咨晴R面反射里的高光顏色。排查思路最終指向歷史緩存區(qū)的內(nèi)容混入。鏡面反射像素的最終顏色來(lái)自多個(gè)表面直接可見(jiàn)的表面和反射中可見(jiàn)的表面。這兩者的材質(zhì)ID完全不同。我的歷史緩存只記錄了一層材質(zhì)反射區(qū)域項(xiàng)目的聲音于是反射中的內(nèi)容寫(xiě)進(jìn)歷史后下一幀采樣到的卻是當(dāng)前可見(jiàn)表面兩者顏色一混合色斑出現(xiàn)。修復(fù)方式是給歷史緩沖增加一個(gè)材質(zhì)分類位記錄該像素是否含有次級(jí)反射貢獻(xiàn)。對(duì)包含次級(jí)反射貢獻(xiàn)的像素ATAA要把它當(dāng)作低歷史信任度像素處理而不是直接禁掉歷史累積。更好的方案是給鏡面反射單獨(dú)開(kāi)一條歷史緩存或者把反射貢獻(xiàn)從主顏色里分離出來(lái)分別做時(shí)間濾波再合成。后者的顯存開(kāi)銷更大但效果最干凈。6. ATAA的適用邊界與后續(xù)演進(jìn)空間6.1 ATAA能取代空間濾波和機(jī)器學(xué)習(xí)降噪嗎直接給結(jié)論不能完全取代。ATAA在時(shí)間維度做文章它利用的是同一像素在不同幀的采樣互補(bǔ)性但1spp下鏡面高光、窄反射這類極端高頻區(qū)域噪聲方差大到即使時(shí)間累積幾十幀也未必壓得住。這種區(qū)域必須先靠空間濾波把方差壓到一個(gè)合理量級(jí)再交給ATAA做時(shí)間穩(wěn)定。實(shí)際工程中我更推薦組合使用先跑一個(gè)輕量空間濾波做初步降噪再跑ATAA做時(shí)間累積和穩(wěn)定。空間濾波的核盡量小只壓高頻噪聲ATAA負(fù)責(zé)長(zhǎng)時(shí)間累積、動(dòng)態(tài)場(chǎng)景的響應(yīng)和邊緣穩(wěn)定。這個(gè)組合在畫(huà)質(zhì)和性能上比任何單打獨(dú)斗的方案都均衡。機(jī)器學(xué)習(xí)降噪又是另一條路線它擅長(zhǎng)在單幀里直接恢復(fù)近似無(wú)噪圖像但容易產(chǎn)生時(shí)間上的不一致靜態(tài)畫(huà)面會(huì)像呼吸燈一樣忽亮忽暗。ATAA的置信度圖恰好可以給ML降噪提供時(shí)間一致性引導(dǎo)兩者的關(guān)系更像是互補(bǔ)而不是互相替代。6.2 與超分辨率方案銜接的可能性DLSS、FSR這類超分方案的核心是低分辨率渲染、高分辨率輸出時(shí)間濾波組件在超分管線里承擔(dān)了大量穩(wěn)定畫(huà)面的工作。ATAA產(chǎn)出的置信度圖天然適合作為超分方案的指導(dǎo)信息因?yàn)樗梦淖种笜?biāo)描述了這個(gè)像素歷史信息有多可信。具體銜接上可以把ATAA輸出的alpha通道當(dāng)作超分銳化強(qiáng)度的調(diào)制因子。置信度高的區(qū)域銳化可以更激進(jìn)細(xì)節(jié)更清晰置信度低的區(qū)域必須減少銳化否則會(huì)把噪聲邊緣放大成線條。我試過(guò)用這個(gè)思路改造簡(jiǎn)單的雙線性超分流程邊緣穩(wěn)定性的提升非常明顯。如果未來(lái)要走機(jī)器學(xué)習(xí)超分ATAA的置信度圖也可以作為網(wǎng)絡(luò)輸入特征之一幫助網(wǎng)絡(luò)學(xué)會(huì)區(qū)分這是高頻紋理和這是歷史殘影。這種特征在傳統(tǒng)方案里需要額外的網(wǎng)絡(luò)預(yù)測(cè)才能得到ATAA直接送出來(lái)成本和精度上都劃算。6.3 落地之后的一些體會(huì)把ATAA接進(jìn)管線之后我最大的感受是該遺忘的時(shí)候必須快速遺忘比該累積的時(shí)候狠狠累積更重要。以前調(diào)TAA參數(shù)我總想著怎么把歷史權(quán)重拉高讓畫(huà)面更干凈結(jié)果每次都被鬼影教育換到ATAA思路之后我開(kāi)始主動(dòng)給歷史信息留后路讓低置信像素快速重置反而得到了更干凈的整體畫(huà)面。調(diào)參過(guò)程中最有價(jià)值的工具不是幀率曲線也不是PSNR統(tǒng)計(jì)而是把置信度圖畫(huà)出來(lái)看。它像一張CT掃描片能直接告訴你算法在哪些區(qū)域喪失了判斷力。一旦置信度圖看起來(lái)邏輯自洽最后的成像質(zhì)量通常不會(huì)太差。如果你打算在自己的項(xiàng)目里嘗試建議從kAlphaMin和kAlphaMax兩個(gè)參數(shù)先動(dòng)手把運(yùn)動(dòng)場(chǎng)景的拖影調(diào)到可以接受的程度再回頭調(diào)置信度公式里的兩個(gè)縮放系數(shù)。方向?qū)α酥笫O碌木褪切捱呥吔墙堑膯?wèn)題了。