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-25 20:03:07 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-07-25 23:07:35 +0300
commit4fd70c99a5a37db00ea26b8e5efa7d351e5e1e2b (patch)
treeae1290d15d970ba72597485f3bde4e043e660aae /source/blender/draw
parent8c3ecc9651f9b3eaa2eddd659e6299c7f4c0588b (diff)
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.
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h1
-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.glsl168
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl13
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl19
-rw-r--r--source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl33
10 files changed, 201 insertions, 62 deletions
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)) {