HLSL ddx / ddy


HLSL ddx / ddy

  在光柵化的時刻,GPUs會在同一時刻並行運行很多Fragment Shader,但是並不是一個pixel一個pixel去執行的,而是將其組織在2x2的一組pixels分塊中,去並行執行。

  偏導數就正好是計算的這一塊像素中的變化率。從下圖可以看出來ddx 就是右邊的像素塊的值減去左邊像素塊的值,而ddy就是下面像素塊的值減去上面像素塊的值。其中的x,y代表的是屏幕坐標。

    

 

偏導數的應用

1、LOD的確定。

  

  大家應該都知道mipmap 的用處,但是可能並不知道mipmap的核心在選擇到底用那一塊mipmap的level時,靠的就是偏導數。屏幕空間的貼圖UV偏導數過大的時候代表貼圖離我們過遠,就會選擇低等級的mipmap。

  比如,原圖的LOD=1,次大的LOD=2,依此類推。

  

  在Shader中使用tex2D(tex, uv)的時候相當於在GPU內部展開成下面:
    

tex2D(sampler2D tex, float4 uv)
{
    float lod = CalcLod(ddx(uv), ddy(uv)); uv.w= lod; return tex2Dlod(tex, uv); }

 

2、計算法線。

  如果調用ddx(Pos),和ddy(Pos)這個代表求出相鄰的2個像素塊之間坐標的差值,即下面圖中的紅色和綠色2個矢量,而這2個矢量都在這個三角形的平面上,那么執行 normalize( cross(ddx(pos),ddy(pos)) ) 就求出的面的法線。

  但是這里要注意,在HlSL上面,或者Unity上面要寫成normalize( cross(ddy(pos),ddx(pos)) ),不然法線是反向的。這個是由於左右手坐標系引起的。

void surf (Input IN, inout SurfaceOutput o)

{

o.Albedo = normalize(cross(ddy(IN.worldPos),ddx(IN.worldPos)));

}

  

3、貼圖加強勾邊。

void surf (Input IN, inout SurfaceOutput o)

{

half4 c = tex2D(_MainTex, IN.uv_MainTex);

//c += ddx(c)*2 + ddy(c)*2;這行代碼開啟和關閉的效果

o.Albedo = c.rgb;

o.Alpha = c.a;

}

  

  左邊是直接顯示圖片,右邊是在圖片上面加上x和y的偏導數。

 【fwidth

  This function computes the following: abs(ddx(x)) + abs(ddy(x)).

  

參考:

1、https://blog.csdn.net/wylionheart/article/details/78026707

2、http://www.aclockworkberry.com/shader-derivative-functions/#footnote_3_1104

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM