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:
authorClément Foucault <foucault.clem@gmail.com>2017-07-19 15:22:03 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-07-24 16:28:27 +0300
commit7938848b636335b0d59cc7cbb42c223ec309c0d7 (patch)
tree3ad09aee025491d3fb65989baa23e17a2b3c7c3c /source/blender
parent14bedf80cd5ed29da70d6f90491d411fccd07ce4 (diff)
Eevee: SSR: Add double buffer so we can read previous frame color.
Also add simple reprojection and screen fade to the SSR resolve pass.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c88
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c13
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h7
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl71
5 files changed, 153 insertions, 32 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index c9ed4970889..f5a943bfb3f 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -45,6 +45,7 @@
#include "eevee_private.h"
#include "GPU_texture.h"
+#include "GPU_framebuffer.h"
#define SHADER_DEFINES \
"#define EEVEE_ENGINE\n" \
@@ -513,6 +514,9 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
if (BKE_collection_engine_property_value_get_bool(props, "ssr_enable")) {
effects->enabled_effects |= EFFECT_SSR;
+ /* Enable double buffering to be able to read previous frame color */
+ effects->enabled_effects |= EFFECT_DOUBLE_BUFFER;
+
int tracing_res[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2};
const bool record_two_hit = false;
const bool high_qual_input = true; /* TODO dither low quality input */
@@ -522,20 +526,27 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
if (txl->ssr_normal_input == NULL) {
DRWTextureFormat nor_format = DRW_TEX_RG_16;
txl->ssr_normal_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], nor_format, 0, NULL);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
}
if (txl->ssr_specrough_input == NULL) {
DRWTextureFormat specrough_format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8;
txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], specrough_format, 0, NULL);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
}
+ /* Reattach textures to the right buffer (because we are alternating between buffers) */
+ /* TODO multiple FBO per texture!!!! */
+ DRW_framebuffer_texture_detach(txl->ssr_normal_input);
+ DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
+
/* Raytracing output */
/* TODO try integer format for hit coord to increase precision */
DRWFboTexture tex_output[2] = {{&txl->ssr_hit_output, (record_two_hit) ? DRW_TEX_RGBA_16 : DRW_TEX_RG_16, 0},
{&txl->ssr_pdf_output, (record_two_hit) ? DRW_TEX_RG_16 : DRW_TEX_R_16, 0}};
+ DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, tracing_res[0], tracing_res[1], tex_output, 2);
+
/* Compute pixel projection matrix */
{
float uvpix[4][4], ndcuv[4][4], tmp[4][4], winmat[4][4];
@@ -547,14 +558,12 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
/* UVs to pixels */
unit_m4(uvpix);
- uvpix[0][0] = tracing_res[0];
- uvpix[1][1] = tracing_res[1];
+ uvpix[0][0] = viewport_size[0];
+ uvpix[1][1] = viewport_size[1];
mul_m4_m4m4(tmp, uvpix, ndcuv);
mul_m4_m4m4(e_data.pixelprojmat, tmp, winmat);
}
-
- DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, tracing_res[0], tracing_res[1], tex_output, 2);
}
else {
/* Cleanup to release memory */
@@ -564,6 +573,23 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
DRW_TEXTURE_FREE_SAFE(txl->ssr_pdf_output);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb);
}
+
+ /* Setup double buffer so we can access last frame as it was before post processes */
+ if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
+ DRWFboTexture tex_double_buffer = {&txl->color_double_buffer, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
+
+ DRW_framebuffer_init(&fbl->double_buffer, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex_double_buffer, 1);
+
+ copy_m4_m4(stl->g_data->prev_persmat, stl->g_data->next_persmat);
+ DRW_viewport_matrix_get(stl->g_data->next_persmat, DRW_MAT_PERS);
+ }
+ else {
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->color_double_buffer);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer);
+ }
}
static DRWShadingGroup *eevee_create_bloom_pass(const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample)
@@ -667,8 +693,10 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
+ DRW_shgroup_uniform_buffer(grp, "colorBuffer", &txl->color_double_buffer);
DRW_shgroup_uniform_buffer(grp, "hitBuffer", &txl->ssr_hit_output);
DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &txl->ssr_pdf_output);
+ DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat);
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_int(grp, "probe_count", &sldata->probes->num_render_cube, 1);
DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
@@ -795,17 +823,6 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
}
}
-#define SWAP_BUFFERS() { \
- if (effects->source_buffer == txl->color) { \
- effects->source_buffer = txl->color_post; \
- effects->target_buffer = fbl->main; \
- } \
- else { \
- effects->source_buffer = txl->color; \
- effects->target_buffer = fbl->effect_fb; \
- } \
-} ((void)0)
-
static void minmax_downsample_cb(void *vedata, int UNUSED(level))
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
@@ -878,11 +895,12 @@ void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *UNUSED(sldata), EEVEE_Data *veda
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
+ if ((effects->enabled_effects & EFFECT_SSR) != 0 && stl->g_data->valid_double_buffer) {
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* Raytrace at halfres. */
- e_data.depth_src = stl->g_data->minmaxz;
+ e_data.depth_src = dtxl->depth;
+ // e_data.depth_src = stl->g_data->minmaxz;
DRW_framebuffer_bind(fbl->screen_tracing_fb);
DRW_draw_pass(psl->ssr_raytrace);
@@ -901,6 +919,26 @@ void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *UNUSED(sldata), EEVEE_Data *veda
}
}
+#define SWAP_DOUBLE_BUFFERS() { \
+ if (swap_double_buffer) { \
+ SWAP(struct GPUFrameBuffer *, fbl->main, fbl->double_buffer); \
+ SWAP(GPUTexture *, txl->color, txl->color_double_buffer); \
+ swap_double_buffer = false; \
+ } \
+} ((void)0)
+
+#define SWAP_BUFFERS() { \
+ if (effects->source_buffer == txl->color) { \
+ effects->source_buffer = txl->color_post; \
+ effects->target_buffer = fbl->main; \
+ } \
+ else { \
+ effects->source_buffer = txl->color; \
+ effects->target_buffer = fbl->effect_fb; \
+ } \
+ SWAP_DOUBLE_BUFFERS(); \
+} ((void)0)
+
void EEVEE_draw_effects(EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
@@ -909,6 +947,9 @@ void EEVEE_draw_effects(EEVEE_Data *vedata)
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
+ /* only once per frame after the first post process */
+ bool swap_double_buffer = ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0);
+
/* Default framebuffer and texture */
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
@@ -1020,6 +1061,15 @@ void EEVEE_draw_effects(EEVEE_Data *vedata)
/* Tonemapping */
DRW_transform_to_display(effects->source_buffer);
+
+ /* If no post processes is enabled, buffers are still not swapped, do it now. */
+ SWAP_DOUBLE_BUFFERS();
+
+ if (!stl->g_data->valid_double_buffer) {
+ /* If history buffer is not valid request another frame.
+ * This fix black reflections on area resize. */
+ DRW_viewport_request_redraw();
+ }
}
void EEVEE_effects_free(void)
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index c8dc8c67c04..59f2613dd06 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -49,6 +49,13 @@ static void EEVEE_engine_init(void *ved)
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_SceneLayerData *sldata = EEVEE_scene_layer_data_get();
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+ stl->g_data->background_alpha = 1.0f;
+ stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
+
DRWFboTexture tex = {&txl->color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
const float *viewport_size = DRW_viewport_size_get();
@@ -56,12 +63,6 @@ static void EEVEE_engine_init(void *ved)
(int)viewport_size[0], (int)viewport_size[1],
&tex, 1);
- if (!stl->g_data) {
- /* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
- }
- stl->g_data->background_alpha = 1.0f;
-
EEVEE_materials_init(stl);
EEVEE_lights_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index f773c48dc32..015bc5b6a9e 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -138,6 +138,7 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *planarref_fb;
struct GPUFrameBuffer *main;
+ struct GPUFrameBuffer *double_buffer;
} EEVEE_FramebufferList;
typedef struct EEVEE_TextureList {
@@ -160,6 +161,7 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *planar_pool;
struct GPUTexture *color; /* R16_G16_B16 */
+ struct GPUTexture *color_double_buffer;
} EEVEE_TextureList;
typedef struct EEVEE_StorageList {
@@ -351,6 +353,7 @@ enum {
EFFECT_DOF = (1 << 2),
EFFECT_VOLUMETRIC = (1 << 3),
EFFECT_SSR = (1 << 4),
+ EFFECT_DOUBLE_BUFFER = (1 << 5), /* Not really an effect but a feature */
};
/* ************** SCENE LAYER DATA ************** */
@@ -447,6 +450,10 @@ typedef struct EEVEE_PrivateData {
float viewvecs[2][4];
/* For planar probes */
float texel_size[2];
+ /* For double buffering */
+ bool valid_double_buffer;
+ float prev_persmat[4][4];
+ float next_persmat[4][4];
} EEVEE_PrivateData; /* Transient data */
/* eevee_data.c */
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 c6a56fa7d82..4bae519b52b 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -97,6 +97,7 @@ mat3 mul(mat3 m1, mat3 m2) { return m1 * m2; }
vec3 transform_point(mat4 m, vec3 v) { return (m * vec4(v, 1.0)).xyz; }
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); }
float saturate(float a) { return clamp(a, 0.0, 1.0); }
vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
@@ -125,6 +126,11 @@ float fast_acos(float x)
return (x >= 0) ? res : M_PI - res;
}
+float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal)
+{
+ return dot(planenormal, planeorigin - lineorigin);
+}
+
float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
{
return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
index 62644c0ac74..e51edec5ddf 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
@@ -17,13 +17,13 @@ void main()
{
ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2;
ivec2 halfres_texel = ivec2(gl_FragCoord.xy);
- float depth = texelFetch(depthBuffer, halfres_texel, 0).r;
+ float depth = texelFetch(depthBuffer, fullres_texel, 0).r;
/* Early discard */
if (depth == 1.0)
discard;
- vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0));
+ vec2 uvs = gl_FragCoord.xy * 2.0 / vec2(textureSize(depthBuffer, 0));
/* Using view space */
vec3 viewPosition = get_view_space_from_depth(uvs, depth);
@@ -61,6 +61,7 @@ void main()
#else /* STEP_RESOLVE */
+uniform sampler2D colorBuffer; /* previous frame */
uniform sampler2D depthBuffer;
uniform sampler2D normalBuffer;
uniform sampler2D specroughBuffer;
@@ -71,6 +72,7 @@ uniform sampler2D pdfBuffer;
uniform int probe_count;
uniform mat4 ViewProjectionMatrix;
+uniform mat4 PastViewProjectionMatrix;
out vec4 fragColor;
@@ -98,6 +100,62 @@ void fallback_cubemap(vec3 N, vec3 V, vec3 W, float roughness, float roughnessSq
}
}
+#if 0 /* Finish reprojection with motion vectors */
+vec3 get_motion_vector(vec3 pos)
+{
+}
+
+/* http://bitsquid.blogspot.fr/2017/06/reprojecting-reflections_22.html */
+vec3 find_reflection_incident_point(vec3 cam, vec3 hit, vec3 pos, vec3 N)
+{
+ float d_cam = point_plane_projection_dist(cam, pos, N);
+ float d_hit = point_plane_projection_dist(hit, pos, N);
+
+ if (d_hit < d_cam) {
+ /* Swap */
+ float tmp = d_cam;
+ d_cam = d_hit;
+ d_hit = tmp;
+ }
+
+ vec3 proj_cam = cam - (N * d_cam);
+ vec3 proj_hit = hit - (N * d_hit);
+
+ return (proj_hit - proj_cam) * d_cam / (d_cam + d_hit) + proj_cam;
+}
+#endif
+
+vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N)
+{
+ /* TODO real motion vectors */
+ /* Transform to viewspace */
+ // vec4(get_view_space_from_depth(uvcoords, depth), 1.0);
+ // vec4(get_view_space_from_depth(uvcoords, depth), 1.0);
+
+ /* Reproject */
+ // vec3 hit_reprojected = find_reflection_incident_point(cameraPos, hit, pos, N);
+
+ vec4 hit_co = PastViewProjectionMatrix * vec4(hit, 1.0);
+ return (hit_co.xy / hit_co.w) * 0.5 + 0.5;
+}
+
+float screen_border_mask(vec2 past_hit_co, vec3 hit)
+{
+ /* Fade on current and past screen edges */
+ vec4 hit_co = ViewProjectionMatrix * vec4(hit, 1.0);
+ hit_co.xy = (hit_co.xy / hit_co.w) * 0.5 + 0.5;
+ hit_co.zw = past_hit_co;
+
+ const float margin = 0.002;
+ const float atten = 0.05 + margin; /* Screen percentage */
+ hit_co = smoothstep(margin, atten, hit_co) * (1 - smoothstep(1.0 - atten, 1.0 - margin, hit_co));
+ vec2 atten_fac = min(hit_co.xy, hit_co.zw);
+
+ float screenfade = atten_fac.x * atten_fac.y;
+
+ return screenfade;
+}
+
void main()
{
ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0);
@@ -122,17 +180,16 @@ void main()
/* Resolve SSR and compute contribution */
- /* We generate the same rays that has been genearted in the raycast step.
+ /* We generate the same rays that has been generated in the raycast step.
* But we add this ray from our resolve pixel position, increassing accuracy. */
vec3 R = generate_ray(-V, N);
float ray_length = texelFetch(hitBuffer, halfres_texel, 0).r;
if (ray_length != -1.0) {
vec3 hit_pos = worldPosition + R * ray_length;
- vec4 hit_co = ViewProjectionMatrix * vec4(hit_pos, 1.0);
- spec_accum.xy = (hit_co.xy / hit_co.w) * 0.5 + 0.5;
- spec_accum.xyz = vec3(mod(dot(floor(hit_pos.xyz * 5.0), vec3(1.0)), 2.0));
- spec_accum.a = 1.0;
+ vec2 ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N);
+ spec_accum.a = screen_border_mask(ref_uvs, hit_pos);
+ spec_accum.xyz = textureLod(colorBuffer, ref_uvs, 0.0).rgb * spec_accum.a;
}
/* If SSR contribution is not 1.0, blend with cubemaps */