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.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
float hit_dist = raycast(depthBuffer, viewPosition, R, rand.x);
|
||||
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(-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;
|
||||
vec3 hit_pos = transform_point(ViewMatrixInverse, hit_co_pdf.xyz);
|
||||
|
||||
/* Find hit position in previous frame. */
|
||||
vec2 ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user