mattkimber / gorender

Go implementation of Transrender sprite renderer
MIT License
9 stars 2 forks source link

GoRender

A Go implementation of Transrender (https://github.com/mattkimber/openttd_transrender)

Concept

GoRender produces dimetric-projection sprites for games such as Transport Tycoon / OpenTTD from voxel objects in the MagicaVoxel file format.

The output is customisable so it can be used for other situations where similar dimetric sprites are required but more/fewer degrees of rotation or different sized sprites are needed. The defaults produce all files needed for both 8bpp and 32bpp OpenTTD sprites at 1x zoom, with masks.

Video Tutorial

If you prefer to watch a video to learn how GoRender works, there is a short tutorial on YouTube.

Usage

GoRender supports the following command line flags:

GoRender will look for a JSON palette file (default files/ttd_palette.json) on run - if this is not present it will exit.

The num_sprites flag from previous versions has been replaced by a new Manifests function.

Note that GoRender will only overwrite output files in the event the input file is newer than at least one of the possible outputs.

Manifest

The Manifest is a JSON file detailing which sprites are to be created and their details. An example manifest:

{
  "lighting_angle": 60,
  "lighting_elevation": 65,
  "depth_influence": 0.1,
  "tiled_normals": false,
  "size": {
    "x": 126,
    "y": 40,
    "z": 48
  },
  "render_elevation": 30,
  "sprites": [
    { "angle": 0,
      "width": 8,
      "height": 32
    },
    { "angle": 45,
      "width": 26,
      "height": 32
    }
  ]
}

The fields are as follows:

Rendering sprites to fit a particular game is a careful balance between widths, heights, and angle settings. The supplied manifest.json file will provide good results for OpenTTD vehicles when used with MagicaVoxel files measuring 126x40x40. house_manifest.json (and the accompanying house.vox) show how this can be adapted to produce different graphical layouts.

Slicing

Some games have limits on how large an individual sprite can be, but allow this to be worked around by assembling multiple sprites. GoRender offers slicing functionality to make automatic generation of these sprites easier.

Slicing is set up as follows:

For an example, see files/manifest_slice.json.

Supersampling

GoRender uses supersampling to improve the quality of rendered output. The default renderer uses a square pattern of double the output resolution. This produces "good enough" results over a wide range of input objects without adversely affecting rendering speed.

However in some situations you may want to use a different kernel, particularly when tiling rotated objects where the artifacts of the square grid will become obvious.

GoRender offers two samplers, set with the sampler manifest directive:

There are also two parameters which can be used to tune the behaviour of the renderer. accuracy increases the number of samples used to generate each output point. Higher values will cause a significant slowdown but improve the recovery of small details, especially when using the disc renderer.

You can also allow overlapping sample sets for adjacent output pixels. overlap controls how much sets overlap. If it is set to a value greater than 0, samples will overlap by this amount. If it is set to less than 0, samples will only be taken close to the centre of each pixel. Values in the range [-0.5, 0.5] produce the best results, although large positive values can be used to produce output with a gaussian blur pre-applied.

As an example of why you might want to use this, consider an example of rendering a chain link fence at small resolution. Overlap <= 0 will produce a "grainy" result in which individual links can be seen, whereas overlap >0 will produce a "smooth" result where the fence links resolve to a uniform transparent surface.

Falloff Adjustment

GoRender uses an "influence-based" renderer for its supersampling. Consider the case in which we have a square grid of accuracy 3:

* * *
* * *
* * *

If all samples contribute to the output evenly, this causes blurring and loss of small details. So the sampler gives more weight to values in the centre, giving a weighted sample grid more like this:

. o .
o O o
. o .

The default settings (since 1.4.0) are chosen to give a sharp falloff for detailed objects. This may not be desirable, so you can adjust how steep (or gentle) the falloff is by tweaking the falloff_adjustment parameter.

Here is an example of how changing falloff_adjustment affects the output:

Demo

To match renderer behaviour from 1.3.x, set falloff_adjustment to 0.5.

Lighting tweaks

There are several values in the palette file used for tweaking the lighting model. These are:

Colour expansion modes

Sometimes objects will be rendered with insufficient variety within a region of colour. You can increase the variety (at the cost of noisier sprites and inconsistencies between angles) by configuring the following:

Special palette colour properties

The following properties can be used to change palette range behaviour in the palette file:

Use the process colour (by default the range of pinks 217-224) to influence how normals are generated for very thin objects.