2012-08-24 18 views
8

Me encontré con este sombreador FxAA ​​que hace anti-aliasing y parece estar funcionando bastante bien. Pero, de alguna manera no podía entender la lógica. ¿Alguien puede explicar?¿Cómo funciona este simple FxAA?

[[FX]] 

// Samplers 
sampler2D buf0 = sampler_state { 
    Address = Clamp; 
    Filter = None; 
}; 

context FXAA { 
    VertexShader = compile GLSL VS_FSQUAD; 
    PixelShader = compile GLSL FS_FXAA; 
} 



[[VS_FSQUAD]] 

uniform mat4 projMat; 
attribute vec3 vertPos; 
varying vec2 texCoords; 

void main(void) { 
    texCoords = vertPos.xy; 
    gl_Position = projMat * vec4(vertPos, 1); 
} 


[[FS_FXAA]] 

uniform sampler2D buf0; 
uniform vec2 frameBufSize; 
varying vec2 texCoords; 

void main(void) { 
    //gl_FragColor.xyz = texture2D(buf0,texCoords).xyz; 
    //return; 

    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(buf0,texCoords+(vec2(-1.0,-1.0)/frameBufSize)).xyz; 
    vec3 rgbNE=texture2D(buf0,texCoords+(vec2(1.0,-1.0)/frameBufSize)).xyz; 
    vec3 rgbSW=texture2D(buf0,texCoords+(vec2(-1.0,1.0)/frameBufSize)).xyz; 
    vec3 rgbSE=texture2D(buf0,texCoords+(vec2(1.0,1.0)/frameBufSize)).xyz; 
    vec3 rgbM=texture2D(buf0,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), 
     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))/frameBufSize; 

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

    if((lumaB < lumaMin) || (lumaB > lumaMax)){ 
     gl_FragColor.xyz=rgbA; 
    }else{ 
     gl_FragColor.xyz=rgbB; 
    } 
} 
+2

whoa que está muy lejos FAAAAR de simple –

Respuesta

9

FxAA ​​es un algoritmo de filtro que realiza un antialiasing en las imágenes. Al contrario que otras técnicas de AA, se aplica a los píxeles de una imagen, no al dibujar sus primitivos. En aplicaciones 3D como juegos, se aplica como un paso posterior al procesamiento en la parte superior de la escena renderizada.

La idea básica es: buscar bordes verticales y horizontales. Desenfoque en dirección ortogonal si está al final del borde.

Aquí hay un good description y el original paper sobre el tema.

+1

Supongo que hay múltiples versiones de FxAA, la versión que he publicado aquí es diferente de lo que describe el documento. Quiere saber aquí qué significan rgbA y rgbB aquí. Cualquiera que signifique la siguiente lógica, 'if ((lumaB lumaMax)) { gl_FragColor.xyz = rgbA; } else { gl_FragColor.xyz = rgbB; } ' – Subhransu

Cuestiones relacionadas