mirror of
https://github.com/minetest/minetest.git
synced 2024-11-26 17:43:45 +01:00
Add antialiasing filters (FXAA, SSAA) (#13253)
This commit is contained in:
parent
442d5fc75c
commit
c09a3a52ac
@ -342,14 +342,27 @@ texture_clean_transparent (Clean transparent textures) bool false
|
||||
# texture autoscaling.
|
||||
texture_min_size (Minimum texture size) int 64 1 32768
|
||||
|
||||
# Use multi-sample antialiasing (MSAA) to smooth out block edges.
|
||||
# This algorithm smooths out the 3D viewport while keeping the image sharp,
|
||||
# but it doesn't affect the insides of textures
|
||||
# (which is especially noticeable with transparent textures).
|
||||
# Visible spaces appear between nodes when shaders are disabled.
|
||||
# If set to 0, MSAA is disabled.
|
||||
# A restart is required after changing this option.
|
||||
fsaa (FSAA) enum 0 0,1,2,4,8,16
|
||||
# Select the antialiasing method to apply.
|
||||
#
|
||||
# * None - No antialiasing (default)
|
||||
#
|
||||
# * FSAA - Hardware-provided full-screen antialiasing (incompatible with shaders)
|
||||
# A.K.A multi-sample antialiasing (MSAA)
|
||||
# Smoothens out block edges but does not affect the insides of textures.
|
||||
# A restart is required to change this option.
|
||||
#
|
||||
# * FXAA - Fast approximate antialiasing (requires shaders)
|
||||
# Applies a post-processing filter to detect and smoothen high-contrast edges.
|
||||
# Provides balance between speed and image quality.
|
||||
#
|
||||
# * SSAA - Super-sampling antialiasing (requires shaders)
|
||||
# Renders higher-resolution image of the scene, then scales down to reduce
|
||||
# the aliasing effects. This is the slowest and the most accurate method.
|
||||
antialiasing (Antialiasing method) enum none none,fsaa,fxaa,ssaa
|
||||
|
||||
# Defines size of the sampling grid for FSAA and SSAA antializasing methods.
|
||||
# Value of 2 means taking 2x2 = 4 samples.
|
||||
fsaa (Anti-aliasing scale) enum 2 2,4,8,16
|
||||
|
||||
[**Occlusion Culling]
|
||||
|
||||
|
116
client/shaders/fxaa/opengl_fragment.glsl
Normal file
116
client/shaders/fxaa/opengl_fragment.glsl
Normal file
@ -0,0 +1,116 @@
|
||||
#define rendered texture0
|
||||
|
||||
uniform sampler2D rendered;
|
||||
uniform vec2 texelSize0;
|
||||
|
||||
varying vec2 sampleNW;
|
||||
varying vec2 sampleNE;
|
||||
varying vec2 sampleSW;
|
||||
varying vec2 sampleSE;
|
||||
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
|
||||
/**
|
||||
Basic FXAA implementation based on the code on geeks3d.com with the
|
||||
modification that the texture2DLod stuff was removed since it's
|
||||
unsupported by WebGL.
|
||||
--
|
||||
From:
|
||||
https://github.com/mitsuhiko/webgl-meincraft
|
||||
Copyright (c) 2011 by Armin Ronacher.
|
||||
Some rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FXAA_REDUCE_MIN
|
||||
#define FXAA_REDUCE_MIN (1.0/ 128.0)
|
||||
#endif
|
||||
#ifndef FXAA_REDUCE_MUL
|
||||
#define FXAA_REDUCE_MUL (1.0 / 8.0)
|
||||
#endif
|
||||
#ifndef FXAA_SPAN_MAX
|
||||
#define FXAA_SPAN_MAX 8.0
|
||||
#endif
|
||||
|
||||
//optimized version for mobile, where dependent
|
||||
//texture reads can be a bottleneck
|
||||
vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 inverseVP,
|
||||
vec2 v_rgbNW, vec2 v_rgbNE,
|
||||
vec2 v_rgbSW, vec2 v_rgbSE,
|
||||
vec2 v_rgbM) {
|
||||
vec4 color;
|
||||
vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;
|
||||
vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;
|
||||
vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;
|
||||
vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;
|
||||
vec4 texColor = texture2D(tex, v_rgbM);
|
||||
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, fragCoord + dir * (1.0 / 3.0 - 0.5)).xyz +
|
||||
texture2D(tex, fragCoord + dir * (2.0 / 3.0 - 0.5)).xyz);
|
||||
vec3 rgbB = rgbA * 0.5 + 0.25 * (
|
||||
texture2D(tex, fragCoord + dir * -0.5).xyz +
|
||||
texture2D(tex, fragCoord + dir * 0.5).xyz);
|
||||
|
||||
float lumaB = dot(rgbB, luma);
|
||||
if ((lumaB < lumaMin) || (lumaB > lumaMax))
|
||||
color = vec4(rgbA, 1.0);
|
||||
else
|
||||
color = vec4(rgbB, 1.0);
|
||||
return color;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 uv = varTexCoord.st;
|
||||
|
||||
gl_FragColor = fxaa(rendered, uv, texelSize0,
|
||||
sampleNW, sampleNE, sampleSW, sampleSE, uv);
|
||||
}
|
27
client/shaders/fxaa/opengl_vertex.glsl
Normal file
27
client/shaders/fxaa/opengl_vertex.glsl
Normal file
@ -0,0 +1,27 @@
|
||||
uniform vec2 texelSize0;
|
||||
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
|
||||
varying vec2 sampleNW;
|
||||
varying vec2 sampleNE;
|
||||
varying vec2 sampleSW;
|
||||
varying vec2 sampleSE;
|
||||
|
||||
/*
|
||||
Based on
|
||||
https://github.com/mattdesl/glsl-fxaa/
|
||||
Portions Copyright (c) 2011 by Armin Ronacher.
|
||||
*/
|
||||
void main(void)
|
||||
{
|
||||
varTexCoord.st = inTexCoord0.st;
|
||||
sampleNW = varTexCoord.st + vec2(-1.0, -1.0) * texelSize0;
|
||||
sampleNE = varTexCoord.st + vec2(1.0, -1.0) * texelSize0;
|
||||
sampleSW = varTexCoord.st + vec2(-1.0, 1.0) * texelSize0;
|
||||
sampleSE = varTexCoord.st + vec2(1.0, 1.0) * texelSize0;
|
||||
gl_Position = inVertexPosition;
|
||||
}
|
@ -8,6 +8,8 @@ struct ExposureParams {
|
||||
uniform sampler2D rendered;
|
||||
uniform sampler2D bloom;
|
||||
|
||||
uniform vec2 texelSize0;
|
||||
|
||||
uniform ExposureParams exposureParams;
|
||||
uniform lowp float bloomIntensity;
|
||||
uniform lowp float saturation;
|
||||
@ -80,7 +82,15 @@ vec3 applySaturation(vec3 color, float factor)
|
||||
void main(void)
|
||||
{
|
||||
vec2 uv = varTexCoord.st;
|
||||
#ifdef ENABLE_SSAA
|
||||
vec4 color = vec4(0.);
|
||||
for (float dx = 1.; dx < SSAA_SCALE; dx += 2.)
|
||||
for (float dy = 1.; dy < SSAA_SCALE; dy += 2.)
|
||||
color += texture2D(rendered, uv + texelSize0 * vec2(dx, dy)).rgba;
|
||||
color /= SSAA_SCALE * SSAA_SCALE / 4.;
|
||||
#else
|
||||
vec4 color = texture2D(rendered, uv).rgba;
|
||||
#endif
|
||||
|
||||
// translate to linear colorspace (approximate)
|
||||
color.rgb = pow(color.rgb, vec3(2.2));
|
||||
|
@ -387,7 +387,8 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
||||
CachedPixelShaderSetting<SamplerLayer_t> m_texture1;
|
||||
CachedPixelShaderSetting<SamplerLayer_t> m_texture2;
|
||||
CachedPixelShaderSetting<SamplerLayer_t> m_texture3;
|
||||
CachedPixelShaderSetting<float, 2> m_texel_size0;
|
||||
CachedVertexShaderSetting<float, 2> m_texel_size0_vertex;
|
||||
CachedPixelShaderSetting<float, 2> m_texel_size0_pixel;
|
||||
std::array<float, 2> m_texel_size0_values;
|
||||
CachedStructPixelShaderSetting<float, 7> m_exposure_params_pixel;
|
||||
float m_user_exposure_compensation;
|
||||
@ -445,7 +446,8 @@ public:
|
||||
m_texture1("texture1"),
|
||||
m_texture2("texture2"),
|
||||
m_texture3("texture3"),
|
||||
m_texel_size0("texelSize0"),
|
||||
m_texel_size0_vertex("texelSize0"),
|
||||
m_texel_size0_pixel("texelSize0"),
|
||||
m_exposure_params_pixel("exposureParams",
|
||||
std::array<const char*, 7> {
|
||||
"luminanceMin", "luminanceMax", "exposureCorrection",
|
||||
@ -547,7 +549,8 @@ public:
|
||||
tex_id = 3;
|
||||
m_texture3.set(&tex_id, services);
|
||||
|
||||
m_texel_size0.set(m_texel_size0_values.data(), services);
|
||||
m_texel_size0_vertex.set(m_texel_size0_values.data(), services);
|
||||
m_texel_size0_pixel.set(m_texel_size0_values.data(), services);
|
||||
|
||||
const AutoExposure &exposure_params = m_client->getEnv().getLocalPlayer()->getLighting().exposure;
|
||||
std::array<float, 7> exposure_buffer = {
|
||||
|
@ -130,6 +130,11 @@ RenderStep* addUpscaling(RenderPipeline *pipeline, RenderStep *previousStep, v2f
|
||||
if (downscale_factor.X == 1.0f && downscale_factor.Y == 1.0f)
|
||||
return previousStep;
|
||||
|
||||
// When shaders are enabled, post-processing pipeline takes care of rescaling
|
||||
if (g_settings->getBool("enable_shaders"))
|
||||
return previousStep;
|
||||
|
||||
|
||||
// Initialize buffer
|
||||
TextureBuffer *buffer = pipeline->createOwned<TextureBuffer>();
|
||||
buffer->setTexture(TEXTURE_UPSCALE, downscale_factor, "upscale", video::ECF_A8R8G8B8);
|
||||
|
@ -118,9 +118,23 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
||||
static const u8 TEXTURE_BLOOM = 2;
|
||||
static const u8 TEXTURE_EXPOSURE_1 = 3;
|
||||
static const u8 TEXTURE_EXPOSURE_2 = 4;
|
||||
static const u8 TEXTURE_FXAA = 5;
|
||||
static const u8 TEXTURE_BLOOM_DOWN = 10;
|
||||
static const u8 TEXTURE_BLOOM_UP = 20;
|
||||
|
||||
// Super-sampling is simply rendering into a larger texture.
|
||||
// Downscaling is done by the final step when rendering to the screen.
|
||||
const std::string antialiasing = g_settings->get("antialiasing");
|
||||
const bool enable_bloom = g_settings->getBool("enable_bloom");
|
||||
const bool enable_auto_exposure = g_settings->getBool("enable_auto_exposure");
|
||||
const bool enable_ssaa = antialiasing == "ssaa";
|
||||
const bool enable_fxaa = antialiasing == "fxaa";
|
||||
|
||||
if (enable_ssaa) {
|
||||
u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa"));
|
||||
scale *= ssaa_scale;
|
||||
}
|
||||
|
||||
buffer->setTexture(TEXTURE_COLOR, scale, "3d_render", color_format);
|
||||
buffer->setTexture(TEXTURE_EXPOSURE_1, core::dimension2du(1,1), "exposure_1", color_format, /*clear:*/ true);
|
||||
buffer->setTexture(TEXTURE_EXPOSURE_2, core::dimension2du(1,1), "exposure_2", color_format, /*clear:*/ true);
|
||||
@ -135,8 +149,6 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
||||
// Number of mipmap levels of the bloom downsampling texture
|
||||
const u8 MIPMAP_LEVELS = 4;
|
||||
|
||||
const bool enable_bloom = g_settings->getBool("enable_bloom");
|
||||
const bool enable_auto_exposure = g_settings->getBool("enable_auto_exposure");
|
||||
|
||||
// post-processing stage
|
||||
|
||||
@ -175,6 +187,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
||||
}
|
||||
}
|
||||
|
||||
// Bloom pt 2
|
||||
if (enable_bloom) {
|
||||
// upsample
|
||||
shader_id = client->getShaderSource()->getShader("bloom_upsample", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
@ -188,6 +201,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic Exposure pt2
|
||||
if (enable_auto_exposure) {
|
||||
shader_id = client->getShaderSource()->getShader("update_exposure", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
auto update_exposure = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_EXPOSURE_1, u8(TEXTURE_BLOOM_DOWN + MIPMAP_LEVELS - 1) });
|
||||
@ -196,11 +210,28 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
||||
update_exposure->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_EXPOSURE_2));
|
||||
}
|
||||
|
||||
// final post-processing
|
||||
shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
PostProcessingStep *effect = pipeline->createOwned<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_COLOR, TEXTURE_BLOOM_UP, TEXTURE_EXPOSURE_2 });
|
||||
// FXAA
|
||||
u8 final_stage_source = TEXTURE_COLOR;
|
||||
|
||||
if (enable_fxaa) {
|
||||
final_stage_source = TEXTURE_FXAA;
|
||||
|
||||
buffer->setTexture(TEXTURE_FXAA, scale, "fxaa", color_format);
|
||||
shader_id = client->getShaderSource()->getShader("fxaa", TILE_MATERIAL_PLAIN);
|
||||
PostProcessingStep *effect = pipeline->createOwned<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_COLOR });
|
||||
pipeline->addStep(effect);
|
||||
effect->setBilinearFilter(1, true); // apply filter to the bloom
|
||||
effect->setBilinearFilter(0, true);
|
||||
effect->setRenderSource(buffer);
|
||||
effect->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_FXAA));
|
||||
}
|
||||
|
||||
// final merge
|
||||
shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
PostProcessingStep *effect = pipeline->createOwned<PostProcessingStep>(shader_id, std::vector<u8> { final_stage_source, TEXTURE_BLOOM_UP, TEXTURE_EXPOSURE_2 });
|
||||
pipeline->addStep(effect);
|
||||
if (enable_ssaa)
|
||||
effect->setBilinearFilter(0, true);
|
||||
effect->setBilinearFilter(1, true);
|
||||
effect->setRenderSource(buffer);
|
||||
|
||||
if (enable_auto_exposure) {
|
||||
|
@ -122,7 +122,8 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
|
||||
|
||||
// bpp, fsaa, vsync
|
||||
bool vsync = g_settings->getBool("vsync");
|
||||
u16 fsaa = g_settings->getU16("fsaa");
|
||||
bool enable_fsaa = g_settings->get("antialiasing") == "fsaa";
|
||||
u16 fsaa = enable_fsaa ? g_settings->getU16("fsaa") : 0;
|
||||
|
||||
// Determine driver
|
||||
auto driverType = chooseVideoDriver();
|
||||
|
@ -780,6 +780,12 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
||||
if (g_settings->getBool("enable_auto_exposure"))
|
||||
shaders_header << "#define ENABLE_AUTO_EXPOSURE 1\n";
|
||||
|
||||
if (g_settings->get("antialiasing") == "ssaa") {
|
||||
shaders_header << "#define ENABLE_SSAA 1\n";
|
||||
u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa"));
|
||||
shaders_header << "#define SSAA_SCALE " << ssaa_scale << ".\n";
|
||||
}
|
||||
|
||||
shaders_header << "#line 0\n"; // reset the line counter for meaningful diagnostics
|
||||
|
||||
std::string common_header = shaders_header.str();
|
||||
|
@ -264,6 +264,7 @@ void set_default_settings()
|
||||
settings->setDefault("enable_waving_plants", "false");
|
||||
settings->setDefault("exposure_compensation", "0.0");
|
||||
settings->setDefault("enable_auto_exposure", "false");
|
||||
settings->setDefault("antialiasing", "none");
|
||||
settings->setDefault("enable_bloom", "false");
|
||||
settings->setDefault("enable_bloom_debug", "false");
|
||||
settings->setDefault("bloom_strength_factor", "1.0");
|
||||
|
Loading…
Reference in New Issue
Block a user