Skip to content

Commit

Permalink
Add fast approximate antialiasing (FXAA) to Environment
Browse files Browse the repository at this point in the history
This backports FXAA from the `master` branch.
  • Loading branch information
Calinou committed Sep 12, 2020
1 parent 8197651 commit 0470861
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 15 deletions.
3 changes: 3 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,9 @@
<member name="rendering/quality/filters/anisotropic_filter_level" type="int" setter="" getter="" default="4">
Maximum anisotropic filter level used for textures with anisotropy enabled. Higher values will result in sharper textures when viewed from oblique angles, at the cost of performance. Only power-of-two values are valid (2, 4, 8, 16).
</member>
<member name="rendering/quality/filters/fxaa" type="bool" setter="" getter="" default="false">
If [code]true[/code], enables fast approximate antialiasing. FXAA is a popular screen-space antialiasing method, which is fast but will make the image look blurry, especially at lower resolutions. It can still work relatively well at large resolutions such as 1440p and 4K.
</member>
<member name="rendering/quality/filters/msaa" type="int" setter="" getter="" default="0">
Sets the number of MSAA samples to use. MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware.
[b]Note:[/b] MSAA is not available on HTML5 export using the GLES2 backend.
Expand Down
11 changes: 11 additions & 0 deletions doc/classes/VisualServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,17 @@
Sets the variables to be used with the fog height effect. See [Environment] for more details.
</description>
</method>
<method name="environment_set_fxaa">
<return type="void">
</return>
<argument index="0" name="env" type="RID">
</argument>
<argument index="1" name="enable" type="bool">
</argument>
<description>
Sets the FXAA value of the environment. FXAA is a popular screen-space antialiasing method, which is fast but will make the image look blurry, especially at lower resolutions. It can still work relatively well at large resolutions such as 1440p and 4K. Equivalent to [member ProjectSettings.rendering/quality/filters/fxaa].
</description>
</method>
<method name="environment_set_glow">
<return type="void">
</return>
Expand Down
2 changes: 2 additions & 0 deletions drivers/dummy/rasterizer_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class RasterizerSceneDummy : public RasterizerScene {
void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {}

void environment_set_fxaa(RID p_env, bool p_enable) {}

void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {}

void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) {}
Expand Down
25 changes: 22 additions & 3 deletions drivers/gles2/rasterizer_scene_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,14 @@ void RasterizerSceneGLES2::environment_set_dof_blur_near(RID p_env, bool p_enabl
env->dof_blur_near_quality = p_quality;
}

void RasterizerSceneGLES2::environment_set_fxaa(RID p_env, bool p_enable) {

Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);

env->fxaa_enabled = p_enable;
}

void RasterizerSceneGLES2::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {

Environment *env = environment_owner.getornull(p_env);
Expand Down Expand Up @@ -2729,8 +2737,10 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
use_post_process = use_post_process && storage->frame.current_rt->width >= 4 && storage->frame.current_rt->height >= 4;
use_post_process = use_post_process && storage->frame.current_rt->mip_maps_allocated;

const bool fxaa_enabled = GLOBAL_GET("rendering/quality/filters/fxaa");

if (env) {
use_post_process = use_post_process && (env->adjustments_enabled || env->glow_enabled || env->dof_blur_far_enabled || env->dof_blur_near_enabled);
use_post_process = use_post_process && (env->adjustments_enabled || env->glow_enabled || env->dof_blur_far_enabled || env->dof_blur_near_enabled || fxaa_enabled);
}

GLuint next_buffer;
Expand Down Expand Up @@ -2784,8 +2794,9 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p

// Order of operation
//1) DOF Blur (first blur, then copy to buffer applying the blur) //only on desktop
//2) Bloom (Glow) //only on desktop
//3) Adjustments
//2) FXAA
//3) Bloom (Glow) //only on desktop
//4) Adjustments

// DOF Blur

Expand Down Expand Up @@ -3040,6 +3051,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[0].color);
}

state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_FXAA, fxaa_enabled);
state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_FILTER_BICUBIC, env->glow_bicubic_upscale);

if (max_glow_level >= 0) {
Expand Down Expand Up @@ -3141,9 +3153,16 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
state.tonemap_shader.set_uniform(TonemapShaderGLES2::BCS, Vector3(env->adjustments_brightness, env->adjustments_contrast, env->adjustments_saturation));
}

if (fxaa_enabled) {
state.tonemap_shader.set_uniform(
TonemapShaderGLES2::PIXEL_SIZE,
Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
}

storage->_copy_screen();

//turn off everything used
state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_FXAA, false);
state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL1, false);
state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL2, false);
state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL3, false);
Expand Down
6 changes: 6 additions & 0 deletions drivers/gles2/rasterizer_scene_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ class RasterizerSceneGLES2 : public RasterizerScene {

int canvas_max_layer;

bool fxaa_enabled;

bool glow_enabled;
int glow_levels;
float glow_intensity;
Expand Down Expand Up @@ -418,6 +420,7 @@ class RasterizerSceneGLES2 : public RasterizerScene {
ambient_energy(1.0),
ambient_sky_contribution(0.0),
canvas_max_layer(0),
fxaa_enabled(false),
glow_enabled(false),
glow_levels((1 << 2) | (1 << 4)),
glow_intensity(0.8),
Expand Down Expand Up @@ -475,6 +478,9 @@ class RasterizerSceneGLES2 : public RasterizerScene {

virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality);
virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality);

virtual void environment_set_fxaa(RID p_env, bool p_enable);

virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale);
virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture);

Expand Down
63 changes: 58 additions & 5 deletions drivers/gles2/shaders/tonemap.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ uniform highp float glow_intensity;
uniform vec3 bcs;
#endif

#ifdef USE_FXAA
uniform vec2 pixel_size;
#endif

#ifdef USE_COLOR_CORRECTION
uniform sampler2D color_correction; //texunit:2
#endif
Expand Down Expand Up @@ -138,7 +142,7 @@ uniform ivec2 glow_texture_size;
vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
float lod = float(p_lod);
vec2 tex_size = vec2(glow_texture_size >> p_lod);
vec2 pixel_size = vec2(1.0) / tex_size;
vec2 pix_size = vec2(1.0) / tex_size;

uv = uv * tex_size + vec2(0.5);

Expand All @@ -152,10 +156,10 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
float h0y = h0(fuv.y);
float h1y = h1(fuv.y);

vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5)) * pixel_size;
vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5)) * pixel_size;
vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5)) * pixel_size;
vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5)) * pixel_size;
vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5)) * pix_size;
vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5)) * pix_size;
vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5)) * pix_size;
vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5)) * pix_size;

return (g0(fuv.y) * (g0x * texture2DLod(tex, p0, lod) + g1x * texture2DLod(tex, p1, lod))) +
(g1(fuv.y) * (g0x * texture2DLod(tex, p2, lod) + g1x * texture2DLod(tex, p3, lod)));
Expand Down Expand Up @@ -210,9 +214,58 @@ vec3 apply_color_correction(vec3 color, sampler2D correction_tex) {
return color;
}

vec3 apply_fxaa(vec3 color, vec2 uv_interp, vec2 pixel_size) {
const float FXAA_REDUCE_MIN = (1.0 / 128.0);
const float FXAA_REDUCE_MUL = (1.0 / 8.0);
const float FXAA_SPAN_MAX = 8.0;

vec3 rgbNW = texture2DLod(source, uv_interp + vec2(-1.0, -1.0) * pixel_size, 0.0).xyz;
vec3 rgbNE = texture2DLod(source, uv_interp + vec2(1.0, -1.0) * pixel_size, 0.0).xyz;
vec3 rgbSW = texture2DLod(source, uv_interp + vec2(-1.0, 1.0) * pixel_size, 0.0).xyz;
vec3 rgbSE = texture2DLod(source, uv_interp + vec2(1.0, 1.0) * pixel_size, 0.0).xyz;
vec3 rgbM = color;
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)) *
pixel_size;

vec3 rgbA = 0.5 * (texture2DLod(source, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + texture2DLod(source, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
vec3 rgbB = rgbA * 0.5 + 0.25 * (texture2DLod(source, uv_interp + dir * -0.5, 0.0).xyz +
texture2DLod(source, uv_interp + dir * 0.5, 0.0).xyz);

float lumaB = dot(rgbB, luma);
if ((lumaB < lumaMin) || (lumaB > lumaMax)) {
return rgbA;
} else {
return rgbB;
}
}

void main() {
vec3 color = texture2DLod(source, uv_interp, 0.0).rgb;

#ifdef USE_FXAA
color = apply_fxaa(color, uv_interp, pixel_size);
#endif

// Glow

#ifdef USING_GLOW
Expand Down
23 changes: 21 additions & 2 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,15 @@ void RasterizerSceneGLES3::environment_set_dof_blur_near(RID p_env, bool p_enabl
env->dof_blur_near_amount = p_amount;
env->dof_blur_near_quality = p_quality;
}

void RasterizerSceneGLES3::environment_set_fxaa(RID p_env, bool p_enable) {

Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);

env->fxaa_enabled = p_enable;
}

void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {

Environment *env = environment_owner.getornull(p_env);
Expand Down Expand Up @@ -3646,8 +3655,8 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p

//order of operation
//1) DOF Blur (first blur, then copy to buffer applying the blur)
//2) Motion Blur
//3) Bloom
//2) FXAA
//3) Bloom (Glow)
//4) Tonemap
//5) Adjustments

Expand Down Expand Up @@ -3984,7 +3993,10 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINHARD_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_REINHARD);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::KEEP_3D_LINEAR, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]);

const bool fxaa_enabled = GLOBAL_GET("rendering/quality/filters/fxaa");

state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, env->auto_exposure);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FXAA, fxaa_enabled);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, env->glow_bicubic_upscale);

if (max_glow_level >= 0) {
Expand Down Expand Up @@ -4062,9 +4074,16 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
state.tonemap_shader.set_uniform(TonemapShaderGLES3::BCS, Vector3(env->adjustments_brightness, env->adjustments_contrast, env->adjustments_saturation));
}

if (fxaa_enabled) {
state.tonemap_shader.set_uniform(
TonemapShaderGLES3::PIXEL_SIZE,
Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
}

_copy_screen(true, true);

//turn off everything used
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FXAA, false);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, false);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, false);
state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, false);
Expand Down
6 changes: 6 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@ class RasterizerSceneGLES3 : public RasterizerScene {

int canvas_max_layer;

bool fxaa_enabled;

bool ssr_enabled;
int ssr_max_steps;
float ssr_fade_in;
Expand Down Expand Up @@ -467,6 +469,7 @@ class RasterizerSceneGLES3 : public RasterizerScene {
ambient_energy(1.0),
ambient_sky_contribution(0.0),
canvas_max_layer(0),
fxaa_enabled(false),
ssr_enabled(false),
ssr_max_steps(64),
ssr_fade_in(0.15),
Expand Down Expand Up @@ -549,6 +552,9 @@ class RasterizerSceneGLES3 : public RasterizerScene {

virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality);
virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality);

virtual void environment_set_fxaa(RID p_env, bool p_enable);

virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale);
virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture);

Expand Down
Loading

0 comments on commit 0470861

Please sign in to comment.