I've got one more chapter for particle systems video for you.
Now, you might have noticed, in all of these examples that I
show throughout the nature of code book,
there's not really a strong design point of view.
It's grayscale circles.
That's pretty much all I ever use,
and one of the wonderful things about working with particle
systems is the kinds of visual effects
you can create with them.
As a reference point, you might look
at some of my previous coding challenges, where I simulate
a rain, rainfall, or snow.
That's one thing you could explore,
but if you look back at that clip from The Wrath of Khan,
the genesis effect, the particles almost burn off
the surface of the planet.
It's a fiery effect.
Particle systems can be used very commonly
they're used in computer graphics
to create smoke or fire, and often, that's
done through the use of rendering the particle, not
as a circle or a geometric shape, but as an image texture.
A texture with fuzzy pixels or some kind of pattern,
and that's what I want to explore in this video.
Now, I'm going to keep it pretty simple
and just hope that you watching this,
you're going to explore the full range of possibilities
here and create your own image [INAUDIBLE]
and play with color and size and all sorts of things,
but I'm just going to give you the nuts and bolts
basic steps for taking this particle system
and adding image textures to it.
But actually, before I do that, I
want to make some adjustments to the code
that I think will allow for a more smoke or fire-like effect.
Looking at the emitter class, you'll
notice I've hard coded this gravity vector in the update
function.
That's not really going to allow me to experiment
with a system of particles that respond
to lots of different forces in their environment.
So I want to take this out of here
entirely and instead add a function called
Apply Force, which receives a force
and then just takes that vector and applies it
to all of the particles.
So let's run the sketch.
Oh, wait, what?
Oh, yeah.
So now, actually, I forgot that I've
given them an initial velocity, so this is actually
quite lovely.
Wait.
Maybe I don't need anything more than this.
I figured out what I want to do.
I'm moving it to the bottom.
The idea here is that I want it to look
like a flame or smoke rising from the bottom of the canvas.
One change I could make is, instead
of creating a random velocity that emanates out
in all directions, restrict that initial angle
to be something that points vertically.
So that might create more of the effect of smoke rising,
but I just want to see if my apply force function works,
so I'm going to create a force that points upwards
and then apply that force.
I don't know if I've improved the visual result here,
but we can see now I have these particles bursting out
from the bottom and rising upwards.
Incidentally, I could add a little bit of a wind force
as well.
There we go, and now we see that the particles are not only
blowing upwards but off and to the right.
And maybe I would say, ah, what if I map this wind to the mouse
location?
I'm going off on a tangent here, but let me just--
humor me for a second.
Let me just add this one extra thing.
Maybe a slider would have been better,
but now you can see, as I move the mouse from left to right,
I'm adjusting that particular wind force.
But this is not what we're here for.
What we're here for in this video
is to look at how can I make this effect look fuzzier,
more smoke like, or more fire like.
What happens if I add an image texture to the way
that I'm rendering the particle?
So first things first, I need to have an image.
What you want in an image texture
is typically a square image and something
with alpha transparency.
You can make something in Photoshop,
you could probably download image textures
from the internet and all sorts of places.
I have chosen to actually create an image texture in P5.js.
This is a sketch that creates a canvas, loops
through every pixel of the canvas,
and draws a bright pixel towards the center
and dark pixels towards the edges.
They're actually not bright and dark,
it's just the amount of transparency in the image.
So I've saved this image out to a PNG file,
and now, I just want to take that PNG file and upload it
to my other P5.js sketch.
In truth, this actually opens an interesting can
of worms, which is that I could, in setup in my particle system
sketch, generate image textures on the fly.
I could use Perlin noise and all sorts of other things.
I'm going to restrict myself here and try
to stay calm and just use this basic image texture.
I want to upload that PNG file to the P5.js web editor.
Once I see that it's shown up there, I can add a variable.
I'll just call it IMG for image.
Let me add the preload function to load the image, and just
quickly to test, let me see-- make sure
that the image is there.
I'll just draw it in the corner of the Canvas.
There it is.
We can see it up there in the corner.
Just to make sure it's transparent,
let me just change the background to green,
for example, and you can see that that
is, in fact, a transparent PNG.
Now, the dimensions of the image that I chose to use here
are 128 by 128, which is probably too large.
Ultimately, your code will probably run the fastest
if you create your image texture at the size you
intend to render it.
But if I have a higher resolution image,
it might give me more flexibility
later that I could grow and shrink
the particle without losing the quality of the texture itself.
So I'm going to keep going with this larger image,
but if I feel like I need to, I could reduce it later.
So in the particle class, I need to find where I'm drawing it,
and it's right there.
I'm just drawing it as an ellipse.
Comment that out, and instead, I want
to use the Image function to draw that image.
So I'm using the R value to enforce a smaller
size for the image, and I'm using the position vector
as to where to place it.
I do want to do something, though,
which is change the image mode to center, because I want
the center of that image to be at the location
of the particle.
Now, stroke and fill don't apply to an image.
So I'm going to take those out, and in a moment,
you'll see I'm going to add something
else back in for the image itself,
but let's just see what this looks like.
Now, does this look more like smoke or fire to you?
I would say no.
Let's try to make some adjustments.
One is, I think I want that image to be much larger.
I've drawn it as almost a tiny dot,
so it's indistinguishable from the point function in P5.
This is starting to look more like what I would expect.
We can start to see the fuzziness of the image texture
as the particles layer on top of each other.
But they're not fading away.
They're just flying up and disappearing,
so I need to add something to reduce the alpha transparency
of the overall image.
The way I do that with an image, it's much like with fill,
but instead of using the fill function,
I'm going to use the tint function.
So I want to not affect the color,
so I'm going to keep the tent at 255,
but I want to affect the transparency,
so I'm going to use the lifetime variable, which counts down
to fade them away.
Oh, my goodness.
Look how slow it runs now.
[LAUGHTER]
So here, we've got an immediate problem.
This blending of the alpha transparency, these images
is incredibly expensive for P5 to do,
and this probably is where I want
to think about reducing the size of my image texture
to be exactly what I'm drawing.
I also could reduce the number of particles.
Let's just do that first to see how much improvement we get.
I'm just going to emit one particle per frame
instead of five.
That's already quite a bit better,
but I'm not getting the full effect of many particles.
So I've now made a version of the image that's just 32
by 32 pixels.
I've called it texture 32.png.
Uploading it to the editor, swapping out the file name
here, and running this again.
OK, this looks like it's running really fast,
but I'm only omitting one particle per frame.
Oh, let me make sure--
yeah, so if r is 16--
this is a little silly.
I'm just going to change this to 32, because it's not
a radius anymore.
It's just the size.
I'm going to remove the times 2, go back to sketch,
emit 5 particles per frame and loops.
Ah, cross your fingers and hope.
Still pretty slow.
Why is it so slow?
Let's try two particles per frame.
It's still running rather slow.
I've improved it a little bit, certainly.
One thing that I think might help that I'm going to do
is have the particles fade away even faster.
And while I'm losing the length of the trails of particles,
we can see that I've got something
close to what might resemble a little bit of like a candle lit
flame.
So this is where I'm going to settle for now
just to have some optimal performance for the next step
that I want to demonstrate.
What I want to look at now is the function blend mode.
I want to encourage you to fully explore the blend mode dot
reference page and look at all the different possibilities,
and you might try a variety of them with your particle system,
but I want to zoom in on this one called
ADD, the sum of A and B.
So there's always a default blend mode
when you layer colors on top of each other in a canvas.
And the default blend mode is actually just called blend.
It's a linear interpolation of the colors.
You can think of that is like, if this is red
and we'll layer some transparent blue and put it on top,
I might get something purple-ish.
I think that's right, but adding doesn't
blend those colors together, it adds them together.
This has the quality of the more colors
you layer, the brighter and brighter the pixels get.
Just the simple act of adding blend mode
add to the top of draw.
So this is kind of interesting.
I don't know whether this is a bug or not.
I mean, really, it's not a bug, because once
I'm adding the colors, when I layer
in the background, that's not actually
erasing what was there before.
That's just adding 0 color to it.
So in order to get the effect that I'm looking for,
I actually also need to add the function clear,
which will clear out what was there from the previous frame.
And now, it might not be so obvious
what the difference is here.
If I zoom in, you could start to see
that it's slightly different.
Let me put them side by side, but I
think this will become much more apparent when
I begin to add color.
So going back to the particle itself,
the tint can include a color.
So what if I were to just say, tint 255, comma 0, comma 0.
So this is going to be a red tint.
So that didn't do what I expected and I'm realizing why.
I want to see this white glow, and I'm never
going to see that white glow if I'm only
ever adding to the green and 0 to the blue channels.
There's nothing for it to add to.
So I've got to at least give it something
if I want it to be a reddish color.
Now, we're seeing more the effect that I would expect.
As the colors layer on top of each other,
they're adding together, reaching a hot white color.
And where there's fewer particles,
I start to see more the color values
that I've put inside the tint function.
And I'm just playing around this,
trying different tent values, and this is what I really
encourage you to do.
And now that I'm using this fuzzy particle,
you might [INAUDIBLE] this tiny little effect in the canvas.
I think I could actually really try
to expand the size of these particles.
And already here, I feel like, oh,
I have this nice almost burning flame
that I can affect with the mouth blowing it
a little bit to the right or a little bit to the left.
So I'm going to just stop here.
I could play with this probably forever.
I'm hoping that I-- by the fact that you watching this
and trying this yourself and sharing with me your results,
I'm going to discover all sorts of possible things
I didn't think about that you could do with image textures
and blend modes and particle systems,
so please, in the comments or go to the coding training
website, where there's a place you can actually
submit a link to any sketches that you make.
I would love to see what kind of stuff
that you're able to discover through this technique.
There's also the possibility of using the WebGL renderer of P5
to improve performance.
I'm not doing anything in a 3D space here,
so that makes less sense, but even
in this 2D world of the particle system, that
might be something to explore.
I would maybe try to investigate that and come back
in a future video, but if you are
able to squeeze out additional performance
by using the WebGL renderer of P5
or improving on my code in any way,
I would also really love to know that.
So thanks for watching this video.
This wraps up chapter 4 until I make some extra particle system
videos, which may happen, and I look forward
to seeing you in future chapters of the nature of code.
[MUSIC PLAYING]