Gray Scale Filter

Functional Shaders: A Colorful Intro-Part4 Gray Scale

Rupert
3 min readSep 22, 2020

--

Rather than using the RGB or CMY color models to define grayscale, three other parameters are defined. These are hue, saturation and brightness . In a grayscale image, the hue (apparent color shade) and saturation (apparent color intensity) of each pixel is equal to 0. The lightness (apparent brightness) is the only parameter of a pixel that can vary. Lightness can range from a minimum of 0 (black) to 100 (white).

For our use each pixel is reduced to representing only an amount of light it’s intensity or luminescence information.

Missed Part 1?

https://medium.com/@rupertontheloose/functional-shaders-a-colorful-intro-b774affe69ad

Starting Point

https://www.shadertoy.com/view/tsccWr

Single Channel Gray Scale

Color images are stacked color channels, each of them representing value levels of the given channel. For example, RGB images are composed of three independent channels for red, green and blue.

Here is an example of splitting a color image into component values.

  • Left shows color channels stacked
  • Middle show isolated color channel
  • Right shows gray scale equivalences:
Breakdown of image components

We can create a gray scale effect by just using one color channel to represent all of the color channels. This is not the most accurate representation because we are throwing the data in the other 2 channels away.

// single channel gray scale

// texColor.rgb = vec3(texColor.r)

// same as above using above
// texColor = texColor.rrra; // red channel
// texColor = texColor.bbba; // blue channel
// texColor = texColor.ggga; // green channel

Average Gray Scale

Averaging the color channels is a more accurate for maintaining the data from the image but falls short with how our eyes see color. Simply averaging all three R,G,B primaries treats them as perceptually equal, which is not the case for the human vision system.

For information check out:

http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/POYNTON1/ColorFAQ.html#RTFToC5

// average gray scale

// float avg = (texColor.r + texColor.g + texColor.b) / 3.0;
// texColor = vec4(vec3(avg), texColor.a);

Weighted Gray Scale

Weighted conversion is the accepted way of doing a gray scale conversion. It uses all three color channels to create the image and shifts them for our sight. Some adjustments can still be made for different levels of brightness, display types, etc…

// weighted gray scale

// vec3(texColor.r * 0.3 + texColor.g * 0.59 + texColor.b * 0.11);

Using a luminous coefficient Vector 3 and dot product calculation as a scalar of texColor.

vec3 lumCoeff = vec3(0.3, 0.59, 0.11);
texColor.rgb = vec3(dot(texColor.rgb, lumCoeff));

You will find there are many ways to solve the same issue. Some are more efficient but that usually depends on platform and individual use case.

Completed Example

In the next article we take what we learned from creating gray scale to tint an image with Sepia Tone.

--

--