GLSL Color LUT

Not sure if there is already a snippet for this, however I didn’t find one, so I’ll just post my code :slight_smile:


vec3 applyColorLUT(sampler2D lut, vec3 color) {
    float lutSize = float(textureSize(lut, 0).y);
    color = clamp(color, vec3(0.5 / lutSize), vec3(1.0 - 0.5 / lutSize));
    vec2 texcXY = vec2(color.r / lutSize, 1.0 - color.g);

    int frameZ = int(color.b * lutSize);
    float offsZ = fract(color.b * lutSize);

    vec3 sample1 = textureLod(lut, texcXY + vec2(frameZ / lutSize, 0), 0).rgb;
    vec3 sample2 = textureLod(lut, texcXY + vec2( (frameZ + 1) / lutSize, 0), 0).rgb;

    return mix(sample1, sample2, offsZ);
}

Usage:

correctedColor = applyColorLUT(myLUTSampler, color);

You can generate the default Color-LUT with this script:

from __future__ import division, print_function

import math
from panda3d.core import PNMImage

lut_size = 64
lut_cols = lut_size
lut_rows = (lut_size + lut_cols - 1) // lut_cols

img = PNMImage(lut_size * lut_cols, lut_size * lut_rows, 3, 2**16 - 1)

def to_linear(v):
    return float(v) / float(lut_size-1)

for r in range(lut_size):
    for g in range(lut_size):
        for b in range(lut_size):
            slice_offset_x = (b % lut_cols) * lut_size
            slice_offset_y = (b // lut_cols) * lut_size
            img.set_xel(r + slice_offset_x, g + slice_offset_y, 
                to_linear(r), to_linear(g), to_linear(b))

img.write("DefaultLUT.png")

The bigger the lut size is, the more precise the result will be. You should set WMClamp on the LUT-Texture, and also set the format to F_rgb16.

What is this usefull for?
I don’t know…

Tone mapping and colour correction come to mind as useful applications. :slight_smile:

Ah! Googled it now.

Thanks! :slight_smile:

I’ve made a small demo to show how to use LUT.

To make a Look Up Table texture:

  1. Make a screenshot (big enough to fit the lut texture, so 1024x??? or more)
  2. Open/Paste the screenshot in your favourite image editing program (eg. Gimp)
  3. Paste the default LUT at the top or bottom of the image
  4. Manipulate the colors of the image (hue, brightness, contrast, saturation, lightness, balance, levels, curves, posterize, desaturate etc)
  5. Cut the LUT out of the image and save it to disk

tobspr says to set the format to F_rgb16, but I have yet to find a way to save a png with more then 8bpp (other then the Panada3D PNMImage)

EDIT: I looks like I was wrong, and you can load a 8bpp png as F_rgb16 as long as it has no alpha, and also a program called Krita can write 16 bit png with no problems. Files updated.

EDIT 2: fix by rdb, now it uses textureLod
LUT.zip (225 KB)