From 4fd70c99a5a37db00ea26b8e5efa7d351e5e1e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Tue, 25 Jul 2017 19:03:07 +0200 Subject: Eevee: SSR: Add support for planar probes. This add the possibility to use planar probe informations to create SSR. This has 2 advantages: - Tracing is less expensive since the hit is found much quicker. - We have much less artifact due to missing information. There is still area for improvement. --- source/blender/draw/engines/eevee/eevee_effects.c | 4 + .../blender/draw/engines/eevee/eevee_lightprobes.c | 12 +- .../blender/draw/engines/eevee/eevee_materials.c | 1 + source/blender/draw/engines/eevee/eevee_private.h | 1 + .../engines/eevee/shaders/bsdf_common_lib.glsl | 6 + .../engines/eevee/shaders/effect_ssr_frag.glsl | 168 +++++++++++++++++---- .../draw/engines/eevee/shaders/lightprobe_lib.glsl | 13 +- .../shaders/lightprobe_planar_downsample_frag.glsl | 6 +- .../engines/eevee/shaders/lit_surface_frag.glsl | 19 +-- .../draw/engines/eevee/shaders/raytrace_lib.glsl | 33 +++- 10 files changed, 201 insertions(+), 62 deletions(-) (limited to 'source/blender/draw/engines/eevee') diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 0ddced10ae0..95280c5f206 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -766,6 +766,9 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_vec2(grp, "ssrParameters", &effects->ssr_stride, 1); DRW_shgroup_uniform_mat4(grp, "PixelProjMatrix", (float *)&e_data.pixelprojmat); DRW_shgroup_uniform_int(grp, "rayCount", &effects->ssr_ray_count, 1); + DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1); + DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_call_add(grp, quad, NULL); psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); @@ -777,6 +780,7 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_buffer(grp, "colorBuffer", &txl->color_double_buffer); 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, "planar_count", &sldata->probes->num_planar, 1); DRW_shgroup_uniform_int(grp, "probe_count", &sldata->probes->num_render_cube, 1); DRW_shgroup_uniform_float(grp, "borderFadeFactor", &effects->ssr_border_fac, 1); DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 151efefcda1..869a9798ce2 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -276,6 +276,7 @@ void EEVEE_lightprobes_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *UNUSED(ved if (!sldata->probes) { sldata->probes = MEM_callocN(sizeof(EEVEE_LightProbesInfo), "EEVEE_LightProbesInfo"); sldata->probes->specular_toggle = true; + sldata->probes->ssr_toggle = true; sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightProbe) * MAX_PROBE, NULL); sldata->grid_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightGrid) * MAX_GRID, NULL); sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL); @@ -962,6 +963,7 @@ static void render_scene_to_probe( /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */ sldata->probes->specular_toggle = false; + sldata->probes->ssr_toggle = false; /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */ tmp_ao_dist = stl->effects->ao_dist; @@ -1045,7 +1047,7 @@ static void render_scene_to_probe( } static void render_scene_to_planar( - EEVEE_Data *vedata, int layer, + EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata, int layer, float (*viewmat)[4], float (*persmat)[4], float clip_plane[4]) { @@ -1066,6 +1068,9 @@ static void render_scene_to_planar( DRW_framebuffer_clear(false, true, false, NULL, 1.0); + /* Turn off ssr to avoid black specular */ + sldata->probes->ssr_toggle = false; + /* Avoid using the texture attached to framebuffer when rendering. */ /* XXX */ GPUTexture *tmp_planar_pool = txl->planar_pool; @@ -1103,6 +1108,7 @@ static void render_scene_to_planar( DRW_state_clip_planes_reset(); /* Restore */ + sldata->probes->ssr_toggle = true; txl->planar_pool = tmp_planar_pool; txl->planar_depth = tmp_planar_depth; DRW_viewport_matrix_override_unset(DRW_MAT_PERS); @@ -1323,7 +1329,7 @@ update_planar: int tmp_num_planar = pinfo->num_planar; pinfo->num_planar = 0; - render_scene_to_planar(vedata, i, ped->viewmat, ped->persmat, ped->planer_eq_offset); + render_scene_to_planar(sldata, vedata, i, ped->viewmat, ped->persmat, ped->planer_eq_offset); /* Restore */ pinfo->num_planar = tmp_num_planar; @@ -1335,7 +1341,7 @@ update_planar: /* If there is at least one planar probe */ if (pinfo->num_planar > 0) { - const int max_lod = 5; + const int max_lod = 9; DRW_framebuffer_recursive_downsample(vedata->fbl->downsample_fb, txl->planar_pool, max_lod, &downsample_planar, vedata); /* For shading, save max level of the planar map */ pinfo->lod_planar_max = (float)(max_lod); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index eae9331fedc..c1112eedf0d 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -272,6 +272,7 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData * DRW_shgroup_uniform_int(shgrp, "grid_count", &sldata->probes->num_render_grid, 1); DRW_shgroup_uniform_int(shgrp, "planar_count", &sldata->probes->num_planar, 1); DRW_shgroup_uniform_bool(shgrp, "specToggle", &sldata->probes->specular_toggle, 1); + DRW_shgroup_uniform_bool(shgrp, "ssrToggle", &sldata->probes->ssr_toggle, 1); DRW_shgroup_uniform_float(shgrp, "lodCubeMax", &sldata->probes->lod_cube_max, 1); DRW_shgroup_uniform_float(shgrp, "lodPlanarMax", &sldata->probes->lod_planar_max, 1); DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 55fb550d940..0b1fc2f5dff 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -299,6 +299,7 @@ typedef struct EEVEE_LightProbesInfo { int shres; int shnbr; bool specular_toggle; + bool ssr_toggle; /* List of probes in the scene. */ /* XXX This is fragile, can get out of sync quickly. */ struct Object *probes_cube_ref[MAX_PROBE]; 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 e6cbcde77c7..99e2132277d 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -153,6 +153,12 @@ vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, return lineorigin + linedirection * dist; } +vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane) +{ + float dist = line_plane_intersect_dist(lineorigin, linedirection, plane); + return lineorigin + linedirection * dist; +} + float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) { /* aligned plane normal */ 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 7b516f27ec9..901d1fa4aea 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -30,10 +30,11 @@ vec3 generate_ray(vec3 V, vec3 N, float a2, vec3 rand, out float pdf) #ifdef STEP_RAYTRACE -uniform sampler2D depthBuffer; uniform sampler2D normalBuffer; uniform sampler2D specroughBuffer; +uniform int planar_count; + uniform mat4 ViewProjectionMatrix; layout(location = 0) out vec4 hitData0; @@ -48,14 +49,53 @@ bool has_hit_backface(vec3 hit_pos, vec3 R, vec3 V) return (dot(-R, hit_N) < 0.0); } -vec4 do_ssr(sampler2D depthBuffer, vec3 V, vec3 N, vec3 viewPosition, float a2, vec3 rand) +vec4 do_planar_ssr(int index, vec3 V, vec3 N, vec3 planeNormal, vec3 viewPosition, float a2, vec3 rand) +{ + float pdf; + vec3 R = generate_ray(V, N, a2, rand, pdf); + + R = reflect(R, planeNormal); + pdf *= -1.0; /* Tag as planar ray. */ + + /* If ray is bad (i.e. going below the plane) do not trace. */ + if (dot(R, planeNormal) > 0.0) { + vec3 R = generate_ray(V, N, a2, rand, pdf); + } + + float hit_dist; + if (abs(dot(-R, V)) < 0.9999) { + hit_dist = raycast(index, viewPosition, R, rand.x); + } + else { + float z = get_view_z_from_depth(texelFetch(planarDepth, ivec3(project_point(PixelProjMatrix, viewPosition).xy, index), 0).r); + hit_dist = (z - viewPosition.z) / R.z; + } + + /* Since viewspace hit position can land behind the camera in this case, + * we save the reflected view position (visualize it as the hit position + * below the reflection plane). This way it's garanted that the hit will + * be in front of the camera. That let us tag the bad rays with a negative + * sign in the Z component. */ + vec3 hit_pos = viewPosition + R * abs(hit_dist); + + /* Ray did not hit anything. No backface test because it's not possible + * to hit a backface in this case. */ + if (hit_dist <= 0.0) { + hit_pos.z *= -1.0; + } + + return vec4(hit_pos, pdf); +} + +vec4 do_ssr(vec3 V, vec3 N, vec3 viewPosition, float a2, vec3 rand) { float pdf; vec3 R = generate_ray(V, N, a2, rand, pdf); - float hit_dist = raycast(depthBuffer, viewPosition, R, rand.x); + float hit_dist = raycast(-1, viewPosition, R, rand.x); vec3 hit_pos = viewPosition + R * abs(hit_dist); + /* Ray did not hit anything. Tag it as failled. */ if (has_hit_backface(hit_pos, R, V) || (hit_dist <= 0.0)) { hit_pos.z *= -1.0; } @@ -102,17 +142,41 @@ void main() vec3 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0).rba; + vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition); + vec3 wN = mat3(ViewMatrixInverse) * N; + + /* Planar Reflections */ + for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) { + PlanarData pd = planars_data[i]; + + float fade = probe_attenuation_planar(pd, worldPosition, wN); + + if (fade > 0.5) { + /* Find view vector / reflection plane intersection. */ + /* TODO optimize, use view space for all. */ + vec3 tracePosition = line_plane_intersect(worldPosition, cameraVec, pd.pl_plane_eq); + tracePosition = transform_point(ViewMatrix, tracePosition); + vec3 planeNormal = mat3(ViewMatrix) * pd.pl_normal; + + /* TODO : Raytrace together if textureGather is supported. */ + hitData0 = do_planar_ssr(i, V, N, planeNormal, tracePosition, a2, rand); + if (rayCount > 1) hitData1 = do_planar_ssr(i, V, N, planeNormal, tracePosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0)); + if (rayCount > 2) hitData2 = do_planar_ssr(i, V, N, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0)); + if (rayCount > 3) hitData3 = do_planar_ssr(i, V, N, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0)); + return; + } + } + /* TODO : Raytrace together if textureGather is supported. */ - hitData0 = do_ssr(depthBuffer, V, N, viewPosition, a2, rand); - if (rayCount > 1) hitData1 = do_ssr(depthBuffer, V, N, viewPosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0)); - if (rayCount > 2) hitData2 = do_ssr(depthBuffer, V, N, viewPosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0)); - if (rayCount > 3) hitData3 = do_ssr(depthBuffer, V, N, viewPosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0)); + hitData0 = do_ssr(V, N, viewPosition, a2, rand); + if (rayCount > 1) hitData1 = do_ssr(V, N, viewPosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0)); + if (rayCount > 2) hitData2 = do_ssr(V, N, viewPosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0)); + if (rayCount > 3) hitData3 = do_ssr(V, N, viewPosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0)); } #else /* STEP_RESOLVE */ uniform sampler2D colorBuffer; /* previous frame */ -uniform sampler2D depthBuffer; uniform sampler2D normalBuffer; uniform sampler2D specroughBuffer; @@ -122,6 +186,7 @@ uniform sampler2D hitBuffer2; uniform sampler2D hitBuffer3; uniform int probe_count; +uniform int planar_count; uniform float borderFadeFactor; uniform float fireflyFactor; @@ -185,19 +250,13 @@ float brightness(vec3 c) return max(max(c.r, c.g), c.b); } -float screen_border_mask(vec2 past_hit_co, vec3 hit) +float screen_border_mask(vec2 hit_co) { - /* 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.003; float atten = borderFadeFactor + 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; + float screenfade = hit_co.x * hit_co.y; return screenfade; } @@ -215,32 +274,65 @@ vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N) } vec4 get_ssr_sample( - sampler2D hitBuffer, vec3 worldPosition, vec3 N, vec3 V, float roughnessSquared, + sampler2D hitBuffer, PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V, float roughnessSquared, float cone_tan, vec2 source_uvs, vec2 texture_size, ivec2 target_texel, inout float weight_acc) { vec4 hit_co_pdf = texelFetch(hitBuffer, target_texel, 0).rgba; bool has_hit = (hit_co_pdf.z < 0.0); + bool is_planar = (hit_co_pdf.w < 0.0); hit_co_pdf.z = -abs(hit_co_pdf.z); + hit_co_pdf.w = abs(hit_co_pdf.w); /* Hit position in world space. */ - vec3 hit_pos = (ViewMatrixInverse * vec4(hit_co_pdf.xyz, 1.0)).xyz; - - /* Find hit position in previous frame. */ - vec2 ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N); + vec3 hit_pos = transform_point(ViewMatrixInverse, hit_co_pdf.xyz); + + vec2 ref_uvs; + vec3 L; + float mask = 1.0; + float cone_footprint; + if (is_planar) { + /* Reflect back the hit position to have it in non-reflected world space */ + vec3 trace_pos = line_plane_intersect(worldPosition, V, pd.pl_plane_eq); + vec3 hit_vec = hit_pos - trace_pos; + hit_vec = reflect(hit_vec, pd.pl_normal); + hit_pos = hit_vec + trace_pos; + L = normalize(hit_vec); + ref_uvs = project_point(ProjectionMatrix, hit_co_pdf.xyz).xy * 0.5 + 0.5; + vec2 uvs = gl_FragCoord.xy / texture_size; + + /* Compute cone footprint in screen space. */ + float homcoord = ProjectionMatrix[2][3] * hit_co_pdf.z + ProjectionMatrix[3][3]; + cone_footprint = length(hit_vec) * cone_tan * ProjectionMatrix[0][0] / homcoord; + } + else { + /* Find hit position in previous frame. */ + ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N); + L = normalize(hit_pos - worldPosition); + mask *= view_facing_mask(V, N); + mask *= screen_border_mask(source_uvs); + + /* Compute cone footprint Using UV distance because we are using screen space filtering. */ + cone_footprint = 1.5 * cone_tan * distance(ref_uvs, source_uvs); + } + mask *= screen_border_mask(ref_uvs); + mask *= float(has_hit); /* Estimate a cone footprint to sample a corresponding mipmap level. */ - /* Compute cone footprint Using UV distance because we are using screen space filtering. */ - float cone_footprint = 1.5 * cone_tan * distance(ref_uvs, source_uvs); float mip = BRDF_BIAS * clamp(log2(cone_footprint * max(texture_size.x, texture_size.y)), 0.0, MAX_MIP); /* Slide 54 */ - vec3 L = normalize(hit_pos - worldPosition); float bsdf = bsdf_ggx(N, L, V, roughnessSquared); float weight = step(0.001, hit_co_pdf.w) * bsdf / hit_co_pdf.w; weight_acc += weight; - vec3 sample = textureLod(colorBuffer, ref_uvs, mip).rgb; + vec3 sample; + if (is_planar) { + sample = textureLod(probePlanars, vec3(ref_uvs, planar_index), mip).rgb; + } + else { + sample = textureLod(colorBuffer, ref_uvs, mip).rgb; + } /* Do not add light if ray has failed. */ sample *= float(has_hit); @@ -248,10 +340,6 @@ vec4 get_ssr_sample( /* Firefly removal */ sample /= 1.0 + fireflyFactor * brightness(sample); - float mask = screen_border_mask(ref_uvs, hit_pos); - mask *= view_facing_mask(V, N); - mask *= float(has_hit); - return vec4(sample, mask) * weight; } @@ -286,6 +374,20 @@ void main() if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0) discard; + /* Find Planar Reflections affecting this pixel */ + PlanarData pd; + float planar_index; + for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) { + pd = planars_data[i]; + + float fade = probe_attenuation_planar(pd, worldPosition, N); + + if (fade > 0.5) { + planar_index = float(i); + break; + } + } + float roughness = speccol_roughness.a; float roughnessSquared = max(1e-3, roughness * roughness); @@ -318,21 +420,21 @@ void main() for (int i = 0; i < NUM_NEIGHBORS; i++) { ivec2 target_texel = halfres_texel + neighbors[i] * invert_neighbor; - ssr_accum += get_ssr_sample(hitBuffer0, worldPosition, N, V, + ssr_accum += get_ssr_sample(hitBuffer0, pd, planar_index, worldPosition, N, V, roughnessSquared, cone_tan, source_uvs, texture_size, target_texel, weight_acc); if (rayCount > 1) { - ssr_accum += get_ssr_sample(hitBuffer1, worldPosition, N, V, + ssr_accum += get_ssr_sample(hitBuffer1, pd, planar_index, worldPosition, N, V, roughnessSquared, cone_tan, source_uvs, texture_size, target_texel, weight_acc); } if (rayCount > 2) { - ssr_accum += get_ssr_sample(hitBuffer2, worldPosition, N, V, + ssr_accum += get_ssr_sample(hitBuffer2, pd, planar_index, worldPosition, N, V, roughnessSquared, cone_tan, source_uvs, texture_size, target_texel, weight_acc); } if (rayCount > 3) { - ssr_accum += get_ssr_sample(hitBuffer3, worldPosition, N, V, + ssr_accum += get_ssr_sample(hitBuffer3, pd, planar_index, worldPosition, N, V, roughnessSquared, cone_tan, source_uvs, texture_size, target_texel, weight_acc); } diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index 196a9888665..154d48eb247 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -164,16 +164,11 @@ vec3 probe_evaluate_world_spec(vec3 R, float roughness) vec3 probe_evaluate_planar( float id, PlanarData pd, vec3 W, vec3 N, vec3 V, - float rand, vec3 camera_pos, float roughness, + float rand, float roughness, inout float fade) { - /* Sample reflection depth. */ - vec4 refco = pd.reflectionmat * vec4(W, 1.0); - refco.xy /= refco.w; - - /* Find view vector / reflection plane intersection. (dist_to_plane is negative) */ - float dist_to_plane = line_plane_intersect_dist(camera_pos, V, pd.pl_plane_eq); - vec3 point_on_plane = camera_pos + V * dist_to_plane; + /* Find view vector / reflection plane intersection. */ + vec3 point_on_plane = line_plane_intersect(W, V, pd.pl_plane_eq); /* How far the pixel is from the plane. */ float ref_depth = 1.0; /* TODO parameter */ @@ -187,7 +182,7 @@ vec3 probe_evaluate_planar( vec3 ref_pos = point_on_plane + proj_ref; /* Reproject to find texture coords. */ - refco = pd.reflectionmat * vec4(ref_pos, 1.0); + vec4 refco = pd.reflectionmat * vec4(ref_pos, 1.0); refco.xy /= refco.w; /* Distance to roughness */ diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl index fa70fb5590f..c2ef085ca01 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl @@ -13,8 +13,9 @@ out vec4 FragColor; void main() { /* Reconstructing Target uvs like this avoid missing pixels */ - vec2 uvs = floor(gl_FragCoord.xy) * 2.0 * texelSize + texelSize; + vec2 uvs = gl_FragCoord.xy * 2.0 / vec2(textureSize(source, 0).xy); +#if 0 /* Slower and does not match the main framebuffer downsampling. */ /* Downsample with a 4x4 box filter */ vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1); @@ -24,4 +25,7 @@ void main() FragColor += texture(source, vec3(uvs + d.zw, layer)).rgba; FragColor /= 4.0; +#endif + + FragColor = texture(source, vec3(uvs, layer)); } \ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index 9a851ac6bad..4a1778091f6 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -5,6 +5,7 @@ uniform int grid_count; uniform int planar_count; uniform bool specToggle; +uniform bool ssrToggle; #ifndef UTIL_TEX #define UTIL_TEX @@ -90,7 +91,7 @@ vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, vec4 spec_accum = vec4(0.0); /* SSR lobe is applied later in a defered style */ - if (ssr_id != outputSsrId) { + if (!ssrToggle || ssr_id != outputSsrId) { /* Planar Reflections */ for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) { PlanarData pd = planars_data[i]; @@ -98,7 +99,7 @@ vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, float fade = probe_attenuation_planar(pd, worldPosition, N); if (fade > 0.0) { - vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); + vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, roughness, fade); accumulate_light(spec, fade, spec_accum); } } @@ -237,12 +238,12 @@ vec3 eevee_surface_clearcoat_lit( float fade = probe_attenuation_planar(pd, worldPosition, worldNormal); if (fade > 0.0) { - if (ssr_id != outputSsrId) { - vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); + if (!ssrToggle || ssr_id != outputSsrId) { + vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, roughness, fade); accumulate_light(spec, fade, spec_accum); } - vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, rand.r, cameraPos, C_roughness, fade); + vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, rand.r, C_roughness, fade); accumulate_light(C_spec, fade, C_spec_accum); } } @@ -258,7 +259,7 @@ vec3 eevee_surface_clearcoat_lit( float fade = probe_attenuation_cube(cd, worldPosition); if (fade > 0.0) { - if (ssr_id != outputSsrId) { + if (!ssrToggle || ssr_id != outputSsrId) { vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); accumulate_light(spec, fade, spec_accum); } @@ -270,7 +271,7 @@ vec3 eevee_surface_clearcoat_lit( /* World Specular */ if (spec_accum.a < 0.999) { - if (ssr_id != outputSsrId) { + if (!ssrToggle || ssr_id != outputSsrId) { vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); accumulate_light(spec, 1.0, spec_accum); } @@ -453,7 +454,7 @@ vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ss /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */ vec4 spec_accum = vec4(0.0); - if (ssr_id != outputSsrId) { + if (!ssrToggle || ssr_id != outputSsrId) { /* Planar Reflections */ for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) { PlanarData pd = planars_data[i]; @@ -461,7 +462,7 @@ vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ss float fade = probe_attenuation_planar(pd, worldPosition, N); if (fade > 0.0) { - vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, cameraPos, roughness, fade); + vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, rand.r, roughness, fade); accumulate_light(spec, fade, spec_accum); } } diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index 421079c0bfa..b4ccb1ca052 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -9,9 +9,22 @@ uniform mat4 PixelProjMatrix; /* View > NDC > Texel : maps view coords to texel coord */ uniform vec2 ssrParameters; +uniform sampler2D depthBuffer; +uniform sampler2DArray planarDepth; + #define ssrStride ssrParameters.x #define ssrThickness ssrParameters.y +float sample_depth(ivec2 hitpixel, int index) +{ + if (index > -1) { + return texelFetch(planarDepth, ivec3(hitpixel, index), 0).r; + } + else { + return texelFetch(depthBuffer, hitpixel, 0).r; + } +} + void swapIfBigger(inout float a, inout float b) { if (a > b) { @@ -22,7 +35,7 @@ void swapIfBigger(inout float a, inout float b) } /* Return the length of the ray if there is a hit, and negate it if not hit occured */ -float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir, float ray_jitter) +float raycast(int index, vec3 ray_origin, vec3 ray_dir, float ray_jitter) { float near = get_view_z_from_depth(0.0); /* TODO optimize */ float far = get_view_z_from_depth(1.0); /* TODO optimize */ @@ -60,7 +73,7 @@ float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir, float ray_ /* If the line is degenerate, make it cover at least one pixel * to not have to handle zero-pixel extent as a special case later */ - P1 += vec2((distance_squared(P0, P1) < 0.0001) ? 0.01 : 0.0); + P1 += vec2((distance_squared(P0, P1) < 0.001) ? 0.01 : 0.0); vec2 delta = P1 - P0; @@ -101,10 +114,16 @@ float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir, float ray_ float end = P1.x * step_sign; /* Initial offset */ - pqk += dPQK * (0.01 + ray_jitter); + if (index > -1) { + pqk -= dPQK * ray_jitter; + } + else { + pqk += dPQK * (0.01 + ray_jitter); + } bool hit = false; float raw_depth; + float thickness = (index == -1) ? ssrThickness : 1e16; for (float hitstep = 0.0; hitstep < MAX_STEP && !hit; hitstep++) { /* Ray finished & no hit*/ if ((pqk.x * step_sign) > end) break; @@ -113,7 +132,7 @@ float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir, float ray_ pqk += dPQK; ivec2 hitpixel = ivec2(permute ? pqk.yx : pqk.xy); - raw_depth = texelFetch(depth_texture, ivec2(hitpixel), 0).r; + raw_depth = sample_depth(hitpixel, index); float zmin = prev_zmax; zmax = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w); @@ -121,7 +140,7 @@ float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir, float ray_ swapIfBigger(zmin, zmax); float vmax = get_view_z_from_depth(raw_depth); - float vmin = vmax - ssrThickness; + float vmin = vmax - thickness; /* Check if we are somewhere near the surface. */ /* Note: we consider hitting the screen borders (raw_depth == 0.0) @@ -146,7 +165,7 @@ float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir, float ray_ pqk += dPQK; ivec2 hitpixel = ivec2(permute ? pqk.yx : pqk.xy); - raw_depth = texelFetch(depth_texture, hitpixel, 0).r; + raw_depth = sample_depth(hitpixel, index); float zmin = prev_zmax; zmax = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w); @@ -154,7 +173,7 @@ float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir, float ray_ swapIfBigger(zmin, zmax); float vmax = get_view_z_from_depth(raw_depth); - float vmin = vmax - ssrThickness; + float vmin = vmax - thickness; /* Check if we are somewhere near the surface. */ if (!((zmin > vmax) || (zmax < vmin)) || (raw_depth == 0.0)) { -- cgit v1.2.3