Monday, October 5, 2015

Tree, Plant, and Grass Leaf Wind

It's been awhile since my last post, but I haven't really been working on much that I can show in screenshots and videos. Most of the effort has been spent on continued improvements to movable object physics and related tasks. I had it working well enough to show some videos last month, but it took a lot more effort to make the system stable and fix all of the strange bugs, including the crazy large water splash when underwater boxes were destroyed. I'm working on object rotational physics and that sort of thing now, but it's difficult to get right, and I don't have anything to show yet. I may end up using a third party physics library such as Bullet for the more complex effects.

I also spent a few hours improving the 3DWorld leaf wind effect and making it work on more vegetation types, so I'll make this the topic of today's post. This post won't be as long as the previous one, which hopefully means that I'll have time to make another post soon. I already had a leaf wind system for trees that was entirely on the CPU, and it's always bothered me that this method is slow and I find myself disabling it at times to improve the frame rate. In 2015 everyone seems to be doing leaf wind on the GPU rather than the CPU, so I decided to try this approach. I've actually been thinking about and experimenting with GPU wind for years, but I was never able to figure out how to update the leaf normals for lighting as the leaf moves in the wind. The problem is that the vertex shader can normally only see one vertex at a time, and it can't determine the orientation (rotation axis and angle) of the leaf from a single vertex. The leaf needs to bend/rotate at the point where it's connected to the tree branch, a point that the vertex shader doesn't know. Sure, I could pass this extra info as additional vertex data, but that takes more GPU memory and hurts the frame rate. I could use a geometry shader, but that turned out to be very complex and also slow.

A few weeks ago I read an online article on leaf wind. The author ran into the same problem with updating the leaf normals, but he went ahead and implemented it anyway with the normals and lighting remaining constant. He claimed that it looked just fine this way - and I agreed! So all this time I had been worried about what was really a minor issue. The solution: do something simple per-leaf that doesn't need to know about the leaf orientation and just use the original normals. I used a simple time-varying sum of two sine waves and that looked pretty good. Even with fixed normals, the lighting can still be somewhat dynamic. Shadows and indirect lighting are computed per pixel, and don't depend (much) on the normal, so these components of the lighting will still change dynamically as the leaves move in the wind.

I still had to deal with the leaf attachment point to the branch. The leaf tip should move, but not the base part where the stem attaches to the tree branch. How can the shader know which vertex is at the tip vs. the base? It can use the texture coordinate, which is 0.0 and the base and 1.0 at the tip. This data is already available since it's used to texture the leaf. The next problem is how to keep the leaf size constant by moving both vertices of the tip (the two vertices that form the far edge of the leaf quad/rectangle near the tip). I solved this by using the world space coordinates of the leaf to determine the magnitude of the wind displacement. Since leaves are small, the coordinate values of their tip vertices are close together, making their wind displacement values similar, therefore keeping the distance between those points relatively constant.

This system worked so well that I ended up using it for the small branches and leaves/needles of pine trees, which previously had no wind effects. Then I enabled it for plant leaves. I was never quite able to get the wind effect to work for the berries on some plant types, so I simply disabled this effect on those plants. Grass was already using a similar wind system, so I left that code alone. [Grass is easier since each blade is drawn as a triangle, where only the tip vertex moves, and it's a lot simpler to animate a single vertex rather than an edge formed from two vertices for leaves. Also, grass blades tend to have a more uniform length and orientation, so the vertex shader can guess at the positions of the other two base vertices.]

Here is a screenshot of some vegetation moving in the wind. Oh, right, you can't actually see it moving. Well, it's still a pretty screenshot.

Trees, plants, and grass moving in the wind. This is just a high resolution image from the video below.

Here is a video of the same scene. You can see the tree leaves, plant leaves, flowers, and grass blades all moving in the wind. The wind speed and direction can be interactively changed with hotkeys and an onscreen slider UI widget (not shown). The video starts with a small amount of wind and gradually increases wind intensity to an extreme value. I had to choose a strange camera angle in the corner of the scene to get the pine trees, deciduous trees, plants, and grass all in the same view.

Here is another video showing that wind works on all vegetation in infinite tiled terrain mode as well. This scene with it's high detail trees ran at only ~50 FPS (frames per second) with CPU wind, but runs at ~90 FPS with GPU wind. In fact, the wind computation time has almost no effect on frame rate. In addition, wind is applied even to distant trees, rather than being limited to only nearby trees in the old mode. It may be hard to see the wind effect in this video, especially since I couldn't stand still and had to run around at high speed just to show off that it was possible. The max speed in tiled terrain mode is very high and when the player is on the ground everything is a blur. The minor lag near the end when I went in the water is probably due to loading the water sound.

Right, back to the wind. I'll note that the new wind system doesn't completely replace the old mode. I still need CPU mode for player interaction with leaves. For example, player collision with trees moves the leaves, leaves can be shot off using projectile weapons, etc. Oh, all right, I'll add a video of that too. I guess every post must now contain at least one video of me shooting or otherwise destroying something. Keep in mind that the particle effects are only a placeholder for better particle effects that I'll likely show off in some future post.

Did you notice that I added new sounds such as the "click" when switching weapons? I'll try to continue to add more sounds and other effects as time allows.

That's about all I have to say about leaf wind and related topics. Next time I'll probably make a post about full-screen postprocessing effects, unless something else interesting comes up. I was considering making a post about snow accumulation and rendering, but I think I'll save that for winter time - not that we actually get snow here in CA.

No comments:

Post a Comment