[埋込みオブジェクト:http://numb3r23.github.io/cgTalk/04_distancefields.html]
A note on the navigation:
space
for the next slidebackspace
for the previous slideleft/right
to jump to the next chapterup/down
to navigate in current chapterEnjoy!
]]>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
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
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)
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
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-axisdFdy
calculates the change of the parameter along the viewport’s y-axisfwidth
is effectively abs(dFdx) + abs(dFdy)
and gives you the positive change in both directionsThe 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:
mix
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!fwidth
once.fwidth
the variable you want to smoothstep
. Not the underlying coordinate – that’s a completely different change and would lead to a wrong-sized filterlength(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!
]]>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!
]]>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.
FILE_PATTERNS: *.frag, *.vert
FILTER_PATTERNS: "*.frag=./glslfilter.py", "*.vert=./glslfilter.py"
EXTENSION_MAPPING=.frag=C++, .vert=C++
(thanks the_summer)@class
to set the class name@namespace
to set the namespace – a categoryIf 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:
/** * 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.
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
Here’s what I found out:
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
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.
]]>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:)
]]>