shader 中,fwidth 或者說 ddx ddy 到底是什麼意思?

時間 2021-05-31 05:29:06

1樓:mike

ddx(para)中的para可以是任何表示式或者是PS輸入的引數,GPU會平行計算每乙個畫素然後再執行ddx(para)。比如:

float2 texcoords = virtCoords.xy * virtTexelsWide;

float2 dx = ddx(texcoords);

float2 dy = ddy(texcoords);

相鄰的畫素都會執行virtCoords.xy * virtTexelsWide計算然後再進行相減。

2樓:光陽果

關於fwidth

fwidth(v) = abs( ddx(v) + ddy(v))

ddx(v) = 該畫素點右邊的v值 - 該畫素點的v值

ddy(v) = 該畫素點下面的v值 - 該畫素點的v值

ddx(v) ddy(v) 在計算出結果的同時,也會儲存該畫素的v值,這樣它周圍的畫素才能獲取到該點的v值

ddx(float3(1,2,3)) = float3(0,0,0) //因為使用該shader的所有畫素輸出的記錄值都是 float3(1,2,3)那麼差值就為float3(0,0,0)

fwidth(Position) 就是計算出該畫素與相鄰兩個畫素的位置的差值

fwidth(Normal) 就是計算出該畫素與相鄰兩個畫素的法線的差值

fwidth(Color) 就是計算出該畫素與相鄰兩個畫素的Color的差值

fwidth(UV) 就是計算出該畫素與相鄰兩個畫素的UV的差值

fwidth ddx ddy 都是有過載形式的。即你輸入什麼型別的引數就是什麼返回值:

float fwidth(float v); float ddx(float v); float ddy(float v);

float2 fwidth(float2 v); floa2t ddx(float v); float2 ddy(float v);

float3 fwidth(float3 v); float3 ddx(float v); float ddy(float v);

3樓:Seto

關於ddx和ddy可以看一下我的這個文章,ddx和ddy只與其中的3個畫素有關,並且4個畫素共享ddx和ddy的值。

Unity HDRP Custom Pass (Post processing) 後處理特效學習(二)總結 - Unity

4樓:Alec

可以求MipMap Level:

想象一下,你有乙個Quad,攝像機的位置又剛好在乙個不錯的位置,Texture的texel剛好和螢幕上的pixel一一對應,這是一種完美的情況。

那麼假如這個Quad離攝像機非常遠呢,這種情況下你在螢幕上占用的pixel就非常小了,可你的texture還是那麼大,結果就是你螢幕上的那塊區域因為取樣不足,有明顯的走樣。

那麼解決方案就很明顯了,既然乙個pixel覆蓋了多個texel,我增加取樣不就ok了,沒錯,我們為遠處的乙個畫素進行多次取樣,計算出來它最終的顏色。

但是仔細想下,我們是否有必要為遠處的少部分畫素投入這麼多計算嗎,沒必要,因為遠處的畫素就算沒那麼精準你可能也留意不到。更何況考慮到移動平台gpu和視訊記憶體之間的頻寬太低,所以你對texture取樣太多的話效能損失慘重。

這就引來了mipmap,我提前把取樣結果計算好不就行了嗎,減少大量的對單一紋理取樣,以原圖為0級,接下來每一級的大小都是前一級的一半,面積就是前一級的四分之一,最後你的整個texture大小是1.33倍,只增加了0.33的儲存,換來非常大的效能提公升。

那麼怎麼計算level呢,很簡單,可以計算乙個畫素a的上面乙個畫素b和右邊乙個畫素c在uv座標空間中的最大長度L(ab,ac)

這裡dx就是ddx,dy就是ddy

du/dx是u對x的偏微分,可以理解為pixel在x方向變換了乙個單位,那麼texture在u方向上變換多少,du/dy是u沿y方向的變化率,dv/dx是v沿著x方向的變化率,dv/dy是v沿著y方向的變化率。

L就是我們求出的長度,還缺乙個Level

Level = log2(L)

舉例來說,L為4,那麼結果為2,也就是我們要用第3張圖,可以理解為第幾層變成乙個畫素的大小。

別的一些小細節:

有時候為了避免不同mipmap層交界處會有接縫或者不連續,可以不只對一層mipmap取樣,對兩層取樣,每層做乙個雙線性過濾,最後把兩個層各自的結果合起來,加乙個權重計算最終結果,這就是三線性過濾。

一些遊戲UI是不用勾選Generate Mipmaps選項的,除了占用記憶體,別的沒任何用。

5樓:minggoddess

你這個問題有了上面兩個specs需要理解的就是 ddx(para)這個para是什麼了

三裡面有例子可以是

ddx(uv)

ddx(pos)

含義是(pix1UV-pix2UV)/(pix1-2)綜上你問的那個引數就是被光柵化的某個頂點屬性通過ddxddy可以看這個屬性值在相鄰兩個畫素間的變化率

fwidth是把這兩個方向的變化abs加一起看總的變化大小含義就是在xy方向變化越大的值越大

6樓:

當代GPGPU在畫素化的時候一般是以2x2畫素為基本單位,那麼在這個2x2畫素塊當中,右側的畫素對應的fragment的x座標減去左側的畫素對應的fragment的x座標就是ddx;下側畫素對應的fragment的座標y減去上側畫素對應的fragment的座標y就是ddy。

ddx和ddy代表了相鄰兩個畫素在裝置座標系當中的距離,據此可以判斷應該使用哪一層的貼圖LOD(如果貼圖支援LOD,也就是MIPS)。這個距離越大表示三角形離開攝像機越遠,需要使用更小解析度的貼圖;反之表示離開攝像機近,需要使用更高解析度的貼圖。

也就是說,在開啟貼圖LOD功能的情況下,這兩個值會被GPGPU的貼圖單元自動參照,從而決定實際訪問的MIPS層級。

而fragment shader當中如何使用這兩個值則由寫shader的人自己決定。

7樓:Bay

這個大佬翻譯的國外大佬的資料,講解的比較詳細。我看完了也只是大概懂了,具體細節可能得你自己去測試吧。

8樓:「已登出」

每個頂點著色器的輸出屬性在光柵化後就變成了乙個離散函式Fp(x,y)p代表某個頂點著色器的輸出屬性 x,y是光柵化後的片段座標你錯誤的理解了ddx,ddy的引數型別

ddx,ddy需要的引數是片段著色器的輸入屬性(對應頂點著色器的輸出屬性)

ddx/ddy的含義是該屬性的離散函式在當前片段位置的x或者y方向上的近似導數也就是差分

fwidth就是abs(ddx(p)) + abs(ddy(p))

Shader中的條件分支能否節省shader的效能?

對於voita之前的架構,如果if導致warp內的執行緒走不同分支,由於simt的以warp為排程單位,且warp內每個執行緒執行相同指令序列,所以這時候不能加速 由於拆散了訪存等原因,效能可能會下降。volta及Turing架構,支援執行緒走不同分支,沒有了上述問題,也許會有收益。 看具體情況,現...

在Unity 3D中,shader是何時編譯的,在何時加載入視訊記憶體中的?

minggoddess 以下是我的看法 我先講下texture資源在dx12向api裡的這個過程很簡單 create的時候建立到視訊記憶體 bindtex的時候把address發給gpu 接著看shader資源它比tex多了從hlsl到binarycode的階段也就是compile shader一開...

推薦系統或者ctr預估中,如何區分或者如何定義高頻低頻特徵 有通用的閾值區分嗎?

失落的薩特 問題中的頻率的定義是什麼。比如在樣本中出現的次數?特徵非空非零值的覆蓋度?還是對於正負樣本的區分度?比如實際情況會考慮的,乙個是特徵的覆蓋度,即非空非零的樣本比例,如果覆蓋度太低那麼這個特徵對於大部分樣本的學習沒有任何幫助 乙個是這個特徵的區分度,即這個特徵能不能把待排序的樣本區分開來。...