Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c13
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h3
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c119
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl25
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl104
6 files changed, 233 insertions, 47 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 14924345d3e..ccb61d3e328 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -251,6 +251,22 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object
}
/**
+ * Setup depth double buffer.
+ */
+ if ((effects->enabled_effects & EFFECT_DEPTH_DOUBLE_BUFFER) != 0) {
+ DRW_texture_ensure_fullscreen_2D(&txl->depth_double_buffer, DRW_TEX_DEPTH_24_STENCIL_8, 0);
+
+ GPU_framebuffer_ensure_config(&fbl->double_buffer_depth_fb, {
+ GPU_ATTACHMENT_TEXTURE(txl->depth_double_buffer)
+ });
+ }
+ else {
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->depth_double_buffer);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_depth_fb);
+ }
+
+ /**
* Setup double buffer so we can access last frame as it was before post processes.
*/
if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index be9a9fa157a..2c459f5ae3b 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -204,12 +204,18 @@ static void eevee_draw_background(void *vedata)
double offset[3] = {0.0, 0.0, 0.0};
double r[3];
+ bool taa_use_reprojection = (stl->effects->enabled_effects & EFFECT_TAA_REPROJECT) != 0;
+
if (DRW_state_is_image_render() ||
+ taa_use_reprojection ||
((stl->effects->enabled_effects & EFFECT_TAA) != 0))
{
- BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r);
+ int samp = taa_use_reprojection
+ ? stl->effects->taa_reproject_sample + 1
+ : stl->effects->taa_current_sample;
+ BLI_halton_3D(primes, offset, samp, r);
EEVEE_update_noise(psl, fbl, r);
- EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1);
+ EEVEE_volumes_set_jitter(sldata, samp - 1);
EEVEE_materials_init(sldata, stl, fbl);
}
/* Copy previous persmat to UBO data */
@@ -217,7 +223,8 @@ static void eevee_draw_background(void *vedata)
if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) &&
(stl->effects->taa_current_sample > 1) &&
- !DRW_state_is_image_render())
+ !DRW_state_is_image_render() &&
+ !taa_use_reprojection)
{
DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 07624100ea7..9c4d7d65ccd 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -483,6 +483,8 @@ typedef enum EEVEE_EffectsFlag {
EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */
EFFECT_SSS = (1 << 11),
EFFECT_VELOCITY_BUFFER = (1 << 12), /* Not really an effect but a feature */
+ EFFECT_TAA_REPROJECT = (1 << 13), /* should be mutually exclusive with EFFECT_TAA */
+ EFFECT_DEPTH_DOUBLE_BUFFER = (1 << 14), /* Not really an effect but a feature */
} EEVEE_EffectsFlag;
typedef struct EEVEE_EffectsInfo {
@@ -506,6 +508,7 @@ typedef struct EEVEE_EffectsInfo {
struct GPUTexture *ssr_hit_output;
struct GPUTexture *ssr_pdf_output;
/* Temporal Anti Aliasing */
+ int taa_reproject_sample;
int taa_current_sample;
int taa_render_sample;
int taa_total_sample;
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index acc1bff6331..06f6293240d 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -27,7 +27,10 @@
#include "DRW_render.h"
+#include "ED_screen.h"
+
#include "BLI_rand.h"
+#include "BLI_string_utils.h"
#include "eevee_private.h"
#include "GPU_texture.h"
@@ -37,16 +40,29 @@
static struct {
/* Temporal Anti Aliasing */
struct GPUShader *taa_resolve_sh;
+ struct GPUShader *taa_resolve_reproject_sh;
/* Pixel filter table: Only blackman-harris for now. */
float inverted_cdf[FILTER_CDF_TABLE_SIZE];
} e_data = {NULL}; /* Engine data */
+extern char datatoc_common_uniforms_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_effect_temporal_aa_glsl[];
static void eevee_create_shader_temporal_sampling(void)
{
- e_data.taa_resolve_sh = DRW_shader_create_fullscreen(datatoc_effect_temporal_aa_glsl, NULL);
+ char *frag_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_effect_temporal_aa_glsl);
+
+ e_data.taa_resolve_sh = DRW_shader_create_fullscreen(frag_str, NULL);
+ e_data.taa_resolve_reproject_sh = DRW_shader_create_fullscreen(frag_str, "#define USE_REPROJECTION\n");
+
+ MEM_freeN(frag_str);
}
static float UNUSED_FUNCTION(filter_box)(float UNUSED(x))
@@ -163,6 +179,11 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
+ if (!e_data.taa_resolve_sh) {
+ eevee_create_shader_temporal_sampling();
+ eevee_create_cdf_table_temporal_sampling();
+ }
+
/* Reset for each "redraw". When rendering using ogl render,
* we accumulate the redraw inside the drawing loop in eevee_draw_background().
* But we do NOT accumulate between "redraw" (as in full draw manager drawloop)
@@ -173,6 +194,14 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
ViewLayer *view_layer = draw_ctx->view_layer;
IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ int repro_flag = 0;
+ if (!DRW_state_is_image_render() &&
+ BKE_collection_engine_property_value_get_bool(props, "taa_reprojection"))
+ {
+ repro_flag = EFFECT_TAA_REPROJECT | EFFECT_VELOCITY_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
+ effects->taa_reproject_sample = ((effects->taa_reproject_sample + 1) % 16);
+ }
+
if ((BKE_collection_engine_property_value_get_int(props, "taa_samples") != 1 &&
/* FIXME the motion blur camera evaluation is tagging view_updated
* thus making the TAA always reset and never stopping rendering. */
@@ -181,17 +210,17 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
{
float persmat[4][4], viewmat[4][4];
- 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
* that the history buffer contains correct information. */
bool view_is_valid = stl->g_data->valid_double_buffer;
view_is_valid = view_is_valid && (stl->g_data->view_updated == false);
+ if (draw_ctx->evil_C != NULL) {
+ struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
+ view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL);
+ }
+
effects->taa_total_sample = BKE_collection_engine_property_value_get_int(props, "taa_samples");
MAX2(effects->taa_total_sample, 0);
@@ -215,6 +244,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
/* OGL render already jitter the camera. */
if (!DRW_state_is_image_render()) {
effects->taa_current_sample += 1;
+ repro_flag = 0;
double ht_point[2];
double ht_offset[2] = {0.0, 0.0};
@@ -238,42 +268,54 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
effects->taa_current_sample = 1;
}
- DRW_texture_ensure_fullscreen_2D(&txl->depth_double_buffer, DRW_TEX_DEPTH_24_STENCIL_8, 0);
-
- GPU_framebuffer_ensure_config(&fbl->double_buffer_depth_fb, {
- GPU_ATTACHMENT_TEXTURE(txl->depth_double_buffer)
- });
-
- return EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
+ return repro_flag | EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
}
effects->taa_current_sample = 1;
- /* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->depth_double_buffer);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_depth_fb);
-
- return 0;
+ return repro_flag;
}
-void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
- if ((effects->enabled_effects & EFFECT_TAA) != 0) {
+ if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) {
+ struct GPUShader *sh = (effects->enabled_effects & EFFECT_TAA_REPROJECT)
+ ? e_data.taa_resolve_reproject_sh
+ : e_data.taa_resolve_sh;
+
psl->taa_resolve = DRW_pass_create("Temporal AA Resolve", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.taa_resolve_sh, psl->taa_resolve);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->taa_resolve);
- DRW_shgroup_uniform_texture_ref(grp, "historyBuffer", &txl->color_double_buffer);
+ DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->color_double_buffer);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &txl->color);
- DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1);
+
+ if (effects->enabled_effects & EFFECT_TAA_REPROJECT) {
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ DRW_shgroup_uniform_texture_ref(grp, "velocityBuffer", &effects->velocity_tx);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ }
+ else {
+ DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1);
+ }
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
+/* Special Swap */
+#define SWAP_BUFFER_TAA() do { \
+ SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer_fb); \
+ SWAP(struct GPUFrameBuffer *, fbl->effect_color_fb, fbl->double_buffer_color_fb); \
+ SWAP(GPUTexture *, txl->color_post, txl->color_double_buffer); \
+ effects->swap_double_buffer = false; \
+ effects->source_buffer = txl->color_double_buffer; \
+ effects->target_buffer = fbl->main_color_fb; \
+} while (0);
+
void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
@@ -282,8 +324,8 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- if ((effects->enabled_effects & EFFECT_TAA) != 0) {
- if (effects->taa_current_sample != 1) {
+ if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) {
+ if ((effects->enabled_effects & EFFECT_TAA) != 0 && effects->taa_current_sample != 1) {
if (DRW_state_is_image_render()) {
/* See EEVEE_temporal_sampling_init() for more details. */
effects->taa_alpha = 1.0f / (float)(effects->taa_render_sample);
@@ -300,19 +342,24 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
GPU_framebuffer_blit(fbl->double_buffer_depth_fb, 0, fbl->main_fb, 0, GPU_DEPTH_BIT);
}
- /* Special Swap */
- SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer_fb);
- SWAP(struct GPUFrameBuffer *, fbl->effect_color_fb, fbl->double_buffer_color_fb);
- SWAP(GPUTexture *, txl->color_post, txl->color_double_buffer);
- effects->swap_double_buffer = false;
- effects->source_buffer = txl->color_double_buffer;
- effects->target_buffer = fbl->main_color_fb;
+ SWAP_BUFFER_TAA();
}
else {
- /* Save the depth buffer for the next frame.
- * This saves us from doing anything special
- * in the other mode engines. */
if (!DRW_state_is_image_render()) {
+ /* Do reprojection for noise reduction */
+ /* TODO : do AA jitter if in only render view. */
+ if ((effects->enabled_effects & EFFECT_TAA_REPROJECT) != 0 &&
+ stl->g_data->valid_double_buffer)
+ {
+ GPU_framebuffer_bind(fbl->effect_color_fb);
+ DRW_draw_pass(psl->taa_resolve);
+
+ SWAP_BUFFER_TAA();
+ }
+
+ /* Save the depth buffer for the next frame.
+ * This saves us from doing anything special
+ * in the other mode engines. */
GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT);
}
}
@@ -330,10 +377,10 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
}
}
}
-
}
void EEVEE_temporal_sampling_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh);
+ DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh);
}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index b5e54c8747a..9f4f508d6fd 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -95,6 +95,30 @@ vec3 project_point(mat4 m, vec3 v) {
return tmp.xyz / tmp.w;
}
+#define min3(a, b, c) min(a, min(b, c))
+#define min4(a, b, c, d) min(a, min3(b, c, d))
+#define min5(a, b, c, d, e) min(a, min4(b, c, d, e))
+#define min6(a, b, c, d, e, f) min(a, min5(b, c, d, e, f))
+#define min7(a, b, c, d, e, f, g) min(a, min6(b, c, d, e, f, g))
+#define min8(a, b, c, d, e, f, g, h) min(a, min7(b, c, d, e, f, g, h))
+#define min9(a, b, c, d, e, f, g, h, i) min(a, min8(b, c, d, e, f, g, h, i))
+
+#define max3(a, b, c) max(a, max(b, c))
+#define max4(a, b, c, d) max(a, max3(b, c, d))
+#define max5(a, b, c, d, e) max(a, max4(b, c, d, e))
+#define max6(a, b, c, d, e, f) max(a, max5(b, c, d, e, f))
+#define max7(a, b, c, d, e, f, g) max(a, max6(b, c, d, e, f, g))
+#define max8(a, b, c, d, e, f, g, h) max(a, max7(b, c, d, e, f, g, h))
+#define max9(a, b, c, d, e, f, g, h, i) max(a, max8(b, c, d, e, f, g, h, i))
+
+#define avg3(a, b, c) (a + b + c) * (1.0 / 3.0)
+#define avg4(a, b, c, d) (a + b + c + d) * (1.0 / 4.0)
+#define avg5(a, b, c, d, e) (a + b + c + d + e) * (1.0 / 5.0)
+#define avg6(a, b, c, d, e, f) (a + b + c + d + e + f) * (1.0 / 6.0)
+#define avg7(a, b, c, d, e, f, g) (a + b + c + d + e + f + g) * (1.0 / 7.0)
+#define avg8(a, b, c, d, e, f, g, h) (a + b + c + d + e + f + g + h) * (1.0 / 8.0)
+#define avg9(a, b, c, d, e, f, g, h, i) (a + b + c + d + e + f + g + h + i) * (1.0 / 9.0)
+
float min_v2(vec2 v) { return min(v.x, v.y); }
float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
float max_v2(vec2 v) { return max(v.x, v.y); }
@@ -252,6 +276,7 @@ void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B)
}
/* ---- Opengl Depth conversion ---- */
+
float linear_depth(bool is_persp, float z, float zf, float zn)
{
if (is_persp) {
diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
index f3df1864317..b3b94b0a391 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
@@ -1,14 +1,102 @@
-uniform sampler2D colorBuffer;
-uniform sampler2D historyBuffer;
-uniform float alpha;
+uniform sampler2D colorHistoryBuffer;
+uniform sampler2D velocityBuffer;
out vec4 FragColor;
+#ifdef USE_REPROJECTION
+
+/**
+ * Adapted from https://casual-effects.com/g3d/G3D10/data-files/shader/Film/Film_temporalAA.pix
+ * which is adapted from https://github.com/gokselgoktas/temporal-anti-aliasing/blob/master/Assets/Resources/Shaders/TemporalAntiAliasing.cginc
+ * which is adapted from https://github.com/playdeadgames/temporal
+ * Optimization by Stubbesaurus and epsilon adjustment to avoid division by zero.
+ *
+ * This can cause 3x3 blocks of color when there is a thin edge of a similar color that
+ * is varying in intensity.
+ */
+vec3 clip_to_aabb(vec3 color, vec3 minimum, vec3 maximum, vec3 average)
+{
+ /* note: only clips towards aabb center (but fast!) */
+ vec3 center = 0.5 * (maximum + minimum);
+ vec3 extents = 0.5 * (maximum - minimum);
+ vec3 dist = color - center;
+ vec3 ts = abs(extents) / max(abs(dist), vec3(0.0001));
+ float t = saturate(min_v3(ts));
+ return center + dist * t;
+}
+
+/**
+ * Vastly based on https://github.com/playdeadgames/temporal
+ */
+void main()
+{
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ float depth = texelFetch(depthBuffer, texel, 0).r;
+ vec2 motion = texelFetch(velocityBuffer, texel, 0).rg;
+
+ /* Compute pixel position in previous frame. */
+ vec2 screen_res = vec2(textureSize(colorBuffer, 0).xy);
+ vec2 uv = gl_FragCoord.xy / screen_res;
+ vec2 uv_history = uv - motion;
+
+ ivec2 texel_history = ivec2(uv_history * screen_res);
+ vec4 color_history = textureLod(colorHistoryBuffer, uv_history, 0.0);
+
+ /* Color bounding box clamping. 3x3 neighborhood. */
+ vec4 c02 = texelFetchOffset(colorBuffer, texel, 0, ivec2(-1, 1));
+ vec4 c12 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 0, 1));
+ vec4 c22 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 1, 1));
+ vec4 c01 = texelFetchOffset(colorBuffer, texel, 0, ivec2(-1, 0));
+ vec4 c11 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 0, 0));
+ vec4 c21 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 1, 0));
+ vec4 c00 = texelFetchOffset(colorBuffer, texel, 0, ivec2(-1, -1));
+ vec4 c10 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 0, -1));
+ vec4 c20 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 1, -1));
+
+ vec4 color = c11;
+
+ /* AABB minmax */
+ vec4 min_col = min9(c02, c12, c22, c01, c11, c21, c00, c10, c20);
+ vec4 max_col = max9(c02, c12, c22, c01, c11, c21, c00, c10, c20);
+ vec4 avg_col = avg9(c02, c12, c22, c01, c11, c21, c00, c10, c20);
+
+ /* bias the color aabb toward the center (rounding the shape) */
+ vec4 min_center = min5(c12, c01, c11, c21, c10);
+ vec4 max_center = max5(c12, c01, c11, c21, c10);
+ vec4 avg_center = avg5(c12, c01, c11, c21, c10);
+ min_col = (min_col + min_center) * 0.5;
+ max_col = (max_col + max_center) * 0.5;
+ avg_col = (avg_col + avg_center) * 0.5;
+
+ /* Clip color toward the center of the neighborhood colors AABB box. */
+ color_history.rgb = clip_to_aabb(color_history.rgb, min_col.rgb, max_col.rgb, avg_col.rgb);
+
+ /* Luminance weighting. */
+ /* TODO correct luminance */
+ float lum0 = dot(color.rgb, vec3(0.333));
+ float lum1 = dot(color_history.rgb, vec3(0.333));
+ float diff = abs(lum0 - lum1) / max(lum0, max(lum1, 0.2));
+ float weight = 1.0 - diff;
+ float alpha = mix(0.04, 0.12, weight * weight);
+
+ color_history = mix(color_history, color, alpha);
+
+ bool out_of_view = any(greaterThanEqual(abs(uv_history - 0.5), vec2(0.5)));
+ color_history = (out_of_view) ? color : color_history;
+
+ FragColor = color_history;
+}
+
+#else
+
+uniform float alpha;
+
void main()
{
- /* TODO History buffer Reprojection */
- vec4 history = texelFetch(historyBuffer, ivec2(gl_FragCoord.xy), 0).rgba;
- vec4 color = texelFetch(colorBuffer, ivec2(gl_FragCoord.xy), 0).rgba;
- FragColor = mix(history, color, alpha);
-} \ No newline at end of file
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ vec4 color = texelFetch(colorBuffer, texel, 0);
+ vec4 color_history = texelFetch(colorHistoryBuffer, texel, 0);
+ FragColor = mix(color_history, color, alpha);
+}
+#endif \ No newline at end of file