Graphics and Media • 57:25
Quartz Composer takes all the graphics capabilities of Mac OS X and combines them into a single code-free environment. We will walk through the content creation process in Quartz Composer, using the editor tool to efficiently create high quality, high performance compositions. Through multiple examples you'll see how to realize your ideas and put them in users' hands. If you have a graphics concept in your head that you're just not sure how to put into action in your application, this session is for you.
Speaker: Alessandro Sabatelli
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
My name is Alessandro Sabatelli and I'm a Quartz Composer motion graphic artist. Today we'll be going through two hands-on tutorials. The first one will be covering some of the fundamentals of working with Quartz Composer. We'll be looking at things like the coordinate system, how to approach animation, and working with groups of elements. And in our second tutorial we'll be looking at how you can use Quartz Composer in production. So some of the things we'll be covering there are particle systems and how to apply effects to different areas of your graph.
First thing that you'll need to do is launch the Quartz Composer editor. If you're on Leopard, this is in Developer Applications Quartz Composer, and on Tiger, Developer Applications Graphics Tools Quartz Composer. You'll notice we got a little bit of a bump here, and we have a new icon. So, this is the first composition we'll be building. Multiple elements animating some nice little reflections. And this is a group of elements.
So again, if you're coming in late, please have the assets for today's session. connect.apple.com/wwdc2006/sessions207.ph p. Everybody got that? All right, if I could have demo one please. We'll get started on our tutorial. So I'm going to launch Quartz Composer, which I've put handily in my dock. Hey, if this is the first time you're launching Quartz Composer, you'll notice that we have a new assistant. I'm going to go ahead and cancel that, close the getting started, and file new. And here we have our editor window and our viewer window. So I'm going to just get that set up for you guys so you can see.
I'm going to adjust my preferences so we have a little bit more contrast in our workspace. So what you just noticed was the workspace change in color, that's the place where we do most of our work in Quartz Composer. To the left of that we have a patch library, and above that we have a search field for the patch library. We also have a viewer, and this is where Quartz Composer is going to be doing its drawing.
And you'll notice here in the toolbar of our editor, if you do not have your viewer, we have a viewer button and you can press that to launch your viewer. So what you'll immediately notice is that our viewer has a white and gray checked background, and that means we're not doing anything within the viewer currently.
So most of the time what we need to do first is we need to clear the screen once per frame. So I'm going to search in my search field here for clear and drag a clear patch out onto my workspace. And for those of you familiar with Quartz Composer or who went to Pierre's session yesterday, a patch is basically a type of function.
There are two types of patches. There's those which take data in and process it, and there are those which draw to the screen. The clear patch is one which draws to the screen. You'll notice that our viewer is now black. We're clearing the screen or drawing to the screen once per frame. And patches which draw to the screen have this special enable port. If I hover over it, I can see that the value is set to true.
If I were to double click on the input port and set the value to false, we'd no longer be clearing the screen. So I'm going to go ahead and re-enable that by setting it to true. You should all have a black viewer. So what we need to do first in decomposing this problem is look at each of the things that we need to do in a step-by-step fashion. So the first thing that we need to do is draw something to the screen.
So if you can go to the assets folder for today's session, if you go to QC Fundamentals, And in the assets folder there, we have a peter.png. So just so you guys know, we also have some milestones set forth. And these are steps which I'll be taking you through throughout the tutorial. So if at any point in time you do get lost, feel free to start up from one of these steps. And you'll know where I'm at because periodically I'll be saving to the desktop.
So in the assets folder of QC Fundamentals, we have peter.png. If you take that and drag that into your workspace, You may think that what we're going to do is immediately we'll have drawn an image. But actually this is just another patch which is outputting an image, and what we need to do is display that image on a surface.
So if you search for "sprite", we'll be using a sprite to display our image. And drag Sprite out onto the workspace. And connect the output image of Peter to the input image of our Sprite. And there we have Peter, who's looking a little bit larger. As you can see.
And in actuality, Peter is not this large. Peter is a healthy man. So the reason why Peter is looking large here is because Our sprite is square and our Peter image is non-square. And you can see the size of the Peter image if you hover over the output port of Peter. You'll notice that it says 174 by 334.
And this is the actual pixel size of our image. And what we need to do is get our sprite to be a little bit more correctly proportioned. So if you were to select your sprite and go to the inspector, Under input parameters, you can control the width. So if I were to drag this counterclockwise, I can get Peter super skinny. Or a little bit, yeah. But if we wanted to exactly proportion this sprite, what we can do, new in Leopard, is we can enter an expression directly in the width field here. So this is 174 divided by 334, and that is .521.
So if you're in Tiger, just go ahead and type 0.521. And you will have a correctly proportioned sprite. So now we have Peter displayed on our viewer. And you may notice that he's wearing a leopard print shirt. And I had actually asked for a picture of a running leopard from marketing, but apparently that was not attainable. So what I did was I went ahead and put, or upgraded Peter's style.
Okay, so I'm going to save that to my desktop as 1-sprite. Okay, so the next thing we're gonna do, or we're gonna look at in approaching this visual problem is how to get the reflection. And in order to get the reflection, we're simply going to take our original image and flip it over the X axis. The X axis runs horizontally. And we're going to do that to a sprite, the surface which we're going to be displaying this reflection on. So we can just go ahead and select our first sprite and option drag. You'll see a green plus.
and release. And what you'll immediately notice is that Peter's gone and he's been replaced by this white rectangle, and that is because we are now drawing a sprite, which is a copy of our original sprite, which is correctly proportioned on top of our sprite which was drawing Peter. And the reason that we know it's on top is because patches which draw to the screen have a rendering order.
So, our first patch, the clear patch, is rendering first, then we're drawing the sprite which is textured with Peter, and then we have our third sprite which is yet to be textured. So, if you go ahead and connect Peter output image to the input image on our second sprite, we're more or less back where we started, except now we're actually drawing Peter on two sprites.
So we're going to adjust our second sprite by again rotating it over the X axis. So if you open up the inspector, go to input parameters, X rotation and drag that clockwise. This is going to take a long time to get to 180. So just as a tip, what you can do is hold down shift to increase the increment here. And I'll need you to just go ahead and type 180. So now we have Peter upside down.
So in order for this to be a reflection, what we need to do is shift this down in Y. And we need to shift this down by the height of our original image. And that was one, if you recall. So if you were to grab Y position and go counterclockwise to negative one, we now have a reflection of Peter. And we're going to adjust the color so that this is a non-perfect reflection to something like that.
So now we have Peter and his reflection. And I'm gonna save that as a milestone. Save as to reflection. All right, so now that we have this image being displayed on a sprite and another image being the reflection, what we're going to look at is how to animate this.
And animation in Quartz Composer can be accomplished in a number of different ways, but all of them work in basically the same way. And what they do is you end up with a patch that references time and outputs a number. So this number will be varying based on the time. And the patch which we're going to be using today is the interpolation patch.
So if you search for interpolation and drag interpolation out, And what we can immediately do is connect interpolation to the X position of our first sprite and the X position of our second sprite. And what you'll see is we have Peter moving from the center of the screen to the right.
I'm going to look at the inspector for our interpolation patch. The first thing I'm going to do is rename the interpolation patch. This is just good practice. It's basically like commenting your code or as low level as naming your functions or methods. It's pretty important, especially if you want help on the developer list, which I encourage you to do. So interpolation X.
And if I were to look at the input parameters for Interpolation X, you'll notice that the start value is 0, the end value is 1, and the duration is 1. So what this means is that over a second, this patch is going to be producing or interpolating between a number 0 and 1 over one second.
And the repeat mode is set to loop, so this number will just be looping. And the interpolation is linear. So as you can see, Peter is moving in a linear fashion from the center of the screen to the right. And so what is zero and one? And you may be asking yourself what these numbers actually mean, and what we're doing is we're animating within the Quartz Composer coordinate system. So I put together actually a little patch so I can show you and talk to you a little bit about the coordinate system.
So here we have our Quartz Composer coordinate system. So as you'll recall, when we rotated the sprite over the x-axis, that the x-axis is the horizontal one and the y-axis is the vertical one. Our X axis goes from -1 on the left to +1 on the right. Our Y axis is variable, which you can see here. If I change the aspect ratio of our rendering destination, you'll notice the number on the left, being the width, remains a 2 and the height is changing.
So this is very important because what this allows you to do is create content for varying destinations. So say for your computer or for somebody else's computer, for different installations or whatever you want to do. So the important thing to recall here is that the width always remains 2 and the height changes. I can show you that. I have a little coordinate of where my mouse is. And you can see that it goes from negative one to positive one in X, and one half the height to negative one half the height.
Okay, so here we are, Peter starting at the center, 00, and moving to the right, 10. So what we need to do is get Peter to move from off-screen left to off-screen right. So in our inspector for our interpolation X patch, under input parameters, I'm going to set the start value to -2.5.
and the end value to 2.5. So Peter is now flying across the screen at a brisk pace. So what we can do is change the duration at which this interpolation is interpolating. So I'm gonna change that to three seconds. And we now have Peter moving at a more reasonable rate from left to right.
[Transcript missing]
All right, the next thing that we're going to look at is adding some animation to Peter's Y position to get him to bounce from left to right. And we can do that with another interpolation patch. So search for interpolation and drag an interpolation patch. Add on to the workspace. Again, the first thing I'm going to do here is change the name or the title of the patch to interpolation Y.
And what I'm going to do is I'm going to connect that to my first sprite, but not to my second sprite immediately, and that'll become apparent in a second for the reasoning behind that. But here we have Peter. Again, by default, the interpolation is interpolating between 0 and 1 over 1 second, so his Y position is changing over 1 second.
And as I mentioned, patches which we use for animation reference time. And in this case, our interpolation patch is referencing time to produce a value which changes over time. And what it's actually doing is it's interpolating between the two values, and by default it's interpolating in a linear fashion. So what we want to do is we want to change the way it's actually interpolating between these numbers.
So by default, the interpolation patch has a few built-in interpolation modes, which you can see in the input parameters of the inspector. There's quite a few. But what we actually want is a custom interpolation curve. So if you go to the settings pane of our interpolation Y patch and go to Customize Interpolation Curve, Add a point somewhere in the middle and then drag the point on the upper right all the way down.
And I can adjust this curve so there's a little bit more acceleration on the outset. And we now have Peter bouncing from left to right. So the next thing that we want to do is get his reflection bouncing as well. So if some of you may have jumped the gun and connected this to your second sprite as well and you did not want to do that. And the reason why you didn't want to do that, as you recall, we had shifted our reflection down in Y.
So what we need to do is we actually need to modulate the output of our interpolation Y so it makes sense for our second sprite. So not only do we need to take the value coming out of the interpolation Y and shift it down one, we also need to flip it over, and we'll be inverting the number by multiplying by negative one, so that as our original image bounces up, our reflection bounces down. So we end up with this kind of bouncing reflection.
So in order to modulate the output of our interpolation Y, we can get a math patch. And just like it's named, it allows you to do simple mathematical operations. So as I mentioned before, we'll need two operations. So in the settings for the math patch, go ahead and click the plus for the number of operations.
And in the Inspector pane, under Input Parameters, set The operation one to multiply, operand one to negative one, Operation 2 to subtract and operand 2 to 1. So if we now were to connect the output of our interpolation Y patch to the initial value of our math patch and the output of that to our Y position of our sprite, what we'll get is this bouncing reflection.
And again, recall the reason why that's working is because we're taking our value, which is going like this, and we're inverting it so it's going like this, and then we're shifting it down. So it's literally doing what you're seeing on the screen. So here we have Peter bouncing most jovially from off-screen left to off-screen right, along with a reflection.
[Transcript missing]
So now that we looked a little bit at animation, we're going to look at how to animate groups of elements in Quartz Composer. And again, there's a number of ways you can do that, but what we'll be using today is the iterator. So the iterator, just like a for loop for those of you with a little bit of a programming background, what it allows you to do is it allows you to execute part of your graph a certain number of times per frame.
And the way that we do that is the iterator is a special type of patch known as a macro patch, and a macro patch allows you to take other patches and put it inside of it. So anything that's inside of this iterator patch is going to be executed a certain number of times per frame.
So what we're going to do is we're going to take everything that we just built, our interpolations, our two sprites, our math, and our original image, and we're going to put that inside of an iterator and execute that a certain number of times per frame. So that'll give us a certain number of Peters bouncing from left to right. So if you search for iterator, And drag the iterator macro patch out onto our workspace, you'll notice that the corners are square. And that is because macro patches have square corners. It's just a little bit of a visual cue.
So what you can do is select our interpolations, Peter, Math, and our two sprites. And edit, cut. Everything's gone away. Go inside our iterator patch by double clicking on it, and edit, paste. So it looks like we're right back where we started, but instead what we're actually doing is we're drawing 10 of these, one on top of the other.
And the reason why I know it's 10 is because the default settings for our iterator patch, the number of iterations is set to 10. So within an iterator patch, just like a for loop, what we need to do is not specify how these iterations are the same, but we need to specify how they're different. And the way that we differentiate iterations within a for loop or our iterator is by using the current index. And you can access the current index by using the iterator variables tool.
Which if you search for iterator, and drag that out onto the workspace, It has three output ports: the current index, the current position, and the number of iterations. So the current position, just so you know, is the normalized index between 0 and 1, 1 inclusive. So we'll be using that today.
So what I'm going to do is I'm going to take the current position, which again, the normalized index, 0 to 1, 1 inclusive, and I'm going to rearrange it so that it goes between negative 2 and 0, and I'm going to apply that to the Z position of our sprite and sprite reflection.
And what we'll end up with is the first iteration, or iteration 0, being at negative 2, and then going all the way forward to 0 with 10 iterations. So I'm going to be using the new mathematical expression patch. For those of you in Tiger, you can simply use a math patch. And what you'll need to do is have, with your two operations, you're going to multiply by 2 and subtract by 2.
But the mathematical expression allows me to do that in a little bit more of an intuitive way, which is easily traced through as well. So if I were to go to the settings pane of our inspector and type current position times two minus two. And connect the current position to the inspector.
And I'm going to connect that to the Z position of both of our sprites. And now we have Peter bouncing from left to right at 10 different Z depths. What you'll immediately notice is that it appears as if the Peter image is on a black background. In actuality, this Peter image has an alpha channel, but what we need to do in order to take advantage of that is adjust the blending mode on our sprites.
So if I were to directly double click on the blending input port and set the blending mode from none to over, and do the same on our reflection, We now have Peter with a clean edge, bouncing from left to right at 10 different Z depths. So again, what we did here is we simply differentiated the behavior of our subgraph by using the index of our iteration or our iterator. So I'm going to save that as five.
Okay. So the next thing that we're going to look at is differentiating the X position of each of these sprites and their reflections. And in order to do that, it's the same thing basically. But what I need to do in order to do that, right now our X position is being driven by this interpolation X, and each one of these iterations is getting the same value.
What I need this to do, recall that patches which animate in Quartz Composer produce numbers which depend on the time. What we need to do is change the time which each of these patches references, and we're going to change it in a way that's based on the index within our iterator.
So patches which reference time have this special menu, if you were to Control-click on our interpolation X, named Time Base. And what this allows you to do, again, is manually control the time which this patch references. So by default, this is set to parent, and this is referencing the time which our iterator patch is providing.
And the iterator patch is providing a time which is also set to parent. So it's actually looking at the root time base. So there's one time, basically, for this entire composition. But what we want to do is control the time which our interpolation X references manually. So we'll set our time base to external.
And you'll immediately notice that everything is gone. And the reason is because if I were to look at the inspector for our interpolation, under Input Parameters, there's a new input port, or a new input here named Patch Time, which I can now control manually. I can get Peter to do all this. to do all kinds of fun stuff.
So what I'm actually doing is I am changing the time which the interpolation X is referencing. At this case, it's referencing some number around one and a half. So this, recall that our interpolation is just simply, in this case, interpolating between negative 2.5 and 2.5 over three seconds. It's also looping, so if I were to go past three, we'd start again back on the left at negative 2.5.
So what I'm going to do is I'm going to modulate the time, or the patch time, that the interpolation X is referencing based on the index within the iterator patch. So the first thing I'm going to do is I'm going to search for patch time. I need something to modulate.
In this case, it'll be the patch time of the parent patch or the iterator. So if I were to directly connect this back to the patch time of our interpolation X, we'd be more or less back where we started with the Peters bouncing from left to right. But now I have this parameter exposed, so I can modulate that.
And I'm simply going to use a math patch to add an offset based on the current index. So if I were to connect the patch time to the initial value of our math patch, and the output of our math patch to the patch time, nothing has changed because by default we're simply adding zero.
So what I'm going to do is I'm simply going to connect the current position from our iterator variables to operand1. And you'll immediately notice is that now each of our successive Peters, again recall that they're starting at negative two and coming forward, so each successive one is offset by some number close to point one in their patch time. So what you get is this kind of diagonal row of Peters bouncing from left to right. So as exciting as that is, what we'll need to do in order to add a little bit more variability to this example is randomize the position based on the index.
So search for random and drag that patch out onto our workspace. And what random does is it'll simply produce a continuously variable number, or an animating number, between the min and the max over time. The key word here is time. The random patch is referencing a time base. So what I'm going to do is I'm going to externalize that time base.
And I'm going to, more or less, look up into this random patch based on the current index. So if I were to connect current index to the patch time of the random, and connect the output of the random patch to operand one, what we now have is a group of Peters, each one with a random offset per index added to our patch time.
And in actuality, what we need to do is we need to set our max value of our random patch to the duration of our interpolation to get a more even distribution. So if I set the max value of our random patch to three, we now have a more or less evenly distributed group of feeders bouncing from left to right at different z-depths.
And what some of you may notice, if you have a keen eye, is that this pattern is actually repeating. And the reason why it's repeating, recall that our interpolation is set to loop, and that our random patch is actually outputting the same number for each iteration within our iterator.
And that's because the time which it's referencing is actually based on the current index. Now if we wanted that changing, we could do some other kind of math and add some patch time the same way that we're adding patch time to our random. But for this example, this should suffice.
The next thing that we're going to look at is randomizing the bounce for each one of these iterations. And we can do that using the exact same technique. So what I'm going to do is I'm going to select my interpolation Y patch. Control click on that and set the time base to external. So we now have our Peters sliding from left to right. This should be familiar by now. And I can control them patch time manually and get them to do this hover type thing.
And you can simply connect the output of our math patch, which is the patch time with a random offset per index, to the patch time of our interpolation Y. You should now have Peters randomly bouncing with random offsets in X from off-screen left to off-screen right at different Z depths. And I'm going to save that as 6 final. Go full screen on that so you guys can see it.
So if we could go to slides please. Alright, some of the things that you learned and some things to remember in this first tutorial is that the Quartz Composer coordinate system is resolution independent. This means, again, is that the Quartz Composer coordinate system uses units and not pixels, and the reason why is so that we can display on differing output destinations.
The other thing to remember is that you need to pay attention to rendering order. If some of you jumped the gun and ended up clearing at some point after which you were drawing, you will not see anything. And it may seem a little abstract or maybe it's concrete, but basically you need to erase first and then draw. The other thing to remember here is that you can control the time for patches which reference the time. This allows you to do interesting things, particularly within an iterator, such as reference a time which is based on the current index.
Okay, so for our second tutorial we'll be looking at how you can use Quartz Composer in production. So you might recall from Steve's keynote that he presented the backup, the new backup system, and the backmost layer of that backup system, of the backup animation was done using Quartz Composer.
So recall that this is a spiral galaxy looking kind of thing and there's a galactic core in the center and some stars flying out. So what we're going to do in this tutorial is we're going to look at how you would approach something like this and do an approximation of how we actually built this for the backup system. So if I could have demo one please. I'm going to create a new file. And get set up.
All right, so old news, the first thing that we need to do is clear the screen. So let's get a clear patch, clear the screen. The next thing that we're going to do in decomposing this problem is we're going to look at the most prominent element of this scene, this being the swirling galactic cloud.
So in order to accomplish that, the first thing that we need is some kind of evolving or billowing cloud. And we can get something pretty quickly by using the particle system. So if you search for particle system and drag a particle system out onto the workspace, If you went to Pierre's session, you'll have a brief overview of a particle system, but for those of you who haven't, particle system basically defines a group of points evolving over time, and each one of these points is birthed, lives for a certain amount of time, and then dies and is reborn. And the motion which these points move at in space is defined by the input parameters of our particle system.
And our particle system allows us to display a whole bunch of images, in this case on these white squares which are always facing the camera. So the first thing that we're going to need to do is texture these squares. So if you go to the assets folder for the galaxy, There is an image in there named Cloud. Let's drag Cloud onto our workspace.
and connect the output of the cloud image to the input image of our particle system. So you should all see a whole bunch of clouds kind of flying around. And just like with Peter, these are on a black background because we need to adjust the blending mode. So double click on the blending mode and set the mode from none to add, because we're looking for a more additive effect here. And we're now going to look at setting up the parameters of our particle system to get it to behave in a way which is a little bit more like a billowing cloud. So I'm going to adjust the input parameters of our particle system.
So if you guys just follow along, I will explain what I'm doing after I set all of our parameters. So the first thing that I'm going to do is I'm going to set the color. I'm going to go for something like a sea green, something over here. And then I'm going to adjust the opacity.
Something like 20%. Going to set the X min velocity to negative 0.0 or negative 0.5. The X max velocity to 0.5, the Y min velocity to -0.5, the Y max velocity to 0.5, the Z min and Z max velocity to 0, The min size to 0.05. Whoops. And the max size to 0.075. Lifetime you can leave it to. We're going to change our size delta to 0.15. Our opacity delta to minus .125. And our attraction to zero. So I'll zoom in on that so you guys can see that.
Alessaandro Sabatelli: Okay, so let's look at what I did to define this behavior. So now that we have this billowing cloud just kind of flying outwards, and again, recall this is just one image, and what we're doing is we're modifying this image over time. So what we did was we set the initial velocity vector. So when each one of these particles is born, it is born with an initial velocity vector. So in this case I'm defining a min and max in the three different dimensions, x, y, and z.
Recall that the z is zero, so what we're doing is we're generating a velocity vector randomly on a flat plane, which is pointing somewhere within negative 0.5 to positive 0.5 in x and y. So what we get are these particles that are kind of flying outwards from a central point.
When each one of these particles is born, we're saying that we want it to be, or have a size, which is somewhere between 0.05 and 0.075 units. It's going to live for two seconds, and over those two seconds the size is going to change by 0.15 units per second, and the opacity is going to change by -0.125 per second as well.
So what we get are these things flying out randomly from the center, and as they fly out, they're growing and fading out. And that's exactly what you see in the viewer. So the next thing that we're going to look at is how to add a little bit of a galactic swirl to this.
One way that we can do that in Quartz Composer is by leveraging Core Image. For those of you unfamiliar with Core Image, Core Image allows you to filter or process pixels in a very efficient and optimized way. What we need to do is we need to pass a Core Image filter an image, have it operate on that image, and then display that image on a surface. So right now we have a particle system which is being rendered to the screen. In order to render this to an image, what we need is a special macro patch called render an image.
So if you search for render an image, you might want to search for render generator as a shortcut. And here's our render an image. Again, a macro patch, square, And what we're going to do is simply select our particle system in our cloud, edit cut, Go inside our render an image by double-clicking it.
And because we're going to be generating an image here, the first thing we need to do, just like when we're generating an image on the viewer, is we need to clear this image once per frame. So I'm going to search for clear, drag clear out onto the workspace, and edit paste.
For those of you that jumped the gun and pasted your particle system and then cleared, recall that you're drawing and then erasing the screen and you won't see anything. So what you need to do is change the rendering order. So for those of you that did that, you can simply the rendering layer to one instead of two. So then you'll be clearing and drawing your particle system. Alessandro Sabatelli So I'm going to do that.
So onto the workspace. Here's our familiar white square. Connect the output of the render an image to the input image port of our sprite. And it'll look a little squished, same reason as Peter being squished. The aspect ratio, or the proportions of the image which we're generating by our render an image, is not square. And you can see this by hovering over the output image port. And you'll notice it says 512 by 384.
What you'll also notice is that new in Leopard, our viewer has a size displayed directly on it, which happens to be 512 by 384. This is not a coincidence. By default, the render an image is producing an image which is sized to the rendering destination. So in order to some cycles when processing our core image filter, what we're going to do is fix the size of our image.
So new in Leopard, you can dynamically change the size of your render and image by just simply double-clicking these input ports. But if you're on Tiger, you can go to the settings pane of our set the width to 512 and the height to 512. So we now have a correctly proportioned image, which we're displaying on a square.
And I'm going to set the size of my sprite to be 2.5. So we're more or less back where we started, except now, just like with time, we can modulate this image in line. So in order to do that, I'm going to need you to get the spin distortion asset.
from the QC Galaxy. So within Assets, there is a galaxyassets.qtz. If you double click on that, you can just close the viewer or wait for it. - Fun little animation in there. But what we need is the spin distortion. So if you select that, I'm going to minimize this to the dock.
We're going to need that a little later on. And I'm going to edit paste. So here is our spin distortion. And as I mentioned, Core Image comes with something like 150 built-in filters. But for this particular project, as you'd guess, we had to write our own. So spin distortion leverages Core Image using the Core Image kernel patch in Quartz Composer. You can see this kernel patch. Let me clean up a little bit.
If you go to the settings inspector on the kernel, after carefully reading our disclaimer, which I'm sure all of you will do, We have our spin distortion kernel. Exercise up to the reader if you guys want to look through that on your own time. But basically what we're going to do is we're going to take an image in and we're going to add some kind of spin to it. And in order to accomplish that, I'm going to route our image through the spin distortion filter. And here we have a spinning gas cloud.
Thank you. So it's going kind of fast, which would be an insane amount of backup. So what we can do is a similar technique. We're going to be modulating the time which our render and image is referencing. Recall that our particle system is animating based on time. Its time base is set to parent. The parent in this case is the render and image. So what we can do is just simply externalize the time base of our render and image.
Again, it's black. If you were to go to input parameters, we have this patch time, and you can simply play around all day long by scratching our time here. But what we're gonna need is a patch time patch. So drag patch time out. And you can connect that to the patch time of our render and image. We'll need a math patch to modulate this number.
Connect that to the initial value. Connect that to patch time. And we're simply going to, in the inspector pane, under input parameters, set our operation one to multiply and set it to something like 0.05. So now we have this slowly evolving gas cloud. Connect that to the initial value.
Connect that to patch time. And we're simply going to, in the inspector pane, under input parameters, set our operation one to multiply and set it to something like 0.05. So now we have this slowly evolving gas cloud. of everything that we had selected, And I'm going to name that Spiral Galaxy. So now we're simply clearing the screen and drawing the spiral galaxy. The next thing that we're gonna look at is adding this kind of blown out center, which is our galactic core. And I have pre-assembled that in our assets folder.
Oh, sorry. That is in the Galaxy Assets Composition. So select the Sun macro and edit copy. Going to re-minimize that and edit paste. So now we have a blown out center. And if you were to look in Sun Macro, we're simply displaying an image, which is this radial gradient on a sprite, which we've named Sun. So pretty easy. The next thing that we're going to grab from our Galaxy assets is the stars. So select the stars macro patch, edit, copy, and paste.
Close that, and you'll now see some stars flying out at us. And if you were to look inside of the stars macro patch, We have a particle system which we've configured a little differently. Now what we're doing is we're generating a random velocity vector within this cone, which is kind of coming out at us, so we get these stars flying out at us. And I'm also modulating the patch time here to slow this entire thing down. And that's really it. So we have these stars flying out at us over this galactic core with this spinning galaxy.
I'm going to save that as Galaxy. So I'll go full screen so you guys can see that. So obviously there was a lot more tweaking that went into the final product, but this should give you an idea of how you can approach production using Quartz Composer. So if we can go back to slides please.
Slides. Thank you. Okay, some of the things that we learned in this last tutorial is that you can use a render an image macro patch to post-process areas of your graph. So simply put them inside of our render an image and then you can leverage core image to apply filters and effects to areas of your graph. We also looked a little bit in both of these tutorials on how to approach visual problem solving.
Basically what you need to do is decompose your problem into smaller steps just like everything else. Some people seem to have difficulty in applying this to visual problems, but it's really the same thing. So recall in the first tutorial our final product was a whole group of Peters bouncing from left to right at different depths in an all randomized fashion.
This may seem kind of daunting at first, but the first thing that we did was we simply displayed our image on the screen, added a reflection, then we got this animating and then applied or then exploded this into a group of elements. And the last thing to remember when working in Quartz Composer is to have fun. What we're working in is an environment where we don't have to deal with this compile, test, you know, run cycle.
We simply can build things, drop patches directly on our workspace, get immediate visual feedback and learn from there. So it's this two-fold process where you're experimenting, learning and also you can use this in production. and get specific results. So for more information you can contact Alan Schaffer, who is our graphics evangelist. But it looks like we have some time, so what I'm going to do is completely decimate our galaxy. So if we can go back to the demo one please.
So if you have any questions, please come to our lab later on during the day and I can help you directly. Since we have time, I'll show you a little bit how I work inside of Quartz Composer. So here we have our galaxy. So what I'm going to do is I'm going to take our galaxy and kind of add a little bit of a different stylistic view to it.
I'm going to go for something late 70s, early 80s, so it's in a wild style or something like that. And we'll get our thing to look a little bit more like some kind of style machine. So the first thing I'm going to change is the look of our spiral galaxy. So I'm going to go inside of my spiral galaxy and look for some patches.
And inside of our render an image, we're displaying our particle system. So I'm going to replace our cloud with a radial gradient. This is a core image, radial gradient. And I'm going to set my color to have an opacity of zero so it's automatically cropped and as a result the radial gradient will produce an image of fixed size as opposed to an image of infinite size.
And I'm simply going to connect this to the input image. This is immediately going to blow out because our color one is completely white and completely opaque. So I'm going to immediately adjust my color. Let's see, that's right. So I'm going to generate a random color per frame, per particle as they're birthed.
Going to search for HSL, which is the hue saturation luminance color generator. For those of you that don't know, this allows you to define a color simply based on the hue saturation and luminance dimensions. And I'm going to connect that to color, adjust my alpha, my luminosity. What I want to do is I want to modulate the hue randomly per frame, so I can use a random patch to do that.
And I'm going to set the variability to zero, so we produce a random number per frame. And connect that to Hue. So what we'll now get is as these particles are birthed, we're gonna get a random Hue value. You can see here's the Hue, randomly changing per frame. If I were to look at the particle system, you'll notice That this color well is changing rather rapidly, and we'll start to see some colors kind of flying out of our galaxy.
Sure. By default, as an optimization inside of Core Image, what it'll do is it'll automatically set the DOD of your image to be wherever there is opaque pixels. So if you had an opaque black that went on forever, it goes on forever. So you would have an image of infinite dimensions which you would need to crop with a Core Image crop.
Okay, so now we have these colors kind of flying out at us. What I'm gonna do is increase the speed here a little bit. Something like. So you'll immediately notice that we got a jump, and that's because we literally jumped in time. And what I can do is because this is inside of a render and image, I can apply other core image filters. So I could do something like edges.
[Transcript missing]
That's kind of interesting looking. So now I'm going to look at changing the stars. And what I'm going to use is inside of the assets folder for QC Galaxy. I added this little RTF file with some stars in it. So I'm going to select one of them. And these are from iTunes. And I'm going to use an image with string patch. And this is simply given a string going to produce an image.
So I'm going to paste that in here. Set our stars. So you'll immediately notice that they look a little chunky, and that's because we're producing a very small image, in this case 22 by 32 pixels, and displaying it rather largely on the screen. So what we can do is change the font size. It's a little bit cleaner.
Maybe we want more particles. I'm going to set that to 128. Lots of stars. And I can modulate the color of these as well. So I can just go back to my Spiral Galaxy, copy this. I'll just set that as the color of my stars as they're birthed. There we go.
So now we have some kind of bad 70s, 80s nightmare. And I will go full screen. So it looks like we still have some time, so we can do a little Q&A if you'd like. Shall we go back to slides please? Recall that we have some labs coming up. We have one tonight and we have a Quartz Composer lab specifically tomorrow. And there is also a Core Image lab tomorrow.