 This is my quarking, perfect. All right, let's go. Hi everyone, my name is Dona Bystedt. I'm a senior concept artist at Goodbye Cancer Studios in Stockholm. This is my talk, using geometry nodes for vehicle concept art. So you might also know me from Google Auto Translation's amazing translation of my name from Lastbender Talk. Dona Biscuit. So Goodbye Cancer Studios. We are a VFX studio that creates game cinematics, VFX for film and TV. And we also provide other services like mocap and scanning. I thought it would be fun to show you our studio reel for a bit. Thank you. So in my free time I like to create personal artwork and tutorials and add-ons. I've also been providing the Blender Institute with demo files and promotion material. So yeah, let's dive into the vehicle concept generator. So here you can see the tool in action. And as you can see it's pretty easy to randomly generate different vehicle designs just by changing the geometry node parameters. And my approach has sort of been to divide the different geometry nodes set up in different modifiers because that way I can sort of like apply the primary shapes, then remodel those and still have the scattering of gribbles for instance like still live and kicking. So breakdown. So the primary shapes is made of a collection of six super simple shapes and these can sort of be replaced at any time. And I start with one object and then I scatter other objects on top of that and sort of randomly rotate them in the y-axis. And then I have this separation value thing. Or does that play? Oh, here we go. So basically that's a separation value to create more sort of complex shapes from this. So then no sci-fi plates and then magically we have sci-fi plates. This is basically just filtering out random faces, duplicate them and extruding them. So then in order to make them all symmetric I take this and just apply a normal mirror modifier because that's the fastest way as far as I know to do it. In geometry notes I guess you would have some kind of Boolean operation but we don't still have a bisect there. So then I add wings, thrusters, etc. So the thrusters always points toward the back and wings point away from the origin of the object. And the cockpit is snapping to the surface and can be moved around. So then I can also add wheels. So this is basically just a mesh line and the wheels are instanced on the points. And then I randomly remove some points to get some sort of like visual interest and so everything is not like super, you know, even. So Grebel's co-sci-fi stuff makes stuff look more interesting than it really is, you know. So basic rubbish shapes. All right, Grebel's are instanced on points and the surface is remeshed first, otherwise since I have a lot of intersecting geometry shapes I would get a lot of like Grebel's inside of the surface. So Grebel's are also aligned to the closest edge so that the x-axis aligns and the z-axis of the Grebel's aligns to the surface normal. Then mapping, so the geometry notes don't really have like a UV so when the vehicle is created and sort of make this attribute called mapping that makes me being able to like texture stuff and tile textures. So here we can see the mapping visualized. Then I have a tiling sci-fi texture and this is very similar to the texture coordinate objects in the normal, you know, shading notes. So then I assign a random value to the ship and this is used to sort of like move the mapping in x-texter space so that I can do like a texture projection with this UDM sequence. Do a top projection and that's the final material. So then I have a tiling sci-fi plate texture so this is basically just scattered stuff and then I shift them in the depth so that they don't intersect and each plate has a curve that goes along the border edge and that's sort of used in the texture to create the separation between the plates and then the geometry is instanced so that I get this tiling texture pattern that is repeating and plates and Grebel's are then rendered on separate view layers and then inside of the composting I sort of like combine these to make like a depth map and a color map. So some fiddling there. So let's dive into the node setups. So due to time limitation I won't be able to go over everything but this will be like a cherry pick of it and I apologize if there's a lot of stuff in here, so okay. So I start off with a single point using the mesh line node. And then I have these primary shapes that comes in to the collection. I use a pick instance to just pick one of these objects and we get this and then I realize the instances so I can mess around with the attributes on the points. Primary shape separation. This is the thing where like we separate the primary shapes so that they get more complex shapes. So first off I have the primary shape here then scatter points on that and then I want to sort of be able to shift the scattered objects along the surface normal. So I have a... let's see here. The normal comes in there from the node distributes points on face. Cool, so the little blue arrow there represents the normal. And then I have the separation value coming in from the user interface and I multiply that with minus 1. So if the input value is 10 I get a minus 10 and 10 and put that into a random value. And then I take the oops, too fast. Then I take the normal and multiply the normal with that random value. So we get this sort of behavior. OK, primary shapes instance on points. So now we have scattered our points, right? And we take in these primary shapes and here's the points that we scattered earlier and then we plug it into the points, right? And we get this. Now I want to add that random rotation along the y-axis. We don't really want to have... It's going to rotate along the direction of the ship because I don't want to do this kind of rotation because it's going to look super weird. So now I have a custom node group and basically I want to get the random rotation here, right? So I have an input value between 0 and 1 and then I remap that to a value between 0 and 360, right? So a value of 0 would remap to a rotation value of 0. 0.5 would remap to 180 and 1 would remap to 360. So, yeah, we got the little... Oh, I should use the laser pointer here. Here we go. 0.5 and we get... Let's just say that we get 180 here, right? And now we want to get that random value and want to get a vector between 0 and 180, right? And here I'm just using integers, so, like... I mean, vectors are float values of 3, but for readability it's integers here in the presentation. So somewhere along this line we're going to get a random rotation and we're just going to say that the result here is 95, 87 and 105. And then we just want to, like, rotate in the y-axis, right? Not in x and z. So we just multiply the rotation value with 0, 1 and 0. So that gives us a value of 0, 87 and 0. Cool stuff. So then I use a snap function in the vector math node and get the 0, 90 and 0 value. So we get a random rotation of 90 degrees, basically. And then we're just going to convert this to radians so that then we can, you know, do the rotation properly. Ja. We don't really need to care what happens there. It's just like we get this proper rotation value. So then we get this sort of behavior. It's just random rotation snapping to 90 degrees. Now it's time to scatter those cool gribbles that we did. Ooh, spaceship. All right. Here we go. So here are the source assets for the gribbles. These are just, like, very simple shapes, nothing fancy. And the z-axis will sort of point along the normal direction, as we said before. And the x-axis, we want to align that to the closest edge of the primary shapes. And the longest side of the bounding box should be one unit, because that's, you know, then you get a more predictable result when you're using random scale. So when I create the primary shapes, I also add an attribute called primary shapes on those points. And this is really handy when you're doing, like, a geometry node setup from modifier to modifier, because then we can pick up this value later and do cool stuff with it. So for instance, I only want to scatter gribbles on the primary shapes, and not the wings, for instance. So then I can just delete that. So the setup looks like this. If the points do not have a value that says primary shapes, then delete them. Look at this. Nice. So here we can see the mesh coming in over here. And we want to, now we sort of want to make sure that we don't get gribbles inside of the spaceship, right? Because we have intersecting shapes. So I convert this to a volume, then back to a mesh. Now we just have an outer hull. Now we want to snap it back to the surface of the original object. So I'm using this geometry proximity node. Take the position, and just set the position of these vertices. So now, finally, we can scatter the points, which then will be gribbles. See here. So in this step, I want to set scale to all of the points. So I get a random value between 0 and 1 over here. And then I want to remap that. So I get 80% small gribbles and 20% big. It's a magic number. OK, line gribbles to closest edge. So this is kind of like an awkward thing where it kind of floats in midair there. We don't like that at all. We want to have it align perfectly along this closest edge. Amazing. So here I have a custom node group called get vector from closest edge. And yeah, first off, I just want to get the index of this edge because we're going to need that later. So basically sample nearest from the position of the gribble, get the closest edge, and get the index. And in this part, we want to get the position of these two vertices. So use that sample index, sample the index of the edge, and get the position of the first vertex, and then the second vertex. So let's say we got a value of 5, 10, 10 on that first vertex and 5, 4, 6 on the second. Now we do some surprisingly simple math, I guess. Someone smarter than me would probably do something more fancy, but I'm like a simple minded person. So the first vertex got this value, and then we subtract the second vertex position, and then we get the direction of the edge. Now we have the vector of the edge, right? And we want to align the x-axis of the gribble along that edge. So we take, we say, oh, it's going to be the x-axis, it's going to be aligned, and we bring in that vector, the direction of the edge. Start off with this, this is bad. This is good, nice. Now it's time to align stuff to the normals, right? We already got the alignments to the closed edge. We got this little custom node, and we want to get the closest normal of the position of the gribble. So the source position is the position of the gribble, and we want to get the normal from this source mesh, output as a vector, direction basically. And then we want to say it's the z-axis of the gribble, that's got to be aligned to the surface. Taking the alignment to the closest edge, that's the current rotation that we already did, and then we plug in the vector of get closest normal, align that to the z-axis of the gribble to the normal. Very good. So some thoughts about proceduralism, pros and cons, and I think it's great, it's fast to iterate different designs, and it's super nice when you're working on a repetitive task and you need to create multiple variations, and if it would take longer time to create 100 spaceships manually, it makes sense to do this procedurally. However, creating procedural setups takes time, so if I would only do one spaceship, it might be better to do it manually. And if there's a low reusability to this kind of setup, then perhaps do it manually. So there's always this kind of estimate of time spent. All right, thank you so much for listening to me talk. It was great being here.