Workbench: Matcaps: Fix matcap under perspective.
authorClément Foucault <foucault.clem@gmail.com>
Sat, 9 Jun 2018 10:28:22 +0000 (12:28 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Sat, 9 Jun 2018 10:44:56 +0000 (12:44 +0200)
This fixes the problem that matcaps have when using a very larg FOV in
perspective view.

This was because it was stupidly using the normal direction which can not
aligned with the view vector under perspective.

So to workaround this problem we don't use the normal as is, but compute
how much it's facing the camera.

This changes how matcaps looks in perspective because they now always use
the full range of the matcap (which is expected).

source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl

index 9a0ec7703c828816367406cb5930f9c85d0380de..8908891d7e63d95b8ca17c170b939914ee2cbf58 100644 (file)
@@ -79,3 +79,16 @@ vec3 view_vector_from_screen_uv(vec2 uv, vec4 viewvecs[3], mat4 proj_mat)
                     : vec3(0.0, 0.0, 1.0);
 }
 
+vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped)
+{
+       /* Quick creation of an orthonormal basis */
+       float a = 1.0 / (1.0 + I.z);
+       float b = -I.x * I.y * a;
+       vec3 b1 = vec3(1.0 - I.x * I.x * a, b, -I.x);
+       vec3 b2 = vec3(b, 1.0 - I.y * I.y * a, -I.y);
+       vec2 matcap_uv = vec2(dot(b1, N), dot(b2, N));
+       if (flipped) {
+               matcap_uv.x = -matcap_uv.x;
+       }
+       return matcap_uv * 0.496 + 0.5;
+}
index 4ae62352e16e42a925233a9257a97f9174d4cc0d..461fb2fb130529d567804d9f6ed9f72ec41cd860 100644 (file)
@@ -67,11 +67,9 @@ void main()
        vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix);
 
 #ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL
-       vec2 matcap_uv = normal_viewport.xy / 2.0 + 0.5;
-       if (world_data.matcap_orientation != 0) {
-               matcap_uv.x = 1.0 - matcap_uv.x;
-       }
-       diffuse_color = texture(matcapImage, matcap_uv);
+       bool flipped = world_data.matcap_orientation != 0;
+       vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped);
+       diffuse_color = textureLod(matcapImage, matcap_uv, 0.0);
 #endif
 
 #ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
index b26bc396283f29acf1508211ca334aac030035f4..4c034460bd3f6dd2304f96941cddba9234403ab0 100644 (file)
@@ -43,7 +43,9 @@ void main()
        vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix);
 
 #ifdef V3D_LIGHTING_MATCAP
-       diffuse_light = texture(matcapImage, normal_viewport.xy / 2.0 + 0.5).rgb;
+       bool flipped = world_data.matcap_orientation != 0;
+       vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped);
+       diffuse_light = texture(matcapImage, matcap_uv).rgb;
 #endif
 
 #ifdef V3D_SHADING_SPECULAR_HIGHLIGHT