Jump to content

Color palette Filter


jkm
 Share

Recommended Posts

This isn't fully pixi related, but I'm looking to swap colors, limit color palette in images. I've had some success blindly painting color palettes and using Color Map Filter but I have no idea how it actually works.

Can someone point me in the right direction? How would I go about making a color palette that for example limits image's colors to 32 given ones?

https://pixijs.io/pixi-filters/docs/PIXI.filters.ColorMapFilter.html

I was able to copy some shaders from shadertoy that also manipulate colors, but for my use case dynamically calculated/painted color map seems like the best solution.

 

Link to comment
Share on other sites

Yep, its possible. You just need to look at the source:

https://github.com/pixijs/pixi-filters/tree/master/filters/color-replace/src

https://github.com/pixijs/pixi-filters/tree/master/filters/color-map/src

https://github.com/pixijs/pixi.js/wiki/v5-Creating-filters

https://github.com/pixijs/pixi.js/wiki/v4-Creating-Filters

Use this to understand how to put custom filter in your app:

https://pixijs.io/examples/#/filters-advanced/pixie-shadow-filter.js , 

https://pixijs.io/examples/#/filters-advanced/custom.js (filter source is here: https://pixijs.io/examples/examples/assets/pixi-filters/shader.frag)

Anyway, many things to read, few things to code.

Link to comment
Share on other sites

Thanks :) I sort of got a pallet limiter shader working. It's probably a monstrosity but it works. Code below in case someone ever finds it useful.

For now I'm hardcoding each color into the fragment shader because I've had a lot of issues passing vec3 uniform into the shader and iterating it. 

 

import { Filter } from 'pixi.js'
import { defaultVertexShader } from './shaderDefaults';

export class PaletteLimiterBuilder extends Filter {
  constructor(palette: RgbColor[]) {
    super(defaultVertexShader, buildFragmentShader(palette));
    console.log(this.program.fragmentSrc)
  }  
}

const buildFragmentShader = (palette: RgbColor[]) => {
  let parsedPalette = ``

  for(const {r,g,b} of palette){
    parsedPalette+= `TRY(${r/255}, ${g/255}, ${b/255});\n`
  }

  return `
  precision mediump float;
  
  varying vec2 vTextureCoord;
  
  uniform sampler2D uSampler;
  
  uniform vec4 filterArea;
  
  float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); }
  
  float compare(vec3 a, vec3 b) {
    a*=a*a;
    b*=b*b;
    vec3 diff = (a - b);
    return dot(diff, diff);
  }
  
  void main(void)
  {
      const float pixelSize = 0.5;
      vec2 c = floor(vTextureCoord.xy / pixelSize);
      vec2 coord = c * pixelSize;
      vec3 src = texture2D(uSampler, vTextureCoord).rgb;
  
      vec3 dst0 = vec3(0), dst1 = vec3(0);
      float best0 = 1e3, best1 = 1e3;
      
      #	define TRY(R, G, B) { const vec3 tst = vec3(R, G, B); float err = compare(src, tst); if (err < best0) { best1 = best0; dst1 = dst0; best0 = err; dst0 = tst; } }    
      
      ${parsedPalette}
      
      #	undef TRY	
  
      gl_FragColor = vec4(mod(c.x + c.y, 2.0) >  (hash(c * 2.0 + fract(sin(vec2(1.0, 1.7)))) * 0.75) + (best1 / (best0 + best1)) ? dst1 : dst0, 1.0);
  }
  `
}

export interface RgbColor {
  r: number
  g: number
  b: number
}

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...