Eevee: Planar Reflection: Add contact hardening normal distortion.

Save radial distance to camera in alpha channel of the planar probe.
Use this distance to modulate distortion intensity when shading the surface.
This commit is contained in:
Clément Foucault 2017-06-24 01:08:26 +02:00
parent a6593645bf
commit e92940c6f3
5 changed files with 34 additions and 4 deletions

View File

@ -142,7 +142,7 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
if (!txl->planar_pool) {
if (num_planar_ref > 0) {
txl->planar_pool = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref),
DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
}
else if (num_planar_ref == 0) {
/* Makes Opengl Happy : Create a placeholder texture that will never be sampled but still bound to shader. */

View File

@ -143,6 +143,7 @@ vec4 saturate(vec4 a) { return clamp(a, 0.0, 1.0); }
float distance_squared(vec2 a, vec2 b) { a -= b; return dot(a, a); }
float distance_squared(vec3 a, vec3 b) { a -= b; return dot(a, a); }
float len_squared(vec3 a) { return dot(a, a); }
float inverse_distance(vec3 V) { return max( 1 / length(V), 1e-8); }
@ -167,6 +168,13 @@ float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeo
return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection);
}
float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane)
{
vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz));
vec3 h = lineorigin - plane_co;
return -dot(plane.xyz, h) / dot(plane.xyz, linedirection);
}
vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
{
float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal);

View File

@ -11,5 +11,5 @@ void main()
vec3 dielectric = vec3(0.034) * specular * 2.0;
vec3 diffuse = mix(basecol, vec3(0.0), metallic);
vec3 f0 = mix(dielectric, basecol, metallic);
FragColor = vec4(eevee_surface_lit((gl_FrontFacing) ? worldNormal : -worldNormal, diffuse, f0, roughness, 1.0), 1.0);
FragColor = vec4(eevee_surface_lit((gl_FrontFacing) ? worldNormal : -worldNormal, diffuse, f0, roughness, 1.0), length(viewPosition));
}

View File

@ -388,8 +388,30 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness,
if (influence > 0.0) {
float influ_spec = min(influence, (1.0 - spec_accum.a));
/* Sample reflection depth. */
vec4 refco = pd.reflectionmat * vec4(sd.W, 1.0);
refco.xy /= refco.w;
float ref_depth = textureLod(probePlanars, vec3(refco.xy, i), 0.0).a;
/* Find view vector / reflection plane intersection. (dist_to_plane is negative) */
float dist_to_plane = line_plane_intersect_dist(cameraPos, sd.V, pd.pl_plane_eq);
vec3 point_on_plane = cameraPos + sd.V * dist_to_plane;
/* How far the pixel is from the plane. */
ref_depth = ref_depth + dist_to_plane;
/* Compute distorded reflection vector based on the distance to the reflected object.
* In other words find intersection between reflection vector and the sphere center
* around point_on_plane. */
vec3 proj_ref = reflect(R * ref_depth, pd.pl_normal);
/* Final point in world space. */
vec3 ref_pos = point_on_plane + proj_ref;
/* Reproject to find texture coords. */
refco = pd.reflectionmat * vec4(ref_pos, 1.0);
refco.xy /= refco.w;
vec3 sample = textureLod(probePlanars, vec3(refco.xy, i), 0.0).rgb;
spec_accum.rgb += sample * influ_spec;

View File

@ -3894,9 +3894,9 @@ void node_eevee_specular(
result = vec4(eevee_surface_lit(normal, diffuse.rgb, specular.rgb, roughness, occlusion) + emissive.rgb, 1.0 - transp);
}
void node_output_eevee_material(vec4 Surface, out vec4 result)
void node_output_eevee_material(vec4 surface, out vec4 result)
{
result = Surface;
result = vec4(surface.rgb, length(viewPosition));
}
#endif