Original image

Table of contents

Color palette light, what?

When you use a regular Light2D, Godot just increments the pixels' RGB values, whitening everything that is enlightened.

Regular light

If you create your own light shader, you control every light and shadow color, and every pixel will be in your color palette, it makes your game more consistent.

Color palette light

Create the project

First you need to create a new project in Godot, using GLES3.

Create new project

Download the assets

For this tutorial we will be using the PICO-8 color palette, so please download the assets file and decompress it into the project’s folder.

assets.zip contains a folder called “assets” with the following images:

Now your project’s file structure must look like this:

Project’s file structure

Reimport all 3 image assets as 2D Pixel.

Reimport as 2D Pixel

Create the scene

Create a new 2D Scene and add the Lospec’s PICO-8 example image to the tree and add a new Light2D.

Project tree

Then assign light.png as Light2D texture, and put its mode as Mix.

Light2D properties

Assign the shader

Select the “pico-8-palette-example-kingdom-of-nerea-in-pico-8-by-davit-masia” Node and assign a new ShaderMaterial and new Shader to it.

ShaderMaterial

Shader

Copy and paste the shader code:

shader_type canvas_item;

// Godot color palette light shader
// Author: Juan Colacelli
// Website: https://poopbits.com
// License: GNU GPLv3

uniform sampler2D color_palette;
uniform bool dark_mode = false;

vec4 getColorByMode(int index, int mode) {
  return texelFetch(color_palette, ivec2(index, mode), 0);
}

vec4 getColor(int index) {
  return getColorByMode(index, 1);
}

vec4 getLightColor(int index) {
  return getColorByMode(index, 2);
}

vec4 getDarkColor(int index) {
  return getColorByMode(index, 0);
}

int getColorPaletteIndex(vec4 color_to_find) {
  for (int i = 0; i < textureSize(color_palette, 0).x; i++) {
    if (color_to_find == getColor(i)) {
        return i;
    }
  }

  return -1;
}

void fragment() {
  vec4 pixel = texture(TEXTURE, UV);
  int color_palete_index = getColorPaletteIndex(pixel);

  if (color_palete_index > -1) {
    vec4 light_color = getLightColor(color_palete_index);
    vec4 dark_color = getDarkColor(color_palete_index);

    if (AT_LIGHT_PASS) {
      if (dark_mode) {
        COLOR = pixel
      } else {
        COLOR = light_color
      }
    } else {
      if (dark_mode) {
        COLOR = dark_color;
      } else {
        COLOR = pixel;
      }
    }
  } else {
    COLOR = vec4(1.0, 1.0, 0.0, 1.0);
  }
}

Now your Shader will have a new param called “Color Palette”, assign pico-8_light.png to it.

Shader param

The shader will search the original color index, and replace it with its equivalent light or shadow color.

Enjoy your new light!

Light mode

If you want to use the dark mode, enable in the shader’s params.

Dark mode param

Dark mode

Shader explained

“Color Palette” param has one image wich contains the original color palette color, and its light and shadow equivalences.

PICO-8 equivalences

Explore new options

If you change the “Color Palette” param for another image, you can use other palettes, or i.e an B/W style light image.

B/W mode

Source code

View full project source code on: GitLab