Search code examples
glslshadercolormatrixcolormatrixfilter

How to implement a Color Matrix Filter in a GLSL shader


I would like to implement a Color Matrix Filter in a GLSL shader but couldn't find any documentation regarding this matter. I'm totaly new to the world of shaders (never coded one myself) so please forgive me if my explanation/vocabulary doesn't make mush sense.

Informations I could gather so far:

  • A color matrix is composed of 5 columns (RGBA + offset) and 4 rows

enter image description here

The values in the first four columns are multiplied with the source red, green, blue, and alpha values respectively. The fifth column value is added (offset)

  • I believe the largest matrices in GLSL are 4×4 mat4 matrices (excluding the 'offset' column)

  • The only mat4 I've seen implemented in a shader looks like this:

colorMatrix = (GPUMatrix4x4){{0.3588, 0.7044, 0.1368, 0.0},
                             {0.2990, 0.5870, 0.1140, 0.0},
                             {0.2392, 0.4696, 0.0912 ,0.0},
                             {0,0,0,1.0}
              };

Question:

  • How can implement one ? As stated above I've never coded a GLSL shader before and unfortunately I'm unable to provide an MCVE. I would love to see an example so I can learn from it.

Thank you

EDIT:

I'm working with Processing and this is the only example I've found of vertex and fragment shaders for color rendering:

colorvert.glsl:

uniform mat4 transform;

attribute vec4 position;
attribute vec4 color;

varying vec4 vertColor;

void main() {
  gl_Position = transform * position;
  vertColor = color;
}

colorfrag.glsl:

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

varying vec4 vertColor;

void main() {
  gl_FragColor = vertColor;
}

Solution

  • For starters I would try :

    Vertex:

    #version 410 core
    layout(location = 0) in vec3 in_vertex;
    layout(location = 3) in vec4 in_color;
    out vec4 color;
    void main()
        {
        const mat4x4 m=mat4x4               // RGBA matrix
            (
            0.3588, 0.7044, 0.1368, 0.0,
            0.2990, 0.5870, 0.1140, 0.0,
            0.2392, 0.4696, 0.0912 ,0.0,
            0.0   , 0.0   , 0.0    ,1.0
            );
        const vec4 o=vec4(0.0,0.0,0.0,0.0); // offset
    
           color    = (m * in_color) + o;   // transformation
        gl_Position = vec4(in_vertex,1.0);
        }
    

    Fragment:

    #version 410 core
    in vec4 color;
    out vec4 out_color;
    void main()
        {
        out_color=color;
        }
    

    Just change the #version, layout and input attributes/uniforms to meet your needs (currently it use default nVidia attribute locations for fixed pipeline)

    Now to convert image for example just render textured quad on <-1,+1> vertex coordinate x,y range.

    If your matrices or colors change inside fragment (for example as a result of some proceduraly generated stuff) than just move the transformation to fragment shader instead.

    You can also change the const to uniform (and move it above main) so you can pass custom parameters on the run ...

    In case you need a GLSL start example see: