Generative line Shader Breakdown

How to bring a still image to life

These breakdowns make it seem like I'm on top of my game. Every step of the way is strategically planned. A master of visualizing the end result step by step and then executing the plan. I am not.

To be clear, I have ideas of how to make certain parts of my vision. But when I'm coding, I'm as clueless as they come about how it's gonna work. What I initially planned never works, and the end result I never make what I intend to make.

But while failing at what I envisioned, a new idea comes along and I often follow it. It's a matter of trusting the process and experimenting. These breakdowns are very much me going back and fully understanding what I did because in the moment I had no clue. Not a "I knew all alongโ€ฆ. my grandpa's deck has no pathetic cards๐Ÿ˜Ž" moment.

To drive this point home, at the end of each section I'll write a line "I had this planned all along๐Ÿ˜Ž" or "I just plugged values until it worked๐Ÿ™‰". You'll notice how many of them just came to me while experimenting.


This demo was what I initially made for the previous newsletter. However, I went with a hand effect on that one instead and left this for the future.

The inspiration was the image on the right, I imagined it as lines that expanded from the center as they moved up. I've forgotten how to create lines from noise, but I had some ideas on how to do something like this.


Triangular UV

To start I needed some kind of gradient that was in the shape of the inspiration, it looked like a triangle to me so I started from there. Displace the uv.x to the center and abs it to get a gradient that grows to both sides towards 1.

Then, to get the triangle sum these two values and normalize it to get the triangle gradient.

vec2 triUV = vec2(abs(uv.x - 0.5), uv.y);
float amp = ((-triUV.x + 1.) + triUV.y) -1.;
amp = smoothstep(0., 1., amp);

I had this planned all along๐Ÿ˜Ž BUT it took some time to figure out the triangle math.


Base level distortion

This project has a loop that distorts the UVs and the resulting color on each step. However, we don't want this change to be too drastic or it'll be a noise mess and we don't want it so little distortion that it's not noticeable.

So, before the loop, the UVs are distorted to a base line distortion and each iteration loop then slightly distorts it to create variation.

uv.x += 0.2 * noise(vec3(uv * 3., uTime * 0.0001));
uv.y += 0.2 * noise(vec3(uv * 3., 1000. + uTime * 0.0001));

I just plugged values until it worked๐Ÿ™‰ - After disliking my result I added this and removed drastic frequencies.



The loop has 8 iterations. It creates noise to displace the UVs and also to create the lines themselves.

We sample with the XY with the uvs, and on the Z axis of the noise we use our:

  1. Use Amp to make it move towards the center triangle
  2. Advance it over time with uTime
  3. Offset the time by the loop index "i" for each iteration to create different lines.

This makes each iteration of the loop go towards the center and also be displaced by a slight amount creating good reparation but similarity.

float n3 = noise(vec3(uv * 2.5 , amp * 6. -uTime * 0.001 +   float(i) * 0.1));

I had this planned all along KINDA๐Ÿ˜Ž๐Ÿ™‰ - I knew I needed a loop, but had no clue what to do inside.


Small lines and big lines

The color is calculated using the triangular amp, and stepped to allow color where lines are located.

To make smaller lines smoothstep over the noise in a really small fraction. Then multiply it by the inverse triangle to only allow lines in the triangle shape instead of the whole screen.

smoothstep(0.0,0.02, n3) * smoothstep(0.1, 0.08, n3) * (1. - triangle)

The larger lines are made with a second triangle2 which is the same triangle modified with the UVs to create a smaller value range this creating a larger blob. Then, it's the sum with the other ones to mix the color palette in.

smoothstep(0.0,0.02, n3) * smoothstep(0.1, 0.08, n3) * (1. - triangle) + triangle2

๐Ÿ™‰ I just plugged values until it worked ๐Ÿ™‰ The result was very noisy and not focused, so I started removing parts and added bigger chunks of color until it looked good.


The UV distortion

While tinkering to make this post, I found out that the distorted UVs create some interesting patterns themselves even though they are not the end result

๐Ÿ™‰ I just plugged values until it worked ๐Ÿ™‰ I discovered this while making the graphics for this newsletter