”FXAA Rules, OK?” (44 posts)

Topic tags: FXAA
  • Profile picture of thetoucher thetoucher349p said 10 months, 2 weeks ago:

    Just found this post over at Real Tim Rendering, very interesting article covering FXAA, thought it was worth sharing:

    FXAA Rules, OK ?

    Further reading :: FXAA white paper

    Cheers
    James

  • Profile picture of nehon nehon590p said 10 months, 2 weeks ago:

    Very interesting!! thanks

  • Profile picture of phate666 phate66670p said 9 months, 1 week ago:

    FXAAFilter.java

    package com.jme3.post.filters;
    
    import com.jme3.asset.AssetManager;
    import com.jme3.material.Material;
    import com.jme3.post.Filter;
    import com.jme3.renderer.RenderManager;
    import com.jme3.renderer.ViewPort;
    
    /**
     * http://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/
     * http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf
     *
     * @author Phate666 (adapted to jme3)
     *
     */
    public class FXAAFilter extends Filter
    {
    	private float FXAA_SUBPIX_SHIFT = 1.0f / 4.0f;
    	private float vx_offset = 0.0f;
    	private float FXAA_SPAN_MAX = 8.0f;
    	private float FXAA_REDUCE_MUL = 1.0f / 8.0f;
    
    	public FXAAFilter()
    	{
    		super("FXAAFilter");
    	}
    
    	@Override
    	protected void initFilter(AssetManager manager,
    			RenderManager renderManager, ViewPort vp, int w, int h)
    	{
    		material = new Material(manager, "Common/MatDefs/Post/FXAA.j3md");
    		material.setFloat("rt_w", w);
    		material.setFloat("rt_h", h);
    		material.setFloat("FXAA_SUBPIX_SHIFT", FXAA_SUBPIX_SHIFT);
    		material.setFloat("vx_offset", vx_offset);
    		material.setFloat("FXAA_SPAN_MAX", FXAA_SPAN_MAX);
    		material.setFloat("FXAA_REDUCE_MUL", FXAA_REDUCE_MUL);
    	}
    
    	@Override
    	protected Material getMaterial()
    	{
    		return material;
    	}
    
    	public void setSpanMax(float spanMax)
    	{
    		FXAA_SPAN_MAX = spanMax;
    		if (material != null)
    		{
    			material.setFloat("FXAA_SPAN_MAX", FXAA_SPAN_MAX);
    		}
    	}
    
    	/**
    	 * set to 0.0f for higher quality
    	 *
    	 * @param subPixelShift
    	 */
    	public void setSubPixelShift(float subPixelShift)
    	{
    		FXAA_SUBPIX_SHIFT = subPixelShift;
    		if (material != null)
    		{
    			material.setFloat("FXAA_SUBPIX_SHIFT", FXAA_SUBPIX_SHIFT);
    		}
    	}
    
    	/**
    	 * set to 0.0f for higher quality
    	 *
    	 * @param reduceMul
    	 */
    	public void setReduceMul(float reduceMul)
    	{
    		FXAA_REDUCE_MUL = reduceMul;
    		if (material != null)
    		{
    			material.setFloat("FXAA_REDUCE_MUL", FXAA_REDUCE_MUL);
    		}
    	}
    
    	public void setVxOffset(float vxOffset)
    	{
    		vx_offset = vxOffset;
    		if (material != null)
    		{
    			material.setFloat("vx_offset", vx_offset);
    		}
    	}
    
    }
    

    FXAA.j3md

    MaterialDef FXAA {
    
        MaterialParameters {
            Int NumSamples
            Texture2D Texture
            Float FXAA_SUBPIX_SHIFT
            Float rt_w
            Float rt_h
            Float vx_offset
            Float FXAA_SPAN_MAX
            Float FXAA_REDUCE_MUL
        }
    
        Technique {
            VertexShader GLSL100:   Common/MatDefs/Post/FXAA.vert
            FragmentShader GLSL120: Common/MatDefs/Post/FXAA.frag
    
            WorldParameters {
                WorldViewProjectionMatrix
            }
        }
    
        Technique FixedFunc {
        }
    
    }

    FXAA.vert

    uniform mat4 g_WorldViewProjectionMatrix;
    
    attribute vec4 inPosition;
    attribute vec2 inTexCoord;
    varying vec2 texCoord;
    
    uniform float m_FXAA_SUBPIX_SHIFT;
    uniform float m_rt_w;
    uniform float m_rt_h;
    varying vec4 posPos;
    
    void main() {
        gl_Position = inPosition * 2.0 - 1.0; //vec4(pos, 0.0, 1.0);
        texCoord = inTexCoord;
    
        vec2 rcpFrame = vec2(1.0/m_rt_w, 1.0/m_rt_h);
      	posPos.xy = inTexCoord.xy;
      	posPos.zw = inTexCoord.xy -
                      (rcpFrame * (0.5 + m_FXAA_SUBPIX_SHIFT));
    }

    FXAA.frag

    #extension GL_EXT_gpu_shader4 : enable
    
    uniform sampler2D m_Texture;
    varying vec2 texCoord;
    
    uniform float m_vx_offset;
    uniform float m_rt_w;
    uniform float m_rt_h;
    uniform float m_FXAA_SPAN_MAX;
    uniform float m_FXAA_REDUCE_MUL;
    varying vec4 posPos;
    
    #define FxaaInt2 ivec2
    #define FxaaFloat2 vec2
    #define FxaaTexLod0(t, p) texture2DLod(t, p, 0.0)
    #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
    
    vec3 FxaaPixelShader(
      vec4 posPos, // Output of FxaaVertexShader interpolated across screen.
      sampler2D tex, // Input texture.
      vec2 rcpFrame) // Constant {1.0/frameWidth, 1.0/frameHeight}.
    {
    /*---------------------------------------------------------*/
        #define FXAA_REDUCE_MIN   (1.0/128.0)
        //#define FXAA_REDUCE_MUL   (1.0/8.0)
        //#define FXAA_SPAN_MAX     8.0
    /*---------------------------------------------------------*/
        vec3 rgbNW = FxaaTexLod0(tex, posPos.zw).xyz;
        vec3 rgbNE = FxaaTexOff(tex, posPos.zw, FxaaInt2(1,0), rcpFrame.xy).xyz;
        vec3 rgbSW = FxaaTexOff(tex, posPos.zw, FxaaInt2(0,1), rcpFrame.xy).xyz;
        vec3 rgbSE = FxaaTexOff(tex, posPos.zw, FxaaInt2(1,1), rcpFrame.xy).xyz;
        vec3 rgbM  = FxaaTexLod0(tex, posPos.xy).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 * m_FXAA_REDUCE_MUL),
            FXAA_REDUCE_MIN);
        float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
        dir = min(FxaaFloat2( m_FXAA_SPAN_MAX,  m_FXAA_SPAN_MAX),
              max(FxaaFloat2(-m_FXAA_SPAN_MAX, -m_FXAA_SPAN_MAX),
              dir * rcpDirMin)) * rcpFrame.xy;
    /*--------------------------------------------------------*/
        vec3 rgbA = (1.0/2.0) * (
            FxaaTexLod0(tex, posPos.xy + dir * (1.0/3.0 - 0.5)).xyz +
            FxaaTexLod0(tex, posPos.xy + dir * (2.0/3.0 - 0.5)).xyz);
        vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
            FxaaTexLod0(tex, posPos.xy + dir * (0.0/3.0 - 0.5)).xyz +
            FxaaTexLod0(tex, posPos.xy + dir * (3.0/3.0 - 0.5)).xyz);
        float lumaB = dot(rgbB, luma);
        if((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA;
        return rgbB; }
    
    vec4 PostFX(sampler2D tex, vec2 uv, float time)
    {
      	vec4 c = vec4(0.0);
      	vec2 rcpFrame = vec2(1.0/m_rt_w, 1.0/m_rt_h);
      	c.rgb = FxaaPixelShader(posPos, tex, rcpFrame);
      	//c.rgb = 1.0 - texture2D(tex, posPos.xy).rgb;
      	c.a = 1.0;
      	return c;
    }
    
    void main()
    {
      	vec2 uv = texCoord.st;
      	gl_FragColor = PostFX(m_Texture, uv, 0.0);
    }
  • Profile picture of nehon nehon590p said 9 months, 1 week ago:

    Oh cool!
    Thanks for this!!

  • Profile picture of wezrule wezrule190p said 9 months, 1 week ago:

    yeh big thanks, much appreciated! dam i need to learn how to make my own shaders xD

  • Profile picture of nehon nehon590p said 9 months, 1 week ago:

    Wow that’s very impressive, with default config it gives almost the same result as x4 AA and for about 7 to 8% frame rate loss compared to no AA at all.

    I thumb you up once more for that phate666

  • Profile picture of madjack madjack487p said 9 months, 1 week ago:

    Purty nice! :)

  • Profile picture of wezrule wezrule190p said 9 months, 1 week ago:

    nehon said:
    Wow that’s very impressive, with default config it gives almost the same result as x4 AA and for about 7 to 8% frame rate loss compared to no AA at all.

    I thumb you up once more for that phate666

    you can give more than 1 thumbs up? dam u :P

  • Profile picture of nehon nehon590p said 9 months, 1 week ago:

    OK that’s in!

    @phate666 I hope you don’t mind, but i changed some variable name to fit more java naming convention, also, i added getters for the attributes because it’s needed to add the filter in the filter editor in jmp
    You don’t have to pass your own width and height to the shader, there is a global uniform called Resolution that you can use as any other global uniforms. It’s a vec2, x id the width and y is the height. Just for you to know for further developments.

    Here are some shots to compare
    No AA
    http://i.imgur.com/GhNPF.jpg

    AA x4
    http://i.imgur.com/9oq0G.jpg

    FXAA
    http://i.imgur.com/B40Y0.jpg

    In fact that’s even better than AAx4 because the water is also anti-aliased, and the frame rate is so much better.

  • Profile picture of nehon nehon590p said 9 months, 1 week ago:

    wezrule said:
    you can give more than 1 thumbs up? dam u :P

    Yeah, admins can, and we can give more than one thumb down :evil:

  • Profile picture of madjack madjack487p said 9 months, 1 week ago:

    Holy crap yeah! Huge difference FPS-wise but the final effect is almost indistinguishable. Wow. I love it. :D

  • Profile picture of atomix atomix72p said 9 months, 1 week ago:

    That what I call awesomeness…
    This technique really “ruined” oops , i mean “ruled” !

  • Profile picture of erlend_sh erlend_sh132p said 9 months, 1 week ago:

    madjack said:
    Holy crap yeah! Huge difference FPS-wise but the final effect is almost indistinguishable. Wow. I love it. :D

    The huge difference is ‘No AA’ and ‘AA x4′. The FPS drop between ‘No AA’ and ‘FXAA’ is a measly 16 frames per second!

    This is an outstanding contribution @phate666

  • Profile picture of Dodikles Dodikles54p said 9 months, 1 week ago:

    That’s plain awesome! :)

  • Profile picture of thecyberbob thecyberbob10p said 9 months, 1 week ago:

    Bloody hell that’s awesome. :o