Eevee: SSR: Add fullscreen raytrace.
authorClément Foucault <foucault.clem@gmail.com>
Fri, 21 Jul 2017 13:06:29 +0000 (15:06 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Mon, 24 Jul 2017 13:28:27 +0000 (15:28 +0200)
source/blender/draw/engines/eevee/eevee_effects.c
source/blender/draw/engines/eevee/eevee_private.h
source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl

index af3d073a6cf7ae1ab984127fbbf16c083591acfb..13c6bf4ee446624de68a02a2b5e591713a468516 100644 (file)
@@ -86,7 +86,9 @@ static struct {
 
        /* Screen Space Reflection */
        struct GPUShader *ssr_raytrace_sh;
+       struct GPUShader *ssr_raytrace_full_sh;
        struct GPUShader *ssr_resolve_sh;
+       struct GPUShader *ssr_resolve_full_sh;
 
        /* Simple Downsample */
        struct GPUShader *downsample_sh;
@@ -197,7 +199,11 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
                BLI_dynstr_free(ds_frag);
 
                e_data.ssr_raytrace_sh = DRW_shader_create_fullscreen(ssr_shader_str, SHADER_DEFINES "#define STEP_RAYTRACE\n");
+               e_data.ssr_raytrace_full_sh = DRW_shader_create_fullscreen(ssr_shader_str, SHADER_DEFINES "#define STEP_RAYTRACE\n"
+                                                                                                         "#define FULLRES\n");
                e_data.ssr_resolve_sh = DRW_shader_create_fullscreen(ssr_shader_str, SHADER_DEFINES "#define STEP_RESOLVE\n");
+               e_data.ssr_resolve_full_sh = DRW_shader_create_fullscreen(ssr_shader_str, SHADER_DEFINES "#define STEP_RESOLVE\n"
+                                                                                                        "#define FULLRES\n");
 
                MEM_freeN(ssr_shader_str);
 
@@ -542,7 +548,10 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
                /* 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};
+               effects->reflection_trace_full = true;
+
+               const int divisor = (effects->reflection_trace_full) ? 1 : 2;
+               int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor};
                const bool record_two_hit = false;
                const bool high_qual_input = true; /* TODO dither low quality input */
 
@@ -704,8 +713,11 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
        }
 
        if ((effects->enabled_effects & EFFECT_SSR) != 0) {
+               struct GPUShader *trace_shader = (effects->reflection_trace_full) ? e_data.ssr_raytrace_full_sh : e_data.ssr_raytrace_sh;
+               struct GPUShader *resolve_shader = (effects->reflection_trace_full) ? e_data.ssr_resolve_full_sh : e_data.ssr_resolve_sh;
+
                psl->ssr_raytrace = DRW_pass_create("SSR Raytrace", DRW_STATE_WRITE_COLOR);
-               DRWShadingGroup *grp = DRW_shgroup_create(e_data.ssr_raytrace_sh, psl->ssr_raytrace);
+               DRWShadingGroup *grp = DRW_shgroup_create(trace_shader, psl->ssr_raytrace);
                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);
@@ -715,7 +727,7 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
                DRW_shgroup_call_add(grp, quad, NULL);
 
                psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
-               grp = DRW_shgroup_create(e_data.ssr_resolve_sh, psl->ssr_resolve);
+               grp = DRW_shgroup_create(resolve_shader, psl->ssr_resolve);
                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);
@@ -1193,7 +1205,9 @@ void EEVEE_effects_free(void)
 {
        DRW_SHADER_FREE_SAFE(e_data.downsample_sh);
        DRW_SHADER_FREE_SAFE(e_data.ssr_raytrace_sh);
+       DRW_SHADER_FREE_SAFE(e_data.ssr_raytrace_full_sh);
        DRW_SHADER_FREE_SAFE(e_data.ssr_resolve_sh);
+       DRW_SHADER_FREE_SAFE(e_data.ssr_resolve_full_sh);
 
        DRW_SHADER_FREE_SAFE(e_data.volumetric_upsample_sh);
 
index eec264f1711097ad3b432a1e172d881ca34fb536..22d100ba13e23924f5191ddbead23e28b11ae08d 100644 (file)
@@ -320,6 +320,7 @@ typedef struct EEVEE_EffectsInfo {
 
        /* SSR */
        bool use_ssr;
+       bool reflection_trace_full;
 
        /* Ambient Occlusion */
        bool use_ao, use_bent_normals;
index e266dac6d226414cf8531a3f3b39962ccee97d98..4473d73c5c830d6b69cf97dc2423ad46c6ce14a8 100644 (file)
@@ -34,15 +34,24 @@ layout(location = 1) out vec4 pdfData;
 
 void main()
 {
+#ifdef FULLRES
+       ivec2 fullres_texel = ivec2(gl_FragCoord.xy);
+       ivec2 halfres_texel = fullres_texel;
+#else
        ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2;
        ivec2 halfres_texel = ivec2(gl_FragCoord.xy);
+#endif
+
        float depth = texelFetch(depthBuffer, fullres_texel, 0).r;
 
        /* Early out */
        if (depth == 1.0)
                discard;
 
-       vec2 uvs = gl_FragCoord.xy * 2.0 / vec2(textureSize(depthBuffer, 0));
+       vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0));
+#ifndef FULLRES
+       uvs *= 2.0;
+#endif
 
        /* Using view space */
        vec3 viewPosition = get_view_space_from_depth(uvs, depth);
@@ -75,8 +84,10 @@ void main()
 
        /* Raycast over screen */
        float hit_dist = -1.0;
+       /* Only raytrace if ray is above the surface normal */
+       /* Note : this still fails in some cases like with normal map.
+        * We should check against the geometric normal but we don't have it at this stage. */
        if (dot(R, N) > 0.0001) {
-               /* Only raytrace if ray is above the surface normal */
                hit_dist = raycast(depthBuffer, viewPosition, R);
        }
 
@@ -195,8 +206,12 @@ float screen_border_mask(vec2 past_hit_co, vec3 hit)
 
 void main()
 {
-       ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0);
        ivec2 fullres_texel = ivec2(gl_FragCoord.xy);
+#ifdef FULLRES
+       ivec2 halfres_texel = fullres_texel;
+#else
+       ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0);
+#endif
        vec2 texture_size = vec2(textureSize(depthBuffer, 0));
        vec2 uvs = gl_FragCoord.xy / texture_size;
        vec3 rand = texelFetch(utilTex, ivec3(fullres_texel % LUT_SIZE, 2), 0).rba;