- 3D Environment setup
- From Render to Sprites
This is the page of YETI technical documentation. I will try to describe the methods I used to get to the final result, that being from setting up the 3D environment, all the way to coding the newGRF.
I hope it is going to be useful to anybody who needs to create something similar to what I am doing, or is just interested in the kind of behind the scenes thing.
3D Environment setup¶
I work with Autodesk 3DS MAX 2014, but the values written here probably apply to every other program too. I also started using blender. I try to have as many values be the same as possible.
Used units are meters.
For my scene, I picked that 1 game tile shall be 10x10 m large.
All [n | n | n] brackets below mean XYZ coordinates in metres with Z being up.
I use this scale for both max and blender.
First has been created a spline under 30° slope, setting the camera to Ortographic, and moving it along the spline until I got somewhat optimal result.
The resulting coordinates of the camera relative the the center point of the 4x4 industry are:
[41,9 | -41,9 | 34,211]
Camera Target is at the center point, so [0 | 0 | 0].
For Blender it looks like orthographic camera position does not seem to matter so I use the same position as for max. [41,9 | -41,9 | 34,211]
What is important in Blender is to set camera to Orthographic, with Camera Sensor set to Horizontal.
Key value is Orthographic scale. For 4 tiles 56,565 seems right.
I tested it with 4096x2048 resolution test render from NUTS and this should work nicely.
The global lighting is handled by a single sun, to be more speficic a VraySun with target position at [0 | 0 | 0] and the actual sun being at [5000 | 500 | 5000]
Sun uses default settings with intensity multiplier of 0,017.
Matting the background¶
In order to get transparent (alpha) background, it is necessary to create a "BLOCKER" around the industry.
For extra safety for specific cases when some industries have holes, I additionally use another blocker below the industry in order to make sure that the sprite is never transparent where it should not be, in case there are some holes in the model.
The blocker AROUND the industry gets following material:
The blocker BELOW the industry gets following material:
Note: you can also solve this by Vray properties of the object, I found the material approach more convenient.
Generally not much special is used for rendering apart from a few settings.
Main rendered size is 1024 x 1280. The 1024 is simply 4x256 which is the size of the 4 diagonal tiles, and the 1280 is just a safe size for tall buildings.
I render PNG sequences later loaded in After Effects.
Other 3D conventions¶
I use groups to separate lights/industries/helper objects/cameras to organize the scene properly.
I use one Multi/Sub-object material for every industry. This gives me easy orientation between materials, and the 24 max slots are enough for me.
From Render to Sprites¶
Here I will describe how to create usable sprites for the game. First I will show how to do separate animation, then we will cut the render into sprites.
If you do not intend to do animation, you can skip the next part and continue with Cutting into Sprites.
Creating separate animation¶
Because loading full sprites with animation takes a lot of space and results in gigantic GRF size, it is a good idea to try and separate the moving parts from the rest.
This has to be done in 3D studio already, I personally took the following approach:
- Move all animated objects into one group, for example 3X_ANIM
- I recommend freezing the ANIM layer with the option "frozen in gray" in order to see better what is animating and what is not.
- Animated also means objects which receive important reflections.
- Move all static objects into another group, for example 3X_MODEL.
- Select the group 3X_MODEL, right click in the viewport and select Vray Properties. Then give these object the following settings.
This makes sure that also the shadows get rendered, and the shadows will not have alpha, they will be 100% solid. We do not care how the shadows look since we are going to take them from the complete render, so we just need the alpha.
Note: Turning on receiving GI and Caustics would be more precise, but the difference in my cases have been so little so far, that I chose to reduce the size a bit more instead.
Creating the underlay sprite¶
To combine the animation into something which looks like the final render, we need an "empty" sprite below it. To do this I just make the ANIM layer invisible, and render the MODEL layer alone.
Note1: If you rendered the mask previously, you need to revert the Vray properties back to original in order to render the MODEL layer properly.
Caustics are optional if you need them.
Note2: in case of 3X Machinery Factory, I also turn off all of the extra lights (not sun).
Cutting into Sprites¶Things to consider:
- Industries need sprites as separate tiles
- Rendering images as separate sprites from 3D or After Effects makes them have some semi-transparent edges
It is now clear to us that we must cut the image into pieces in order to get the tile sprites properly. The issue is that normal methods would just cut it and leave semi-transparent edges. When the image would combine, there would be tiny sub-pixel dark lines between industry tiles.
-> we need PRECISE cutting mask which has no alpha on the tile edges. But how?
We can make After Effects output precise images by giving it precise masks from Photoshop (drawn by pencil for proper hard edges).
For my industries I use the following cutting pattern (each colour area is one tile sprite with the top tiles going all the way to the top of the image to ensure that no tall buildings are clipped out from the render):
- Create a new composition called TILE_CUT with resolution 1024x1280 (size of our render), and 128 frames long (length of our animations)
- Import the full rendered sequence of our industry and put it into the TILE_CUT composition
- Pre-compose the full rendered sequence and call the composition RENDER. Then duplicate RENDER inside TILE_CUT 15 times so we have 1 duplicate for every tile of our industry.
- Import our CUTTING MASK from Photoshop. While importing select to import the layer MASK 00 instead of importing the whole PSD image. (you will need to import 16 times, once per every mask layer)
- Add CUTTING MASKs to each of the RENDER compositions in TILE_CUT, then apply Alpha TrkMatte to each of the RENDER layers.
- Pre-compose pairs of CUTTING MASK + RENDER into new compositions, call those compositions by tiles - for example 00 etc. (I will call them Tile Compositions)
- Resize TILE_CUT composition to our final output size - 4096x704
- Carefully move the Tile Compositions around to get them to the position you need them for the final output. Select all Tile Compositions and press P to open position numbers. Make sure those numbers are exact, ie always ending with ,0 - otherwise the edges of tiles are going to have semi-transparent pixels again.
- Now you can go to TILE_CUT and press Ctrl+M to put the composition into render queue. Select PNG sequence with RGB+Alpha, and render your sequence where you want it.
more fiddling with RENDER¶
We have pre-composed the rendered sequence into one RENDER composition so that we can change it! Now we can import all of our industries into RENDER composition, add them their animating mask, add the Underlay, and then we can just swap between them in order to render the industry we need. There are definitely many ways to do this, you could have one TILE_CUT composition per industry for easier re-rendering for example. I chose this way though. Following steps show how to add all of our stuff into RENDER composition.
- Import UNDERLAY and put it into RENDER composition
- Duplicate our full rendered sequence in RENDER composition
- Import Anim Mask and put it into RENDER composition and put it above one of the full rendered sequences
- Set TrkMatte of that full rendered sequence to Alpha
- Make visible either the masked full render, or Underlay and render them separately. Note that Underlay only needs to render 1 frame - set that in TILE_CUT by going to frame 0 and pressing N (end).
- Bonus: use shy switches to make the unmasked full render and the mask in order to make them invisible in most cases
- Bonus: it is very helpful to create another composition I call PUT_BACK_TOGETHER which gets all Tile Compositions and puts them together so you can quickly see if your sprites are correct. You definitely do not have to do this but it helped me to check if and what is wrong in case of problems.
After all the hard work and setting things up, from 3D to postproduction, now we can go ask OpenTTD how it likes our sprites, and load them there. The NML Code documentation of YETI can help you with that