FXAA Shader

Tweet glsl shaders code-archives
(Posted 3 years ago) RonTek

FXAA shader for OpenB3D. Tested on BlitzMax-NG with latest OpenB3DMax version (5/18).


Setup where width/height is your screen width/height resolution... (see blur2pass example)

Local shader:TShader=LoadShader("","../glsl/default.vert.glsl", "../glsl/fxaa.frag.glsl")
ShaderTexture(shader,colortex,"sceneTex",0) ' Our render texture
SetFloat(shader,"rt_w", width)
SetFloat(shader,"rt_h", height)
ShadeEntity(screensprite, shader)


// FXAA (Fast approximate anti-aliasing)
// OpenB3D version by RonTek
// www.blitzcoder.org

uniform vec2 resolution;
uniform sampler2D texture0;

uniform float rt_w; // render target width
uniform float rt_h; // render target height

void main( void ) {

    vec2 texCoords = gl_TexCoord[0].xy;

    resolution = vec2(rt_w, rt_h);

    float FXAA_SPAN_MAX = 8.0;
    float FXAA_REDUCE_MUL = 1.0/8.0;
    float FXAA_REDUCE_MIN = 1.0/128.0;

    vec3 rgbNW=texture2D(texture0,texCoords+(vec2(-1.0,-1.0)/resolution)).xyz;
    vec3 rgbNE=texture2D(texture0,texCoords+(vec2(1.0,-1.0)/resolution)).xyz;
    vec3 rgbSW=texture2D(texture0,texCoords+(vec2(-1.0,1.0)/resolution)).xyz;
    vec3 rgbSE=texture2D(texture0,texCoords+(vec2(1.0,1.0)/resolution)).xyz;
    vec3 rgbM=texture2D(texture0,texCoords).xyz;

    vec3 luma=vec3(0.299, 0.587, 0.114);
    float lumaNW = dot(rgbNW, luma);
    float lumaNE = dot(rgbNE, luma);
    float lumaSW = dot(rgbSW, luma);
    float lumaSE = dot(rgbSE, luma);
    float lumaM  = dot(rgbM,  luma);

    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));

    vec2 dir;
    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));

    float dirReduce = max(
        (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),

    float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);

        dir = min(vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX),
          max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
          dir * rcpDirMin)) / resolution;

    vec3 rgbA = (1.0/2.0) * (
        texture2D(texture0, texCoords.xy + dir * (1.0/3.0 - 0.5)).xyz +
        texture2D(texture0, texCoords.xy + dir * (2.0/3.0 - 0.5)).xyz);
    vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
        texture2D(texture0, texCoords.xy + dir * (0.0/3.0 - 0.5)).xyz +
        texture2D(texture0, texCoords.xy + dir * (3.0/3.0 - 0.5)).xyz);
    float lumaB = dot(rgbB, luma);

    if((lumaB < lumaMin) || (lumaB > lumaMax)){
(Posted 3 years ago) markcwm commented:

Wow thanks Ron!

I was thinking the blur shader would maybe do for AA but this is better especially if it's fast.

I'm just going to be an old lazy bones and ask how to we set the AA samples level? That is, how do we increase the blur amount?

You may know that Angelo added an AA function to the latest Openb3d, I'm going to upgrade to that in a few months after I get a few other things done.

(Posted 3 years ago) RonTek commented:

Sure thing! Yes, actually this method does resemble blurring but I agree it does seem to be much faster.

That is great to hear and I do prefer built-in gl functions (MSAA) or gfx card supported compared to shader solutions like this when it comes to AA even if it is a bit slower. They say this is faster than multi-sampling, but the whole scene blurring part is really a downside for me.

As for the sampling, this is more of a fixed, simple and older version and I do see modern implementations (FXAA 3.x?) where you can set quality and edge threshold. We could also probably look into that next.

Nice! looking forward to the AA update and I hope it is somehow similar with MiniB3D.

(Posted 3 years ago) markcwm commented:

Hi Ron,

FPS is a bit low on my rig compared to other fast shaders like pixelate but it's real AA and not blur, though the difference is subtle, so it is ideal if you just want to remove jaggies. Yes, multisampling was pretty slow on Minib3d which is why Angelo removed it from Openb3d, it seems he's added MSAA but I haven't found the render code yet.

I just uploaded the FXAA shader to my repo and having looked at it I think there is no need for more sample levels, the purpose is only to remove jaggies, so there's no real need for a more complex shader.

Btw, I had to edit the frag code a bit to get it to build!

Thanks again.

(Posted 3 years ago) RonTek commented:

I see and sounds good. Btw, I have updated the code with a more recent version since the previous one was designed to work with the older openb3d version. There are some changes, but pretty much the same method.

Yes, about the repo and I was wondering where can I find the latest examples. I have noticed recently that they were not included in the latest commits anymore and I got my set from way back. I did find some issues now which I have to post on a separate thread.

I did checkout how MSAA works with MiniB3D but could not find any trace from OpenB3D, only the empty functions though. If I'm not mistaken, MiniB3D's version works by adding another extra RenderWorld function and switching to that when AA is enabled. It seems to be straightforward, but I'm not sure how it is compatible with OpenB3D or if it used the same before, never tested it out as I was not aware it was supported earlier.


(Posted 3 years ago) markcwm commented:

Hi Ron,

well you had varyings not found in default.vert. I just added them to main. I think I prefer your changed version now so thanks!

I move all examples to a separate repo because they took up a lot of room particularly media, it's called openb3dmax.help

The anti-alias in Minib3d used the Accum buffer and wasn't MSAA, which is hardware supported and so a lot faster. It was not added to Openb3d because Angelo thought it was too slow for real use as it rendered the scene for every sample. MSAA was never added to Bmx but Josh K got it working in Leadwerks and shared his code in Bmx module tweaks but it was only for Windows, but better than nothing! The latest Openb3d only adds glEnable(GL_MULTISAMPLE) to the AntiAlias function which just turns it on/off but it has to be initialized either in an FBO or graphics context. With a context the window also must be shut down to change sample size. It might be easier to set up an FBO as it should be cross-platform but using a context will leave the FBO for extra effects so I'll go this way.

(Posted 3 years ago) RonTek commented:

Ok I see. I have updated the code again so it just use the default fragment shader without any changes. It seems it does not rely on any varyings anymore and the gl_TexCoord[0] for the texCoords is already set there.

That is awesome for the new multisample! Yes, I do see the Accumulation Buffer technique to be quite old but should be useful on not so older setups if you're targeting for that type of distribution for a game/app.

Ah thanks, got my samples updated now!

(Posted 8 months ago) hardcoal commented:

Hey ron, where can i get openb3d example code?

(Posted 8 months ago) RonTek commented:

Hey ron, where can i get openb3d example code?

There's already one in the OpenB3DMax examples

Reply To Topic (minimum 10 characters)

Please log in to reply