2015-05-30 72 views
10

我想在GLSL中編寫一個函數,它將帶符號的距離返回到矩形。矩形是軸對齊的。我感覺有點卡住了;我無法將我的頭圍繞在我需要做的工作上。計算點和矩形之間的帶符號距離

我想出的最好的是這樣的:

float sdAxisAlignedRect(vec2 uv, vec2 tl, vec2 br) 
{ 
    // signed distances for x and y. these work fine. 
    float dx = max(tl.x - uv.x, uv.x - br.x); 
    float dy = max(tl.y - uv.y, uv.y - br.y); 
    dx = max(0.,dx); 
    dy = max(0.,dy); 
    return sqrt(dx*dx+dy*dy); 
} 

其產生的矩形,看起來像:

enter image description here

該行顯示的矩形距離。它工作正常,但只適用於矩形外的距離。矩形內的距離是一個靜態的0.

如何使用統一公式獲得矩形內的準確距離?

回答

13

這個怎麼樣...

float sdAxisAlignedRect(vec2 uv, vec2 tl, vec2 br) 
{ 
    vec2 d = max(tl-uv, uv-br); 
    return length(max(vec2(0.0), d)) + min(0.0, max(d.x, d.y)); 
} 

這裏的result,其中綠色標記的正距離和紅色負(代碼如下):

enter image description here


故障:

  1. 從x和y邊界獲取帶符號的距離。 u - leftright - u是兩個x軸距離。取這些值的最大值給出最接近邊界的帶符號距離。查看d.xd.y分別顯示在下面的圖片中。

  2. 聯合x和y:

    1. 如果兩個值是負的,取最大值(即最接近的邊界)。這是通過min(0.0, max(d.x, d.y))完成的。

    2. 如果只有一個值是正的,這就是我們想要的距離。

    3. 如果兩個值是正的,最接近的點是轉角,在這種情況下,我們需要的長度。這可以結合上面的情況通過採取長度無論如何,並確保兩個值都是正面的:length(max(vec2(0.0), d))

    這兩個等式是互斥的,即只有一個會產生一個非零值,並且可以相加。

enter image description hereenter image description here


void mainImage(out vec4 fragColor, in vec2 fragCoord) 
{ 
    vec2 uv = fragCoord.xy/iResolution.xy; 
    uv -= 0.5; 
    uv *= vec2(iResolution.x/iResolution.y,1.0); 
    uv += 0.5; 
    float d = sdAxisAlignedRect(uv, vec2(0.3), vec2(0.7)); 
    float m = 1.0 - abs(d)/0.1; 
    float s = sin(d*400.0) * 0.5 + 0.5; 
    fragColor = vec4(s*m*(-sign(d)*0.5+0.5),s*m*(sign(d)*0.5+0.5),0,1); 
} 
+0

好極了!完美的工作。 – tenfour

+0

@jozxyqk你是怎麼想出這個功能的? –

+0

@ v.shashenko真的試錯了。我已經更新了答案,以便更詳細地介紹。 – jozxyqk