Showing posts with label TechArt. Show all posts
Showing posts with label TechArt. Show all posts

Friday, 14 February 2025

Houdini Workshop Week 5 - Spring 2025

 Part 2 of our VBD smoke session. 

NOTE: I had an issue where I left the display flag on the solver when i saved and exited the file. When I tried to reopen it it kept wanting to cook and would not respond. To fix this, go to the bottom right where it says Auto Update and turn it to manual (you might have to hit escape a bunch of times here). This will make it so that it only updates when you tell it to. Now you can hit the display flag on the file cache we made last time. 

Making a volume to contain it

burger

    We want to contain the smoke so that its not clipping through the pipe we made. To do this we'll make a bounding box for our volume. Make a time shift node and navigate to the frame with the biggest volume in the viewport. For us it was around 450. Right click on the Frame parameter in the timeshift node > delete channel. We want it to be a static frame, we don't want it to change depending on the timeline. 
    Next make a bound box, renamed to BoundingBox. You don't need to change any parameters here. It will create a polygon box around your volume.
    Then you'll need a vdb from polygons node. We want to make sure that the voxel size is the exact same from our pyrosolver. Go back to the pyrosolver node and find the voxel size parameter. Right click on it and select 'copy parameter'. Then go back to our vdb from polygons node. In that voxel size parameter, right click and hit 'Paste Relative References'. You'll see that it pastes 'ch("../pyrosolver_billowy_smoke/divsize")'. This connects the two parameters, so this vdb from polygons node will update when you update the pyrosolver.
    We also need to change the distance vdb to off and the fog vdb on. 
    Now grab a volume mix node. the first input is our vdb from polygons node, the second input is our original smokestack file cache node. The mix group should be @name = temperature. 
we have a defined volume

Clipping the smoke stack

    Now we want to clip the smoke stack so it doesn't look like its going through the geo. 

    We could use another volume mix with the subtract operation, or a volume VOP (node based network to program VEX). But the best solution we've got is to just use a volume wrangle node and write in VEX. 
Example of the inside of a volume VOP to do this. Its reading the first and second input's density primitive name and then mixing them 
    We do need another extruded tube to block out the shape that we don't want our vdb to go through. Add a vdb from polygon node to turn it into a vdb to subtract with. 

    The tube has a center of -0.7 and 20 columns. The poly extrude has a distance of 6 with output back on. Make sure the vdb is a fog one instead of distance one. Also paste the relative reference of voxel size from the pyrosolver.
    Now in the volume wrangle node, write this: 
density = lerp( volumesample(0,"density", @P), 0, volumesample(1, "density", @P));
    It's just a default lerp from the original volume, to 0, with the new volume we made determining where the 0 should go. 
    Our volume should now no longer clip through it

Making Volumes Loop

    Now we need to loop the smoke sim. This is a bit tricky, but we can do it with some vex code. Create a null node and name it LoopControl. 

Press z to bring up the shape node selections and c to bring up the colors for nodes

    In the parameters, go to the icon next to the name at the top left > Parameters and Channels > Edit Parameter Interface.

    You'll see this window pop up. Drag 5 Integer Type parameters from the left side into the middle 'Existing Parameters'. You can change the name of the variable and the label that shows up in the parameter box in the right box 'Parameter Description. You'll need:
  • Transition Amount
  • Offset Amount
  • Start Transition
  • End Frame
  • Offset Second Cache
    For transition amount and offset amount you can change their default values to 40 and 140 respectively in the channels tab to the right. 
Offset amount default value
    Hit apply and you should see these parameters appear for the null node. 
    We're going to edit the channel expressions for start transition, end frame and offset second cache. Press alt + e to bring up the code editor.
Start Transition: 
ch("./end_frame")-ch("./transition_amount")
End Frame: 
ch("../smokeBake1/f2")-ch("./offset_amount")
Offset Second Cache:
ch("./end_frame")-ch("./offset_amount")

Note that '../' means to go up a level to another node, while './' means within this node. The ch("../smokeBake1/f2") is our original file cache node, and the f2 specifically means the second frame or end frame. 
    Now we need two time shift nodes into a volume mix node.

    In the first time shift node's frame, write: 
$F+ch("../LoopControl/offset_amount")
    In the second time shift node's frame, write: 
$F-ch("../LoopControl/offset_second_cache")
    Then for the volume mix, change the mix method to blend. In the blend parameter,  open up the expression editor (alt+e) and write this: 
if($F<ch("../LoopControl/start_transition"), 
    0,
    if($F>ch("../LoopControl/start_transition") + 
        ch("../LoopControl/transition_amount"),
        1,
        ($F-ch("../LoopControl/start_transition"))/
        ch("../LoopControl/transition_amount")
        ))

what's kinda happening with our blend

    If you've done it correctly, you should be able to change the timeline to 1-360 and watch a seamless loop. 

    For the final nodes, make a convert vdb node, and convert to VDB. 

    Make a final file cache node. For the end frame setting, write: 
ch("../LoopControl/end_frame")
    Save this to Disk. This will take awhile but thats all that needs to be done.

Importing into Unreal

Look into the folder, you'll see a bunch of files were generate them. You only need to drag one of these into the unreal project. It understands it is part of an animated sequence, so long as they're all named the same. 


    For the settings, change the attributes A to 32bit float. The dimensions at the bottom is how big our smoke is going to be. 

    WARNING: this can be memory intensive and can cause Unreal to crash. Close out any other programs to help with importing this.

    Once that's done importing. Go into the content browser, in the engine folder look for sparse volume texture viewer. Drag it into the scene. This is only used to see if we've imported it correctly.


    Change the sparse volume to our looping smoke and make sure that playing and looping is turned on. If you don't see it it might be because it's really small. 
    Now that we know it worked. Look for a SparseVolumeMaterial in the engine folder. Make a copy of it and put it in your content folder. Create a material instance of this. 
    Inside the material instance, change the sparse volume texture to our vdb we exported. 
    Look for heterogenous Volume in the place actors box. Drag and drop it in the scene. Change the material of the volume to our material instance we just made. Also make sure looping and playing is turned on as well. 

        Now the heterogenous volume should show our smoke (although still tiny). Rotate it 90 degrees and scale it up, and it should be done. This material should also allow you to color the smoke however you want for now. 



Friday, 7 February 2025

Houdini Workshop Week 4 - Spring 2025

 - We skipped last weeks but I'm still going to call this week 4 -

VDB Smoke Part 1

We'll be using raymarching (raytracing's dumb cousin) to help render the smoke, cause at the moment its the only thing that works well and fast.

Setting up the Geometry

    We first need some geometry. Make a geo node named 'Smoke Stack'. Drop inside and create a polygon tube SOP node. Change the parameters so that the radius is (0.9, 0.9), height 10, rows 2, and columns 30. You don't need the end caps on. 

    We're going to make the smoke come out of the smoke stack. 

    Add a Match size node to have it sit on top of the origin.

    Append a PolyExtrude SOP. Distance is 0.1 and make sure you're outputing all the groups
    We want to put a cap around the top. SO grab another tube sop. 
    We want to procedurally put the second tube to the top of the first tube. We can do this with a transform node. 
    Inside the transform node, in the translate y input write:
ch("../tube1/height")
    This is getting the float from the first tube to use as the input. If you left click on the 'translate' text, it will change back to the actual number it's using. 'Ch' means channel, means when we're getting the channel value using the path we give it. This is Hscript (not as great as python)
    If you wanted to write a multiline hscript or python script, while selecting the input, hit ctrl +e to bring up this window. 

    Back to the tube, it's moved up to the height of the column, but it's not flush to the top of the first tube. 

    To change this with the transform node, write this in the y input box:
ch("../tube1/height")-0.5*ch("../tube2/height")

    Extra note: this can also be achieved by using a matchsize node, with the y being max. 

    Get another Polyextrude node with a normal node to thicken up the second tube. Then merge the two tubes
    Note: We need a null node for the tube1 to reference for later. Put it right before the merge node. 
    We need to uv unwarp this tube to put into unreal. Drop a uv Texture node. Change the texture type to cylindrical. There might be a weid boundary seam, so turn on 'fix boundary seams'. 


    Make an null node for the output. To change the colors of nodes, press c on the keyboard. Change outputs to green, and then the tubes to yellow (yellow means the start of a network).
    Drop an ROP FBX node to export the geo. Just make the output file something like $JOB/geo/SmokeyPole. (Make sure you've set your project beforehand)

Save to disk to save out your geo. 
The Final network

Making the Smoke

Go back to the object level. Create a new geo node named Smoke. Drop inside
    We want to get a reference of the smoke stack we made. Drop an object merge node down. For object 1 look for STACK_CENTER from out SmokeStack. Choose to give a relative path. 
    In transform object, write '.' (Literally just a period) inside of 'Transform Object'
    This means that we want to transform the referenced object in local space. 
    Drop a match size node with Justify Y set to max.
    Now we need to create an object to act as a burn source. Get a polygon sphere node. Change the Radius to (1, 0.8, 1). Change primitive type to polygon and the frequency to 4
    We want to have irregularity with the smoke. If you check the normals of the sphere, you'll notice they're created in a uniform fashion. 
uniform normals
    We don't want that. Create a mountain SOP.

    The name 'mountain' is a misnomer, It's putting the vertices through a 3 dimensional noise space. It's currently using simplex. Change amplitude to 0.66.
    Go back to the pyroSource (sphere) node and lower the uniform scale so that it approximately fits within the smoke stack. 
    We're not going to be using DOPs for this, instead we're using sparse convulution for this. 
    Drag off the mountain node and look for pyro configure billowy smoke
    It will give you several nodes.
    Change the torus that appears for the sphere we've made.

    The particle separation determines how close the particles are to each other, lower values mean more particles. We'll change ours to 0.02. 
    For the other parameters, Density refers to the smoke density, and the temperature drives the speed of the smoke as it rises. The hotter it is the faster it will rise up. You can see these attributes in the geometry spreadsheet.
    The next one is controlling the velocity of the smoke particles. By default the velocity of the smoke is (0,1,0), meaning it points in an upward direction.
    To see what this node is doing, drag off to the side and create an attribute wrangle node.

    VExpressions run parallel, on as many particles at once. Write: 
v@N = v@v;
    This does nothing at first, but you can see it when you display normals in the viewport. The normals will point in the direction of the velocity of points
    Change the attribute adjust vector to a point velocity node.

    Parameters you can change:
  •     The scale changes the magnitude of the vector. 
  • Cone angle allows for a wider angle of where the velocity goes. 
  • Curl Noise adds more perlin noise to make it more varied. (we had it at 0.5 and then changed it to 10 (makes it look more like a burst of dirt rather than smoke, so do with it what you wish))
    The Volume rasterize attributes node transforms the shapes into a volume. If you click on the info of the node, it has 3 VDB volumes, density, temperature, and v. You can also see the voxel (3d pixel) size. 
    Next, the Pyrosolver. Make sure the start frame is 1. Now hit play with the pyrosolver to see the smoke. 
    Parameters to change: 
  • Setup:
    •  change the voxel size to make it bigger and courser 0.25
    • change cache memory to something like 20000 so it will actually remember the cache when you play through the timeline, instead of forgetting the last thing because memory ran out (note: this is resource intesive)
  • Sourcing: 
    • density input source scale is 3
    • Changing the source temperature source scale to 15 you'll notice it immediately goes up and goes faster (remember higher temp = faster)
  • Fields: 
    • Make sure flame is true.
    • change dissipation to 0.08, so it looks more wispy and will disappate faster 
  • Shape:
    • Turbulence changes the frequency and does nothing to the amplitude, it takes all the negative values and makes them positive. Change turbulence to 0.7, you'll get more detail in the smoke
    • Change swirl size to 1.2 and roughness 0.7 to make it go up a bit higher. Roughness adds more surface detail to the smoke, more chunk.
    • Max octaves to 3, the amount of information in the smoke, we're putting more noise into it. 
  • Output:
    • We don't need the color since we'll be getting that from the raymarching, and we don't need the flame or velocity anymore
    At the end in setup, change the voxel size to 0.1 and global substeps to 3. We're done with changing settings so even though it's going to take more memory it'll look better now, and we don't need to worry about recaching multiple times after this. Global substeps is reducing the aliasing experienced by the frame sample. We want more detail between each frame. Think about sampling a sin graph multiple times inbetween the points to get more info. 
    Since we'll be rendering in Unreal, we don't need the pyro Bake volume and null node at the end. You can leave them be.
unnecessary nodes
    Its getting slow so we're going to want to save this out as a filecache. 
    We changed the timeline to 500 to get a longer sim. 

Tip: Look up Mythbusters for explosions to check out the different types of smoke. 

Next week we're going to be making another volume with a pinhole at the top to contain this volume. 

Easy Notes Archive

 Tech Art Blueprints Demo Animation State Machines Part 1 Animation State Machines Part 2 Math for Tech Art Part 1 Math for Tech Art Part 2 ...