So guys…the last shader video kinda exploded
and you wanted more. It's the same deal as last time: You keep
liking and commenting, I keep explaining shaders! Shaders always look so intimidating. But honestly, they are not complicated - just
really really strange. And once you got used to them you can make
amazing stuff really fast. This is because many effects tend to use the
same simple techniques and just combine them in a new way. We already covered
- Grayscale - Screen reading
- and mapping stuff to a gradient Another thing that is almost always the answer
is texture scrolling. If you look for it, you can find it in a ton
of effects. We start with a looping texture. The easiest way to create a one is to use
a noise texture with open simplex noise and make sure "seamless" is enabled. We add a shader and sample the texture at
its UV. And we can see…a bit of black and white
noise. We can make it scroll by adding a vector that
we multiply with the TIME builtin. This way whenever the time advances, the UVs
are calculated differently. The scrolled UVs are not between 0 and 1 anymore,
but that’s okay since our texture is wrapping and that makes it basically infinite. Here’s how it would look like without the
seamless flag. If you want you can play around and put a
sine around the time to make it oscillate. Or multiply it with a sine of the time to
make it zoom in and out! Play around and put the sine at different
places. But for this effect we just keep it moving
forever. Let's make the scroll a uniform so we can
change it. When we change it at runtime by sliding the
values, we see very strange movement. This is because the texture does not move
incrementally. Instead, its position is calculated based
on the time, independent of the last frame. So when we change the scrolling speed it moves
where it would have been if it moved like that from the start. In case this is ever a problem, remove the
TIME builtin and animate the complete scroll directly. We now add another noise texture by adding
a uniform sampler2D and sample it. Don’t forget to make it seamless again. It needs its own scroll uniform just like
we did for the first one. We now multiply the color values to get the
overlapping brightness, let’s call it energy. When we write it to the COLOR, we see quite
organic morphing around. Based on the scrolling speeds and the properties
of the noise, it can look very different. We can color it by adding another texture
as a sampler2D. This time we use a gradient. Based on how bright the image is, we sample
a different point of the gradient. So, the black pixels get this part on the
left, and the white pixels this part on the right. We can make a lot of different effects with
this, lets start with a fire. The lowest energy parts should be invisible. After that we make black for the smoke, and
then red and yellow. You should play around a lot with this gradient,
you can make the color transitions sharper. It generally looks good to have some non linear
parts so you see more of the morphing around. We can adjust the scroll to make the fire
go upwards. One remaining problem is that we still have
sharp borders, this just looks bad. Also, fire should fade out. So what if we reduce the energy at the top
of the image? Subtract (1 - UV.y) from the energy, so that
there is no energy left at the very top. Since the average energy is around 0.5 before
this step, we get pretty small energy values, so add a factor of 0.5. We can also boost the gradient a bit to make
up for it. If we want to we can also sample another texture
instead and multiply it to the energy. That way we can bend it in the craziest shapes,
as we did here with burning text! We can level the whole effect up by using
custom noise textures. For these, we typically use Krita, because
it has a wrap around mode. You can draw flames if you want flames, bubbles
if you want bubbles, electric sparks if you want or even skulls and whatever. Import them and make sure the repeat flag
is set or it will not show up! So for a flame effect, we use flames. Of course you can make them green. Or black. I won't judge you. And for a water spell, you could use bubbles
and color the gradient blue. For a water effect like we made in our game
Furcifers Fungeon, we combined texture scrolling with distortion. Also, we added white to the high energy parts! Another effect that you can find almost everywhere
is a dissolve. For the simplest form, we sample the texture. Then we calculate the pixel’s brightness,
which is its grayscale value. Add a uniform that describes how dissolved
the texture is. Whenever the dissolve value is higher than
the pixel’s brightness, simply don't draw it. We could do this with an IF, but because branching
is difficult for GPUs there is also the step() function. It returns 0 when the first argument is larger,
and 1 otherwise. When we look at its graph, we see it looks
like a step. The first parameter, the dissolve uniform,
defines where the step is, and if the brightness is below the dissolve the output is 0 and
if it is higher, the output is 1. We can just multiply the alpha with that. And now our image disappears! By the way, there’s also the smoothstep
function, which looks like this. It has three parameters - the left and the
right border of the transition and the value to compare. You should play around with it! But for now, let’s get back to the dissolve. You usually will find a more complex variant
of the dissolve. We can also use it for a nice electrical type
effect. For this, calculate the distance between the
pixel's brightness and the dissolve value. If it is below a certain threshold, maybe
add a little color. We now have this flash wandering around! You can customize it, make multiple ones etc. Often another texture is used for the dissolve. For this, take another uniform sampler2D,
give it a noise. It can be generated, it can be custom. Usually it’s in grayscale. We can sample the brightness from there, and
don't even have to average the color values because they all are the same anyway. You can also combine flashing and removing
for a burn type effect. And of course we can combine it with a gradient
texture! For this, sample your sprite, calculate the
greyscale and map it to the gradient like we did in the first video. But now, subtract the dissolve value from
the brightness! When we set our gradient up correctly with
transparency at the left, we can see that it disappears! This can be used for a lot of visual effects,
like a snowflake melting! We can scale it a bit to make it more convincing. In most cases, you would like many snowflakes
at once, which is where a particle system shines. And we can make a particle system out of every
effect, with some trickery. Add a particle system and give it a snowflake
texture. Now go aaaaall the way down here and add our
shader. We can see them and they are nice, but they
all melt together. And this is not great. To distinguish the particles, we’ll need
the particle lifetime in the fragment shader. Luckily, the lifetime can be accessed from
the vertex function, in INSTANCE_CUSTOM.y. To demonstrate it, we can multiply it to the
VERTEX position. But we can not access that down here in the
fragment function. For this, we need a varying. Varyings are variables that exist for each
vertex. In this case, each particle has 4 vertices
with the same instance custom. So each pixel of the particle will have the
same value in it. But different particles can have different
values. We can just write the lifetime into the varying,
and read that in the fragment shader. Shader effects are made by layering different
techniques. And we already use a lot of layers. We used grayscale here, we used mapping stuff
to a gradient. We kinda dissolved, but we plugged it into
a particle system. And no one would stop us from reading the
screen, or doing texture scrolling on that! These effects here are done using texture
scrolling on particles for example! We made a video about that specifically! If this was helpful to you, please give the
video a like! As long as you guys are interested can go
on forever.