I'm trying to make a lightbulb that glows a little and then it becomes less intense. Also at the edges to be a little bit dimmer. I found the a code, that I think creates the effect I want to create, but I don't seem to understand it very well. Here's the code:
mat2 rotate2d(float angle){
return mat2(cos(angle),-sin(angle),
sin(angle),cos(angle));
}
float variation(vec2 v1, vec2 v2, float strength, float speed) {
return sin(
dot(normalize(v1), normalize(v2)) * strength + iGlobalTime * speed
) / 100.0;
}
vec3 paintCircle (vec2 uv, vec2 center, float rad, float width) {
vec2 diff = center-uv;
float len = length(diff);
len += variation(diff, vec2(0.0, 1.0), 5.0, 2.0);
len -= variation(diff, vec2(1.0, 0.0), 5.0, 2.0);
float circle = smoothstep(rad-width, rad, len) - smoothstep(rad, rad+width, len);
return vec3(circle);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
uv.x *= 1.5;
uv.x -= 0.25;
vec3 color;
float radius = 0.35;
vec2 center = vec2(0.5);
//paint color circle
color = paintCircle(uv, center, radius, 0.1);
//color with gradient
vec2 v = rotate2d(iGlobalTime) * uv;
color *= vec3(v.x, v.y, 0.7-v.y*v.x);
//paint white circle
color += paintCircle(uv, center, radius, 0.01);
fragColor = vec4(color, 1.0);
}
I don't understand why we need the dot product of the normalized vectors and how it's chosen exacly:
len += variation(diff, vec2(0.0, 1.0), 5.0, 2.0);
len -= variation(diff, vec2(1.0, 0.0), 5.0, 2.0);
I mean - why is there first adding, then subtraction? Then why is that:
vec2 uv = fragCoord.xy / iResolution.xy;
uv.x *= 1.5;
uv.x -= 0.25;
and how does this
vec2 v = rotate2d(iGlobalTime) * uv;
color *= vec3(v.x, v.y, 0.7-v.y*v.x);
make the color gradient? Here's a link of the code if someone prefers watching it there and what it does: https://www.shadertoy.com/view/ltBXRc. I'm obviously not very good at geometry. If someone could help me, I'd appreciate it :)
If we wanted to draw a perfect circle, we would simply plot all points lying a certain distance from the center of the scene. Speaking procedurally, we would start from the center, pick any random direction, go some distance r
in that direction, and plot a point. Then return to the center, pick some other direction, go the same distance r
, and plot another point. And so on, until we have a smooth circle:
r = 1
To plot a distorted circle we can vary the distance r
depending on the direction we're facing. If we express the direction as an angle in radians (theta
), then r
will be some function of that angle. What function exactly? Let's try something simple first: r = theta
Not quiet what we want, it should be more like a circle (r = 1), but with a bit of waviness (r = 1 + waviness). The simplest wavy function is sin(x). Let's try to add it: r = 1 + 0.1 * sin(5 * theta)
By changing the numbers we can manipulate the amplitude and the frequency of the waves. But there's too much symmetry, to break it we need something more complex than a sine wave.
How about this monster sin(5 * sin(x)) - sin(5 * cos(x))
Let's add it to the circle r = 1 + 0.1 * sin(5 * sin(theta)) - 0.1 * sin(5 * cos(theta))
Looks pretty good to me.
The shader performs exactly this distortion, but in a different manner. Taking a dot product with a standard basis vector simply gives you the X or Y coordinate of the vector. We can rewrite that bit as:
len += 0.02 * sin(normalize(diff).y * 5.0 + 2.0 * iGlobalTime);
len -= 0.02 * sin(normalize(diff).x * 5.0 + 2.0 * iGlobalTime);
X and Y coordinates of a normalized vector are just sin
and cos
of an angle represented by that vector. So, normalize(diff).y
gives you the sine of an angle, and normalize(diff).x
gives you the cosine.
Hopefully this clears things up a bit.