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.

Monday, January 19, 2026

Procedural Restaurants

My previous "restaurants" post was a bit misnamed because mall food court fast food stores aren't really restaurants. This time I've added proper restaurants in their own buildings. I decided to start with the house floorplan, since restaurants are smaller than office buildings and there are plenty of houses available to reassign. I limited restaurants to simple single cube houses to keep the logic simple. There are no garages or sheds. I also restricted them to two floor tall buildings with a large horizontal footprint, to provide ample space for the dining area and additional rooms. This produced a reasonable number of restaurants that seems to be around 5% of all secondary city houses. (None of the residential city houses are large enough to be a restaurant.)

The internal floorplan of a restaurant is simple and shared across all buildings of that type. The main dining area occupies around two thirds of the total space, which is separated by the remaining rooms by a wall that runs the entire length of the building and a series of doors. The other rooms consist of a kitchen, two bathrooms, and an optional storage room for large restaurants. The kitchen takes up about two thirds of that extra space. The actual size distribution depends on the number of windows along the exterior walls as the interior room dividing walls can't end at windows. The storage room can either be connected to the dining area or the kitchen with a door. All doors remain unlocked as there are no items for the player to search to find keys. Restaurants currently have no attic or basement.

The dining area features many small wood tables arrayed in a 2D grid pattern. Most of these tables have four wood chairs. Tables can be either square, rectangular, or round, with optional place mat or table cloth of a variety of textures/patterns. Each table has full place settings for each seat with a plate, cup, and silverware. Some plates have food such as fish on them, while some cups contain coffee. I placed either a custom procedural vase or a candle at the center of each table. The result is very repetitive, but also very orderly. I suppose it makes up for the randomness of the kitchen object placement.

I hung spherical lights from the ceiling in a grid pattern and placed rotating ceiling fans between some of these lights. The perimeter of the dining room is decorated with a variety of objects such as 1-2 wine racks, potted plants, pictures, an optional TV, and an optional fish tank. I placed rugs on the floor by the exterior doors and a podium with chair next to the main entrance for guests to wait at to be seated. The ceiling uses a white panel texture, and the floor uses one of two marble or granite tile textures.

3DWorld's procedural buildings are full of critters: rats, spiders, snakes, roaches, and flies. Restaurants are no different. It's actually quite fun chasing rats as they run between the tables and chairs. 

I've included some pictures of restaurant dining areas below. 

Restaurant with pink walls and square tables with table cloths.

The upper row of windows looks a bit odd, but I have the same layout in factories and two story retail buildings. This is one limitation of the current window logic. It's run on the exterior of buildings before the interior is generated, so it can't easily be customized by building type.

Restaurant with light green walls and round tables with darker wood.

Restaurant with pink walls and square table with red table cloths.

Restaurant with light blue walls and rectangular tables, viewed from above.
 

After taking the screenshots above, I realized that the ceilings look kind of plain. There's not much contrast between the light ceiling tiles and the bright walls. I decided to add wooden beams crossing the ceiling and hang the lights on these. Here is how this looks in the first restaurant. It's definitely an improvement. I like how all of the wood textures and colors match between the tables, chairs, wine racks, and beams.

First restaurant with wooden beams added to the ceiling that the lights hang from, and people.
 

Restaurants have commercial kitchens that use the same object placement logic as kitchens found in malls, prisons, schools, and hospitals. They have the same walk-in freezers, ceiling ducts/vents, and shiny reflective cooking equipment. The only difference is that the logic for placing hoods and some of the other objects is a bit more complex to handle the windows.

Kitchen from the restaurant in the first screenshot. There are snakes, rats, spiders, and roaches in here! (And the plates are metal?)

Restaurant kitchen, looking out through the door into the dining area.

The bathrooms are quite small with a single toilet, a sink, and urinal in the men's room. I placed gender appropriate signs on the outside of the doors. They look very similar to office building single use bathrooms, so I'm not adding screenshots of them. I included the medicine cabinets found in house bathrooms because this is a source of healing items for the player, and there are no other drawers or doors for the player to open in these buildings. The only major difference is that they have tall ceilings.

This post was much shorter than the last one, mostly because I only had one topic compared to three. I feel like I'm done with food related items for now. The next task on the list is car washes, so I guess it's back to working on commercial cities. I won't be surprised if I find more restaurant related changes to make though.

Saturday, December 20, 2025

Restaurants and Kitchens

I'm continuing my work on 3DWorld's interiors for special building types. This post will cover some additions I've made to procedural buildings: kitchen pantries, walk-in freezers, commercial kitchens, and mall food court restaurants. Each of these features required implementing new object types and placement algorithms. The last three are also related by containment, since restaurants contain commercial kitchens which contain walk-in freezers. I'll discuss these four topics below in the (inside-out) order in which I added them.

Kitchen Pantries

Up to this point, only retail stores contained food items. I put a lot of effort into making some of these objects, so I wanted to add them to houses as well. Many houses have a pantry in the kitchen, which is a small room for storing food related items. It's actually quite similar to a single door bedroom closet, so I decided to reuse that code. Pantries are placed in one of the corners of the room that doesn't block a window. The only real differences are that these "closets" are in kitchens rather than bedrooms, contain shelves instead of hanger rods, and have food items in place of clothing. The walls, door, and ceiling light are identical to closets.

I decided to add three rows of shelves that wrap around three sides of the interior. The side with the door is of course excluded. A random type of object is selected for each side of every shelf, and in some cases are added to the floor under the bottom shelf. This is the same set of food items placed in retail stores: boxes of crackers and cereal, bottles of water, Coke, beer, or wine, and cans of Coke or beer. I thought of adding pizza boxes, but they generally don't fit on these narrow shelves. Here's an example early version of the kitchen pantry.

Kitchen pantry filled with food boxes and drinks.

I later added non-food items that are still food related such as stacks of plates and rolls of paper towels. I'll continue to add more items when I think of them, or when I add new food related items to other room types in the future. Keep in mind that the player can take and use all of these objects.

Kitchen pantry in another house, with the addition of paper towel rolls.
I added one new type of object for pantries: the spice jar. This is a small semi-transparent glass container with a random amount of colored "spice". These are usually placed in a row on a shelf with various types (colors) of spices randomly selected. Sometimes the placement is uneven with gaps. It's a simple addition, but everything helps to improve realism and variety.

Kitchen pantry with a row of jars of spices. And a rat on the floor!

Walk-In Freezers

Next, I added walk-in freezers. And guess what? I reused the closet code yet again! In fact, walk-in freezers were copied from pantries since they have the same shelf system. The major difference is in the materials used. In place of plaster walls there's shiny steel for both the interior and exterior. The hardwood floor and wooden door are replaced with metal flooring and a metal door. Even the shelves are metal, in the form of a horizontal grid of thin bars.

Freezers are placed in a corner of the kitchen. These are always one standard floor spacing tall and don't extend to the tall ceiling of mall stores, which means that the top surface may need to be drawn. I added extra clearance around the door to allow it to open (with a different sound). The door is still recessed and thin because it uses the same geometry and rotation logic as interior building doors.

Walk-in freezer in a commercial kitchen, exterior view. Shiny! In fact  most of the kitchen objects are shiny.

Now I'll show the freezer interior. I placed a freezer fan in the top back of the interior using the same code as house AC units. Shelves are metal racks with some vertical supports at the inside corners and objects placed on or below them. I didn't really have any good frozen object types other than stacks of pizza boxes, so I added closed cardboard boxes that the player can imagine has some type of frozen food in them. They can't be opened because I don't have anything good to draw inside the opened box. I may place additional items in freezers later when I think of them. Maybe frozen fish?

Interior view of a walk-in freezer with shelves full of boxes, a few stacks of frozen pizzas, and an AC unit in the top back.

Commercial Kitchens

Pantries and freezers were relatively easy to add. Now that I had freezers, it was time to start on commercial kitchens. These rooms are placed in buildings that can have cafeterias or other eating areas such as schools, prisons, hospitals, and malls. One easy first step was adding a tile floor over the concrete, carpeting, or whatever base floor material the building was using. The remaining steps proved far more difficult, mostly due to the large number of new object types I needed. At first I attempted to create these various kitchen appliances with procedural geometry. I didn't get very far though before I realized it would take countless hours to write the code for all of these. So, with a heavy heart, I deleted the initial code and went looking for 3D models. At least the freezer is procedurally generated.

I found 12 different commercial kitchen object models on Sketchfab which included refrigerators, ovens, microwaves, deep fryers, stoves, grills, and sinks. Most of these were low poly models that should allow me to add quite a few objects without running into framerate problems. I tried to find models that had plain white textures so that I could more easily change the materials. Combined with the existing refrigerator and walk-in freezer objects, that meant I had a total of 14 item types to place. The goal was to add a system that selected and placed random models like I had done with prison gyms.

I already have some nice functions to place 3D models along walls that checks for blocking windows, doors, stairs, other objects, player/AI paths, etc. It takes a height value and automatically calculates the object width and depth based on the relative model sizes in each dimension. My first attempt to use this approach created a random set of objects scattered around the perimeter of the room with gaps of empty space everywhere. That's a reasonable start on the programming side, but it's an absolute mess visually and looks like a very inefficient kitchen layout.

This needs a number of fixes. First, I need to solve the problem of everything placed along the perimeter that leaves empty space in the center of the room. If the kitchen is large enough, a procedural metal table is added in the center. I can then place a variety of smaller items on the table such as the small deep fryer model, a microwave, a toaster, and cooking items that include pans, plates, cups, and trays. I even found a simple 3D model of a milk carton to add. The center of the kitchen is no longer empty space.

The second part of this fix was placing some random rolling carts in areas of empty space. I reused the "trolley" model I had placed in hospital operating rooms, since it seemed like something that could be found in the kitchen. Then I placed stacked plates on these, and configured them so that the player could push and pull them around. (This is important because these carts can sometimes block the path to the door.) One problem down, several to go.

The next issue is the random gaps between objects. Normally a commercial kitchen is packed with adjacent appliances to fit as much as possible into the limited space. Rather than randomly placing individual objects, I changed it to place a single seed object and then iteratively add new random models to each side until there's no available space left. This produces a dense group of adjacent objects along one wall. It's not always the entire wall, as objects such as doors break up the groups.

It's still a mess of object types though. To make matters worse, some of them have very different aspect ratios that don't fit well together. The solution to this is to group the objects by function, which conveniently also somewhat groups them by size and shape. The three categories I came up with are:

  • Objects needing a vent/hood: grills, fryers, stoves
  • Other cooking related objects: ovens and microwaves
  • Non-cooking objects: fridges, freezers, sinks, and dishwashers

Each of these categories has 4-5 different items/models. The entire contiguous group of objects is assigned the same category. Categories are randomly selected, with a higher weight given to the one with the fewest placed objects so far. The placement system also attempts to place at least one of each unique object when possible. This approach mostly balances out the model distributions and maximizes variety. This did a reasonable job of object placement and created a kitchen that looked much more organized.

The only remaining problem was that the models used different colors, materials, and styles. They didn't all fit well together. So I did the only reasonable thing I could come up with: make everything uniformly shiny. I Set almost every material to reflective metal, which removed almost all of the color and texture. The appliances also now match the metal freezer and center table as well. Even the trolleys are shiny metal. Everything is better when it's shiny, right? I need to take advantage of the cube map reflections I added a few months ago. It's actually less obvious that reflections are incorrect when the room is full of many small objects with surfaces at different angles.

There's still one thing missing: ventilation. Kitchens need good airflow to remove all of the smoke, fumes, and steam from cooking. I began by adding rectangular ducts with vents along the ceilings using the same code I had added for malls. That's a good start for general ventilation, but I needed something more industrial for the fryers and grills. After changing my mind a few times, I eventually decided on rectangular metal hoods with internal fans hanging on the ceiling above the first category of items (grills, fryers, and stoves) and spanning the bounds of the entire row of models. That's another bonus of combining rows by type.

Since hoods have to scale to the size and shape of the objects, I create them procedurally rather than using 3D models. These objects have sloped edges so that the front is higher than the back. I added a repeating fan texture to the interior top surface (the same as an AC unit) and a metal grid texture (street grate) to the back.

With everything combined, here is what we get: 

Commercial kitchen inside the windowless room of a school. Shiny!

Very large commercial kitchen inside a prison, with a central table and appliances lining the walls. An open freezer is in the back.

Stoves and some grills have pans on them. To finish things off, I placed some stains on the floor using common food colors like white, black, dark red, and dark green. I liked the look of those stains, so I added similar stains to some of the trays and plates as well.

Mall restaurant kitchen showing some new features such as fish on plates, objects on trays, and stains on trays.

I'm sure I could add more objects such as pots, pans, hanging utensils, etc. to fill in the remaining empty spaces. I don't want to load or draw too many 3D models just for kitchens though. It may be okay if I can find models that can be added to other room types in the future. We'll see.

Mall restaurant kitchens have counters that run their length and separate them from the public areas. I placed more food related items on these counters.

Mall kitchen with a bowl of apples on a counter.

Mall Food Stores/Restaurants

My final food related addition was mall restaurants. These aren't the fancy sit down restaurants with small tables though. No, they're the type of fast food places typically found at food courts. I felt like this simplified layout was an easier place to start. I actually worked on restaurants and commercial kitchens at the same time as this required several iterations to get right. There are also many similarities between the two, in particular the metal surfaces and the various placed food items. And of course commercial kitchens account for about half of the interior space of the restaurant.

There are two different styles of restaurants. The first type has a simple counter and no public interior space. This is your typical fast food counter full of cash registers where customers order their food and then sit down at the central mall food court tables to eat. These are divided into a smaller space where the cashiers and packagers work and a larger back kitchen area. Here are two examples of this type of restaurant, viewed from both inside and outside.

Mall restaurant shown from inside looking out into the mall concourse. The reverse side of the image above. The cash register model is new. Note that some of the store sign backgrounds are colored now.

Mall restaurant walk-up counter with cash registers. Orders to go only. Note that the name sign is directly above the order counter. I really should be using multiple fonts for these signs.

The second style has a public area with entrance doors and large store front windows. This is the same geometry as non-food stores found in malls. In fact I had to add custom code to remove the doors and windows for the counter-only restaurants described above. Here the counter with the register is further inside and separates the public area from the kitchen. I placed a food and drink vending machine in the public section if they fit.

There are two sub-types of this style of restaurant, chosen depending on the size of the public area. If the space is deep enough, rows of tables are added and this becomes a sit down restaurant. Otherwise, the public space is left mostly empty except for the vending machines. Customers buy their food and then go back to the central food court area to eat it. I may decide to add more small items here later. Below are screenshots of both the empty space and tables cases. 

Mall restaurant with an indoor area for ordering and vending machines, but no seating.

Mall restaurant with indoor seating. Vending machines are off-screen to the sides.

I'll finish this post by showing some of the new detail items that I've added to restaurants. First, I added a bowl type to complement the plate type. The only real difference is the use of a spherical section rather than a conical section when drawing. Bowls can be empty or contain apples or soup. Soup is drawn as a simple circle at a random height, using the same set of food colors as floor stains. I reused the liquid drawing code from cups of coffee and buckets.

Bowls of apples can be seen in the screenshot below and also an earlier commercial kitchen screenshot. I originally wanted to use a sphere packing algorithm to place the apples as densely as possible. Unfortunately, packing spheres into a spherical section is quite a complex problem, and I wasn't able to find a simple mathematical way to do that. It's really not worth spending days working on the solution to such a minor feature. So instead, I placed one apple on the bottom and three more in a second ring/level. The player can take apples and then take the bowl itself when empty.

If bowls can be nonempty, then some plates should be nonempty as well. The only existing object I could find that worked well for a plate was a fish. I can conveniently reuse the same fish model I have for house aquariums, I just have to flip it on its side. I can even take advantage of the stacking/containment logic and place these new nonempty bowls and plates on trays. Now you can find a fish on a bowl on a tray on a table, and the game logic requires the player to pick up these objects in the correct stacking order to avoid having anything become floating in the air. The stack of objects will also move with the table if pushed by the player.

As an added bonus, I can reuse some of these food related objects in house kitchens and cafeterias. 

Closer view of bowl of apples and fish on plate on tray.

Abandoned bowl of soup on a tray on a cafeteria table.

Wow, that was a ton of work! I'm surprised I was able to get all of this done before Christmas. I feel like I'm not 100% done yet. I'll probably spend a few weeks debugging, tweaking, and optimizing kitchens. Maybe I'll go back and add some smaller objects to fill the empty space.


Tuesday, November 11, 2025

Adding Damage and Wear to Procedural Building Basements

I'm back to working on building interiors. I wanted to add more wear and damage to buildings, in particular the maze-like extended basement hallways. They're currently somewhat plain with no objects on the floor, and only rows of doors to either side, with an occasional picture on the wall or rug on the floor. It's too easy to get lost because there are no real landmarks, since every hallway looks similar. The cracks and water damage I added a while back applies uniformly to each room.

I've added more localized damage: missing ceiling tiles, broken lights, trash on the floor, mushrooms, graffiti, and holes in walls. I'll go into more detail on each of these topics below, listed in the order in which I added them.

Missing Ceiling Tiles

My first change was to cut out some areas of basement ceilings to add missing acoustic tiles. Any hallway that's selected to have missing tiles gets an additional rectangular space above the ceiling. This is only legal for underground rooms that have sufficient space between the bottom of the ceiling and the terrain or buildings above. Multiple tiles can be removed per hallway, and they end up as randomly placed and rotated rectangular objects on the floor that the player can pick up and add to their inventory.

The space above the ceiling is filled with pipes, ducts, wires, and spider webs. These are only placed in locations where they're visible through the openings. The pipes and ducts aren't actually connected to anything yet. I added hanging electrical wires to the corners of some tiles. Sometimes missing tiles are adjacent to ceiling lights, so I had to add metal support brackets to the lights to keep them from floating in space if their surrounding tiles are removed. The walls inside the ceiling space are textured with concrete and have per-vertex lighting where the brightness varies based on the distance to the nearest opening. This makes the space lit above the opening while extending into darkness. I added a brown frame around the edges of each opening to give it some thickness and fill the gaps next to the walls.

Surprisingly, the most difficult step was aligning the texture to tile exactly to the width and length of the  hallway in a way where I could calculate the exact coordinates of individual tiles. This required varying the length and width of a tile's texture coordinates to match the room dimensions, and then recording enough info about this to reconstruct the grid in the part of the code that places objects. The ceiling itself is drawn by the "building interior" system, while the tiles and holes themselves are drawn by the "room object" system, using different drawing code.

Extended basement hallway with a missing ceiling tile, showing pipes and a round duct in the ceiling and a hanging wire by the doorway.

The player, people, zombies, and rats can all walk over any ceiling tiles on the floor. Spiders will avoid them as their legs will clip through, and they will also avoid the openings in the ceiling. I haven't written the code for spiders to use these spaces yet. Technically, the area is outside the building.

Hallway with ceiling tiles that fell onto the floor, exposing pipes and a rectangular duct. This person will walk over the tiles.

Tiles placed on the floor are added within a small distance from their previous spot on the ceiling and in a random orientation. They're constrained to avoid the path of doors and stairs. Hallways don't have any other objects on the floors that must be avoided. This is helpful because I don't actually have a list of colliders for each room, since they're added in an earlier step than the ceiling tiles.

Another hallway with missing ceiling tiles and stairs at the far end.

Broken Ceiling Lights

There are two new types of broken ceiling lights found in extended basements. The first is a light that's missing the outer plastic cover and has the inner fluorescent tubes visible. These are emissive when the light is on. I added reflectors to the sides that function as mirrors using the cube map reflections added in an earlier post. This doesn't work all that well though, since the reflections are centered on the camera. This often means the lights reflect the texture of the floor under the player. That's why the reflectors look like concrete in the image below.

This ceiling light is missing its plastic cover, which is on the floor. The fluorescent tubes and reflectors are visible. The top of the wall is dark inside the hole because it doesn't pick up any indirect light from the room below the ceiling.

The second addition is a light that's fallen down and is hanging vertically by one end. These lights are rotated by 90 degrees and have a horizontal spotlight pattern that produces bright walls on one side and dark hallways on the other.

I originally wanted to make these colliders for the player, building people, and zombies. The player can easily walk around them. It's annoying to have to do so, but I usually find myself walking around them even if they don't have collision enabled. The problem is that the person/zombie AI path finding may not be able to navigate around these hanging lights in narrow hallways. I had to add sufficient clearance to the path finding to prevent 3D models from clipping through objects in any animation frame. The primary goal of gameplay is that each room can be navigated by the AI as they chase the player. It's no fun if a zombie can't follow you down a hallway. So for now I'm not making these lights collidable, and people may clip through them when walking. 

This ceiling light has fallen down and is hanging by one end. The light emitted is now horizontal rather than vertical, leaving a dark hallway behind it.

Mushrooms

Ah, mushrooms. These can be found in extended basements with wetness > 50%. I originally added these as decorations placed in groups of 2-3 along walls and in corners of rooms. Later I decided the player should be able to pick and eat them, and they would serve a gameplay purpose. The effects must be generally positive to encourage the player to walk around picking them up. But I also wanted to add a negative effect so that they're not too overpowered, considering how many mushrooms can be found in some areas.

I had a lot of fun writing postprocessing effect shaders for when the player was drunk a few years ago. I already had a wavy image shader, a blur shader, and a double vision shader. The problem with double vision is that it only happens when the player is extremely drunk, which is rare considering the sparse placement of alcoholic drinks and the fact that you can't drink the bottles found on store shelves. So I reused the double vision shader for one species of mushrooms. This is implemented as an effect that lasts for 10 seconds and then slowly fades away. It's stackable, so eating multiple mushrooms in a short period of time will extend the effect's duration.

But one effect is no fun. I need more variety. I added two more mushroom types with different stats, and two new shader effects. Now I have:

  • White Mushroom: +25% health, 10s of double vision
  • Red Mushroom: +25% drunk/high (damage reduction), 10s of psycho color effects
  • Red with White Spots Mushroom: 30s of invincibility, -25% health, 30s of floating/moving colored spots

All of these effects are very disorienting and distracting. What's great is that they stack/accumulate as well, so you can have two or all three active at once. And to encourage this, I added the 25% health loss for spotted mushrooms so that the player is more likely to eat a white mushroom at the same time to gain back the health. All three shaders were fun to create, a nice break from generating building geometry. The double vision and color changing shaders look very good to me. The floating dots shader was more of an experiment with GPU based particle simulation, and consists of 40 brightly colored emissive circles that float across the screen in random directions and speed, with randomly varying size/intensity and color.

Extended basement room with small white mushrooms against the wall and in the corner. The picture on the left is one of my shader generated procedural art images.

I would like to add that the framed picture on the left is one of the shader-based images I added a few months ago. I found several interesting shader effects, including various types of fractals and noise, and render these to images that are then used as pictures placed on room walls. Each picture uses a random time or position offset so that each one is unique.

Mushrooms are placed non-uniformly across rooms. Most rooms have none, but some rooms have quite a few. In fact you can sometimes find a single room that has all three mushroom types. Here is such a room.

A bathroom with all three mushroom types: red with white spots in the front left, red in the back center, and white in the back right corner. The picture on the right is another shader effect.

Here are some screenshots of the three shader effects. The first effect is double vision.

Double Vision: Makes is very difficult to pick up and interact with objects.

Then we have the newer color changing shader effect. Input colors are mapped to bright reds, blues, and greens. If you think this image is bad, imagine what it's like when the colors are constantly moving!

Trippy Colors: This is done by applying a nonlinear equation to the RGB color values to get a very different set of RGB values out, plus it varies with time. Very disorienting.

And finally we have the random colored dots shader. This is supposed to simulate some sort of hallucinations or spots in the player's vision. These are constantly moving and changing, which makes them very distracting to gameplay. At least the player is invincible during this time. Eating too many of these mushrooms in a short period of time will lead to death.

Floating Dots: 2D screen space particle simulation with bright circles that move and change size/color. Maybe not as bad as the other effects, but still distracting.

And here's a video showing all of these in action. The screenshots aren't enough to show just how difficult it is to play the game with these effects active. I even got lost in the basement in the video.


Graffiti

I've been wanting to add graffiti to 3DWorld's buildings for a while now. My daughter recently had a school art project where she had to draw graffiti, and I think that's what finally pushed me to add it to my buildings. I initially started by looking for free textures I could use, but I couldn't find any really good ones. Most of them weren't alpha masked and were difficult to separate the paint from the background wall image. Many of them had art or letters clipped, or other non-graffiti objects. It's not enough to select a few of these images. I probably need at least ten to avoid being too repetitive.

So instead I did what I always do, and turned to procedural generation. But how? I couldn't find any good approaches described online. There was an Unreal Engine graffiti plugin, but it looked too complex to include in 3DWorld and required a variety of input art assets such as a custom character font. I have no experience with graffiti and can't even read the text in many of the reference images. That doesn't help.

I eventually gave up trying to do something complex and went with a simple set of random overlapping lines with varying thickness in a rectangular area. This is very similar to how I implemented spray paint, and it even uses the same rendering system. The only big difference is that it's formed from lines rather than dots, which means I can get more color with fewer vertices. But it still looks very close to something the player can create with the spray paint can.

Extended basement hallway with graffiti on the walls, both sides.

These graffiti "blobs" are placed at random locations along hallway walls. They're applied over vents, outlets, and light switches. I limited them to hallways because there aren't any other objects blocking the walls. For example, it definitely looks wrong to have graffiti on the wall behind a machine in a machine room. I still sometimes see pictures hanging over graffiti, but I guess we can assume someone put them up to cover it.

I originally had a check that each new graffiti region had no overlaps with any previously placed graffiti. Then I realized that overlapping multiple colors actually looked better. Each stroke is applied over the previous stroke and alpha blended on top of it for a natural looking spray paint effect. I changed the code so that it sometimes places new graffiti at the same location as the previous graffiti using a different color. The screenshot below shows what this looks like.

A second hallway with more graffiti, this time with overlapping colors. Also, more missing ceiling tiles.

I know, it's not the greatest result. These aren't real letters or symbols. It somewhat reminds me of those paint lines added to roads and sidewalks to mark where the pipes are before digging. However, it does make each hallway feel more unique. I'm sure it also helps the player find their way through these hallway mazes. "Turn right at the orange and white paint blob."

Holes/Gaps in Walls

This was the last effect I added. Holes in walls are a great complement to holes in ceilings. I originally wanted to cut larger numbers of irregular circular holes in extended basement walls, but I couldn't find a visually pleasing and efficient way to do this. It's not so easy to subtract 3D geometry, and the building interior system doesn't currently support alpha blending, alpha testing, or masking of walls/ceilings/floors. The best solution I could find was to remove entire rectangular sections of walls (and trim) and then add parts of them back in to create a final large and irregular "hole". I cut at most one hole into random walls that are at least a minimum length and not adjacent to neighboring rooms.

Wall gaps are visual effects only. They function just like regular walls for blocking the player, building AI, animals, balls, etc. Only cockroaches can pass through them. 

I drew a plywood surface on the back side of the wall and added vertical wooden studs about every 16 inches horizontally, plus an extra 2x4 along the top and bottom to cover the ceiling and floor gaps. Then I added a number of pipes and Romex wire cables in multiple colors that cross through the studs from left to right at various heights. This combination should model a realistic wall interior.

I wanted to have rough, broken edges on the plaster, so I extended the edges toward the center using points randomly displaced both horizontally and vertically. These are textured to match the walls to either side with no visible seam. The edges of the front face (the sheet rock) are also drawn as thin quads. Each edge has unique procedural geometry for a more natural look. The only limitation is that cracks drawn on the wall with a special shader aren't added to these extended triangles because it uses a different control flow and different shader settings. 

Extended basement hallway with many cracks and missing sections of wall on both sides. Conduits/pipes and wires are visible through the holes.

I think the wet basement shader effect looks pretty good on these wall cutouts. The increased specular component interacts well with the normal maps on the wooden studs to make them appear slimy. Should there be plaster/stucco triangle fragments on the floor as well?

Broken section of wall with a wet shader effect applied to it.

Some walls have that pink fiberglass insulation inside them. I'm reusing my "cotton candy" texture from house attics. Here's the post, but I don't seem to have an image with that insulation in it. This is actually a cloud texture where I've changed the sky color from blue to pink and kept the clouds as white. It's not the greatest and has no normal map, but it seems to do the job.

Missing wall with pink fiberglass insulation visible through the hole.

The wood in the previous screenshots was dark and rough. I experimented with a few other lighter wood textures with more fine details until I found one that I liked. This is shown below. It's still not the typical light lumber texture with darker knots in the wood. The problem with that texture is the repeating pattern of the knots that looks artificial when tiled over all wood elements.

Missing plaster section with a lighter wood texture. Also, more mushrooms.

Is this lighter texture better than the darker one? It makes the wood look more fresh, but that's not exactly the look I'm going for. As a compromise, I set 50% of buildings to use each of the two textures.

What else can I add? Maybe some of these walls should allow the player to walk through them and connect to other rooms or caves. That would certainly be interesting. I'll have to consider caves for my next post topic.