Eevee: Planar Ref.: Invert view matrix to remove triangle front face flip

This was the cause of some issue with normal mapping. This way is cleaner
since it does not modify the state of the drawcalls and other ad-hoc
solutions to fix the problems down the road. Unfortunately, it does require
to fix every sampling coordinate for this texture.

Fix T62215: flipped normals in reflection plane
This commit is contained in:
Clément Foucault 2019-03-12 15:45:44 +01:00
parent ccb4484ea3
commit aaeca5d872
Notes: blender-bot 2023-02-14 11:20:29 +01:00
Referenced by issue #62215, flipped normals in reflection plane
5 changed files with 35 additions and 27 deletions

View File

@ -654,23 +654,19 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob, EEVEE_PlanarReflectio
}
static void lightbake_planar_compute_render_matrices(
EEVEE_PlanarReflection *eplanar, DRWMatrixState *r_matstate, const float viewmat[4][4])
EEVEE_PlanarReflection *eplanar, DRWMatrixState *r_matstate,
const float viewmat[4][4], const float winmat[4][4])
{
/* Reflect Camera Matrix. */
mul_m4_m4m4(r_matstate->viewmat, viewmat, eplanar->mtx);
/* TODO FOV margin */
/* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */
DRW_viewport_matrix_get(r_matstate->winmat, DRW_MAT_WIN);
/* Invert X to avoid flipping the triangle facing direction. */
r_matstate->viewmat[0][0] = -r_matstate->viewmat[0][0];
r_matstate->viewmat[1][0] = -r_matstate->viewmat[1][0];
r_matstate->viewmat[2][0] = -r_matstate->viewmat[2][0];
r_matstate->viewmat[3][0] = -r_matstate->viewmat[3][0];
/* Apply Projection Matrix. */
mul_m4_m4m4(r_matstate->persmat, r_matstate->winmat, r_matstate->viewmat);
/* This is the matrix used to reconstruct texture coordinates.
* We use the original view matrix because it does not create
* visual artifacts if receiver is not perfectly aligned with
* the planar reflection probe. */
mul_m4_m4m4(eplanar->reflectionmat, r_matstate->winmat, viewmat); /* TODO FOV margin */
/* Convert from [-1, 1] to [0, 1] (NDC to Texture coord). */
mul_m4_m4m4(eplanar->reflectionmat, texcomat, eplanar->reflectionmat);
/* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */
mul_m4_m4m4(r_matstate->persmat, winmat, r_matstate->viewmat);
}
static void eevee_lightprobes_extract_from_cache(EEVEE_LightProbesInfo *pinfo, LightCache *lcache)
@ -783,12 +779,13 @@ static void render_reflections(
{
DRWMatrixState matstate;
float original_viewmat[4][4];
float original_viewmat[4][4], original_winmat[4][4];
DRW_viewport_matrix_get(original_viewmat, DRW_MAT_VIEW);
DRW_viewport_matrix_get(original_winmat, DRW_MAT_WIN);
for (int i = 0; i < ref_count; ++i) {
/* Setup custom matrices */
lightbake_planar_compute_render_matrices(planar_data + i, &matstate, original_viewmat);
lightbake_planar_compute_render_matrices(planar_data + i, &matstate, original_viewmat, original_winmat);
invert_m4_m4(matstate.persinv, matstate.persmat);
invert_m4_m4(matstate.viewinv, matstate.viewmat);
invert_m4_m4(matstate.wininv, matstate.winmat);
@ -884,9 +881,7 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
/* Be sure that cascaded shadow maps are updated. */
EEVEE_draw_shadows(sldata, vedata);
/* Since we are rendering with an inverted view matrix, we need
* to invert the facing for backface culling to be the same. */
DRW_state_invert_facing();
/* Compute offset plane equation (fix missing texels near reflection plane). */
copy_v4_v4(sldata->clip_data.clip_planes[0], eplanar->plane_equation);
sldata->clip_data.clip_planes[0][3] += eplanar->clipsta;
@ -924,7 +919,6 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
}
DRW_draw_pass(psl->transparent_pass);
DRW_state_invert_facing();
DRW_state_clip_planes_reset();
DRW_stats_group_end();

View File

@ -18,7 +18,11 @@ vec2 decode_hit_data(vec2 hit_data, out bool has_hit, out bool is_planar)
{
is_planar = (hit_data.x < 0);
has_hit = (hit_data.y > 0);
return vec2(abs(hit_data)) / 32767.0; /* 16bit signed int limit */
vec2 hit_co = vec2(abs(hit_data)) / 32767.0; /* 16bit signed int limit */
if (is_planar) {
hit_co.x = 1.0 - hit_co.x;
}
return hit_co;
}
#ifdef STEP_RAYTRACE
@ -219,6 +223,7 @@ vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N)
float get_sample_depth(vec2 hit_co, bool is_planar, float planar_index)
{
if (is_planar) {
hit_co.x = 1.0 - hit_co.x;
return textureLod(planarDepth, vec3(hit_co, planar_index), 0.0).r;
}
else {
@ -237,6 +242,8 @@ vec3 get_hit_vector(
vec3 trace_pos = line_plane_intersect(worldPosition, V, pd.pl_plane_eq);
hit_vec = hit_pos - trace_pos;
hit_vec = reflect(hit_vec, pd.pl_normal);
/* Modify here so mip texel alignment is correct. */
hit_co.x = 1.0 - hit_co.x;
}
else {
/* Find hit position in previous frame. */

View File

@ -200,7 +200,8 @@ vec3 probe_evaluate_planar(
/* TODO: If we support non-ssr planar reflection, we should blur them with gaussian
* and chose the right mip depending on the cone footprint after projection */
vec3 sample = textureLod(probePlanars, vec3(refco.xy * 0.5 + 0.5, id), 0.0).rgb;
/* NOTE: X is inverted here to compensate inverted drawing. */
vec3 sample = textureLod(probePlanars, vec3(refco.xy * vec2(-0.5, 0.5) + 0.5, id), 0.0).rgb;
return sample;
}

View File

@ -10,5 +10,5 @@ void main()
{
vec4 refco = ViewProjectionMatrix * vec4(worldPosition, 1.0);
refco.xy /= refco.w;
FragColor = vec4(textureLod(probePlanars, vec3(refco.xy * 0.5 + 0.5, float(probeIdx)), 0.0).rgb, 1.0);
FragColor = vec4(textureLod(probePlanars, vec3(refco.xy * vec2(-0.5, 0.5) + 0.5, float(probeIdx)), 0.0).rgb, 1.0);
}

View File

@ -59,7 +59,7 @@ float refine_isect(float prev_delta, float curr_delta)
}
void prepare_raycast(
vec3 ray_origin, vec3 ray_dir, float thickness, out vec4 ss_step, out vec4 ss_ray, out float max_time)
vec3 ray_origin, vec3 ray_dir, float thickness, int index, out vec4 ss_step, out vec4 ss_ray, out float max_time)
{
/* Negate the ray direction if it goes towards the camera.
* This way we don't need to care if the projected point
@ -106,10 +106,16 @@ void prepare_raycast(
/* Convert to texture coords. Z component included
* since this is how it's stored in the depth buffer.
* 4th component how far we are on the ray */
ss_ray = ss_start * 0.5 + 0.5;
ss_step *= 0.5;
#ifdef PLANAR_PROBE_RAYTRACE
/* Planar Reflections have X mirrored. */
vec2 m = (index > -1) ? vec2(-0.5, 0.5) : vec2(0.5);
#else
const vec2 m = vec2(0.5);
#endif
ss_ray = ss_start * m.xyyy + 0.5;
ss_step *= m.xyyy;
ss_ray.xy += 0.5 * ssrPixelSize * 2.0; /* take the center of the texel. * 2 because halfres. */
ss_ray.xy += m * ssrPixelSize * 2.0; /* take the center of the texel. * 2 because halfres. */
}
/* See times_and_deltas. */
@ -127,7 +133,7 @@ vec3 raycast(
{
vec4 ss_step, ss_start;
float max_time;
prepare_raycast(ray_origin, ray_dir, thickness, ss_step, ss_start, max_time);
prepare_raycast(ray_origin, ray_dir, thickness, index, ss_step, ss_start, max_time);
float max_trace_time = max(0.001, max_time - 0.01);