Category Archives: Tutorial

Using fwidth for distance based anti-aliasing

Analytic, function-based distance fields are great for drawing things procedurally in the shader. As long as you can combine a few function and model the distance right you can simply create sharp-looking geometrical objects – even complex combinations are possible. The following is also true for texture-based distance fields (sdf fonts), but I’ve decided to give distance functions the space they deserve.

2D portal, composed of 2D distance field functions

2D portal, composed of 2D distance field functions

One of the great aspects of these functions is that they can be evaluated for every pixel independent of a target resolution and can thus be used to create a proper, anti-aliased images. If you set it up right.

Instead of the usual circle example where the distance is simple the distance(coordinate, center) and create a diamond pattern:

Distance Field Diamond

Distance Field Diamond

float dst = dot(abs(coord-center), vec2(1.0));

Using a radius as a step/threshold we can very easily create “diamonds” in the size we like:

Diamond Step Function

Diamond Step Function

vec3 color = vec3(1.0 - step(radius, dst));

So far so good. what’s missing is now the antialiasing part of it all – the step function creates a hard edge. Enter smoothstep, a function that performs a hermite interpolation between two values:

y = smoothstep(0.3, 0.7, x)

y = smoothstep(0.3, 0.7, x)

If both values are the same, it boils down to a step. What we now want is to “blend” the diamond into the background, ideally on the border pixels (and therefor not wider than 1 pixel). If we had such a value, let’s call it “aaf” (= anti-aliasing-factor), we could smoothly fade-out the diamond into the background:

Diamond Smoothstep

Diamond Smoothstep

vec3 color = vec3(1.0 - smoothstep(radius - aaf, radius, dst));

Luckily most OpenGL implementations have the three functions dFdx, dFdy and fwidth:

  • dFdx calculates the change of the parameter along the viewport’s x-axis
  • dFdy calculates the change of the parameter along the viewport’s y-axis
  • fwidth is effectively abs(dFdx) + abs(dFdy) and gives you the positive change in both directions

The functions are present in >= GLSL 110 on desktop or >= GLSL ES 3.0. For es pre-GLSL 3.0 there’s an extension GL_OES_standard_derivatives that allows to enable the usage:

#extension GL_OES_standard_derivatives : enable

But how does it connect together? What we need is the effective change of the distance field per pixel so we can identify a single pixel for the distance field. Since we need this for both axis we can do this:

float aaf = fwidth(dst);

fwidth evaluates the change of the distance field, the value stored in the variable dst, for the current pixel – relative to it’s screen tile. The size of that change determines how wide our smoothstep interpolation needs to be set up in order to fade out the pattern on a per pixel level. The antialiasing fade can be used in numerous ways:

  • store it in the alpha-channel and do regular alpha-blending
  • use it to blend between two colors with a mix
  • use it to blend in a single pattern element

The whole shader boils down to this:

float dst = dot(abs(coord-center), vec2(1.0));
float aaf = fwidth(dst);
float alpha = smoothstep(radius - aaf, radius, dst);
vec4 color = vec4(colDiamond, alpha);

Selected remarks:

  • fwidth is not free. in fact, it’s rather expensive. Try not to call it too much!
  • it’s great if you can sum up all distances so that you can arrive at a single dst-value so you only call fwidth once.
  • give fwidth the variable you want to smoothstep. Not the underlying coordinate – that’s a completely different change and would lead to a wrong-sized filter
  • length(fwidth(coord)) is “ok”, but not great if you look closely. Depending e.g. on the distortion/transformation applied to the coordinates to derive the distance value it might look very odd.

Enjoy!

libSOIL

As I was working with libSOIL (https://github.com/smibarber/libSOIL for a mac makefile) an exception occured and I couldn’t load anything. Turns out, libSOIL is not OpenGL 3.2 core compatible. Main reason for this is the beautiful safety-net which I encountered in the function

int query_NPOT_capability( void ){
  ...
  if((NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ), 
      "GL_ARB_texture_non_power_of_two")){
  ...

This mechanism can be found elsewhere too. As this specific feature is definitely part of OpenGL 3.2 core the problem was easy to resolve (remove the check) and it works now as expected. Yay!

Doxygen and GLSL shader

As I’ve finished the documentation-madness I stumbled over my GLSL shader. Doxygen, _the_ documentation tool of choice, reads them (as they are very c-like) but dumps them rather unfancy. Doxygen is not only very flexible – it is also extensible with filters to process other languages.

Idea

Write a small filter, that pads every shader into a class and set a namespace that acts kinda like a category (e.g. class Gauss in namespace GLSL::FILTER::BLUR). The result is my glslfilter.py python-script.

Usage
  1. Make Doxygen aware of the filter and the newly supported file extensions. To do this, edit your Doxyfile:
    • Add FILE_PATTERNS: *.frag, *.vert
    • Add FILTER_PATTERNS: "*.frag=./glslfilter.py", "*.vert=./glslfilter.py"
    • Add EXTENSION_MAPPING=.frag=C++, .vert=C++ (thanks the_summer)
  2. If you want, add annotations to your shader:
    • Use @class to set the class name
    • Use @namespace to set the namespace – a category

    If you set no name, the script will use the bare filename and the default namespace is “GLSL”.

    Of course you can further document your shader with doxytags – they are fully processed by Doxygen. The only limitation here (blame my lazyness or my thought it just wasn’t worth it) is that you have to put the “class” comment (= the shader information) at the very beginning in one big blockcomment starting with /* or /**. But seriously – why would you comment it in any other way? ;-)

To better illustrate the procedure here’s a little GLSL fragment shader:

Example
/**
 * A simple 3x3 gaussian convolution filter, non-separated version
 * @author Sebastian Schaefer
 * @date 2012
 * @namespace GLSL::FILTER::BLUR
 * @class Gauss3x3
 */
#version 150 core

uniform sampler2D image; ///< the input image

in vec2 tex;	///< texture coordinated
out vec4 color; ///< the color output

/**
 * The main routine: read the 3x3 neighbours and multiply with kernel
 */
void main()
{
    ...
}

Click here to see how the above example can look like.

Download

Grab the filter at my github-repository github.com/numb3r23/glslAdditions
This page might get updated so please link to this page only, not the direct download. thank you!


edit: moved source to github

Mac: Automator Service for a Google popup

As I was documenting a big amount of source-code today, I ran into the problem of looking up some stuff in the web (OpenGL-SDK docs to be specific) while inside XCode. There may be better ways to do this, but I ended up seeing that service entry in the context-menu and thought – hey, why not make a service to look up that stuff?

Here’s what I found out:

  1. Create a new Automator Service
  2. On the top right, set “Service recieves selected text” in “any application
  3. Drop a “Run AppleScript” from the Actions Library
  4. Add the following text:
    	on run {input, parameters}
    		set theURL to ("http://www.google.com/search?btnI=I%27m+Feeling+Lucky&q=" & input & "&go=Go")
    		return theURL
    	end run
    	
  5. Drop a “Website Popup” from the Actions Library and configure it as desired

    I choose size & agent “iPhone” so it’s not too big but readable.

The selected text is searched by google and the first hit is opened (a.k.a. I’m feeling lucky). Good enough for my documentation problems as the service can be mapped to a global shortcut.

Integrating FXAA

Revently I’ve integrated Timothy Lottes extreme powerful Anti-Alising filter Fast Approximate Anti-Aliasing into my ph.d.-project (might be introduced later on…).  It didn’t really take a long time as the filter source is documented quite well.

As I already have a class CPostProcessor that takes a base image and filters it using a generic vertex- and a custom fragment-shader I’ve created a class CPPFXAA that applies the FXAA filter.

1. Setup

Before integrating the FXAA shader you have to set it up, meaning going through the first part of the downloadable header-file and choose the defines to what you need/want.

2. Texture to RGBL

This step is not really necessary, but I somehow ended up integrating it anyway. Instead of an alpha value the alpha channel stores the luminace: (for me: color.a = dot(color.rgb, vec3(0.299, 0.587, 0.114));).

3. FXAA filter

Disable blending (if it was enabled) and apply the filter: render a screen-aligned quad with a fxaa as a fragment-shader. Set the input image as your “BaseImage” and set the correct viewport dimensions (“screenwidth” and “screenheight”).

4. done.

That’s it.

 

I hope it works as good for you as it does for me:)