From 5bd5421f313706f0aa85486a2fc0add0e7a5d008 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Tue, 4 Mar 2025 08:33:40 +0100 Subject: [PATCH] [orx-shader-phrases] Add SDF shader phrases for ellipse and star shapes --- .../src/commonMain/kotlin/sdf/SDFPhrases.kt | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 orx-shader-phrases/src/commonMain/kotlin/sdf/SDFPhrases.kt diff --git a/orx-shader-phrases/src/commonMain/kotlin/sdf/SDFPhrases.kt b/orx-shader-phrases/src/commonMain/kotlin/sdf/SDFPhrases.kt new file mode 100644 index 00000000..9e7b3019 --- /dev/null +++ b/orx-shader-phrases/src/commonMain/kotlin/sdf/SDFPhrases.kt @@ -0,0 +1,61 @@ +package org.openrndr.extra.shaderphrases.sdf + +import kotlin.math.PI + +const val sdEllipsePhrase = """#ifndef SP_SDELLIPSE +#define SP_SDELLIPSE +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); +} +#endif +""" + +const val sdStarPhrase = """#ifndef SP_SDSTAR +#define SP_SDSTAR +float sdStar( in vec2 p, in float r, in int n, in float sharpness) +{ + float m = mix(2.0, float(n), sharpness); + + // next 4 lines can be precomputed for a given shape + float an = ${PI}/float(n); + float en = ${PI}/m; // m is between 2 and n + 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); +} +#endif +""" \ No newline at end of file