This blog series is a part of the write-up assignments of my Real-Time Game Rendering class in the Master of Entertainment Arts & Engineering program at University of Utah. The series will focus on C++, Direct3D 11 API and HLSL.
In this post, I will talk about how I experimented with pivot-based vertex wind simulation, which is a part of the Naughty Dog’s Uncharted 4 General-Purpose Vertex Processing technique.
General-Purpose Vertex Processing
All the general-purpose vertex processing techniques showed by Naughty Dog are some really clever and efficient ways to solve problems and add so much to the games. From wind simulation, character/vehicle foliage interaction, hair gravity, to vertex shader keyframe animation and ambient animation. Naughty Dog shows some really creative approaches toward some of the really tricky problems we have.
It is also extremely important to remember that even though the shaders in the rendering pipeline are generally used for shading, they are just data streams that we can use however we want.
Pivot Information Baking
We need the pivot position of each object to simulate the wind displacement for each vertex correctly. To obtain our pivot information in the shaders, we can bake the pivot location in our vertex color.
Naughty Dog provided their python script in Maya which they used to bake the pivots information into the vertex color.
def bakePivots(): selection = cmds.ls(sl=1) for object in selection: pivot = cmds.xform( object, query=True, pivots=True, worldSpace=True ) cmds.polyColorPerVertex( object, rgb=( pivot, pivot, pivot ))
Below is the result of me running the script with a simple grass model that I found. You can see that pivot positions in the scripting window on the right side.
In order to try to simulation some sort of wind motion, I decided to start with something simple. In the video below, I am setting a wind vector, which contains direction and strength, in the per-frame constant buffer and then accesses it in the shader to simulate the motion.
As you can see, the motion is pretty unrealistic in terms of multiple aspects.
- The wind wouldn’t cause that kind of sinusoidal motion.
- The grass motion is determined solely by the wind vector, the grass will stay still if the wind vector doesn’t change.
I will talk about and experiment with some solutions in the sections below.
First, I am going to add in a high-frequency term that creates a vibration-like motion according to the vertex normal vector. In the video below, you can see this actually gives a nice touch to the grass dynamic. I also added a simple scaling term so that the close the vertex is to the pivot, the less motion it will have.
Notice that it seems like the grass model is splitting itself, this is because of the different normal direction on both sides. We can simply fix this by taking the dot product between the normal and the wind vector, which would make sense from a physics standpoint.
Now, let’s see how it looks when we combine the previous simulation. I also factored in the strength of wind so that it creates a higher frequency movement when the strength is strong, and lower the frequency when the wind is weaker.
I also added in an arrow mesh to indicate the direction of the wind, along with some debug control to dynamically modify the direction and strength of the wind.
This is only a rudimentary experiment on the vertex-based wind simulation. If this system is to be used in an actual game or game engine, I would need to allow the artists to bake in more information such as individual stiffness, or more detailed pivot positions for different parts of the vegetation. Besides that, instead of simply displace the vertices positions and normalize them back according to the distance to the pivot before, I could use some more realistic estimation such as simply rotating around the pivot.