Fix T51724: Blender 2.80 EEVEE, Cycles, Clay Black Wall Graphical Glitch
[blender.git] / source / blender / draw / modes / shaders / object_grid_frag.glsl
1
2 /* Infinite grid
3  * ClĂ©ment Foucault */
4
5
6 out vec4 FragColor;
7
8 uniform mat4 ProjectionMatrix;
9 uniform vec3 cameraPos;
10 uniform vec3 planeNormal;
11 uniform vec3 planeAxes;
12 uniform vec3 eye;
13 uniform vec4 gridSettings;
14 uniform vec2 viewportSize;
15 uniform vec4 screenvecs[3];
16 uniform float gridOneOverLogSubdiv;
17
18 #define gridDistance      gridSettings.x
19 #define gridResolution    gridSettings.y
20 #define gridScale         gridSettings.z
21 #define gridSubdiv        gridSettings.w
22
23 uniform int gridFlag;
24
25 #define AXIS_X    (1 << 0)
26 #define AXIS_Y    (1 << 1)
27 #define AXIS_Z    (1 << 2)
28 #define GRID      (1 << 3)
29 #define PLANE_XY  (1 << 4)
30 #define PLANE_XZ  (1 << 5)
31 #define PLANE_YZ  (1 << 6)
32
33 #define GRID_LINE_SMOOTH 1.15
34
35 float get_grid(vec3 co, vec3 fwidthCos, float grid_size)
36 {
37         float half_size = grid_size / 2.0;
38         /* triangular wave pattern, amplitude is [0, grid_size] */
39         vec3 grid_domain = abs(mod(co + half_size, grid_size) - half_size);
40         /* modulate by the absolute rate of change of the coordinates
41          * (make lines have the same width under perspective) */
42         grid_domain /= fwidthCos;
43
44         /* collapse waves and normalize */
45         grid_domain.x = min(grid_domain.x, min(grid_domain.y, grid_domain.z)) / grid_size;
46
47         return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x);
48 }
49
50 vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size)
51 {
52         vec3 axes_domain = abs(co);
53         /* modulate by the absolute rate of change of the coordinates
54          * (make line have the same width under perspective) */
55         axes_domain /= fwidthCos;
56
57         return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH, axes_domain - line_size);
58 }
59
60 vec3 get_floor_pos(vec2 uv, out vec3 wPos)
61 {
62         vec3 camera_vec, camera_pos, corner_pos;
63         vec3 floored_pos = planeAxes * floor(screenvecs[2].xyz);
64         corner_pos = screenvecs[2].xyz - floored_pos;
65
66         vec3 pixel_pos = corner_pos + uv.x * screenvecs[0].xyz + uv.y * screenvecs[1].xyz;
67
68         /* if perspective */
69         if (ProjectionMatrix[3][3] == 0.0) {
70                 camera_pos = cameraPos - floored_pos;
71                 camera_vec = normalize(pixel_pos - camera_pos);
72         }
73         else {
74                 camera_pos = pixel_pos;
75                 camera_vec = normalize(eye);
76         }
77
78         float plane_normal_dot_camera_vec = dot(planeNormal, camera_vec);
79         float p = -dot(planeNormal, camera_pos);
80         if (plane_normal_dot_camera_vec != 0) {
81                 p /= plane_normal_dot_camera_vec;
82         }
83         vec3 plane = camera_pos + camera_vec * p;
84
85         /* fix residual imprecision */
86         plane *= planeAxes;
87
88         /* Recover non-offseted world position */
89         wPos = plane + floored_pos;
90
91         return plane;
92 }
93
94 void main()
95 {
96         vec2 sPos = gl_FragCoord.xy / viewportSize; /* Screen [0,1] position */
97
98         /* To reduce artifacts, use a local version of the positions
99          * to compute derivatives since they are not position dependant.
100          * This gets rid of the blocky artifacts. Unfortunately we still
101          * need the world position for the grid to scale properly from the origin. */
102         vec3 gPos, wPos; /* Grid pos., World pos. */
103         gPos = get_floor_pos(sPos, wPos);
104
105         vec3 fwidthPos = fwidth(gPos);
106
107         float dist, fade;
108         /* if persp */
109         if (ProjectionMatrix[3][3] == 0.0) {
110                 vec3 viewvec = cameraPos - wPos;
111                 dist = length(viewvec);
112                 viewvec /= dist;
113
114                 float angle;
115                 if ((gridFlag & PLANE_XZ) > 0)
116                         angle = viewvec.y;
117                 else if ((gridFlag & PLANE_YZ) > 0)
118                         angle = viewvec.x;
119                 else
120                         angle = viewvec.z;
121
122                 angle = 1.0 - abs(angle);
123                 fade = 1.0 - angle * angle;
124                 fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance);
125         }
126         else {
127                 dist = abs(gl_FragCoord.z * 2.0 - 1.0);
128                 fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5);
129                 dist = 1.0; /* avoid branch after */
130
131                 if ((gridFlag & PLANE_XY) > 0) {
132                         float angle = 1.0 - abs(eye.z);
133                         fade *= 1.0 - angle * angle * angle;
134                         dist = 1.0 + angle * 2.0;
135                 }
136         }
137
138         if ((gridFlag & GRID) > 0) {
139                 float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv;
140
141                 float blend = fract(-max(grid_res, 0.0));
142                 float lvl = floor(grid_res);
143
144                 /* from biggest to smallest */
145                 float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0));
146                 float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0));
147                 float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0));
148
149                 float gridA = get_grid(wPos, fwidthPos, scaleA);
150                 float gridB = get_grid(wPos, fwidthPos, scaleB);
151                 float gridC = get_grid(wPos, fwidthPos, scaleC);
152
153                 FragColor = vec4(colorGrid.rgb, gridA * blend);
154                 FragColor = mix(FragColor, vec4(mix(colorGrid.rgb, colorGridEmphasise.rgb, blend), 1.0), gridB);
155                 FragColor = mix(FragColor, vec4(colorGridEmphasise.rgb, 1.0), gridC);
156         }
157         else {
158                 FragColor = vec4(colorGrid.rgb, 0.0);
159         }
160
161         if ((gridFlag & (AXIS_X | AXIS_Y | AXIS_Z)) > 0) {
162                 /* Setup axes 'domains' */
163                 vec3 axes_dist, axes_fwidth;
164
165                 if ((gridFlag & AXIS_X) > 0) {
166                         axes_dist.x = dot(wPos.yz, planeAxes.yz);
167                         axes_fwidth.x = dot(fwidthPos.yz, planeAxes.yz);
168                 }
169                 if ((gridFlag & AXIS_Y) > 0) {
170                         axes_dist.y = dot(wPos.xz, planeAxes.xz);
171                         axes_fwidth.y = dot(fwidthPos.xz, planeAxes.xz);
172                 }
173                 if ((gridFlag & AXIS_Z) > 0) {
174                         axes_dist.z = dot(wPos.xy, planeAxes.xy);
175                         axes_fwidth.z = dot(fwidthPos.xy, planeAxes.xy);
176                 }
177
178                 /* Computing all axes at once using vec3 */
179                 vec3 axes = get_axes(axes_dist, axes_fwidth, 0.1);
180
181                 if ((gridFlag & AXIS_X) > 0) {
182                         FragColor = mix(FragColor, colorGridAxisX, axes.x);
183                 }
184                 if ((gridFlag & AXIS_Y) > 0) {
185                         FragColor = mix(FragColor, colorGridAxisY, axes.y);
186                 }
187                 if ((gridFlag & AXIS_Z) > 0) {
188                         FragColor = mix(FragColor, colorGridAxisZ, axes.z);
189                 }
190         }
191
192         FragColor.a *= fade;
193 }