I try to code an antialiasing FXAA, but the result is very far of my dream ; I’ve a feeling to code the right thing, like I found in different post…but that’s dont work and give a me a very glitch result.
The problem to solve that, it’s understand how that work, but my knowladge in shader is very very limitated.
I’m pretty sure my problem is from the glsl because my processing code work prefectly with the other shader.
I try to make the code short but it was little hard. sorry.
GLSL
/**
* Antialiasing FXAA_1
* @see @stanlepunk
* @see https://github.com/StanLepunK/Shader
* v 0.0.1
* 2018-2019
*/
// Processing implementation
#ifdef GL_ES
precision highp float;
#endif
#define PROCESSING_TEXTURE_SHADER
varying vec4 vertColor;
varying vec4 vertTexCoord;
uniform vec2 resolution; // WARNING VERY IMPORTANT // need this name for unknow reason :( here your pass your resolution texture
// vec2 texOffset = vec2(1) / resolution; // only work with uniform resolution
// Rope implementation
uniform sampler2D texture_source;
uniform vec2 resolution_source;
uniform ivec2 flip_source; // can be use to flip texture source
uniform vec4 level_source;
uniform vec2 nw;
uniform vec2 ne;
uniform vec2 sw;
uniform vec2 se;
// UTIL TEMPLATE
vec2 set_uv(int flip_vertical, int flip_horizontal, vec2 res) {
vec2 uv;
if(all(equal(vec2(0),res))) {
uv = vertTexCoord.st;
} else if(all(greaterThan(res,vertTexCoord.st))) {
uv = vertTexCoord.st;
} else {
uv = res;
}
// flip
float condition_y = step(0.1, flip_vertical);
uv.y = 1.0 -(uv.y *condition_y +(1.0 -uv.y) *(1.0 -condition_y));
float condition_x = step(0.1, flip_horizontal);
uv.x = 1.0 -(uv.x *condition_x +(1.0 -uv.x) *(1.0 -condition_x));
return uv;
}
vec2 set_uv(ivec2 flip, vec2 res) {
return set_uv(flip.x,flip.y,res);
}
vec2 set_uv() {
return set_uv(0,0,vec2(0));
}
#define FXAA_REDUCE_MIN (1.0/ 128.0)
#define FXAA_REDUCE_MUL (1.0 / 8.0)
#define FXAA_SPAN_MAX 8.0
vec4 fxaa(sampler2D tex, vec2 uv, vec2 res) {
// vec2 inverseVP = vec2(1.0 / res.x, 1.0 / res.y);
vec2 inverseVP = vec2(1.0,1.0);
vec3 rgbNW = texture2D(tex, uv + nw * inverseVP).xyz;
vec3 rgbNE = textureOffset(tex, uv + ne * inverseVP,ivec2(1,0)).xyz;
vec3 rgbSW = textureOffset(tex, uv + sw * inverseVP,ivec2(0,1)).xyz;
vec3 rgbSE = textureOffset(tex, uv + se * inverseVP,ivec2(1,1)).xyz;
/*
vec3 rgbNE = texture2D(tex, uv + ne * inverseVP).xyz;
vec3 rgbSW = texture2D(tex, uv + sw * inverseVP).xyz;
vec3 rgbSE = texture2D(tex, uv + se * inverseVP).xyz;
*/
vec4 texColor = texture2D(tex, uv * inverseVP);
vec3 rgbM = texColor.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)));
//---------------------------------------
mediump 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), FXAA_REDUCE_MIN);
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)) * inverseVP;
//-------------------------------------------------------
vec3 rgbA = 0.5 * (
texture2D(tex, uv * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
texture2D(tex, uv * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
vec3 rgbB = rgbA * 0.5 + 0.25 * (
texture2D(tex, uv * inverseVP + dir * -0.5).xyz +
texture2D(tex, uv * inverseVP + dir * 0.5).xyz);
float lumaB = dot(rgbB, luma);
if ((lumaB < lumaMin) || (lumaB > lumaMax))
return vec4(rgbA, texColor.a);
else
return vec4(rgbB, texColor.a);
//return color;
}
void main() {
vec2 uv = set_uv(flip_source,resolution_source);
// vec2 uv = vertTexCoord.st;
gl_FragColor = fxaa(texture_source, uv, resolution_source);
}
Processing
/**
* Antialiasing FXAA_1
* @see @stanlepunk
* @see https://github.com/StanLepunK/Shader
* v 0.0.1
* 2018-2019
*/
void setup() {
size(640,480,P2D);
}
void draw() {
background(255);
multi_pix();
if(!mousePressed) fx_antialiasing(g,true,true,1);
}
PShader fx_antialiasing;
PGraphics pg_antialiasing;
PGraphics fx_antialiasing(PImage source, boolean on_g, boolean filter_is, int mode) {
if(!on_g && (pg_antialiasing == null
|| (source.width != pg_antialiasing.width
|| source.height != pg_antialiasing.height))) {
pg_antialiasing = createGraphics(source.width,source.height,P2D);
}
if(fx_antialiasing == null) {
String path = "AA_FXAA_1.glsl";
fx_antialiasing = loadShader(path);
} else {
fx_antialiasing.set("texture_source",source);
fx_antialiasing.set("resolution_source",(float)source.width,(float)source.height);
PVector nw = new PVector(0,0);
PVector ne = new PVector(1,0);
PVector sw = new PVector(0,1);
PVector se = new PVector(1,1);
fx_antialiasing.set("nw",nw.x,nw.y); // value from -1 to 1
fx_antialiasing.set("ne",ne.x,ne.y); // value from -1 to 1
fx_antialiasing.set("sw",sw.x,sw.y); // value from -1 to 1
fx_antialiasing.set("se",se.x,se.y); // value from -1 to 1
// rendering
render_shader(fx_antialiasing,pg_antialiasing,source,on_g,filter_is);
}
// return
reset_reverse_g(false);
if(on_g) {
return null;
} else {
return pg_antialiasing;
}
}
boolean filter_reverse_g_source;
boolean filter_reverse_g_layer;
void reset_reverse_g(boolean state){
filter_reverse_g_source = state;
filter_reverse_g_layer = state;
}
void render_shader(PShader shader, PGraphics pg, PImage src, boolean on_g, boolean filter_is) {
if(on_g) {
render_filter_g(shader);
} else {
if(filter_is) {
render_filter_pgraphics(shader,pg);
} else {
render_shader_pgraphics(shader,pg,src);
}
}
}
void render_shader_pgraphics(PShader ps, PGraphics pg, PImage src) {
if(pg != null) {
pg.beginDraw();
pg.shader(ps);
pg.image(src,0,0,src.width,src.height);
pg.resetShader();
pg.endDraw();
}
}
void render_filter_pgraphics(PShader ps, PGraphics pg) {
if(pg != null) {
pg.filter(ps);
}
}
void render_filter_g(PShader ps) {
filter(ps);
}
float rot;
void multi_pix() {
rot += 0.001;
for(int i = 0 ; i < 50 ; i++) {
pix(rot + (i*0.1));
}
}
void pix(float rot) {
PVector src = new PVector(width/2,height/2);
float radius = width/3;
float dx = sin(rot);
float dy = cos(rot);
g.loadPixels();
for(int i = 0; i < radius ; i++) {
PVector dst = new PVector(dx,dy).mult(i).add(src);
// dst.constrain(new PVector(0,0),new PVector(width,height));
int target = 0;
target = (int)dst.y * width + (int)dst.x;
if(target >= g.pixels.length) {
target = 0;
}
g.pixels[target] = color(0);
}
g.updatePixels();
}