Tuesday, November 17, 2020

Procedural Buildings: Improvements Based on Feedback

Yes, I'm still working on procedural building interiors. It seems like there are an infinite number of things to add and fix. This set of improvements to interiors is mostly the result of feedback and suggestions from my nine year old daughter and Paul Spooner. A few of these were old TODO items as well that I finally got a chance to work on. I'll list them here in the approximate order I that implemented them, along with lots of screenshots.

Lamps with Ambient Lighting

I didn't really like the look of the dark walls next to the lamps in the screenshots of my previous post. There should be some diffuse light passing through the lampshade to reach the wall, and also indirect light reflected from the ceiling and top of the dresser or nightstand. The easiest fix was to add a small radius unshadowed light source inside the lampshade and hope that it was small enough that it didn't bleed through the wall onto objects in the adjacent room. Here is a screenshot of that third light source. It looks a bit odd due to the lack of a smooth transition between the top/middle/bottom lights, but I guess it's better than having no middle light.

Lamps now have a small unshadowed light source inside the lampshade that makes it appear to diffusely illuminate the wall around the lamp.

Bed Posts and Canopy Beds

So far my beds have used simple and plain geometry, with single cube bottom, legs, headboard, and foot board. I decided to add bed posts to some of them. Bed posts are randomly selected to be either square or cylindrical. Here is a bed with square posts.

Bed with square bed posts and a lamp on a nightstand next to it.

I took this a bit further and added top bars to some of the beds with posts, making them into canopy beds. So far I haven't added any canopy material, so they're bare wood. Cloth for things like canopies or window curtains is difficult to add. There are two problems. First, what geometry do I use? Cubes won't work here. This cloth needs to be curved into folds to make it look realistic, which would require a large number of triangles. Maybe that's okay for canopies, but there are far too many windows in a house to add high polygon count curtains to each one.

The second problem is that real cloth transmits some amount of light. It's not quite the same as making the material semi-transparent with an alpha value between 0.0 and 1.0. Instead, they need some sort of two-sided lighting model that includes transmission through the back/lit side, similar to tree leaves. This may require a custom shader. I'll have to get back to this problem later. For now, the canopy beds have no canopy and the windows have no curtains.

A large canopy bed that casts interesting shadows. I haven't added the canopy cloth/material yet.

Storage Room Shelves with Boxes

Storage rooms still looked a bit empty to me. I needed to add objects to the shelves, but what? I guess the only objects I currently have that are intended for storage rooms are the same wooden crates I placed on the floors. I decided to add some smaller crates randomly placed on the shelves. Some shelves have none, and others are full of them. I also added an occasional random office chair in the corner of the room (not pictured below).

Storage room with shelves on all walls and crates on the shelves and floor.

I would like to add cardboard boxes, but so far I haven't been able to create a convincing cardboard material. The don't really look like proper boxes if I make them a uniform tan color. I tried to find good box textures online, ones that had various box-like symbols, text, tape, etc. The problem here is that boxes generally don't look right if I use the same texture on all six cube sides. Do I need three different textures, one for the top and bottom, one for the sides, and another for the ends? Maybe, it's tough to justify adding three new textures and three new materials just for cardboard boxes. Maybe adding plastic storage bins would be easier.

I could also just add random room objects to the shelves: books, lamps, bottles (see below), pieces of wood, etc. I don't know how that would look. None of those are really items you see stacked on storage room shelves. Do I need to create several new objects that only appear on shelves in storage rooms?

Walled Stairs with Railings

Most office buildings have enclosed stairs. I hear that's related to fire safety, which I suppose makes sense. I changed my office building stairs so that they at least have walls on the sides. Walls are skipped when the stairs are up against an existing exterior wall of the building. There's still no stairwell door, but this is an improvement. Railings are connected to the walls of the stairs and continue to have vertical support poles when they fit. U-shaped stairs don't have vertical poles due to the complexity of adding them at the correct height. Here is an example of office stairs in a main hallway leading down to an open elevator. The dark spot on the ground is my shadow.

Office building walled stairs with railings. There's an open elevator at the bottom of the stairs.

Computer Keyboards

I added computer monitors to some desks a few weeks ago using the same 3D model as the TV. That's good, but monitors aren't usually placed by themselves (except for in the focus rooms where I work). Monitors are usually connected to a computer, and the computer is often connected to a keyboard and mouse. Keyboards are easy to draw, so I added them first. There are no cords, computers, or mice yet.

Desks with computer monitors now also have a computer keyboard. (That Windows desktop is a screenshot of my home computer's desktop.)

Maybe someone was using the monitor and keyboard with a laptop that's no longer on the desk. ... In that case, then why is the monitor showing a desktop? I don't know, I suppose the computer could be hidden behind the desk somewhere. I'll have to add one under the desk later. Maybe then I can add some desktop computers and keyboards to those storage shelves. I may even be able to get away with making them a single textured cube so that they're basically free to draw.

Colored House Walls

Paul pointed out that the contrast between building walls and trim is too low. The easiest way to fix that is to change the wall color, the trim color, or both. I've left some houses with white walls, but made others have light blue, green, pink, and peach colored walls. Some of these are shown in the screenshots below.

Railings with Balusters and Stair Overhangs

My railings and stairs were looking a bit plain. I was originally worried about having too many triangles for detailed stairs, so I tried to keep them minimal. I've made a lot of optimizations since then, including adding a class of "small" objects and materials that are only generated and drawn when the player is close to the building. This is intended for high detail objects with curved surfaces that can't easily be seen from a distance. This form of level-of-detail is what allows me to add so many different objects to thousands of buildings and still draw everything in realtime.

I split stairs into top and bottom cube parts, where the top is slightly darker in color and overhangs a bit. This makes it easier to tell where the tops of the individual steps are. I also added vertical cylinders for railing balusters to keep the little kids (or careless adults) from falling off the sides of the stairs. I placed one on each stair, which looks pretty good. I put another cylinder along the bottoms so that I can skip adding end cap circles to each baluster. These railings work as proper collision objects for the player as well, to avoid the frustration of unintentionally falling all the way to the bottom of the stairs when making a wrong move trying to reach the top floor.

Stairs with railings, balusters, and overhanging steps in a room with light green walls.

Dark Trim for Office Buildings 

I wanted to keep office building walls white because that's the most common color. My real life office (which I haven't been to since March) does have some colored walls, but they're mostly white. Instead of changing the wall colors to get good contrast, I'll change the trim color to dark gray. There, that looks much better.

Office buildings now have dark gray trim to contrast with the light colored walls, ceilings, and floors.

Maybe I should add trim along the ceilings as well like I have in houses? I haven't quite gotten the angled ceiling trim to meet properly at outside corners of hallways. You can see this on the corners of closets in houses as well, though it's difficult to spot. I think for now I'll add ceiling trim to smaller office buildings, but leave it out of larger buildings with intersecting hallways. That should help with polygon count as well since the largest buildings can have over a thousand rooms.

Reception Desks in Office Lobbies

Most large office buildings don't have their front doors open to a long hallway with rooms on each side. The doors open to a lobby instead. What better object to place in the lobby than a nice big reception desk. I can put one at each end of the hall/lobby to handle both doors.

I originally wanted to use the desk model I created in my earlier (hand made, not procedural) office building scene with the rounded corners created from cylinders. I attempted that, but I couldn't get the textures to line up using the texture coordinate system I implemented for building interiors. There's just no easy/automatic way to remove texture seams from the intersection of a cube and a cylinder. Oh well, I guess I'll just have to make the top surface out of cubes and settle for square corners for now.

An office building lobby reception desk.

Office Building Libraries

3DWorld already places libraries with up to eight bookcases on an upper floor of some large houses. I can reuse that code to turn offices into small libraries for office buildings as well. I need to make sure to limit the number of libraries, because all these books really add up for thousand room office buildings. This was an easy change and adds some variety to offices. Here's an example with a rectangular table. Some libraries have round tables.

A library inside an office building with many bookcases and a rectangular table in the center.

Bathroom Showers

My daughter asked me why there are no showers in the bathrooms of houses. That's a great suggestion! I can create a simple shower out of mostly cubes. I found a nice bathroom tile texture to use and got to work. My showers are always placed in an empty corner of the bathroom against two interior (windowless) walls. The back and floor are made of tile, with a shiny metal frame and two transparent glass panes on the outside. One of these panes is the door. One of the walls has the shower head, and there's a drain in the tile floor. That's a minimal design, but it works well enough.

A shower placed in the corner of a bathroom with light blue walls.

It took some effort to update the material drawing system so that I could draw transparent objects last, which is required for proper alpha blending. I did eventually get everything to work properly, even when viewed through a mirror.

This shower has an additional door handle, which I later realized was missing in the previous version.

A shower (with door handle added) placed in the corner of a bathroom with peach walls.

I also used that same tile texture for kitchen counter backsplashes. I only added these to interior walls because the windows on exterior walls are large enough that there's no exposed wall space for a backsplash.

Kitchen counter with a tile backsplash added to non-window wall sections.

Improved Light Culling

I was having lots of problems with room lighting, both fragment shader performance issues and light leaking though walls. I already have a system in place that performs ray casts in various directions to determine the bounds of each room light. This allowed me to do some light culling on the CPU side. Rays that hit room walls mean the light is confined to the room containing it, while rays that exit through doorways allow the light to influence other rooms. This lets me to use large light sources while constraining their areas of influence to only a few rooms. I store the computed bounding cube of each light in a texture and use it inside the fragment shader for light source culling.

It took me a few months to finally add fragment shader support for this. I was originally worried it would be very complex to pull this off, and would hurt framerate. In reality it only took about two hours, worked the first time, and actually improved draw time. I guess the ability to early exit out of lighting computations more than offsets the dynamic branching cost in the fragment shader.

This change allowed me to increase the radius/brightness and angle of upward pointing, unshadowed room lights without having to worry about light bleeding through walls into adjacent rooms. You can compare the two shower screenshots above and see that the lower one has more light on the upper walls. I was then able to go and re-tweak other lighting parameters to remove some of the annoying light leaking and unwanted shadows. This really makes a big difference when moving around the city as well because there is far less "popping" from shadow maps being switched on and off.

Bottles and Wine Racks

Paul suggested I add wine racks. I'm not sure how common wine racks are, and I definitely think I'm missing some other household objects that are far more common. I do have a very small wine rack built into a kitchen counter in my house. I guess I can add wine racks, but first I have to add wine bottles. Fortunately, a bottle is pretty easy to make by gluing spheres and cylinders together. I already have support for this. Here is a green bottle with a white cap and label. It's not a wine bottle, but that's fine, I can add other types of bottles on top of tables, desks, and kitchen counters.

A bottle of Sprite, 7Up, or maybe beer on a table.

Once I had a bottle, I could combine those with a modified bookcase to get a wine rack. Real wine racks normally are angled or have extra pieces so that the bottles can't roll around, but this is good enough for now. Maybe I can reuse this geometry for storage cubes later. I added wine racks to 75% of dining rooms, at most one per house. Here is one example.

A wine rack full of wine placed in a dining room with light green walls.

Wait! I can add these bottles to my storage room shelves as well. Now they sort of look like supermarket shelves where customers put their returned items back in the wrong place, or shelves in a recycling center. Or maybe the janitor is an alcoholic. Or the employees had a party down here.

Bottles next to boxes on storage room shelves. This room also has a spare chair against the wall.