I need a lookup table in a shader. The input values would be color values and the output other color values. Something like:

uniform float lut[256];

color = vec3(lut[int(color.r*255.)], lut[int(color.g*255.)], lut[int(color.b*255)]);

does what I need but certain implementations of OpenGL ES do not allow arrays with variable indexing so finally I've arrived to the conclusion that the most portable way is to have a 2D texture as the LUT. A texture of 256x256 could store many different lookup tables, each one (256 entries) in a single row.

In order to load a row in the texture (c++) I would use:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);

to store a table in the first row (I assume that internally in the texture I'd have the value repeated in R, G and B)

To fetch the LUT in the fragment shader I'd use texture2D(lut,vec2(index, constRow)) (index in the range 0-1 and constRow = 0 being the row in the texture where it is stored the lut).

Is that a reasonable way to implement that?

Update: In order to fetch values in the texture-LUT you need normalized indexes (0.0-1.0), so to access row 7 I have to index it as texture2D(lut, vec2(index, 7./255.)); From what I see the result is (or may be) an interpolation with the two other consecutive rows.

  • \$\begingroup\$ Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. \$\endgroup\$
    – Kromster
    Sep 1 '14 at 17:04
  • \$\begingroup\$ Sorry for the fuzzy question. I've edited it, hopefully it's clear now. \$\endgroup\$
    – Joan
    Sep 1 '14 at 18:14
  • \$\begingroup\$ If everything works, then what is the problem that you are facing? GDSE is not a "review my solution" kind of place. It's more like a QA ;) \$\endgroup\$
    – Kromster
    Sep 2 '14 at 5:39
  • \$\begingroup\$ I was asking for the case someone addressed the same problem with a different aproach (I though the problem posed was quite frequent). So far my solution is not as simple to implement as one would say at first sight, at least for me. \$\endgroup\$
    – Joan
    Sep 2 '14 at 10:10
  • 1
    \$\begingroup\$ Have you tried setting the texture sampling to GL_NEAREST for the texture? You just want to explicitly disable the bilinear filtering \$\endgroup\$
    – Steven Lu
    Sep 2 '14 at 15:00

Your normalization is not exactly correct. You need to note that the OpenGL standard says

A fragment is located by its lower left corner, which lies on integer grid coordinates. Rasterization operations also refer to a fragment’s center, which is offset by (1/2,1/2) from its lower left corner (and so lies on half-integer coordinates).

Therefore, the integer pixel coordinate (i,j) is located at the normalized coordinate ((i+0.5)/W, (j+0.5)/W).


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.