Palette Cycling Shader - Fixed shader array sizes

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

I am also just starting with shaders, see * discourse.threejs.hofk.de ShaderBeginner

Search the web

That works,


uniform float u_radiusArr[ 100 ];
uniform int u_circleNo;

           for( int i = 0; i < u_circleNo; i ++ ) {
            
                aCircle[ i ] = 1.0; // visible

but loops in the shader are not performant.

Thanks, I’ll have a look.

For the palette itself, I’m dynamically creating a single line (n x 1px) THREE.DataTexture image, attached it as a uniform and then did a texture2D position lookup to get the color value. So, that’s seems like a much better solution.

Undoubtedly, I can do the same for the pixel data, but this is essentially jus a single array of ints, so I’d have to do the same but just set and lookup the values for the red channel etc, but I’d prefer to just send a lot less data. I’ll keep researching. Thanks

Update fiddle - https://jsfiddle.net/dangarfield/Le4t7w60/360/

All sorted. I just added the pixel data as a texture anyway and did a lookup:

Updated fiddle - THREE Palette Shader - JSFiddle - Code Playground

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 );
}