Intro
The
3D SDF functions articleis pretty popular, so I decided to write a similar one for 2D primitives, since most of the 3D primitives are grown as extrusions or revolutions of these 2D shapes. So getting these right is important. In particular, the functions bellow use the minimum number of square roots and divisions possible, and also produce better/faster results than constructing them from other primitives (when possible).
Note that all the primitives listed here come with a link to a realtime online demo in Shadertoy. In fact, this public playlist contains all the Shadertoy examples:
https://www.shadertoy.com/playlist/MXdSRf, so don't miss that out.
Lastly, as with all in this website, all formulas and code are derived by myself (unless otherwise stated), so there might be errors or better ways to do things. Let me know if you think that's the case.
Primitives
All primitives are centered at the origin; you will have to transform the point to get arbitrarily rotated, translated and scaled objects (see below). The
dot2(v) function returns the dot product of a vector with itself (or the square of its length).
Chamfer Box - exacthttps://www.shadertoy.com/view/3fc3zsfloatsdChamferBox(in vec2p,in vec2b,in floatchamfer ) { p =abs(p)-b; p = (p.y>p.x) ? p.yx : p.xy; p.y += chamfer;const floatk =1.0-sqrt(2.0);if( p.y<0.0&& p.y+p.x*k<0.0)returnp.x;if( p.x<p.y )return(p.x+p.y)*sqrt(0.5);return length(p); }
Oriented Box - exacthttps://www.shadertoy.com/view/stcfznfloatsdOrientedBox(in vec2p,in vec2a,in vec2b,floatth ) {floatl =length(b-a);vec2d = (b-a)/l;vec2q = (p-(a+b)*0.5); q =mat2(d.x,-d.y,d.y,d.x)*q; q =abs(q)-vec2(l,th)*0.5;returnlength(max(q,0.0)) +min(max(q.x,q.y),0.0); }
Rhombus - exacthttps://www.shadertoy.com/view/XdXcRBfloatsdRhombus(in vec2p,in vec2b ) { b.y = -b.y; p =abs(p);floath =clamp( (dot(b,p)+b.y*b.y)/dot(b,b),0.0,1.0); p -= b*vec2(h,h-1.0);return length(p)*sign(p.x); }
Isosceles Trapezoid - exacthttps://www.shadertoy.com/view/MlycD3floatsdTrapezoid(in vec2p,in floatr1,floatr2,floathe ) {vec2k1 =vec2(r2,he);vec2k2 =vec2(r2-r1,2.0*he); p.x =abs(p.x);vec2ca =vec2(p.x-min(p.x,(p.y<0.0)?r1:r2),abs(p.y)-he);vec2cb = p - k1 + k2*clamp(dot(k1-p,k2)/dot2(k2),0.0,1.0);floats = (cb.x<0.0&& ca.y<0.0) ? -1.0:1.0;returns*sqrt(min(dot2(ca),dot2(cb)) ); }
Parallelogram - exacthttps://www.shadertoy.com/view/7dlGRffloatsdParallelogram(in vec2p,floatwi,floathe,floatsk ) {vec2e =vec2(sk,he); p = (p.y<0.0)?-p:p;vec2w = p - e; w.x -=clamp(w.x,-wi,wi);vec2d =vec2(dot(w,w), -w.y);floats = p.x*e.y - p.y*e.x; p = (s<0.0)?-p:p;vec2v = p -vec2(wi,0); v -= e*clamp(dot(v,e)/dot(e,e),-1.0,1.0); d =min( d,vec2(dot(v,v), wi*he-abs(s)));returnsqrt(d.x)*sign(-d.y); }
Equilateral Triangle - exacthttps://www.shadertoy.com/view/Xl2yDWfloatsdEquilateralTriangle(in vec2p,in floatr ) {constfloatk =sqrt(3.0); p.x =abs(p.x) - r; p.y = p.y + r/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*r,0.0);return-length(p)*sign(p.y); }
Isosceles Triangle - exacthttps://www.shadertoy.com/view/MldcD7floatsdTriangleIsosceles(in vec2p,in vec2q ) { p.x =abs(p.x);vec2a = p - q*clamp(dot(p,q)/dot(q,q),0.0,1.0);vec2b = p - q*vec2(clamp( p.x/q.x,0.0,1.0),1.0);floats = -sign( q.y );vec2d =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); }
Triangle - exacthttps://www.shadertoy.com/view/XsXSz4floatsdTriangle(in vec2p,in vec2p0,in vec2p1,in vec2p2 ) {vec2e0 = p1-p0, e1 = p2-p1, e2 = p0-p2;vec2v0 = p -p0, v1 = p -p1, v2 = p -p2;vec2pq0 = v0 - e0*clamp(dot(v0,e0)/dot(e0,e0),0.0,1.0);vec2pq1 = v1 - e1*clamp(dot(v1,e1)/dot(e1,e1),0.0,1.0);vec2pq2 = v2 - e2*clamp(dot(v2,e2)/dot(e2,e2),0.0,1.0);floats =sign( e0.x*e2.y - e0.y*e2.x );vec2d =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); }
Uneven Capsule - exacthttps://www.shadertoy.com/view/4lcBWnfloatsdUnevenCapsule(vec2p,floatr1,floatr2,floath ) { p.x =abs(p.x);floatb = (r1-r2)/h;floata =sqrt(1.0-b*b);floatk =dot(p,vec2(-b,a)); if( k <0.0)returnlength(p) - r1; if( k > a*h )returnlength(p-vec2(0.0,h)) - r2;returndot(p,vec2(a,b) ) - r1; }
Regular Pentagon - exacthttps://www.shadertoy.com/view/llVyWWfloatsdPentagon(in vec2p,in floatr ) {constvec3k =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);returnlength(p)*sign(p.y); }
Regular Hexagon - exactfloatsdHexagon(in vec2p,in floatr ) {constvec3k =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);returnlength(p)*sign(p.y); }
Regular Octogon - exacthttps://www.shadertoy.com/view/llGfDGfloatsdOctogon(in vec2p,in floatr ) {constvec3k =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);returnlength(p)*sign(p.y); }
Hexagram - exacthttps://www.shadertoy.com/view/tt23RRfloatsdHexagram(in vec2p,in floatr ) {const vec4k =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);returnlength(p)*sign(p.y); }
Pentagram - exacthttps://www.shadertoy.com/view/t3X3z4floatsdPentagram(in vec2p,in floatr ) {const floatk1x =0.809016994;const floatk2x =0.309016994;const floatk1y =0.587785252;const floatk2y =0.951056516;const floatk1z =0.726542528;const vec2v1 =vec2( k1x,-k1y);const vec2v2 =vec2(-k1x,-k1y);const vec2v3 =vec2( k2x,-k2y); p.x =abs(p.x); p -=2.0*max(dot(v1,p),0.0)*v1; p -=2.0*max(dot(v2,p),0.0)*v2; p.x =abs(p.x); p.y -= r;return length(p-v3*clamp(dot(p,v3),0.0,k1z*r)) *sign(p.y*v3.x-p.x*v3.y); }
Regular Star - exacthttps://www.shadertoy.com/view/3tSGDyfloatsdStar(in vec2p,in floatr,in intn,in floatm) {floatan =3.141593/float(n);floaten =3.141593/m;vec2acs =vec2(cos(an),sin(an));vec2ecs =vec2(cos(en),sin(en));floatbn =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);returnlength(p)*sign(p.x); }
Pie - exacthttps://www.shadertoy.com/view/3l23RKfloatsdPie(in vec2p,in vec2c,in floatr ) { p.x =abs(p.x);floatl =length(p) - r;floatm =length(p-c*clamp(dot(p,c),0.0,r));returnmax(l,m*sign(c.y*p.x-c.x*p.y)); }
Cut Disk - exacthttps://www.shadertoy.com/view/ftVXRcfloatsdCutDisk(in vec2p,in floatr,in floath ) {floatw =sqrt(r*r-h*h);p.x =abs(p.x);floats =max( (h-r)*p.x*p.x+w*w*(h+r-2.0*p.y), h*p.x-w*p.y );return(s<0.0) ?length(p)-r : (p.x<w) ? h - p.y :length(p-vec2(w,h)); }
Arc - exacthttps://www.shadertoy.com/view/wl23RKfloatsdArc(in vec2p,in vec2sc,in floatra,floatrb ) { // sc is thesin/cosof the arc's aperture p.x =abs(p.x);return((sc.y*p.x>sc.x*p.y) ?length(p-sc*ra) :abs(length(p)-ra)) - rb; }
Ring - exacthttps://www.shadertoy.com/view/DsccDHfloatsdRing(in vec2p,in vec2n,in floatr,floatth ) { p.x =abs(p.x); p =mat2x2(n.x,n.y,-n.y,n.x)*p;return max(abs(length(p)-r)-th*0.5,length(vec2(p.x,max(0.0,abs(r-p.y)-th*0.5)))*sign(p.x) ); }
Horseshoe - exacthttps://www.shadertoy.com/view/WlSGW1floatsdHorseshoe(in vec2p,in vec2c,in floatr,in vec2w ) { p.x =abs(p.x);floatl =length(p); p =mat2(-c.x, c.y, c.y, c.x)*p; p =vec2((p.y>0.0|| p.x>0.0)?p.x:l*sign(-c.x), (p.x>0.0)?p.y:l ); p =vec2(p.x,abs(p.y-r))-w;returnlength(max(p,0.0)) +min(0.0,max(p.x,p.y)); }
Vesica - exacthttps://www.shadertoy.com/view/XtVfRWfloatsdVesica(vec2p,floatw,floath) {vec3d =0.5*(w*w-h*h)/h; p =abs(p);vec3c = (w*p.y<d*(p.x-w)) ?vec3(0.0,w,0.0) :vec3(-d,0.0,d+h);return length(p-c.yx) - c.z; }
Oriented Vesica - exacthttps://www.shadertoy.com/view/cs2yzGfloatsdOrientedVesica(vec2p,vec2a,vec2b,floatw ) {floatr =0.5*length(b-a);floatd =0.5*(r*r-w*w)/w;vec2v = (b-a)/r;vec2c = (b+a)*0.5;vec2q =0.5*abs(mat2(v.y,v.x,-v.x,v.y)*(p-c));vec3h = (r*q.x<d*(q.y-r)) ?vec3(0.0,r,0.0) :vec3(-d,0.0,d+w);return length( q-h.xy) - h.z; }
Moon - exacthttps://www.shadertoy.com/view/WtdBRSfloatsdMoon(vec2p,floatd,floatra,floatrb ) { p.y =abs(p.y);floata = (ra*ra - rb*rb + d*d)/(2.0*d);floatb =sqrt(max(ra*ra-a*a,0.0));if( d*(p.x*b-p.y*a) > d*d*max(b-p.y,0.0) )returnlength(p-vec2(a,b));returnmax( (length(p )-ra), -(length(p-vec2(d,0))-rb)); }
Circle Cross - exacthttps://www.shadertoy.com/view/NslXDMfloatsdRoundedCross(in vec2p,in floath ) {floatk =0.5*(h+1.0/h); p =abs(p);return( p.x<1.0&& p.y<p.x*(k-h)+h ) ? k-sqrt(dot2(p-vec2(1,k))) :sqrt(min(dot2(p-vec2(0,h)),dot2(p-vec2(1,0)))); }
Simple Egg - exacthttps://www.shadertoy.com/view/XtVfRWfloatsdEgg(in vec2p,in floathe,in floatra,in floatrb,in floatbu ) {floatr =0.5*(he + ra+rb)/bu;floatda = r - ra;floatdb = r - rb;floaty = (db*db - da*da - he*he)/(2.0*he);floatx =sqrt(da*da - y*y);p.x =abs(p.x);floatk = p.y*x - p.x*y;if( k>0.0&& k<he*(p.x+x) )return length(p+vec2(x,y))-r;return min(length(p)-ra,length(vec2(p.x,p.y-he))-rb ); }
Heart - exacthttps://www.shadertoy.com/view/3tyBzVfloatsdHeart(in vec2p ) { p.x =abs(p.x);if( p.y+p.x>1.0)returnsqrt(dot2(p-vec2(0.25,0.75))) -sqrt(2.0)/4.0;returnsqrt(min(dot2(p-vec2(0.00,1.00)),dot2(p-0.5*max(p.x+p.y,0.0)))) *sign(p.x-p.y); }
Cross - exact exterior, bound interiorhttps://www.shadertoy.com/view/XtGfzwfloatsdCross(in vec2p,in vec2b,floatr ) { p =abs(p); p = (p.y>p.x) ? p.yx : p.xy;vec2q = p - b;floatk =max(q.y,q.x);vec2w = (k>0.0) ? q :vec2(b.y-p.x,-k);returnsign(k)*length(max(w,0.0)) + r; }
Polygon - exacthttps://www.shadertoy.com/view/wdBXRWfloatsdPolygon(in vec2[N] v,in vec2p ) {floatd =dot(p-v[0],p-v[0]);floats =1.0;for(inti=0, j=N-1; i<N; j=i, i++ ) {vec2e = v[j] - v[i];vec2w = p - v[i];vec2b = w - e*clamp(dot(w,e)/dot(e,e),0.0,1.0); d =min( d,dot(b,b) ); bvec3c = bvec3(p.y>=v[i].y,p.y<v[j].y,e.x*w.y>e.y*w.x);if(all(c) ||all(not(c)) ) s*=-1.0; }returns*sqrt(d); }
Ellipse - exacthttps://www.shadertoy.com/view/4sS3zzfloatsdEllipse(in vec2p,in vec2ab ) { p =abs(p);if( p.x > p.y ) {p=p.yx;ab=ab.yx;}floatl = ab.y*ab.y - ab.x*ab.x;floatm = ab.x*p.x/l;floatm2 = m*m;floatn = ab.y*p.y/l;floatn2 = n*n;floatc = (m2+n2-1.0)/3.0;floatc3 = c*c*c;floatq = c3 + m2*n2*2.0;floatd = c3 + m2*n2;floatg = m + m*n2;floatco;if( d<0.0) {floath =acos(q/c3)/3.0;floats =cos(h);floatt =sin(h)*sqrt(3.0);floatrx =sqrt( -c*(s + t +2.0) + m2 );floatry =sqrt( -c*(s - t +2.0) + m2 ); co = (ry+sign(l)*rx+abs(g)/(rx*ry)- m)/2.0; }else{floath =2.0*m*n*sqrt( d );floats =sign(q+h)*pow(abs(q+h),1.0/3.0);floatu =sign(q-h)*pow(abs(q-h),1.0/3.0);floatrx = -s - u - c*4.0+2.0*m2;floatry = (s - u)*sqrt(3.0);floatrm =sqrt( rx*rx + ry*ry ); co = (ry/sqrt(rm-rx)+2.0*g/rm-m)/2.0; }vec2r = ab *vec2(co,sqrt(1.0-co*co));returnlength(r-p) *sign(p.y-r.y); }
Parabola - exacthttps://www.shadertoy.com/view/ws3GD7floatsdParabola(in vec2pos,in floatk ) { pos.x =abs(pos.x);floatik =1.0/k;floatp = ik*(pos.y -0.5*ik)/3.0;floatq =0.25*ik*ik*pos.x;floath = q*q - p*p*p;floatx;if( h>0.0) {floatr =pow(q+sqrt(h),1.0/3.0); x = r + p/r; }else{floatr =sqrt(p); x =2.0*r*cos(acos(q/(p*r))/3.0); }returnlength(pos-vec2(x,k*x*x)) *sign(pos.x-x); }
Parabola Segment - exacthttps://www.shadertoy.com/view/3lSczzfloatsdParabola(in vec2pos,in floatwi,in floathe ) { pos.x =abs(pos.x);floatik = wi*wi/he;floatp = ik*(he-pos.y-0.5*ik)/3.0;floatq = pos.x*ik*ik/4.0;floath = q*q - p*p*p;floatx;if( h>0.0) {floatr =pow(q+sqrt(h),1.0/3.0); x = r + p/r; }else{floatr =sqrt(p); x =2.0*r*cos(acos(q/(p*r))/3.0); } x =min(x,wi);returnlength(pos-vec2(x,he-x*x/ik)) *sign(ik*(pos.y-he)+pos.x*pos.x); }
Quadratic Bezier - exacthttps://www.shadertoy.com/view/MlKcDDfloatsdBezier(in vec2pos,in vec2A,in vec2B,in vec2C ) {vec2a = B - A;vec2b = A -2.0*B + C;vec2c = a *2.0;vec2d = A - pos;floatkk =1.0/dot(b,b);floatkx = kk *dot(a,b);floatky = kk * (2.0*dot(a,a)+dot(d,b)) /3.0;floatkz = kk *dot(d,a);floatres =0.0;floatp = ky - kx*kx;floatp3 = p*p*p;floatq = kx*(2.0*kx*kx-3.0*ky) + kz;floath = q*q +4.0*p3;if( h >=0.0) { h =sqrt(h);vec2x = (vec2(h,-h)-q)/2.0;vec2uv =sign(x)*pow(abs(x),vec2(1.0/3.0));floatt =clamp( uv.x+uv.y-kx,0.0,1.0); res =dot2(d + (c + b*t)*t); }else{floatz =sqrt(-p);floatv =acos( q/(p*z*2.0) ) /3.0;floatm =cos(v);floatn =sin(v)*1.732050808;vec3t =clamp(vec3(m+m,-n-m,n-m)*z-kx,0.0,1.0); res =min(dot2(d+(c+b*t.x)*t.x),dot2(d+(c+b*t.y)*t.y) );}returnsqrt( res ); }
Bobbly Cross - exacthttps://www.shadertoy.com/view/NssXWMfloatsdBlobbyCross(in vec2pos,floathe ) { pos =abs(pos); pos =vec2(abs(pos.x-pos.y),1.0-pos.x-pos.y)/sqrt(2.0);floatp = (he-pos.y-0.25/he)/(6.0*he);floatq = pos.x/(he*he*16.0);floath = q*q - p*p*p;floatx;if( h>0.0) {floatr =sqrt(h); x =pow(q+r,1.0/3.0)-pow(abs(q-r),1.0/3.0)*sign(r-q); }else{floatr =sqrt(p); x =2.0*r*cos(acos(q/(p*r))/3.0); } x =min(x,sqrt(2.0)/2.0);vec2z =vec2(x,he*(1.0-2.0*x*x)) - pos;returnlength(z) *sign(z.y); }
Tunnel - exacthttps://www.shadertoy.com/view/flSSDyfloatsdTunnel(in vec2p,in vec2wh ) { p.x =abs(p.x); p.y = -p.y;vec2q = p - wh;floatd1 =dot2(vec2(max(q.x,0.0),q.y)); q.x = (p.y>0.0) ? q.x :length(p)-wh.x;floatd2 =dot2(vec2(q.x,max(q.y,0.0)));floatd =sqrt(min(d1,d2) );return(max(q.x,q.y)<0.0) ? -d : d; }
Stairs - exacthttps://www.shadertoy.com/view/7tKSWtfloatsdStairs(in vec2p,in vec2wh,in floatn ) {vec2ba = wh*n;floatd =min(dot2(p-vec2(clamp(p.x,0.0,ba.x),0.0)),dot2(p-vec2(ba.x,clamp(p.y,0.0,ba.y))) );floats =sign(max(-p.y,p.x-ba.x) );floatdia =length(wh); p =mat2(wh.x,-wh.y, wh.y,wh.x)*p/dia;floatid =clamp(round(p.x/dia),0.0,n-1.0); p.x = p.x - id*dia; p =mat2(wh.x, wh.y,-wh.y,wh.x)*p/dia;floathh = wh.y/2.0; p.y -= hh;if( p.y>hh*sign(p.x) ) s=1.0; p = (id<0.5|| p.x>0.0) ? p : -p; d =min( d,dot2(p-vec2(0.0,clamp(p.y,-hh,hh))) ); d =min( d,dot2(p-vec2(clamp(p.x,0.0,wh.x),hh)) );returnsqrt(d)*s; }
Quadratic Circle - exacthttps://www.shadertoy.com/view/Nd3cW8floatsdQuadraticCircle(in vec2p ) { p =abs(p);if( p.y>p.x ) p=p.yx;floata = p.x-p.y;floatb = p.x+p.y;floatc = (2.0*b-1.0)/3.0;floath = a*a + c*c*c;floatt;if( h>=0.0) { h =sqrt(h); t =sign(h-a)*pow(abs(h-a),1.0/3.0) -pow(h+a,1.0/3.0); }else{floatz =sqrt(-c);floatv =acos(a/(c*z))/3.0; t = -z*(cos(v)+sin(v)*1.732050808); } t *=0.5;vec2w =vec2(-t,t) +0.75- t*t - p;returnlength(w) *sign( a*a*0.5+b-1.5 ); }
Hyperbola - exacthttps://www.shadertoy.com/view/DtjXDGfloatsdHyberbola(in vec2p,in floatk,in floathe ){ p =abs(p); p =vec2(p.x-p.y,p.x+p.y)/sqrt(2.0);floatx2 = p.x*p.x/16.0;floaty2 = p.y*p.y/16.0;floatr = k*(4.0*k - p.x*p.y)/12.0;floatq = (x2 - y2)*k*k;floath = q*q + r*r*r;floatu;if( h<0.0) {floatm =sqrt(-r); u = m*cos(acos(q/(r*m))/3.0); }else{floatm =pow(sqrt(h)-q,1.0/3.0); u = (m - r/m)/2.0; }floatw =sqrt( u + x2 );floatb = k*p.y - x2*p.x*2.0;floatt = p.x/4.0- w +sqrt(2.0*x2 - u + b/w/4.0); t =max(t,sqrt(he*he*0.5+k)-he/sqrt(2.0));floatd =length( p-vec2(t,k/t) );returnp.x*p.y < k ? d : -d; }
Cool S - exacthttps://www.shadertoy.com/view/clVXWcfloatsdfCoolS(in vec2p ) {floatsix = (p.y<0.0) ? -p.x : p.x; p.x =abs(p.x); p.y =abs(p.y) -0.2;floatrex = p.x -min(round(p.x/0.4),0.4);floataby =abs(p.y-0.2)-0.6;floatd =dot2(vec2(six,-p.y)-clamp(0.5*(six-p.y),0.0,0.2)); d =min(d,dot2(vec2(p.x,-aby)-clamp(0.5*(p.x-aby),0.0,0.4))); d =min(d,dot2(vec2(rex,p.y -clamp(p.y ,0.0,0.4))));floats =2.0*p.x + aby +abs(aby+0.4) -0.4;return sqrt(d) *sign(s); }
Circle Wave - exacthttps://www.shadertoy.com/view/stGyztfloatsdCircleWave(in vec2p,in floattb,in floatra ) { tb =3.1415927*5.0/6.0*max(tb,0.0001);vec2co = ra*vec2(sin(tb),cos(tb)); p.x =abs(mod(p.x,co.x*4.0)-co.x*2.0);vec2p1 = p;vec2p2 =vec2(abs(p.x-2.0*co.x),-p.y+2.0*co.y);floatd1 = ((co.y*p1.x>co.x*p1.y) ?length(p1-co) :abs(length(p1)-ra));floatd2 = ((co.y*p2.x>co.x*p2.y) ?length(p2-co) :abs(length(p2)-ra));return min(d1, d2); }
Making shapes rounded
All the shapes above can be converted into rounded shapes by subtracting a constant from their distance function. That, effectively moves the isosurface (isoperimeter I guess) from the level zero to one of the outer 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. You can learn more about this in
this Youtube video.
floatopRound(in vec2p,in floatr ) {returnsdShape(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 or the layers of an onion), but taking their
absolute value and then subtracting 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:
floatopOnion(in vec2p,in floatr ) {returnabs(sdShape(p)) - r; }
These are a few examples: annular rounded line, an annular triangle, an annular box and a annular pentagon:




Rigid deformations, domain repetition, range distortion, boolean operations, smooth connections, etc
All of these work just as well as in 3D case, so I won't repeat the examples already exist in
this article.