Reverse engineering procedural generation in No Man's Sky
No Man's Sky is a game about space exploration, which uses procedural generation technology of the game environment and resources (textures, models, relief, etc.). I was delighted when they announced its development in 2013, not only because of the game itself, but mainly because of the opportunity to study the game files and find out how it works. After the release, the game received the most controversial reviews, but I still wonder what is happening inside it.
If you install the game, you will see that in terms of volume it is very small, and this is true. The main reason for this is that the game works with a very limited set of resources and, using procedural generation, creates literally hundreds of options based on them. I will focus on the content associated with the 3D-models of the game, because for me they are always the most interesting. The article will be divided into three main categories: geometry, textures and animations.
Geometry
So, in the game, geometry files (vertices, index buffers, etc.) are stored in files with the extension ".GEOMETRY.MBIN". Already using these files, you can create fairly simple parsers that convert geometry to work in 3D modeling software. But this file is not enough by itself. This geometry file is used as a container for pure geometric data.
')
The game loads resources as scenes. This means that all model resources are defined as files of individual scenes with their own hierarchies of objects, several parts of grids, several types of objects (hinges, light sources, interaction points, collisions, other scene files), etc. This type of information is stored in ".SCENE.MBIN" files. They are real descriptors of a particular scene, and usually such files refer to one geometry container, from which all parts of the grids in the scene receive the relevant information about the geometry.
So far, this is nothing new. The same situation in many different games. No Man's Sky is different from other games (at least, I have never come across this before) because in this scene file there is not just one ready-made creature that can be spun in a game under certain conditions, procedural generation comes into play.
I will briefly explain how this looks by attaching several images from the NMS Model Viewer that I created.
Triceratops Model
As you can see, at first glance, the scene is a complete chaos, you can not even say exactly what we see. Of course, such a model cannot be spawned in a scene.
The most important thing in this data is the actual names of the objects. You can clearly see that there is a definite connection between them and the way the game learns how to combine these parts and eliminate unnecessary parts when creating the model.
Noticing this, I began to look for other files that can control the organization of the scene, and it turned out that these are the ".DESCRIPTOR.MBIN" files. Not all models have such files. It turned out that only procedurally generated models have them, and static models (such as an astronaut model or materials created for the trailer) do not have them.
I began reverse engineering the NMS file format by parsing these descriptor files. But at that time they seemed to me some kind of porridge, I could not understand what they were doing. After parsing the scenes, I already realized what to look for and returned to these descriptor files. They are very similar to scene files. They use the same way of defining parts and everything else, but they can only refer to other parts of the grids or entire scene files. These files work as follows:
The procedure is as follows: there is a main part that decides what it will be, in our example it is _HEAD_. Usually parts whose names begin with an underscore mean that they belong to a group of descriptors and only one of them will be selected for the final model. As you can see, this part is defined in the TkResourceDescriptorList list. Its elements contain the “Descriptors” property, the child elements of which are candidates for selection. Next you just need to select one of the child elements of the Descriptors property. For example, a head model is selected. After selecting this particular head model, there is another “Descriptors” property, which has its own list of possible options, and from this one must again choose one. And so on.
After performing these operations for all elements in the descriptor.mbin file, we end up with a set of selected parts, from which a unique complete model is created.
SHARKRIG Example
Fighter exported from No Man's Model Viewer
Guardians
The whole procedure is actually a traversal of the tree tops. The root node is a scene with all the parts, and at the end we get a unique branch of the tree, which is a complete model with the necessary parts.
The most important in this procedure is the method of selecting the part. If you look closely at the XML code presented above, you can see that each part has the “Chance” property, but quite a few parts have a value of 0. I think that the real probabilities of selecting parts are either determined by the engine when the game is executed, or are set to other game parameter files. In my model viewer, I randomized the selection. All parts have the same probability of choice and this leads to the appearance of rather different models.
Random generation of creatures based on the Triceratops model
Procedural generation of fighters (cubes are unmapped decals)
Procedural generation of boarding boats
Procedural generation of SHARKRIG
I spent about 70 hours in the game, and in all this time I have never met a creature that looks like diplodocus. This means that either the engine contains an error and these parts are not selected (which I doubt), or the probability of choosing these parts is so small that they rarely appear in the game. A lot of discussions (mostly angry ones) touched upon the missing content and content that is present only in game trailers, as well as related topics. I can not judge the work of the game or the gameplay possibilities, but judging by the number of creature models I studied, there are a lot of content in the game, which due to engine (?) Solutions does not appear very often (or does not appear at all) in the game. In my opinion, procedurally generated models of diplodok are 10 times better than static ones, and if the developers wanted to, they could force the engine to load static models (and, of course, all the content from the trailer) at any moment, so this is good or bad, but This is most likely a design decision.
Diplodocus model from the E3 trailer
This is how the main part of the procedural model generation works. This is a very elegant and reasonable procedure, because artists can very conveniently add new content for procedural generation. In fact, as each new part is added, the number of combinations increases exponentially (if this part is available on all tree paths). As far as I know, two or three artists worked on the models for the developers. A brainstorming fact about procedural generation: if they doubled the number of people working only on this part of the work, the game content (concerning creatures) would be hundreds of times more. And this fact alone proves the capabilities and potential of the NMS game engine.
Textures
Textures are another complex aspect of NMS models. As I mentioned in the “Geometry” section, all parts of the grids are defined in the SCENE.MBIN files. The elements of these files look like this:
As you can see, there are several attributes that I will not describe now, and I will only talk about the latter. It defines the material used for the mesh. As you can see, this node refers to the material file to be used. Let's look at this material file:
An important part of the content files is the “Samplers” section. Obviously, this section defines the textures used in the model part. And what is interesting: for static models, all textures are very high-quality textures, which can be used directly on models without any problems. But if the grid is used for a procedurally generated model, only the normal texture is correct. The diffuse texture, which contains all the color information about the part, is an empty white texture.
At first I decided that all the colors and textures are also selected when playing the game, but in reality this is not the case. These texture files are always accompanied by the ".TEXTURE.MBIN" files, which, as you might guess, work exactly like model descriptor files. They determine how to combine textures to create the final diffuse texture of the model. The artists of the game not only created different parts of the models, but also painted many different textures for each part. Therefore, by traversing this file in the same way as by the descriptor file, you can calculate the final diffuse texture of the procedurally generated model. Moreover: even if two models are the same in terms of geometry, thanks to procedural generation of textures, they can have completely different colors, marks, shapes, etc.
Sample texture with stains
Details of the texture during procedural generation can be very different. It seems that the textures are created in layers. I will show an example of assembling a procedurally generated creature texture. Usually the bottom layer is the base texture, which adds the main color and shade of the model (the names of such textures end in .BASE.DDS). On the next layer is the texture of the underbelly (.UNDERBELLY.DDS), which adds detail to the belly of the animal. Then there is another layer that adds more detail to random parts of the model (.UNDERLAYER.X.DDS). Then come the markings (.MARKINGS.X.DDS), which determine the most visible details of the skin of the model. On the next layer, there are again skin details located on top of the marks (.SKIN.DDS), and on the last layer another texture is applied (TOP.X.DDS), adding details to the individual parts of the model.
It seems that the maximum number of layers in procedural textures is 8 (usually 5 or 6 is used). Obviously, there are many textures that need to be mixed together. Therefore, all textures are accompanied by a corresponding mask texture containing the necessary information about the alpha channel so that the blending is as accurate as possible. Most often, the textures are also accompanied by a corresponding normal map, which creates details on each part.
But all this chaos with textures is not enough, even with all the mixes the final texture does not have the correct coloring. And the developers came up with another ingenious technical trick. They wanted the creatures to have a color that matches the colors of the medium, and implement it in the game using palettes. I am not 100% sure how they work in the game, but I will describe what they do in my opinion. I applied my method of implementation in the viewer, and, apparently, it is quite accurate.
FURPALETTE.DDS
PAINTPALETTE.DDS
So, in the process of creating a planet (or creating a star system) certain colors are chosen that will be used for the living beings of the entire planet. I’m talking about color choices, because game files have specific 8 × 8 color palettes (in the PCBANKS / TEXTURES / PALETTES folder). These palettes probably make up different forms. This means that the 64 colors contained in the palettes are usually combined in groups of 4 or 8 colors. Therefore, when the game creates the environment of the planet, it selects from these groups, which will be used later. These groups are easy to identify by looking at the palettes, because they are actually a gradient of two boundary colors.
Indexing in the selected group is performed with the information contained in the .texture.mbin file. The description of the texture in such files is as follows:
Again I will not talk about what the other options do. We are concerned only with the description in the Palette property. From the information in this property we can find out which color we need to choose for the part. In our case, it can be seen that the index of the “Fur” (fur) palette (which, as we saw earlier, consists of groups of 4 colors) is required, and in the selected group we need the color “Alternative1”. This is how colors are indexed in palettes. These values ​​of the “ColorAlt” property can be equal to “Primary”, “Alternative1”, “Alternative2”, “Alternative3”, etc. So, primary will be the first color in the group, alternative1 - the second, and so on. Here I am also not 100% sure, but I use the palettes like this, and this is logical, based on the principle of color groups in the palette.
So, we have one base color for a particular texture, what do we do with it? You just need to multiply it by the color of the texture. Usually gaming textures by default have a bluish color that looks neutral. After multiplying by the color of the palette, the texture gets the desired saturated color.
Again, this operation is performed for each individual texture applied to the model. In total there can be 8 of them, we get them, combine them with suitable colors of the palette, mix layers from bottom to top and apply to the model.
Thanks to such combinations of textures, diffuse textures can be very different and geometrically identical models can have completely different skin. Such a technique of procedural generation of textures along with procedural generation of models is enough to give the generated models a unique appearance. As I wrote above, if artists worked only on adding layer variations and more detailed color palettes, the resulting world would become richer and more detailed.
Animations
Triceratops skeletal animation
Astronaut walk animation loop
Slow walk animation of a procedurally generated Spiderrig model
Honestly, I didn’t explore animation in as much detail as geometry and textures. All I did (and it was not as simple as it seems: P) - performed the parsing animations and successfully reproduced them in my model viewer. In this category, too, there are many interesting and unique details.
First, the skeletons of the models are defined in the “SCENE.MBIN” files. They represent a hierarchical system of hinges, to which parts of models are attached with the help of vertex skinning. There is nothing surprising. It is interesting that, as I mentioned in the “Geometry” section, there are many parts of grids in the SCENE.MBIN file. Therefore, to control the animation and movement of all these parts, the assigned hinge system affects all parts of the scene.
Animations work the same way, they animate the entire skeleton, even if not all hinges are used for the final generated model. At first glance, this seems like a waste of resources. In fact, the only waste is here the parsing of the entire animation file. When playing a game, the MBIN SCENE and GEOMETRY files provide enough information to load only the data needed for each specific part of the model to the graphics processor.
Playing the game, I understand that there is a final generation procedure that processes the articulated skeleton. Somehow the engine can change the skeleton. Lower the model's center of gravity, make the legs longer or shorter, change the size of the head, etc. I didn’t explore it long enough to figure out how this is controlled, but I know that this is happening, and it adds a completely new dimension to the procedural generation of creatures, because it is a way of changing the final shape of the model. In fact, the final form can be changed to such an extent that it will not resemble the basic model. In addition, the necessary inverse kinematics calculations that must be performed to apply old animations to a new articulated skeleton, lead to a change in animations. Such a change can make creatures look completely different.
findings
I tried to explain how the game works, as I understand it after three weeks of work. I focused on generating creatures, but the same principles apply to other aspects (ships, NPCs, buildings, plants). When I started working with files, everyone was fascinated by the game, looking for novelty and diversity. Weeks passed, and the game began to be considered monotonous. The question is: was the procedural generation of usage in the NMS worth it?
There is no clear answer to this question.
As a software developer and reverse video game developer, I answer: yes, it was definitely worth it. From a technical point of view, I have never seen game mechanics that are similar to the mechanics of NMS, and I doubt that I will see in new games using procedural generation technology. Because no one will try to create fictional worlds with such a level of randomness. Technically, No Man's Sky has become a real treasure , and everyone who tries to deny it simply lies to himself, or does not know how the game works (or is not interested in it). The game engine has a lot of potential, and I constantly think about what the game could be if the engine were in the hands of a large game studio. Even with the limited resources, I still like the variety of creatures that I see in the game (and I believe that with the help of finer tuning we can squeeze even more of the available resources).
My feelings as a player are contradictory. Although this is not my style of play, but from the very pre-order No Man's Sky, I knew that this would be a game in which I could just relax. Study the environment, plants and animals. At first they all look the same, but if you look closely, we will see differences in most of them. Maybe only textures are different, but they are different: it can be a small horn on the head of a creature, or different spots, or a different part of the ship. Content is in the game (even the gameplay that developers would be able to spawn if they wanted to) can not be said to be absent. All that we get is the result of an extremely good generation procedure. In fact, the content created by the NMS engine for a system of 2-3 planets far exceeds the resources that can be seen, for example, in ARK. Of course, no creatures will be completely perfect, like dinosaurs in ARK, but this is their charm. That engine can create luxurious and majestic creatures, and at the same time - the most obscure animals that were in computer games.That's why I bought this game, and why I love it. I live for those moments when, after exploring various tedious nonsense, I suddenly land on the most beautiful planet I have ever seen. Again, I don’t compare RPG elements or gameplay features. I am only talking about procedural content. This does not mean that the game could not be better. I believe that I could, and I expect that the developers will improve it.
In the end, after all my research, I know that the game has enough content to at least create everything in a new way on every planet, so I can't blame the game or the engine. I can blame the configuration and configuration of the engine. I can also blame the damn multi-platform releases and the publisher. I’m sure on 100000000000000000% that the developers were forced to rush in with the release of the game. The game we got is far from complete, and does not even come close to 80% of the capabilities provided by the engine. After studying the files it is absolutely clear to me.. It is closer to the technical demo, and not to the game. Attempting to shove the same content on PC and PS4 simply tore the game, and the desire to make it work on weak machines further reduced the quality. Personally, I am waiting for updates, and there should be a lot of them . I can forgive a lot of Hello Games errors when releasing a game, overpriced, lack of communication with consumers, even the lack of many features (for example, a multiplayer mode, which, frankly, I don't give a damn). But even with the confusion and stress before the release, I can not forgive what they could not fully show what the engine with the correct configuration is capable of. Modders are now immersed in the jungle of files and are trying to find ways to create the same enginemore rich and diverse content. And most often they get it, because the engine can provide a much better game. All of these options should be available to any player, not just modders. Obviously, the developers decided not to give players such an opportunity that they all were in the same universe and could have common points of the route, creatures and planets. But they should have left such an opportunity. Focus on a single player game and show all players what the engine is capable of.
For some reason it seems to me that sooner or later HG will do that. They can not just forget more than four years of work on the engine, which is actually remarkable. And to all fans of conspiracy theories about Hello Games, I can say that developers had a thousand ways to get your money, and if they had such a desire, it could have happened much earlier.
Even before the game engine becomes so beautiful ...