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
hofk
December 15, 2021, 7:29pm
2
I am also just starting with shaders, see * discourse.threejs.hofk.de ShaderBeginner
Search the web
Is it possible to declare something dynamic sized inside shader? For example uniform blocks? I would specify size (or better, send it to shader) by another uniform so I know what are the boundaries. As GLSL miss pointers in it, I have feeling that...
opengl, glsl
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 );
}