I’m trying to draw an ellipse with smoothed edges using smoothstep function.
If I draw a circle and squash it, the edge transition is different horizontally and vertically:
void main() {
vec2 spread = vec2(0.1, 0.4);
float trans = 0.1;
float color = smoothstep(1.0 - trans, 1.0 + trans, length((vuv - vec2(0.5)) / spread));
gl_FragColor = vec4(0.25 * color, 0.0, 0.0, 1.0);
}
I can draw concentric ellipses with equal gap between them, but I’m not sure how to feed this to smoothstep:
void main() {
vec2 uv = vuv - vec2(0.5);
vec2 spreadVar = vec2(0.05);
vec2 spread = vec2(0.2, 0.4);
vec2 spreadIn = spread - spreadVar;
float dist = length(uv / spread);
float dist2 = length(uv / spreadIn);
float circle = step(1.0, dist) + step(1.0, dist2);
gl_FragColor = vec4(0.25 * circle, 0.0, 0.0, 1.0);
}
Hi!
Not sure, if this is what you’re looking for, but here is an option with fwidth()
:
<script type='x-shader/x-fragment' id='fs_smooth'>
varying vec2 vuv;
void main() {
vec2 spread = vec2(0.1, 0.4);
vec2 fw = fwidth(vuv); // added
float trans = min(fw.x, fw.y); // changed
float color = smoothstep(1.0 - trans, 1.0 + trans, length((vuv - vec2(0.5)) / spread));
gl_FragColor = vec4(0.25 * color, 0.0, 0.0, 1.0);
}
</script>
Result:
3 Likes
My problem is the different size of the transition zone horizontally and vertically (left image), I’d like it to be the same (right image).
I faked the right image by blurring sharp oval in PS.
I don’t want to blur, I’d like to use something fast and producing visually similar result (like smoothstep).
fwidth() doesn’t help me in this case, I’m working with a quad without perspective, so dFdxy
is constant across the canvas, but so is trans
already, if you set vec2 fw = 100.0 * fwidth(vuv);
you’ll get the same image as with trans = 0.1
.
Why not search shadertoy for SDF of ellipse, there are some implemetations.
For example: Shader - Shadertoy BETA
3 Likes
Tried another option:
<script type='x-shader/x-fragment' id='fs_sharp'>
varying vec2 vuv;
void main() {
vec2 uv = vuv - vec2(0.5);
float spreadVal = 0.05;
vec2 spreadVar = vec2(spreadVal);
vec2 spread = vec2(0.2, 0.3);
vec2 spreadIn = spread - spreadVar;
float dist = length(uv / spread);
float dist2 = length(uv / spreadIn);
float circle = smoothstep(dist2, dist, dist2/dist);
gl_FragColor = vec4(0.5 * circle, 0.0, 0.0, 1.0);
}
</script>
2 Likes
float circle = smoothstep(dist2, dist, 1.);
2 Likes
I found SDF solution, but I believe this one is slightly faster, nice!
Added all versions of code to the original fiddle.
Thanks everyone!
2 Likes