Saturday, June 2, 2018

City Trees and Other Improvements

I haven't done too much work on cities since the last post. I've been working on a variety of other things in 3DWorld, including portals and a weapon that fires teleporters that bounce around the scene, teleporting anything they touch into the clouds above the scene. However, I'm not here to discuss these changes. You can read about these here.

Previously I had added windows and night time window lights to city buildings. The results looked pretty good, but I did go back and make some improvements to window lights. A Google image search for city lights gave me some ideas for how to make lighting look more realistic. I added a brightness gradient to make the bottom of the windows a bit darker, as if furniture and other objects were blocking some of the light. I made the dark windows have a small amount of light, as if there was some indirect lighting coming from adjacent lit rooms. I also added some random color variation to window lights. Colors are washed out by the bloom effect in bright windows but are more apparent in the darker windows.

The latest version of city window lights at night. Lights have variable brightness and slight color variation.

Night time city streetlights, car headlights, and building window lights.

I would like to add more detail to window lights to make them look more varied, such as dark shadows due to furniture and other objects blocking the light. Shamus Young did a good job with this in PixelCity. However, he took a pre-generated texture approach. That doesn't really work in my flow where the windows themselves are drawn in the fragment shader. I would need to somehow create the darker shapes and color variation within the shader itself. That should be possible, but so far I haven't figured out quite how to do it in a clean and efficient way.


The next type of city object I added was trees. I already had a system for generating and placing procedural trees in the scene, but it was quite a bit more work to add trees to cities. First, I had to generate tree placements that didn't overlap buildings, streetlights, traffic lights, roads, etc. Here are some screenshots showing trees placed in a city.

Procedurally generated and placed trees inside a city, with shadows.

Procedural city trees viewed from above.

The most difficult part was getting dynamic lighting (including shadows) from streetlights and car headlights to work with trees. Dynamic lighting and shadows works with trees in other scene/viewing modes, but I had to make it work with the city system and tiled terrain mode. It's more challenging to get the dynamic lighting solution to work when the player can move over a very large area. This required piecing together various bits of C++ and shader code, and a lot of trial-and-error. The process was different for tree branches vs. leaves, each of which uses a different rendering system. Here are the results. Note that tree leaves use a double sided lighting model, the light is facing downward, the camera is looking mostly at the unlit sides of leaves, which is why they appear so dark.

Night time city trees receiving light from cars and streetlights and casting shadows on the scene.

More lit and shadowing trees at night.

Another view of city trees at night.

I also made some improvements that I can't show in screenshots. For example, I implemented player collision detection with streetlights and traffic lights. [I already had collision detection with buildings.] I tried to add car collision detection, but I found that it didn't work very well. There were various problems. For one, it's too easy for the player to get stuck between parked cars and cars stopped at traffic lights. Maybe I need to make the player model smaller, or less round? It's not clear exactly how cars interact with the player anyway. I haven't figured out how to turn this into a game yet.

I'm still working on adding benches and other city details. I already have the framework to in place. Benches can be placed and integrated into the collision system. The problem is that it's not very fun and interesting. If I draw benches using downloaded 3D models like the cars, it's just more work finding models and fiddling with all the parameters to make them look good and draw fast at the same time. On the other hand, creating them myself is also not really something I want to do. I don't have any good 3D modeling software and I'm not sure how far I can get by hard-coding the shapes into the source code. I know I did that with streetlights and traffic lights, and I could do that again with benches. But it doesn't really seem like productive work. I just have to copy the code for those other objects and change it all to work with benches. Repeat for any other object type. I guess it would really help if I had someone with more artistic skills working on this project.

Update:
Someone suggested adding rows of lit window lights for buildings. I made the change, and here's how it looks:

Buildings with groups of lit windows on each floor.

You can definitely see the groups of lit windows now. Not all buildings should have long rows of lit vs. dark windows. I changed the shader code so that building window group sizes varies per-building and per-floor. I also made the ratio of lit to dark windows vary per-floor. Here is what that looks like:

Rows of lit windows that vary in group size per building and per floor.

Are these results better (as in more realistic)? I don't know, maybe, it's hard to tell.

6 comments:

  1. Looking great! A few things I noticed that might make light look better. The shadows on the street lights cast behind the pole should probably diffuse(?)/ get softer quicker with distance. the further from the pole I think the light would scatter back into the shadow quicker. Just a small idea you might already have on your todo list but It jumped out at me! Here is a city algorithm I was working on, much more simple without lighting but might be interesting. https://imgur.com/a/bjuPk

    ReplyDelete
    Replies
    1. I agree that soft shadows would look better, but that's quite expensive to add to this many streetlights. I changed some lighting parameters since I created these screenshots, so it might look a bit better now. I do have soft shadows with proper penumbra/umbra in universe mode where I only have a single nearby star to deal with.

      Delete
  2. Yes! The lighting groups really improve the look!

    One thing I've been noticing over the posts, but has become very evident with the addition of urban trees, is that you don't generally put in transition elements. The trees (in cities) need planters. The buildings need ground floors. The cities need suburbs. Even the forests could use some scrub.

    ReplyDelete
    Replies
    1. I suppose so. I've been adding the larger items and planning to add the smaller details later, but I end up working on something else and never get back to it. I did add smaller buildings and houses around the city center later. I also have some cities where the taller buildings are in the center and shorter buildings along the perimeter.

      Delete
    2. Also I have shorter trees ("bushes") and "leafy plants" that are generated now, which fill in some of the gaps under and between the trees in the forests. I'm not sure if I officially created a blog post for that.

      I think tree planters would be easy to add using my building interior object/material system. It's more difficult to add those types of objects to cities. Maybe I can find a way to reuse that code, then I can change bridges, tunnels, streetlights, traffic lights, benches, etc. to use that system.

      Delete
    3. A unified interior/exterior system sounds like the elegant solution for sure. Would be fun to do a recursive forest-building generator. Diorama in a snowglobe in a bonsai garden in a gazebo in a garden courtyard in a building in a grass field in a city park in a jungle in a (snowglobe for recursion | crater dome on a moon)

      Delete