-
Notifications
You must be signed in to change notification settings - Fork 0
2D SDF(2): Wave and Segment
- shadertoy: https://www.shadertoy.com/view/XcdGzX
- geogebra: https://www.geogebra.org/classic/hzn9s6cn
Firstly, Add a beautiful ripple to the circle for displaying
exp(x)
can make value approach 1.0
sin
function can generate regular waves. In GLSLShading, n
typically represents the frequency or wavenumber. the frequency controls the number of wave peaks wihtin a cycle. effectively make the wavelength shorter and the wave peaks more compact.
m*uTime
represents a dynamic phase shift over time. enabling the creation of animated wave patterns.
- geogebra: https://www.geogebra.org/classic/pnzuxsmy
- shadertoy: https://www.shadertoy.com/view/4ftGDj
Assuming there's a line segement(A, B) in space, the shortest distance from all points in space to this line segment can be categorized into three scenarios:
- For a point
$P$ lying between A and B, the distance is hte pependicular distance from the point to he line AB. - For a point
$P$ outside of AB and closter to the point B, the shortest distance is the distance from$P$ to the point$B$ - For a point
$P$ outside of AB and closer to the point A, the shortest distance is the distance from$P$ to hte point A
An intuitive method to determine this is to calculate the lengths of the three vectors
- for the point
$P1$ , The length of the vetor$\overrightarrow{PC}$ can be using the angle$\theta$ between$\overrightarrow{PA}$ $\overrightarrow{PB}$ ,and then calculating$sin(\theta) \times ||\overrightarrow{PA}||$ .$\theta$ can be determined via the dot product of the vectors.Note the parameter$hh$ in the figure,whic represents the radito of the length of the projection of$P$ onto$AB$ to the length of$AB$ . Only if this value$hh$ lies within the interval$(0, 1)$ - For a point
$P2$ $P3$ outside AB, Directly take the minimum of the two distance
float sd_segment(vec2 pct, vec2 pa, vec2 pb) {
vec2 v1 = pct - pa;
vec2 v2 = pb - pa;
vec2 v3 = pct - pb;
float hh = dot(v1, v2) / length(v2) / length(v2);
if (0. < hh && hh < 1.0) {
float theta = acos(dot(v1 ,v2) /length(v1)/length(v2));
float d1 = sin(theta) * length(v1);
return d1;
} else {
return min(length(v1), length(v3)) ;
}
}
Here, we can optimize the code. The length of the vetor
float sd_segment2(vec2 pct, vec2 pa, vec2 pb) {
vec2 v1 = pct - pa;
vec2 v2 = pb - pa;
vec2 v3 = pct - pb;
float hh = dot(v1, v2) / length(v2) / length(v2);
if (hh < 0.0) {
return length(v1 - 0. * v2);
} else if (0. < hh && hh < 1.0) {
return length(v1 - hh * v2);
} else {
// v3 = v1 - v2 = pct -pb;
return length(v1 - v2);
}
}
Through the optimization mentioned above, one can notice the similarity between the three conditionals. By introducing the clamp function, we eliminate the need for if conditions, thus optimizing performance. Furthermore, by using dot(v2, v2)
. We reduce the calculation of length by on instance. Ultimatly we arrive at hte final result
float sd_segment3(vec2 pct, vec2 pa, vec2 pb) {
vec2 v1 = pct - pa;
vec2 v2 = pb - pa;
float h = clamp(dot(v1,v2)/dot(v2,v2), 0.0, 1.0);
return length(v1-h*v2);
}