Skip to content
Geraint White edited this page Mar 2, 2017 · 3 revisions

In Pycraft there are currently two renderers, one written in Python and one in C, you are able to switch between the two renderers in the settings menu (provided the compiled C renderer exists). The C renderer is recommended if possible as it is faster and better maintained, the Python renderer is kept to support Python implementations other than CPython.

The original renderer was written in Python and was very slow. We rewrote the renderer in C to increase the speed and in the process we restructured it to be much more efficient. This means the code is very different between the two renderers, the C renderer is much more logical and easy to follow, whereas the Python is very messy and confusing.

C Renderer

Compiling and Using

To compile the renderer run python3 setup.py build in the root of the repository. Then you should be able to go into settings and toggle the C renderer option on.

How it Works

This renderer is split into two main components, the lighting calculations, and the rasteriser.

Lighting

Three (theoretical) Z depth layers are considered when calculating the lighting:

  • 0 is the foreground, this is where the blocks in the map are located.
  • -1 is the lights layer, this is where player placed lights (and the sun) are located. The cave backgrounds are also here.
  • -2 is the background, this is where the rest of the background (and the moon) is located.

The entry point to the lighting calculation code is the create_lighting_buffer function in render_c_module.c. This function stores lighting values for the given position, size, lights, and map in the global LightingBuffer data structure:

typedef struct
{
    int current_frame;
    long width;
    long height;

    long x;
    long y;

    struct PixelLighting
    {
        Colour background_colour;
        float background_colour_lightness;
        int background_colour_set_on_frame;

        float lightness;
        int lightness_set_on_frame;
    } *screen;
} LightingBuffer;

This structure contains a buffer which stores several values for every pixel in the width * height of the structure:

  • background_colour: is the colour of the background (sky, caves and sun/moon blocks)
  • background_colour_lightness: the lightness value of this pixel's colour, this is generated by a heuristic and is only used for selecting the max colour value generated from overlapping lights.
  • background_colour_set_on_frame: used to indicate whether the two colour values have been set or not.

The code to generate the background colour and lightness values is lazy and will skip any values it knows will not be needed because they will not be used or are constant. It will only set values for pixels where the background is visible, and there is a light radius covering it. When the rasteriser comes to use the value, if it is unset, it will just use the constant sky colour.

  • lightness: the lightness value for this pixel (these are set for every pixel).
  • lightness_set_on_frame: used to indicate whether the lightness value has been set or not.

Rasteriser

This is

Python Renderer

Clone this wiki locally