A walking simulator about climbing gray stairs surrounded by gray walls surrounded by gray structures in gray rooms stretching for gray kilometers situated on the gray floors of a gray onion-like Dyson sphere containing many gray floors and lots of gray stairs. Occasionally you see some black rectangles.
Just a few duplicates of a simple test object built using the modular system described in the previous post. I'll detail what went into the modular assets like staircases in some of the later posts, when I'll have some more eye candy and some lighting issues sorted out.
Hey again, and sorry for the long absence! There was nothing special about it, I’m alive and well - just had a few busy months at my job, shipping some projects and consequently working lots of overtime with little free time for the fun stuff like this game. But that’s dealt with for now, and I’m back to fiddling with this project.
First let’s get the boring stuff out of the way. I moved to Unity 5, yay. Nothing too interesting about that, especially since I’m using Jove (so we already had PBR, neat lights, neat shadows and other shiny goodies for a long time).
Now to something interesting. Environments: how do they work?
As I got back some free time, I started working on a new environment, and as the work progressed on the lovely stairs, railings and pipes, I started questioning the content creation process and scene structure I have adopted a year ago. Lets consider the following environment (as usual, all images are clickable and link to the original sizes).
Before, I would jump ahead and export the whole floor of that structure as a single mesh. But there are some problems with that.
Occlusion culling has nothing to work with. No matter how you spin your head around, the engine will be forced to submit entire enormous mesh to the GPU every frame, even if all you’re looking at is a tiny section of an outermost railing of an outermost platform. Not very nice for performance, especially when dozens of floors like those can be in a frame at once.
Art updates are pain in the ass. Want to change the design of 1m catwalk segment used across 23 environments? Pray you have them all in one file with all instancing links intact and if you somehow actually do, have fun reexporting 23 enormous meshes from scratch.
Lightmapping is horrifying. Good luck getting decent texel density on that chunk when it contains hundreds of square meters and thousands of isolated elements which have to be padded. And speaking of which, you’ll have to recalculate the lighting after you made that tiny change to one catwalk section because duh, all lightmapping UVs assumed a different layout now.
Primarily I’m worried about art changes being pain in the ass, of course. Because let’s be clear here: this is shovelware where I make my fun doing environment art and pretend to touch some code once a year, so any art-related inconveniences really bum me out.
If only I had a way to export individual modular pieces I use in the 3d pacakage, assemble levels from them, and have every environment automatically updated to the newest versions of those pieces every time I export a new version of them. That will solve lightmaps being stretched over enormous objects and occlusion culling being forced to work with enormous chunks. Except wait a minute, that’s already a thing in Unity, and it’s called prefabs.
Nice, now I can change the shape of some railing or a platform and have every instance of them already placed in the scenes perfectly updated. Except in contrast with SketchUp, where you have godlike alignment, movement and rotation tools allowing you to set up perfectly snapped scenes like one depicted above literally in minutes, in Unity you have nothing but few dinky gizmos and a grid. Have fun assembling that scene with hundreds of off-grid attachments and various chained rotations in the Unity Editor.
Okay, that’s not very fun, and fun is of essence here - otherwise what’s the point of working on a game, right? So, if I want to enjoy the niceties of prefab use, I need to do one of the following:
Figure out a way to save scenes from SketchUp: should definitely be possible by writing a SketchUp plugin with will serialize positions/rotations/scales/ids of components into a file and a Unity tool which will use that file to instantiate stuff in the scene. Except I’m too lazy to learn Ruby and SketchUP API to write something like that.
Figure out a way to replicate the tools I use in SketchUp in Unity. Sounds harder, but hey, I can probably avoid learning something new that way, so let’s definitely choose that.
Replicating whole toolset and inferencing system from SketchUp sounds like a year-long project, of course, so first I thought about actual intent of my actions there and the tools I used most frequently to accomplish my goals. What was my intention? To snap stuff together, of course.
And it just so happens that there exists a perfect inspiration for a system to snap stuff together. It’s the craft editor in Kerbal Space Program.
You have parts, parts are objects with nodes, nodes snap together, dragging object rotation and position into a very specific place. How about implementing something like that for level editing? Define attachment nodes once per object type, save the object to prefab, reuse the nodes forever for automatic perfect attachments. Once you drop more complex and irrelevant parts of KSP editor attachment system, like pointer-attached hovering pieces or surface attachment, the spec for your system ends up pretty simple. And so I implemented something like that:
The attachment is performed after four simple clicks. First click selects the attached object (one which will be moved into place), available nodes on that object light up; second click selects the node which will be used for attachment; third click selects the parent object, available nodes on that object light up; and finally, fourth click selects the parent node used for attachment. Works nicely. Except the instant nature of attachment is pretty disorienting - you can’t exactly wrap your head about the movement and rotation of objects, and frequently make mistakes because of that, misjudging the sides that have to be attached and such. I’m still unwilling to implement KSP-like pointer-attached pieces hovering around, so let’s try another route: animating every change.
Implementing simple in-editor tweening system every change is submitted to instantly makes things more readable and satisfying. But we’re only starting, of course. For once, those standard spheres look boring, we should outdo KSP by using something nicer.
As an added bonus, those peeled spheres visualize the rotations of the nodes, which is very useful for checking whether they are configured correctly. Let’s also implement attachment node types, so that it’s impossible to attach together pieces that should not go together, like a 3m pipe cross section and a ladder, and add neat labels on top of every node showing you their types:
Okay, some basic use cases covered. Except it’s still impossible to assemble the environment from SketchUp screenshots in the beginning of the post. Why? Because of those pesky chained attachments using diagonal pieces, which make it impossible to close the loops without case-specific unique segments of weird lengths like 1.279133m. How do we solve that?
By implementing stretchy pieces, of course. The concept is pretty simple - those are supporting segments that have no turns, only have nodes on borders on one axis, and stretch themselves on that axis to meet the selected parent object. If the arrival position of the endpoint node matches the node of a parent object, the attachment is performed straight away - if not, then you have to do some alignment on another axis using another stretchy piece. Works quite easily once you get the hang of using them. Let’s also implement a way to quickly swap the attachment point:
We also have a problem with pieces like stairs. One-sided platforms can be flipped around to accomodate any direction, but pieces like wall-mounted stair segments will always go up or down relative to a wall. So let’s solve that too.
Yes, fancy lights and neat arrow models are mandatory, I don’t want those scrub tier default gizmos offered by the editor. :^) Now, what about pieces like pipes which should have an option to rotate around the attachment point to allow spaghetti-like mess from the first screenshots? Let’s implement that too.
Let’s also add a way to quickly clone the selected piece (nope, standard duplication isn’t suitable, as we want to reliably modify the state of our custom component every time we do duplication like that):
Okay, I also did that because I wanted a nice animation on pasting. Don’t judge.
So, with that covered, what do I have left? Evidently I do have some stuff left to implement, because the post is missing some in-Unity screenshots of that fancy environment from the beginning. Let’s see:
First of all, I need a way to group multiple modular objects into prefabs. For example, to create a floor out of 20 pieces or a neat reusable tangle of pipes out of 15 pipe pieces. It just so happens that Unity has absolutely no support for nested prefabs, so if I would save anything like that into a prefab, I would lose prefabs linked to individual pieces and would lose a way to reliably update them. Anyway, long story short, I’m almost done with that - I’ve implemented a simple imitation of nested prefabs that works fine enough for the specific case of saving and instantiating a group of modular objects. It can be saved into a prefab but it keeps the child modular objects as prefabs too, which is neat.
Some additions left with that, but overall it works. I hope it will be easy to adapt the resulting chunks to work with the procedural level system I have outlined in the previous posts.
Another problem I have to tackle is recursive operations. It’s not an immediately obvious thing, but I’d like to be able to do stuff like rotation or detachment of pieces in the middle of a long connection chains, which every subsequent attachment being rotated or shifted in sync with their neighbours. This is hard to implement, but should be possible, and will make it easier for me to iterate through multiple designs quickly.
That’s it for this post, I guess. Future is looking bright.
I haven't had much free time over the last half a year so the development dragged on a bit (and well, what time I had, I often used on KSP modding). But the game is back on track now. I'll make a long post like in the old times a bit later, but for now, here is a picture for you.
Clickable, full res album here. It's one of the new environments I'm working on, using some new techniques I'll detail in later posts.
Having a 50km long staircase between you and the next level sounds exciting only for as long as you don't start climbing it. So, obviously, I needed a system in place that would allow you to skip the travel distance/time through some homogenous parts of the world, only stopping you for some rare random encounters (or if you think there could be an interesting place at a particular point). Sounds easy, but not so easy to implement. But it works now.
You can start it at any time near the central shaft provided you are not in motion (no exploiting to save yourself when falling), you can drop out of it at any time/be kicked out of it by mid-travel random encounter. On exit you will be placed onto a closest walkable platform and the time/distance you've skipped through will be properly logged. 100km tunnels can finally be crossed upwards in reasonable time instead of being strictly a place for skydiving. I should probably disable the mouse-controlled rotation completely and emphasize those stair-climbing feeds from the corner more, so that the player won't get the impression he's flying up on some jetpack.
I have also finally linked the transition level to normal levels properly, so the tunnel isn't infinite anymore and next levels upwards and downwards are seamlessly loaded as you cross the range covered by the tunnel. So, uh, sooner or later you'll splat on the ground, no more infinite loops.
In other news, I made a fancy flashlight with a cheap light scattering imitation. Has it ever bothered you how in every game with a flashlight you can just walk to a wall and blast it right into it, only to see a tiny white disk from the spotlight? To think of it, it's pretty easy to somewhat fix it.
I have a player with an animated main spotlight attached (which sways through animation). Every 1/10th of a frame I make a raycast from the spotlight forward vector to a maximum distance of spotlight range. If it hits anything, I move usually hidden point light object to that spot and offset it from the wall using hit point normal so that it won't be partially invisible. I then determine the intensity of that point light source using proportion between the spotlight range and the distance of raycast so strength of a scattered light changes depending on how strong spotlight itself was at this point. The result is multiplied by a value from 0 to 1 that I get by calculating dot product between raycast direction and surface normal.
So, if I hit a surface from an almost parallel direction, next to no scattered light will be shown, but if I hit it perpendicularly, scattered light will be at full intensity.
Additionally, of course, the spotlight has charge, can be toggled on and off, and has two focus modes that trade between range and spot angle - all those nicely tween the values instead of insta-switching them if triggered. Not the most important item, but certainly a fun part to dedicate some time to.
Okay, time for some actual features instead of endless environments. Take a look at this blueprint again. The levels are connected through tunnels of an arbitrary length. The distance between the levels is equally absurd everywhere, though, five kilometers being the very minimum. So, first:
There could be a system in place that handles exit triggers on each level, and on the player entering them, randomly loads the next one from the pool of available areas, then moves the player into a starting position on it. Absolutely trivial to implement. Absolutely disgusting.
I want the locations to be connected for real. I want it to be possible to actually walk the whole way from one place to another without a loading screen. I want my game to be used for Desert Bus charity marathons making gozillions of dollars. Among more trivial things, the system should also properly store and handle the whole chain of selected levels instead of randomly generating a new level ID every time you leave an area (so that you will be able to retrace your steps back to wherever you want), it should properly store the position of the player relative to the world and use it to hide all scene loading, it should store the velocity to make it possible to skydive through multiple levels should you trip on a staircase once, and it should somehow take care of precision issues that inevitably rear their head when you wander few thousands kilometers off the origin point of a level. Now that's something worth spending time on.
But first, being insufferably obsessive over that sort of thing, I just had to create a whole object set consisting of 15 modular stairwell sections that can be assembled into chains. Because, you know, testing any system with planes and boxes is bad for your health.
Then, I got the basics down and working. Here is what happens: there is an exit trigger on each level, which covers an entrance to a stairwell upwards, like this one:
As you start walking upwards a few tunnel sections and lose the area behind you from the view, you get a prompt telling you the estimated distance and time towards the next area (both levels in chains and distances between them are randomly generated once per playthrough and then saved persistently). The prompt asks whether you want to skip time to arrival at your destination You can do that, or you can continue walking upwards. Or, well, you can go find a stairwell going downwards, and jump into it - no prompts for you then, you're taking the trip whether you want it or not.
No matter what you choose, once you pass a few tunnel sections and lose the area you came from from the view, your position relative to a closest tunnel section is saved, a special next level loads asynchronously and your position is restored in it from the saved offset to make the transition seamless.
You are now within a procedurally generated tunnel.
If you have chosen to skip time to the destination, all you will see a distance/time data and a progress stat quickly climbing to 100% on your screen, while the camera repeatedly fades to black showing few short preanimated snippets of your climb in the background. Pretty trivial, and, of course, could be done with a tiny carefully organized level. No need for any need technical trickery. Just include only the environments seen during the cutscenes and you're done.
But nope, we're playing fair, and such a level will fall apart the minute player decides to walk up a few floors or decides he needs some skydiving. Not to mention that time skip mode could include much more interesting visuals - like a camera flying through the whole way on fast-forward. So we have to build a tunnel for real, spanning whole 27 kilometers or whatever the proper distance to the next area is.
We'll quickly run into a few problems if we'll attempt to do that. First of all, good luck compiling lightmaps for a 27km long tunnel filled with thousands of light sources and storing the resulting data. Second, good luck getting no physics precision issues and position artifacts as you wander such a ridiculous distance away from the level origin. Third, good luck making the loading of such a level unnoticeably short for the player. And finally, good luck making whole thing again and again if you want areas to have random distance from the neighbors.
Final problem can, of course, be solved by using just one level which you fill automatically with whatever amount of tunnel sections that's right for representing input distance. One transition will require 982 sections, another 126, another 2614, whatever, you can just keep adding them until you get the whole way done. Except all other issues still stand.
There is a neat way to sidestep them all at once. Look at this:
Here is what's happening here. The tunnel is an array of objects occupying a limited set of possible positions around the point of origin of the level. Once a player position exceeds a certain threshold relatively to the point of origin, few things come into motion.
Whole scene is offset back using the same distance threshold, which also happens to be a standard length of one tunnel section in a current modular set.
Farthest tunnel section in the opposite direction (e.g. array object 0) is destroyed.
All object references in the array are shifted by one position to account for the destroyed object and free one new slot in front of the player.
Random index is generated and used to select a tunnel section from a separate array storing all tunnel section types. The random selection is instantiated to an empty position in front of you and soon comes into view as you proceed forward.
Voila, now you can fall through stairwells for days without any precision errors, loading screens of gigabytes of lightmap data. The position resets and tunnel shifts are completely unnoticable because absolutely nothing changes relatively to your point of view. As you proceed forward (or backwards, whatever), the distance you have travelled is tracked appropriately, with corrections applied to account for your position being reset constantly.
After you clock the distance required to reach the next area (or fall back to where you came from), the next area is seamlessly loaded, your position is restored relatively to the closest tunnel section again, and you emerge into the next traditional level. Nice, eh.
As bonus, here are few more gifs, one with the entry prompt I'm considering and another with a small cutscene I put together.
As a follow up to the previous post. Made an illustration about the world, because saying "imagine an onion the size of a Dyson sphere" every time is a bit weird and isn't conveying the right image. Here's where all action takes place.
Obviously it's not physically possible to build anything like that without it collapsing into itself, but presumably the structure has embedded systems that bypass laws of physics to stabilize it - the original story mentions one of them called gravity mill, whatever that is. Another concern is amount of matter required to build such a structure. In the original story, there is an empty spherical room approximately the size of Jupiter where matter for the construction was harvested at one point - but harvesting every planet in the solar system wouldn't necessarily be enough to create something like this, so we can assume neighboring solar systems were stripped as well. And finally, the creating something like this will take quite a lot of time - but that is in abundance in canonical setting where control over automatic builders expanding the structure was lost many thousands of years ago.
Overall, it's a pretty good setting for a walking simulator to take place in. Enough space to walk for a few lifetimes.
Okay, time for some proper explanation on what this game is about. I tried writing a wall of text at first, but it got inconvenient quick, so here you go with an image. It covers the setting, the structure of the content that makes it feasible for me to make all the content myself, and so on.Click on it to get a full-size version with readable text.
They are done with a fresnel-based shader on cylinder shaped vertical and disk-shaped horizontal meshes, so you never see ugly intersections: when you observe the cloud ring from up high or from below, you see the disk shaped mesh at almost full opacity and cylinder based shape fades into nothing because of the angle you view it from - and in the opposide, when you are on the same level with the cloud layer, only the cylindrical part perpendicular to you is seen. Pretty neat.
Time for another environment study. This time, I tried to find an appropriate design for the gap between two layers of the megastructure. At 30km high, it will be one of the larger environments player has to cross - probably by finding an elevator or something.
It's a paintover, but most of the geometry is already in place. The surfaces are covered with an optimized unwrap and manually painted because I wasn't satisfied with precision of lightmaps there.
I have yet to add those darker parasite structures into the mesh, but majority of work on this particular background is done. I'd love to put more detail into animated elements, though - the clouds should scroll around, and static electricity should run around the "floor" and the "ceiling" in random directions. For now, though, I got static animation.
Made an attempt at modeling and texturing of a simple character. Not completely satisfied with results, but it's good enough and hopefully I'll be able to pull off some more complicated designs later. Even though doing complex character animations and action scenes is beyond my capabilities, few interactions with lone wanderers, someone like a trader, or other encounters of that sort are feasible to do as they don't have big requirements on the content. I should definitely make them, along with some more characters.
Aside from that model, got a quick a sketch of another character. Probably too human and not stylized enough for the setting, but anyway.
The environment should be all flat walls, of course. It needs lots of detail to look convincing. So I started making some props. First, you need a good texture atlas you can reuse over multiple objects, with enough pieces in it to be sufficient for props you want to make. There is nothing worse than an object that's using multiple materials when it was avoidable, both for performance reasons and because using one atlas is inherently more convenient. So, first I need some rubble and garbage for the floors. Here is the first set.
There is some space left in the middle of the atlas for adding more pieces as I figure out what's lacking, but even with this small set, you can already create some pretty convincing groups.
Pretty neat cracks and rubble. Next, some lights, because lighting up environments with some invisible sources is weird.
Good, no issues there either. And a final bit - I have discovered a very nice application for the Light Cookies functionality Unity light sources have. Point lights can accept cubemaps as masks, which I can exploit to get a very cheap imitation of occlusion by the frame surrounding the light. Finally, no overexposed ceilings glowing bright white under lights that don't even face them. Here is the cubemap and the results:
With background sorted out and tools familiar, I started work on the first proper environment for the project. It would be a tower situated in the middle of roughtly 15x15x2km room, reaching from the floor to the ceiling. The player will have to climb it to reach the exit. Pretty straightforward. And too big to be done within reasonable time.
Or not. All done within just a few days.
The trick to it is using modular approach, similar to the way Bethesda artists build their environments. The tower being the central piece of enormous size here, requires just such an approach. So, what I do is create a set of modular pieces, 45-degree sections of varied height, radius and purpose (carved out sections, lip sections, flat sections, inner tunnel sections, stair sections, and so on), overall a set of approximately 100 parts. And then assemble the final object from them, saving myself tons of time:
Next, I update the background using, again, a set of about 15 modular buildings to break up the flat shapes in it. Buildings use just one additional texture to provide black space for contrast and some nice high-frequency detail.
The geometry is pretty simple, but with proper textures and baked lighting, it really shines.
The environment is obviously not complete, with e.g. the whole ceiling being pretty much bare and untouched, but at this point I'm pretty satisfied with how much I was able to achieve in such a short time, and confident that my current workflow could really be used to make many more environments in a reasonable time. Confidence in that feels great.
With that in mind, I move on to make some other things before fully commiting myself to the drivel of creating 190230298004322984 additional environments.
With the fancy guns from the original story being impossible to implement (good luck coming up with a way to carve kilometer-long tunnels through detailed level geometry), we switch to the honorable genre of walking simulators. There are few issues to tackle before I start working on large environments properly, though. First of them is rendering long-range backgrounds.
Let’s start with admitting that skyboxes suck because you can’t animate them, can’t match their resolution with the rest of the scene and can’t tune their lighting dynamically, and proceed to using full 3d environments for the whole range of view distance. There are issues with that, though, and most importanty of them is the depth buffer precision. I want to make a game with first-person perspective with environments dozens of kilometers across, all within the render distance.
Guess what happens when you use a camera with 0.05-20000 range? Lots of Z-fighting, yeah. Thankfully, it’s pretty easy to solve. At first I experimented with Unreal Tournament style 3d background where whole thing is rendered by a separate camera rotations of which are replicated from the player, with said camera looking at a scaled down background environment. The background itself is situated on a separate layer so that the player won’t be able to see the scaled down piece floating somewhere. And I drafted out the first environment, because I just can’t bring myself to use boxes and planes to test stuff.
A few issues quickly became apparent, though, and I have switched to more efficient and simple setup: adding a secondary camera to the main first person one and tuning it’s depth settings to start where main camera depth ends (e.g. 1500m).
This way, I get no lag in rotation sync, and more importantly, I don’t have to manage player coordinates and replicate his scaled down movements within some remote room to get properly working parallax effects. Which is pretty nice, because when you climb kilometers upon kilometers up, the environment should really reflect the change of your position with differences in perspective. Another very important advantage is ease of environment design - you don’t have to work on two pieces separately but can instead build one large, integrated environment situated on one layer - which is pretty important, because I will need to make lots of environments.
A year ago I happened to land at a job as an environment artist in a studio that used Unity for multiple projects, and quickly got some experience of working with it. It’s a nice and very flexible engine, and with each month I grew increasingly more attached to it. CryENGINE will always have place in my heart for it’s “real time all the time” approach and incredibly optimized yet striking visuals, but Unity is just too good. Content I had to create wasn’t very exciting, though - mostly industrial stuff.
So, naturally, I started doing personal projects in my free time, using the same tools and further learning Unity.
Few months ago I started learning C#, having never touched code outside of some rudimentary mods before. To my surprise it turned out to be reasonably easy to use for my purposes, without any horrors of calculus or hard to memorize syntax I fully expected from the field. The experience of finally being able to make your own applications and to showcase and structure your content the way you want it, with full control, was pretty liberating. Finally, my environments weren’t stuffed into scenes made by someone else and controlled by code made by someone else. That’s a nice feeling.
And, obviously, I finally had an opportunity to do one thing that was always missing from my pretty rooms. With C#, I finally could just like make game.
After dissatisfying results with outdoor environments, I decided to try some working with a more minimal environment. Flat lighting, heavy grime on the textures, graphical shapes, toying with perception of volume, all that in small enclosed rooms. First, I needed some textures.
With some trim sets made in that aesthetic, I quickly created a small environment.
As you can see, it’s pretty easy to build some striking imagery and show volume in a style like that.
It looked nice. But it wasn’t an environment suitable for the game I had in mind. For Netsphere-based cutscenes, maybe it would be fitting, but it’s not a place that’s pleasant on your eyes when you’re walking around for hours. So I stopped the work on that scene too
With this direction discarded too, I dropped the project and moved on to do different stuff - post-soviet desolate environments inspired by Stalker, modern architecture visualization and so on, with the work on the The City environments abandoned about until few months ago. That concludes the recap of previous episodes, now we can cover the development of the current, Unity-based and very much alive version of the game.
First of all, lighting was a problem. Everything looked like a prop situated in some backyard and lit by the usual sun, not a a location within some megastructure. So, I dimmed the sunlight. I needed a way to highlight the geometry though, so it was time to use some local lights.
Next, dark areas. All empty space between the plates was effectively wasted and failed to hint at the size of the thing, so I made a texture filled with emissive lights to break up those spaces. Next, I made a semi-transparent derivative texture from it, something like a chatotic forest of structural armature, wires and blocks, which I then used to break up the otherwise borking silhouettes of white blocks.
Scene finally started coming together.
I toned the ambient lighting down even further and expanded the background, breaking up very simple shapes with emissive textures to provide illusion of rich detail:
It made for a few nice screenshots, but it wasn't satisfied with results. The scene was a whole lot of work just to get north and west background done (note how every single screenshot is facing into the same direction - there is nothing behind), for a very small playable area you could actually cross in a minute. The postprocessing, colored lighting and reflective materials weren't conveying the style I wanted.
And most importantly, whole scene was done in an early buiild of CryENGINE3 SDK, which made the prospects of turning it into a playable game pretty grim (considering bugs, lack of documentation, limits on vertex precision and overall state of most systems that were polished to work best for AAA shooters taking place in small closed-off environments).
I quickly lost enthusiasm to continue it further and started experimenting with more minimal scenes still inspired by Nihei style.
So, a development blog about some game. Where should I start from?
I'm an environment artist by trade and I always loved art of Tsutomu Nihei. The scale of his world, the architecture of environments he creates, the atmosphere of inhumane industrial hell he built were amazing and greatly inspired me.
So, few years ago I started by trying to copy some of his environments. It's not a very trivial task despite minimal style some of them are executed in. Even if some surface is composed from large plates with lots of white space, it still relies on sharp and tiny details to convey the sense of scale properly - human-sized doors, rust, leaks, power cables, staircases - they are always somewhere, and help a lot to give a clear visual difference between 10m high wall and 1km high wall.
So, I needed to come up with a workflow that allows me to use lots of detail over extremely large areas. Obviously, I can't just make a texture atlas with high resolution per square meter that will cover everything - either memory requirements will be insane, or the level of detail will be too low for good closeups and sharp silhouettes. I don't exactly have a megatexturing tech like lucky artists from id Software do, so it's not an option either.
Another thing to consider is amount of manual work. You have enormous area in need of the texture mapping work. You can't use greeble generators and simple algorithms like square division to fill your environment with detail - Nihei had quite a lot of irregular detail and non-repeating shapes in his environments, necessitating manual work on each wall if I want to replicate his style.
I started with a pretty simple approach of using three materials: one for white spaces, another for dark fills, and another containing trims and detail, like that one:
That texture set allowed me to start working on a small scene inspired by a page from "Noise". Here are first stages of work on it.
Not very pretty, but replicates the essence well enough and with sufficient detail. I continued working on it for a week or so. Over the course of that week I gradually expanded the wall.
As I progressed, few issues became apparent.
First, it still takes too much of my time with all the manual texture mapping necessary on every single edge, applying trim and doing other things. Second, seams often look out of place and don't blend with white spaces properly, being just neighboring faces with a noticeable border. Third, whole thing is a background that can't be appreciated by the player because the player has nowhere to walk.
To solve the latter, I started adding bridges and interiors allowing you to look at the structure from multiple points. Obviously, bridges must be nauseatingly narrow and have no handrails, otherwise it wouldn't be a proper Nihei environment. Something like that sketch.
Which turns into this:
Then, obviously, those entrances should lead somewhere. I quickly threw together a set of textures consisting of another trim set, concrete and some panels, and created some interior spaces:
At this point I'm increasingly dissatisfied with the direction it goes to. Wall panels look too organized, whole place lacks dirt and a touch of chaos, needs stuff like pipes and wires, - while base shapes, like wall supports, are in opposite, too detailed for their own good. I set out to do some improvement work on outdoors while figuring out how to fix that. Continued in the next post.