Normal Filter Anti Aliasing Shader


Tweet blitzmax shaders code-archives openb3d
(Posted 1 month ago) RonTek

Another anti-aliasing shader for OpenB3D. NFAA is a shader-based post processing anti-aliasing method that applies normal filter for edge detection.

Example setup below or use FXAA example and just replace the fragment shader file in LoadShader with nfaa.frag.glsl.

Image

Local width%=800,height%=600
Graphics3D width, height,0,2

Global colortex:TTexture=CreateTexture(width,height,1+256)
ScaleTexture colortex,1.0,-1.0

' in GL 2.0 render textures need attached before other textures (EntityTexture)
CameraToTex colortex,Camera
TGlobal.CheckFramebufferStatus(GL_FRAMEBUFFER_EXT) ' check for framebuffer errors

Global screensprite:TSprite=CreateSprite()
EntityOrder screensprite,-1
ScaleSprite screensprite,1.0,Float( GraphicsHeight() ) / GraphicsWidth() ' 0.75
MoveEntity screensprite,0,0,1.0 ' set z to 0.99 - instead of clamping uvs
EntityParent screensprite,Camera

PositionEntity Camera,0,7,0 ' move camera now sprite is parented to it
MoveEntity Camera,0,0,-25

Local shader:TShader=LoadShader("","../glsl/default.vert.glsl", "../glsl/nfaa.glsl")
ShaderTexture(shader,colortex,"sceneTex",0) ' Our render texture
SetFloat2(shader,"resolution", width,height)
ShadeEntity(screensprite, shader)

nfaa.frag.glsl

uniform sampler2D texture0;
uniform vec2 resolution;

float width = resolution.x; //texture width
float height = resolution.y; //texture height

vec2 inverse_buffer_size = vec2(1.0/width, 1.0/height);

vec2 texCoord = gl_TexCoord[0].st;

float lumRGB(vec3 v)
{   
return dot(v, vec3(0.212, 0.716, 0.072));
}

vec2 vPixelViewport = vec2( 1.0 / width, 1.0 / height );

const float fScale = 3.0;

void main()
{

// Offset coordinates

vec2 upOffset = vec2( 0.0, vPixelViewport.y ) * fScale;
vec2 rightOffset = vec2( vPixelViewport.x, 0.0 ) * fScale;

float topHeight = lumRGB( texture2D( texture0, texCoord.xy + upOffset).rgb );
float bottomHeight = lumRGB( texture2D( texture0, texCoord.xy - upOffset).rgb );
float rightHeight = lumRGB( texture2D( texture0, texCoord.xy + rightOffset).rgb );
float leftHeight = lumRGB( texture2D( texture0, texCoord.xy - rightOffset).rgb );
float leftTopHeight = lumRGB( texture2D( texture0, texCoord.xy - rightOffset + upOffset).rgb );
float leftBottomHeight = lumRGB( texture2D( texture0, texCoord.xy - rightOffset - upOffset).rgb );
float rightBottomHeight = lumRGB( texture2D( texture0, texCoord.xy + rightOffset + upOffset).rgb );
float rightTopHeight = lumRGB( texture2D( texture0, texCoord.xy + rightOffset - upOffset).rgb );

// Normal map creation

float sum0 = rightTopHeight + topHeight + rightBottomHeight;
float sum1 = leftTopHeight + bottomHeight + leftBottomHeight;
float sum2 = leftTopHeight + leftHeight + rightTopHeight;
float sum3 = leftBottomHeight + rightHeight + rightBottomHeight;
float vect1 = (sum1 - sum0);
float vect2 = (sum2 - sum3);

// Put them together and scale.

vec2 Normal = vec2( vect1, vect2); // * vPixelViewport * fScale;

// Color

Normal.xy = clamp(Normal,-float2(1.0,1.0)*0.4,float2(1.0,1.0)*0.4); //Prevent over-blurring in high-contrast areas
Normal.xy *= vPixelViewport * fScale;   // Increase pixel size to get more blur

vec4 Scene0 = texture2D( texture0, texCoord.xy );
vec4 Scene1 = texture2D( texture0, texCoord.xy + Normal.xy );
vec4 Scene2 = texture2D( texture0, texCoord.xy - Normal.xy );
vec4 Scene3 = texture2D( texture0, texCoord.xy + vec2(Normal.x, -Normal.y) * 0.5 );
vec4 Scene4 = texture2D( texture0, texCoord.xy - vec2(Normal.x, -Normal.y) * 0.5 );

// Final color

gl_FragColor.rgb = (Scene0.rgb + Scene1.rgb + Scene2.rgb + Scene3.rgb + Scene4.rgb) * 0.2;

//gl_FragColor.rgb = (vec3(Normal , 1.0) * 0.5 + 0.5);
gl_FragColor.a = 1.0;

}
(Posted 1 month ago) markcwm commented:

Thanks Ron! Seems like a good alternative to FXAA.

As I see it the main difference is that NFAA has an edge-blur method but FXAA is more actual AA with a much harder edge. The nice thing about NFAA is the blur sharpens the farther it is from the camera, so you get a depth effect. From reading a bit it should also be faster than FXAA.

I got an error in your code though! Fix below. As I see it clamp doesn't really support vec2.

  // Color

  //Normal.xy = clamp(Normal, -float2(1.0, 1.0) * 0.4, float2(1.0, 1.0) * 0.4); //Error: buffer overflow detected
  Normal.x = clamp(Normal.x, -float(1.0) * 0.4, float(1.0) * 0.4); //Prevent over-blurring in high-contrast areas
  Normal.y = clamp(Normal.y, -float(1.0) * 0.4, float(1.0) * 0.4);
(Posted 1 month ago) RonTek commented:

cheers Mark yes, it seems this is faster and newer technique, but yes I also prefered FXAA in comparison.

Thanks for the update! The error might be with newer OpenB3D versions, as I dug this from my older archives a couple of years ago.

Reply To Topic (minimum 10 characters)

Please log in to reply