Graphic shaders
Above A simple box blur – functional and fast
If you missed previous articles or are new to graphic shaders,
here is a quick primer.
Multiple shaders work together in the graphics pipeline. Some
are programmable, some are locked to the hardware. We’re most
interested in two shaders in the pipeline – vertex shaders and
fragment shaders. These are the core of the OpenGL Shading
Language and the WebGL graphics pipeline. We’re going to focus
on fragment shaders in these tutorials.
GLSL (OpenGL Shading Language) shaders compile and run on
a wide range of platforms. You can apply what you learn to any
environment that uses OpenGL, OpenGL ES or WebGL. This means
you can use this knowledge for websites, three.js, iOS games,
interactive installations, Unity, openFrameworks, Processing and
many others.
What is a fragment shader?
This shader, which is typically the last in the pipeline, instructs
each fragment or pixel what colour it should be. It does this by
setting a value for fragColor in the code’s ‘main’ function. It’s
where we’ll create our photo filters, animations, effects and so
much more by manipulating the colours of the pixels.
Vertex shaders
Vertex shaders handle the processing of individual vertices.
They take a vertex as an input and return one as an output in a
1:1 mapping. Because we won’t be diving into manipulation of
2D or 3D primitives or geometry, we don’t need to do anything
with these to get started. Just know that it is the first step in the
pipeline and for now is essentially giving us a canvas to colour.
WHAT ARE
GRAPHIC SHADERS?
Shaders can be used to create advanced effects that are optimised
for performance
SHADERS
Select the Texture tab and pick an image you’d
like to use as a texture.
- You’ll see a sample shader code all ready to go in
the code window. Delete it, so that we can write
our own. - Type in this new code and press the black play
icon at the bottom of the window. This will
execute the shader code.
float blur = 5.0; // box blur strength OR box size
void mainImage( out vec4 fragColor, in vec2 fragCoord ){
vec3 total = vec3(0.0); // holder for the colour values
for (float i=-blur; i <= blur; ++i) {
for (float j = -blur; j <= blur; ++j) {
vec2 xy = fragCoord.xy + vec2(float(i), float(j));
vec2 uv =xy/iResolution.xy;
vec4 col = texture(iChannel0, uv);
total += col.rgb;
}
}
float area = pow((2.0*blur+1.0),2.0); // area of box
vec3 avg = total.rgb/area;
fragColor = vec4(avg, 1.0);
}
If all went according to plan, you should see a blurred
version of your image. So what did we do?
This blur effect is commonly known as a box blur.
There are many types of blurs, such as fast blur and
gaussian blur. Each one has a different approach,
but typically involve a process of passes or multi-
sampling. The simplest way to think of this effect is
that it averages the values of pixels nearby a given
pixel to blend them together.
We start out the process by defining a blur amount.
This sets the dimensions of the ‘box’ around the
pixel we will sample and then average. We set up
a total variable in order to store the colour values,