Commit: cc1e88b37a3b897f1b0c490e8cb80eb4de3eb5da Author: Clément Foucault Date: Sat Feb 3 23:48:00 2018 +0100 Branches: blender2.8 https://developer.blender.org/rBcc1e88b37a3b897f1b0c490e8cb80eb4de3eb5da
Eevee: AA: Add Blackmann-Harris pixel filter distribution. This leads to a huge improvement of AntiAliasing quality. There is no other distribution now and there is not settings displayed to the user. That's for another commit. =================================================================== M source/blender/draw/engines/eevee/eevee_private.h M source/blender/draw/engines/eevee/eevee_temporal_sampling.c =================================================================== diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index cc78a9db8dd..6159126d71e 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -858,7 +858,7 @@ void EEVEE_mist_free(void); /* eevee_temporal_sampling.c */ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_temporal_sampling_matrices_calc( - EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], double ht_point[2]); + EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], const double ht_point[2]); void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata); void EEVEE_temporal_sampling_free(void); diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 24b8117b6f5..0324310d398 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -32,9 +32,14 @@ #include "eevee_private.h" #include "GPU_texture.h" +#define FILTER_CDF_TABLE_SIZE 512 + static struct { /* Temporal Anti Aliasing */ struct GPUShader *taa_resolve_sh; + + /* Pixel filter table: Only blackman-harris for now. */ + float inverted_cdf[FILTER_CDF_TABLE_SIZE]; } e_data = {NULL}; /* Engine data */ extern char datatoc_effect_temporal_aa_glsl[]; @@ -44,17 +49,91 @@ static void eevee_create_shader_temporal_sampling(void) e_data.taa_resolve_sh = DRW_shader_create_fullscreen(datatoc_effect_temporal_aa_glsl, NULL); } +static float blackman_harris(float x) +{ + /* Hardcoded 1px footprint [-0.5..0.5]. We resize later. */ + const float width = 1.0f; + x = 2.0f * M_PI * (x / width + 0.5f); + return 0.35875f - 0.48829f * cosf(x) + 0.14128f * cosf(2.0f * x) - 0.01168f * cosf(3.0f * x); +} + +/* Compute cumulative distribution function of a discrete function. */ +static void compute_cdf(float (*func)(float x), float cdf[FILTER_CDF_TABLE_SIZE]) +{ + cdf[0] = 0.0f; + /* Actual CDF evaluation. */ + for(int u = 0; u < FILTER_CDF_TABLE_SIZE - 1; ++u) { + float x = (float)(u + 1) / (float)(FILTER_CDF_TABLE_SIZE - 1); + cdf[u + 1] = cdf[u] + func(x - 0.5f); /* [-0.5..0.5]. We resize later. */ + } + /* Normalize the CDF. */ + for(int u = 0; u < FILTER_CDF_TABLE_SIZE - 1; u++) { + cdf[u] /= cdf[FILTER_CDF_TABLE_SIZE - 1]; + } + /* Just to make sure. */ + cdf[FILTER_CDF_TABLE_SIZE - 1] = 1.0f; +} + +static void invert_cdf(const float cdf[FILTER_CDF_TABLE_SIZE], float invert_cdf[FILTER_CDF_TABLE_SIZE]) +{ + for (int u = 0; u < FILTER_CDF_TABLE_SIZE; u++) { + float x = (float)u / (float)(FILTER_CDF_TABLE_SIZE - 1); + for (int i = 0; i < FILTER_CDF_TABLE_SIZE; ++i) { + if (cdf[i] >= x) { + if (i == FILTER_CDF_TABLE_SIZE - 1) { + invert_cdf[u] = 1.0f; + } + else { + float t = (x - cdf[i])/(cdf[i+1] - cdf[i]); + invert_cdf[u] = ((float)i + t) / (float)(FILTER_CDF_TABLE_SIZE - 1); + } + break; + } + } + } +} + +/* Evaluate a discrete function table with linear interpolation. */ +static float eval_table(float *table, float x) +{ + CLAMP(x, 0.0f, 1.0f); + x = x * (FILTER_CDF_TABLE_SIZE - 1); + + int index = min_ii((int)(x), FILTER_CDF_TABLE_SIZE - 1); + int nindex = min_ii(index + 1, FILTER_CDF_TABLE_SIZE - 1); + float t = x - index; + + return (1.0f - t) * table[index] + t * table[nindex]; +} + +static void eevee_create_cdf_table_temporal_sampling(void) +{ + float *cdf_table = MEM_mallocN(sizeof(float) * FILTER_CDF_TABLE_SIZE, "Eevee Filter CDF table"); + + /* Use blackman-harris filter. */ + compute_cdf(blackman_harris, cdf_table); + invert_cdf(cdf_table, e_data.inverted_cdf); + + MEM_freeN(cdf_table); +} + void EEVEE_temporal_sampling_matrices_calc( - EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], double ht_point[2]) + EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], const double ht_point[2]) { const float *viewport_size = DRW_viewport_size_get(); - /* TODO Blackman-Harris filter */ + float filter_size = 1.5f; /* TODO Option. */ + filter_size *= 2.0f; /* Because of Blackmann Harris to gaussian width matching. */ + /* The cdf precomputing is giving distribution inside [0..1]. + * We need to map it to [-1..1] THEN scale by the desired filter size. */ + filter_size *= 2.0f; + float ofs_x = (eval_table(e_data.inverted_cdf, (float)(ht_point[0])) - 0.5f) * filter_size; + float ofs_y = (eval_table(e_data.inverted_cdf, (float)(ht_point[1])) - 0.5f) * filter_size; window_translate_m4( effects->overide_winmat, persmat, - ((float)(ht_point[0]) * 2.0f - 1.0f) / viewport_size[0], - ((float)(ht_point[1]) * 2.0f - 1.0f) / viewport_size[1]); + ofs_x / viewport_size[0], + ofs_y / viewport_size[1]); mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat); invert_m4_m4(effects->overide_persinv, effects->overide_persmat); @@ -89,6 +168,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data if (!e_data.taa_resolve_sh) { eevee_create_shader_temporal_sampling(); + eevee_create_cdf_table_temporal_sampling(); } /* Until we support reprojection, we need to make sure _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs