前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >2D Distance Functions

2D Distance Functions

作者头像
Ning@
发布2021-11-10 15:25:43
发布2021-11-10 15:25:43
1.3K00
代码可运行
举报
文章被收录于专栏:烤包子烤包子
运行总次数:0
代码可运行

Primitives


所有基本体都在原点处居中。您必须转换点以获得任意旋转、转换和缩放的对象(请参见下文)。

圆-精确

代码语言:javascript
代码运行次数:0
复制
float sdCircle( vec2 p, float r ) 
{ 
    return length(p) - r; 
}

线 - 精确   (https://www.shadertoy.com/view/lsXGz8)

代码语言:javascript
代码运行次数:0
复制
float sdLine( in vec2 p, in vec2 a, in vec2 b ) 
{ 
    vec2 pa = p-a, ba = b-a; 
    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); 
    return length( pa - ba*h ); 
}

盒子 - 精确

代码语言:javascript
代码运行次数:0
复制
float sdBox( in vec2 p, in vec2 b ) 
{ 
    vec2 d = abs(p)-b; 
    return length(max(d,vec2(0))) + min(max(d.x,d.y),0.0); 
}

菱形 - 精确   (https://www.shadertoy.com/view/XdXcRB)

代码语言:javascript
代码运行次数:0
复制
float sdRhombus( in vec2 p, in vec2 b ) 
{ 
    vec2 q = abs(p); 
    float h = clamp((-2.0*ndot(q,b)+ndot(b,b))/dot(b,b),-1.0,1.0); 
    float d = length( q - 0.5*b*vec2(1.0-h,1.0+h) ); 
    return d * sign( q.x*b.y + q.y*b.x - b.x*b.y ); 
}

等边三角形 - 精确   (https://www.shadertoy.com/view/Xl2yDW)

代码语言:javascript
代码运行次数:0
复制
float sdEquilateralTriangle( in vec2 p ) 
{ 
    const float k = sqrt(3.0); 
    p.x = abs(p.x) - 1.0; 
    p.y = p.y + 1.0/k; 
    if( p.x+k*p.y>0.0 ) p = vec2(p.x-k*p.y,-k*p.x-p.y)/2.0; 
    p.x -= clamp( p.x, -2.0, 0.0 ); 
    return -length(p)*sign(p.y); 
}

等腰三角形 - exact   (https://www.shadertoy.com/view/MldcD7)

代码语言:javascript
代码运行次数:0
复制
float sdTriangleIsosceles( in vec2 p, in vec2 q ) 
{ 
    p.x = abs(p.x); 
    vec2 a = p - q*clamp( dot(p,q)/dot(q,q), 0.0, 1.0 ); 
    vec2 b = p - q*vec2( clamp( p.x/q.x, 0.0, 1.0 ), 1.0 ); 
    float s = -sign( q.y ); 
    vec2 d = min( vec2( dot(a,a), s*(p.x*q.y-p.y*q.x) ), vec2( dot(b,b), s*(p.y-q.y) )); 
    return -sqrt(d.x)*sign(d.y); 
}

不均匀的胶囊 - exact   (https://www.shadertoy.com/view/4lcBWn)

代码语言:javascript
代码运行次数:0
复制
float sdUnevenCapsule( vec2 p, float r1, float r2, float h ) 
{ 
    p.x = abs(p.x); 
    float b = (r1-r2)/h; 
    float a = sqrt(1.0-b*b); 
    float k = dot(p,vec2(-b,a)); 
    if( k < 0.0 ) return length(p) - r1; 
    if( k > a*h ) return length(p-vec2(0.0,h)) - r2; return dot(p, vec2(a,b) ) - r1; 
}

三角形 - exact   (https://www.shadertoy.com/view/XsXSz4)

代码语言:javascript
代码运行次数:0
复制
float sdTriangle( in vec2 p, in vec2 p0, in vec2 p1, in vec2 p2 ) 
{ 
    vec2 e0 = p1-p0, e1 = p2-p1, e2 = p0-p2; 
    vec2 v0 = p -p0, v1 = p -p1, v2 = p -p2; 
    vec2 pq0 = v0 - e0*clamp( dot(v0,e0)/dot(e0,e0), 0.0, 1.0 ); 
    vec2 pq1 = v1 - e1*clamp( dot(v1,e1)/dot(e1,e1), 0.0, 1.0 ); 
    vec2 pq2 = v2 - e2*clamp( dot(v2,e2)/dot(e2,e2), 0.0, 1.0 ); 
    float s = sign( e0.x*e2.y - e0.y*e2.x ); 
    vec2 d = min(min(vec2(dot(pq0,pq0), s*(v0.x*e0.y-v0.y*e0.x)), vec2(dot(pq1,pq1), s*(v1.x*e1.y-v1.y*e1.x))), vec2(dot(pq2,pq2), s*(v2.x*e2.y-v2.y*e2.x))); 
    return -sqrt(d.x)*sign(d.y); 
}

正五边形 - exact   (https://www.shadertoy.com/view/llVyWW)

代码语言:javascript
代码运行次数:0
复制
float sdPentagon( in vec2 p, in float r ) 
{ 
    const vec3 k = vec3(0.809016994,0.587785252,0.726542528); 
    p.x = abs(p.x); 
    p -= 2.0*min(dot(vec2(-k.x,k.y),p),0.0)*vec2(-k.x,k.y); 
    p -= 2.0*min(dot(vec2( k.x,k.y),p),0.0)*vec2( k.x,k.y); 
    p -= vec2(clamp(p.x,-r*k.z,r*k.z),r); 
    return length(p)*sign(p.y); 
}

正六边形 - exact

代码语言:javascript
代码运行次数:0
复制
float sdHexagon( in vec2 p, in float r ) 
{ 
    const vec3 k = vec3(-0.866025404,0.5,0.577350269); 
    p = abs(p); 
    p -= 2.0*min(dot(k.xy,p),0.0)*k.xy; 
    p -= vec2(clamp(p.x, -k.z*r, k.z*r), r); 
    return length(p)*sign(p.y); 
}

八边形 - exact   (https://www.shadertoy.com/view/llGfDG)

代码语言:javascript
代码运行次数:0
复制
float sdOctogon( in vec2 p, in float r ) 
{ 
    const vec3 k = vec3(-0.9238795325, 0.3826834323, 0.4142135623 ); 
    p = abs(p); 
    p -= 2.0*min(dot(vec2( k.x,k.y),p),0.0)*vec2( k.x,k.y); 
    p -= 2.0*min(dot(vec2(-k.x,k.y),p),0.0)*vec2(-k.x,k.y); 
    p -= vec2(clamp(p.x, -k.z*r, k.z*r), r); 
    return length(p)*sign(p.y); 
}

六角星形 - exact   (https://www.shadertoy.com/view/tt23RR)

代码语言:javascript
代码运行次数:0
复制
float sdHexagram( in vec2 p, in float r ) 
{ 
    const vec4 k = vec4(-0.5,0.8660254038,0.5773502692,1.7320508076); 
    p = abs(p); 
    p -= 2.0*min(dot(k.xy,p),0.0)*k.xy; 
    p -= 2.0*min(dot(k.yx,p),0.0)*k.yx; 
    p -= vec2(clamp(p.x,r*k.z,r*k.w),r); 
    return length(p)*sign(p.y); 
}

五角星形 - exact   (https://www.shadertoy.com/view/3tSGDy)

代码语言:javascript
代码运行次数:0
复制
float sdStar(in vec2 p, in float r, in int n, in float m) 
{ 
// next 4 lines can be precomputed for a given shape 
    float an = 3.141593/float(n); 
    float en = 6.283185/m; 
    vec2 acs = vec2(cos(an),sin(an)); 
    vec2 ecs = vec2(cos(en),sin(en)); 
// ecs=vec2(0,1) for regular polygon, 
    float bn = mod(atan(p.x,p.y),2.0*an) - an; 
    p = length(p)*vec2(cos(bn),abs(sin(bn))); 
    p -= r*acs; 
    p += ecs*clamp( -dot(p,ecs), 0.0, r*acs.y/ecs.y); 
    return length(p)*sign(p.x); 
}

等腰梯形 - exact   (https://www.shadertoy.com/view/MlycD3)

代码语言:javascript
代码运行次数:0
复制
float sdTrapezoid( in vec2 p, in float r1, float r2, float he ) 
{ 
    vec2 k1 = vec2(r2,he); vec2 k2 = vec2(r2-r1,2.0*he); 
    p.x = abs(p.x); 
    vec2 ca = vec2(p.x-min(p.x,(p.y<0.0)?r1:r2), abs(p.y)-he); 
    vec2 cb = p - k1 + k2*clamp( dot(k1-p,k2)/dot2(k2), 0.0, 1.0 ); 
    float s = (cb.x<0.0 && ca.y<0.0) ? -1.0 : 1.0; 
    return s*sqrt( min(dot2(ca),dot2(cb)) ); 
}

饼状图 - exact   (https://www.shadertoy.com/view/3l23RK)

代码语言:javascript
代码运行次数:0
复制
float sdPie( in vec2 p, in vec2 c, in float r ) 
{ 
    p.x = abs(p.x); 
    float l = length(p) - r; 
    float m = length(p-c*clamp(dot(p,c),0.0,r)); 
    // c = sin/cos of the aperture 
    return max(l,m*sign(c.y*p.x-c.x*p.y)); 
}

弧形 - exact   (https://www.shadertoy.com/view/wl23RK)

代码语言:javascript
代码运行次数:0
复制
float sdArc( in vec2 p, in vec2 sca, in vec2 scb, in float ra, float rb ) 
{ 
    p *= mat2(sca.x,sca.y,-sca.y,sca.x); 
    p.x = abs(p.x); 
    float k = (scb.y*p.x>scb.x*p.y) ? dot(p.xy,scb) : length(p.xy); 
    return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb; 
}

马蹄形 - exact   (https://www.shadertoy.com/view/WlSGW1)

代码语言:javascript
代码运行次数:0
复制
float sdHorseshoe( in vec2 p, in vec2 c, in float r, in vec2 w ) 
{ 
    p.x = abs(p.x); 
    float l = length(p); 
    p = mat2(-c.x, c.y, c.y, c.x)*p; 
    p = vec2((p.y>0.0)?p.x:l*sign(-c.x), (p.x>0.0)?p.y:l ); 
    p = vec2(p.x,abs(p.y-r))-w; 
    return length(max(p,0.0)) + min(0.0,max(p.x,p.y)); 
}

胶囊形 - exact   (https://www.shadertoy.com/view/XtVfRW)

代码语言:javascript
代码运行次数:0
复制
float sdVesica(vec2 p, float r, float d) 
{ 
    p = abs(p); 
    float b = sqrt(r*r-d*d); 
    return ((p.y-b)*d>p.x*b) ? length(p-vec2(0.0,b)) : length(p-vec2(-d,0.0))-r; 
}

十字形 - exact   (https://www.shadertoy.com/view/XtGfzw)

代码语言:javascript
代码运行次数:0
复制
float sdCross( in vec2 p, in vec2 b, float r ) 
{ 
    p = abs(p); 
    p = (p.y>p.x) ? p.yx : p.xy; 
    vec2 q = p - b; 
    float k = max(q.y,q.x); vec2 w = (k>0.0) ? q : vec2(b.y-p.x,-k); 
    return sign(k)*length(max(w,0.0)) + r; 
}

多边形 - exact   (https://www.shadertoy.com/view/wdBXRW)

代码语言:javascript
代码运行次数:0
复制
float sdPolygon( in vec2[N] v, in vec2 p ) 
{ 
    float d = dot(p-v[0],p-v[0]); 
    float s = 1.0; 
    for( int i=0, j=N; i=v[i].y,p.ye.y*w.x); 
    if( all(c) || all(not(c)) ) s*=-1.0; } 
    return s*sqrt(d); 
}

椭圆 - exact   (https://www.shadertoy.com/view/4sS3zz)

代码语言:javascript
代码运行次数:0
复制
float sdEllipse( in vec2 p, in vec2 ab ) 
{ 
    p = abs(p); 
    if( p.x > p.y ) 
    {
        p=p.yx;ab=ab.yx;
    } 
    float l = ab.y*ab.y - ab.x*ab.x; 
    float m = ab.x*p.x/l; 
    float m2 = m*m; 
    float n = ab.y*p.y/l; 
    float n2 = n*n; 
    float c = (m2+n2-1.0)/3.0; 
    float c3 = c*c*c; 
    float q = c3 + m2*n2*2.0; 
    float d = c3 + m2*n2; 
    float g = m + m*n2; 
    float co; 
    if( d<0.0 ) 
    { 
        float h = acos(q/c3)/3.0; 
        float s = cos(h); 
        float t = sin(h)*sqrt(3.0); 
        float rx = sqrt( -c*(s + t + 2.0) + m2 ); 
        float ry = sqrt( -c*(s - t + 2.0) + m2 ); 
        co = (ry+sign(l)*rx+abs(g)/(rx*ry)- m)/2.0; 
    } else { 
        float h = 2.0*m*n*sqrt( d ); 
        float s = sign(q+h)*pow(abs(q+h), 1.0/3.0); 
        float u = sign(q-h)*pow(abs(q-h), 1.0/3.0); 
        float rx = -s - u - c*4.0 + 2.0*m2; 
        float ry = (s - u)*sqrt(3.0); 
        float rm = sqrt( rx*rx + ry*ry ); 
        co = (ry/sqrt(rm-rx)+2.0*g/rm-m)/2.0; 
    } 
    vec2 r = ab * vec2(co, sqrt(1.0-co*co)); 
    return length(r-p) * sign(p.y-r.y); 
}

抛物线 - exact   (https://www.shadertoy.com/view/ws3GD7)

代码语言:javascript
代码运行次数:0
复制
float sdParabola( in vec2 pos, in float k ) 
{ 
    pos.x = abs(pos.x); 
    float p = (1.0-2.0*k*pos.y)/(6.0*k*k); 
    float q = -abs(pos.x)/(4.0*k*k); 
    float h = q*q + p*p*p; 
    float r = sqrt(abs(h)); 
    float x = (h>0.0) ? pow(-q+r,1.0/3.0) - pow(abs(-q-r),1.0/3.0)*sign(q+r) : 2.0*cos(atan(r,-q)/3.0)*sqrt(-p); 
    return length(pos-vec2(x,k*x*x)) * sign(pos.x-x); 
}

二次贝塞尔曲线 - exact   (https://www.shadertoy.com/view/MlKcDD)

代码语言:javascript
代码运行次数:0
复制
float sdBezier( in vec2 pos, in vec2 A, in vec2 B, in vec2 C ) 
{ 
vec2 a = B - A; 
vec2 b = A - 2.0*B + C; 
vec2 c = a * 2.0; 
vec2 d = A - pos; 
float kk = 1.0 / dot(b,b); 
float kx = kk * dot(a,b); 
float ky = kk * (2.0*dot(a,a)+dot(d,b)) / 3.0; 
float kz = kk * dot(d,a); 
float res = 0.0; 
float p = ky - kx*kx; 
float p3 = p*p*p; 
float q = kx*(2.0*kx*kx - 3.0*ky) + kz; 
float h = q*q + 4.0*p3; 
if( h >= 0.0) { 
h = sqrt(h); 
vec2 x = (vec2(h, -h) - q) / 2.0; 
vec2 uv = sign(x)*pow(abs(x), vec2(1.0/3.0)); 
float t = uv.x + uv.y - kx; 
t = clamp( t, 0.0, 1.0 ); 
vec2 qos = d + (c + b*t)*t; 
res = dot(qos,qos); 
} else { 
float z = sqrt(-p); 
float v = acos( q/(p*z*2.0) ) / 3.0; 
float m = cos(v); 
float n = sin(v)*1.732050808; 
vec3 t = vec3(m + m, -n - m, n - m) * z - kx; 
t = clamp( t, 0.0, 1.0 ); 
vec2 qos = d + (c + b*t.x)*t.x; 
res = dot(qos,qos); 
qos = d + (c + b*t.y)*t.y; 
res = min(res,dot(qos,qos)); 
qos = d + (c + b*t.z)*t.z; 
res = min(res,dot(qos,qos)); 
} 
return sqrt( res ); 
}

Making shapes rounded

使形状变圆


All the shapes above can be converted into rounded shapes by subtracting a constant from their distance function. That, effectivelly moves the isosurface (isopetimeter I guess) from the level zero to one of the outter rings, which naturally are rounded, as it can be seen in the yellow areas in all the images above. So, basically, for any shape defined by d(x,y) = sdf(x,y), one can make it sounded by computing d(x,y) = sdf(x,y) - r:

代码语言:javascript
代码运行次数:0
复制
float sdRoundedShape( in vec2 p, in float r ) 
{ 
    return sdShape(p) - r; 
}

These are a few examples: rounded line, rounded triangle, rounded box and a rounded pentagon:

Making shapes annular

使形状变环状的


Similarly, shapes can be made annular (like a ring), but taking their absolute value and then substracting a constant from their field. So, for any shape defined by d(x,y) = sdf(x,y) compute d(x,y) = |sdf(x,y)| - r:

代码语言:javascript
代码运行次数:0
复制
float sdAnnularShape( in vec2 p, in float r ) 
{ 
    return abs(sdShape(p)) - r; 
}

These are a few examples: annular rounded line, an annular triangle, an annular box and a annular pentagon:

Rigid deformations, domain repetitiion, range distortion, boolean operations, smooth connections

All of these work just as well as in 3D case, so I won't repeat the examples already exist in this article

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Primitives
  • Making shapes rounded
  • 使形状变圆
    • Making shapes annular
    • 使形状变环状的
      • Rigid deformations, domain repetitiion, range distortion, boolean operations, smooth connections
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档