Wednesday, March 11, 2026

Procedural City Car Washes, Service Stations, and Convenience Stores

I've been working on various optimizations and improvements to 3DWorld's building indirect lighting and reflections. There's not much to show or explain in a blog post though because it's mostly technical details. Everything is faster but looks similar. I did continue working on city gas stations on and off over the past month. I've added some other smaller buildings around the gas stations: car washes, service stations, and convenience stores. I'll show my progress on each of these building types below.

Car Dirt

The first type of gas station sub-building I added was the car wash. But wait, we can't have car washes without dirty cars. I added a dirt shader effect that's applied to car drawing using 3D volumetric noise at two different size scales to add both large and small dark spots of dirt to car exteriors. This is similar to the shader used to draw wet areas onto extended basement walls, ceilings, and floors. A dirty car is shown below.

A very dirty red car about to enter the car wash.
 

Cars start with a random amount of dirt between 0 and 1, and it increases slowly over time while the car is moving. When dirt exceeds 0.5, the dirty shader effect starts to show, with dark areas growing in size and frequency as the value increases to 1. When max dirt is reached, the car will attempt to reserve a spot at the nearest car wash. The dirt value decreases back to 0 while the car is being washed. Dirt does not apply to ambulances, and trucks have a lower dirt cap because they're too large to fit in car washes. I haven't yet applied a dirt effect to cars parked in building parking garages because they have no way to clean themselves.

Car Washes 

Now that we have car dirt, we can have car washes. These are small buildings placed next to gas stations that share the entrance driveway/parking lot. The building is rectangular with a sloped metal roof and four "bays" for cars, with lights on the ceiling of each bay. I've left both ends open so that cars can drive straight through and exit on a second driveway back onto the road. These buildings aren't named and don't have signs. They're treated as city objects rather than buildings, which means the player can't interact with them but cars can.

Car washes use a lane reservation system for both the four individual bays and one shared exit driveway. There's no need to reserve the entrance driveway because all cars enter it from the same point in the feeder road, and the traffic system can only allow one car to enter at a time. Bay reservation is needed to prevent cars from queuing up and blocking the road. The exit lane must be reserved so that a car doesn't collide with another car that already exited and is either driving down the exit driveway or waiting to turn onto the road. The traffic system that controls car behavior isn't activated until the car pulls out onto the road.

Car logic is instead run by a finite state machine while in the gas station area and on driveways. The states for using a car wash are:

  • Turning into driveway
  • Driving on driveway
  • Turning into bay
  • Entering bay
  • Stopped + washing
  • Exiting bay
  • Turning onto exit driveway
  • Driving down exit driveway
  • Turning into road 

The wash cycle itself starts by turning on the light above the car. I've changed these lights so that they're enabled during both day time and night time. Shortly after entering, water starts to flow, and is drawn by a series of random semi-transparent lines running down the space from the inside roof to the ground. Then soap is applied, which is rendered using a foam shader effect. Foam is similar to dirt but uses a lower frequency noise, a sharper edge cutoff, and a vertical animation to make it look like the soap is running down toward the ground. I've added day time and night time screenshots of the water and foam effects.

Car wash with a car in one bay where the water is running and the car is soapy.


The same car wash, viewed from the other side and at night.

I actually recorded three different videos as I worked on car wash graphics. Each time I found something that I needed to improve on. You can find them on my YouTube channel, but I'll also link them here. 




Service Stations

I added service stations next, with a 50/50 chance of service station or car wash. They're very similar to car washes and have the same size, number of bays, texture, roof type, and lack of player interaction. The only difference in drawing is that they have only one end open rather than two. This allowed me to reuse much of the code.

Service station with one car inside and one light on.

Service stations have stacks of tires in front. I wrote new code to generate thick cylinder geometry so that I could add these tires. In the end, I didn't use that code for tires, but I did use it to replace the drawing of toilet paper rolls, paper towel rolls, and tape in buildings. The previous code drew these as a cylinder with a transparent hole cut into it. This was inefficient and didn't always alpha blend correctly with objects visible through the hole, in particular when the player was holding the cylinder. Now this has been fixed by making the hole out of real geometry.

Service station with stacks of tires in front.

I haven't added any dynamic car update for service stations yet. Currently, cars are spawned there at object placement time and never leave. They're the same as parked cars placed elsewhere in the city. 

Convenience Stores

Where are the gas station employees? Shouldn't someone be watching the pumps and car wash? I'm missing something that often comes with gas stations: small convenience stores such as 7 Elevens. These are now added on the other side of the gas station away from the road, 90 degrees from the car wash or service station. Of course they're only placed when they fit, which means they may be absent in situations where gas stations are placed close to office buildings. Since gas stations are the first city objects to be placed, they override anything else such as parking lots.

Convenience stores use the same random name generator as houses and some office buildings. And what do you suppose was the name of the first store I saw near the player's starting location?

Apparently my name generator has chosen "Farto" for this store. Sigh. Really, this is the first store I found.

Convenience stores are similar to the retail areas I added to the ground floors of some office buildings, thought they're much smaller. They have rows of shelves with food and drink items placed over tile floors with bright lights overhead. I added a counter to the front and a single user bathroom and a storage room at the back. There's one exterior front door facing the gas pumps and an optional back door on the opposite side. It's a fixed floorplan, though it does stretch to fit a building that's variable sized based on the amount of available space.

Interior of convenience store with a person browsing the items. Yes, I know the pizzas should be frozen or at least refrigerated.

The front area has a counter with a cash register and a person standing behind it. There are other items such as a coffee machine and various food and drink related objects. I placed a drink vending machine to one side and a snack vending machine on the other side. A digital clock that shows the actual time can be found on the back wall. As a final touch, I hid a handgun under the edge of the front counter near the cash register. The player can search for and take the gun for some fun target practice.

Front counter of store with someone at the register and a view outside through the windows.

I added a new type of object to these stores: the commercial drink fridge. They can be found along the back wall near the storage and restrooms, and sometimes along the sides between windows. These contain drink bottles, drink cans, and cartons of milk. The player can slide the two front glass doors back and forth to access the drinks inside. There's also a small interior light to illuminate the contents even when the room lights are turned off. I made the interior surfaces and glass reflective using the cube map system described in an earlier post.

A pair of commercial fridges along the back wall of the store, filled with drinks behind glass doors.

I made sure to leave enough space around all of these smaller buildings for pedestrians to walk between them and along the sidewalks. Dumpsters are placed behind most of the stores. I may add other trash related items in the future if I get back to this at some point.

Back side of a convenience store with a dumpster and storage room visible through the window.

Stationary People in Buildings 

There are some additions I made to my AI people to make them behave more realistically in buildings such as these. The first was to add support for what I call "stationary" people. These are extra people placed in specific locations and facing in particular directions. They're implemented by assigning slots during building room object generation. I added these locations at counters in front of cash registers in stores and mall restaurants, as seen above. I also added people behind checkout counters in retail stores, and at the front entrance of restaurants where they can greet customers.

I would like to take this further in the future. For example, if I ever add sitting animations, I can place people sitting at desks. That would probably work well for office building reception desks on the ground floor. I just have to be careful not to add so many people that there are performance problems. For this reason, I capped the number of filled positions to the max number of people that can be placed in that building type. When there are more slots than there are available people, they're randomly assigned to, and some will be vacant.

Note that stationary people don't become stationary zombies. They'll leave their positions and come after the player when zombie gameplay mode is enabled, and will continue to walk around even after gameplay mode is disabled. This helps to increase the density of zombies in large open areas such as malls and retail stores.

Building AI People Points of Interest

While I was working on the building people AI logic for convenience stores, I noticed that they would walk around aimlessly and stand in random places. So I took a break before finishing convenience store interiors to work on what I call "points of interest". These are locations around objects placed in buildings that include information for where people stand and what directions they look in. The goal was to have people walk up to and face store objects such as shelf racks, vending machines, and the front counter. I later expanded this to include various rows of items in mall stores (shelves, clothing racks, bookcases), restaurant counters, and checkout counters. I even added points of interest for bathroom toilets, sinks, and urinals. Now people have a reason to enter the bathrooms!

POIs are grouped by room and are selected from when the person chooses that room as their destination. POIs override the default location, which is often the center of the room, but only when they're reachable from the entrance. (It's the job of the object placer to ensure all POIs are reachable.) I plan to add more similar features in the future to improve the realism of 3DWorld's AI behaviors.

No comments:

Post a Comment