Search code examples
three.jsshaderfragment-shader

Three JS Palette Cycling Shader


I'm implementing a palette cycling shader in THREE.js (my first shader).

All is working so far, but I'm struggling in that fact that I'm:

  • Unable to pass a dynamically sized array of pixels into fragment shader
  • Unable to pass a dynamically sized array of palette colors into fragment shader

Full example: https://jsfiddle.net/dangarfield/Le4t7w60/265/

uniform int w;
uniform int h;
uniform int paletteSize;
uniform int[12] pixels; // Has to be fixed 
uniform vec4[3] colors; // Has to be fixed 
varying vec2 vUv;

vec4 getPixelColorFromPalette (int pixelIndex, int[12] pixels, vec4[3] colors) {
    return colors[pixels[pixelIndex]];
}

void main() {
    float wF = float(w);
    float hF = float(h);

    vec2 xyPos = floor(vec2(vUv.x*wF,hF-vUv.y*hF));
    int pixelIndex = int((wF * xyPos.y) + (xyPos.x));
    vec4 color = getPixelColorFromPalette( pixelIndex, pixels, colors );
    gl_FragColor = color;
}

Any ideas as to how to optimise this so that I don't have to be confined by fixed array sizes?

Thanks


Solution

  • All sorted. I just added the pixel and palette data as a THREE.DataTexture and did a lookup:

    Updated fiddle - https://jsfiddle.net/dangarfield/Le4t7w60/398/

    Final fragment shader:

    uniform int w;
    uniform int h;
    uniform int paletteSize;
    uniform sampler2D palette;
    uniform sampler2D pixels;
    varying vec2 vUv;
    
    vec4 getPixelColorFromPalette (int pixelIndex, int w, int h, vec2 xyPos, sampler2D pixels, sampler2D palette, int paletteSize) {
        vec4 pixelColor = texture2D(pixels, vec2(1.0 / float(w) * float(xyPos.x),1.0 / float(h) * float(xyPos.y)));
        float paletteIndex = pixelColor.x*255.0;
        vec4 color = texture2D(palette, vec2(1.0 / float(paletteSize) * paletteIndex,0));
        return color;
    }
    
    void main() {
        float wF = float(w);
        float hF = float(h);
            
        vec2 xyPos = floor(vec2(vUv.x*wF,hF-vUv.y*hF));
        int pixelIndex = int((wF * xyPos.y) + (xyPos.x));
        gl_FragColor = getPixelColorFromPalette( pixelIndex, w, h, xyPos, pixels, palette, paletteSize );
    }