Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl')
-rw-r--r--source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl232
1 files changed, 232 insertions, 0 deletions
diff --git a/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl b/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl
new file mode 100644
index 00000000000..25f4984f119
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl
@@ -0,0 +1,232 @@
+/**
+ * Infinite grid:
+ * Draw antialiazed grid and axes of different sizes with smooth blending between Level of details.
+ * We draw multiple triangles to avoid float precision issues due to perspective interpolation.
+ **/
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+
+/**
+ * We want to know how much a pixel is covered by a line.
+ * We replace the square pixel with acircle of the same area and try to find the intersection area.
+ * The area we search is the circular segment. https://en.wikipedia.org/wiki/Circular_segment
+ * The formula for the area uses inverse trig function and is quite complexe. Instead,
+ * we approximate it by using the smoothstep function and a 1.05 factor to the disc radius.
+ */
+#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */
+#define DISC_RADIUS (M_1_SQRTPI * 1.05)
+#define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS)
+#define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS)
+#define GRID_LINE_STEP(dist) smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist)
+
+float get_grid(vec2 co, vec2 fwidthCos, float grid_scale)
+{
+ float half_size = grid_scale / 2.0;
+ /* Triangular wave pattern, amplitude is [0, half_size]. */
+ vec2 grid_domain = abs(mod(co + half_size, vec2(grid_scale)) - half_size);
+ /* Modulate by the absolute rate of change of the coordinates
+ * (make line have the same width under perspective). */
+ grid_domain /= fwidthCos;
+ /* Collapse waves. */
+ float line_dist = min(grid_domain.x, grid_domain.y);
+ return 1.0 - GRID_LINE_STEP(line_dist - grid_buf.line_size);
+}
+
+vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size)
+{
+ vec3 axes_domain = abs(co);
+ /* Modulate by the absolute rate of change of the coordinates
+ * (make line have the same width under perspective). */
+ axes_domain /= fwidthCos;
+ return 1.0 - GRID_LINE_STEP(axes_domain - (line_size + grid_buf.line_size));
+}
+
+#define linearstep(p0, p1, v) (clamp(((v) - (p0)) / abs((p1) - (p0)), 0.0, 1.0))
+
+void main()
+{
+ vec3 P = local_pos * grid_buf.size.xyz;
+ vec3 dFdxPos = dFdx(P);
+ vec3 dFdyPos = dFdy(P);
+ vec3 fwidthPos = abs(dFdxPos) + abs(dFdyPos);
+ P += cameraPos * plane_axes;
+
+ float dist, fade;
+ bool is_persp = ProjectionMatrix[3][3] == 0.0;
+ if (is_persp) {
+ vec3 V = cameraPos - P;
+ dist = length(V);
+ V /= dist;
+
+ float angle;
+ if (flag_test(grid_flag, PLANE_XZ)) {
+ angle = V.y;
+ }
+ else if (flag_test(grid_flag, PLANE_YZ)) {
+ angle = V.x;
+ }
+ else {
+ angle = V.z;
+ }
+
+ angle = 1.0 - abs(angle);
+ angle *= angle;
+ fade = 1.0 - angle * angle;
+ fade *= 1.0 - smoothstep(0.0, grid_buf.distance, dist - grid_buf.distance);
+ }
+ else {
+ dist = gl_FragCoord.z * 2.0 - 1.0;
+ /* Avoid fading in +Z direction in camera view (see T70193). */
+ dist = flag_test(grid_flag, GRID_CAMERA) ? clamp(dist, 0.0, 1.0) : abs(dist);
+ fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5);
+ dist = 1.0; /* Avoid branch after. */
+
+ if (flag_test(grid_flag, PLANE_XY)) {
+ float angle = 1.0 - abs(ViewMatrixInverse[2].z);
+ dist = 1.0 + angle * 2.0;
+ angle *= angle;
+ fade *= 1.0 - angle * angle;
+ }
+ }
+
+ if (flag_test(grid_flag, SHOW_GRID)) {
+ /* Using `max(dot(dFdxPos, screenVecs[0]), dot(dFdyPos, screenVecs[1]))`
+ * would be more accurate, but not really necessary. */
+ float grid_res = dot(dFdxPos, screenVecs[0].xyz);
+
+ /* The grid begins to appear when it comprises 4 pixels. */
+ grid_res *= 4;
+
+ /* For UV/Image editor use grid_buf.zoom_factor. */
+ if (flag_test(grid_flag, PLANE_IMAGE) &&
+ /* Grid begins to appear when the length of one grid unit is at least
+ * (256/grid_size) pixels Value of grid_size defined in `overlay_grid.c`. */
+ !flag_test(grid_flag, CUSTOM_GRID)) {
+ grid_res = grid_buf.zoom_factor;
+ }
+
+ /* From biggest to smallest. */
+ vec4 scale;
+#define grid_step(a) grid_buf.steps[a].x
+#if 0 /* Inefficient. */
+ int step_id = 0;
+ scale[0] = 0.0;
+ scale[1] = grid_step(0);
+ while (scale[1] < grid_res && step_id != STEPS_LEN - 1) {
+ scale[0] = scale[1];
+ scale[1] = grid_step(++step_id);
+ }
+ scale[2] = grid_step(min(step_id + 1, STEPS_LEN - 1));
+ scale[3] = grid_step(min(step_id + 2, STEPS_LEN - 1));
+#else
+ /* For more efficiency, unroll the loop above. */
+ if (grid_step(0) > grid_res) {
+ scale = vec4(0.0, grid_step(0), grid_step(1), grid_step(2));
+ }
+ else if (grid_step(1) > grid_res) {
+ scale = vec4(grid_step(0), grid_step(1), grid_step(2), grid_step(3));
+ }
+ else if (grid_step(2) > grid_res) {
+ scale = vec4(grid_step(1), grid_step(2), grid_step(3), grid_step(4));
+ }
+ else if (grid_step(3) > grid_res) {
+ scale = vec4(grid_step(2), grid_step(3), grid_step(4), grid_step(5));
+ }
+ else if (grid_step(4) > grid_res) {
+ scale = vec4(grid_step(3), grid_step(4), grid_step(5), grid_step(6));
+ }
+ else if (grid_step(5) > grid_res) {
+ scale = vec4(grid_step(4), grid_step(5), grid_step(6), grid_step(7));
+ }
+ else if (grid_step(6) > grid_res) {
+ scale = vec4(grid_step(5), grid_step(6), grid_step(7), grid_step(7));
+ }
+ else {
+ scale = vec4(grid_step(6), grid_step(7), grid_step(7), grid_step(7));
+ }
+#endif
+#undef grid_step
+
+ float blend = 1.0 - linearstep(scale[0], scale[1], grid_res);
+ blend = blend * blend * blend;
+
+ vec2 grid_pos, grid_fwidth;
+ if (flag_test(grid_flag, PLANE_XZ)) {
+ grid_pos = P.xz;
+ grid_fwidth = fwidthPos.xz;
+ }
+ else if (flag_test(grid_flag, PLANE_YZ)) {
+ grid_pos = P.yz;
+ grid_fwidth = fwidthPos.yz;
+ }
+ else {
+ grid_pos = P.xy;
+ grid_fwidth = fwidthPos.xy;
+ }
+
+ float gridA = get_grid(grid_pos, grid_fwidth, scale[1]);
+ float gridB = get_grid(grid_pos, grid_fwidth, scale[2]);
+ float gridC = get_grid(grid_pos, grid_fwidth, scale[3]);
+
+ out_color = colorGrid;
+ out_color.a *= gridA * blend;
+ out_color = mix(out_color, mix(colorGrid, colorGridEmphasis, blend), gridB);
+ out_color = mix(out_color, colorGridEmphasis, gridC);
+ }
+ else {
+ out_color = vec4(colorGrid.rgb, 0.0);
+ }
+
+ if (flag_test(grid_flag, (SHOW_AXIS_X | SHOW_AXIS_Y | SHOW_AXIS_Z))) {
+ /* Setup axes 'domains' */
+ vec3 axes_dist, axes_fwidth;
+
+ if (flag_test(grid_flag, SHOW_AXIS_X)) {
+ axes_dist.x = dot(P.yz, plane_axes.yz);
+ axes_fwidth.x = dot(fwidthPos.yz, plane_axes.yz);
+ }
+ if (flag_test(grid_flag, SHOW_AXIS_Y)) {
+ axes_dist.y = dot(P.xz, plane_axes.xz);
+ axes_fwidth.y = dot(fwidthPos.xz, plane_axes.xz);
+ }
+ if (flag_test(grid_flag, SHOW_AXIS_Z)) {
+ axes_dist.z = dot(P.xy, plane_axes.xy);
+ axes_fwidth.z = dot(fwidthPos.xy, plane_axes.xy);
+ }
+
+ /* Computing all axes at once using vec3 */
+ vec3 axes = get_axes(axes_dist, axes_fwidth, 0.1);
+
+ if (flag_test(grid_flag, SHOW_AXIS_X)) {
+ out_color.a = max(out_color.a, axes.x);
+ out_color.rgb = (axes.x < 1e-8) ? out_color.rgb : colorGridAxisX.rgb;
+ }
+ if (flag_test(grid_flag, SHOW_AXIS_Y)) {
+ out_color.a = max(out_color.a, axes.y);
+ out_color.rgb = (axes.y < 1e-8) ? out_color.rgb : colorGridAxisY.rgb;
+ }
+ if (flag_test(grid_flag, SHOW_AXIS_Z)) {
+ out_color.a = max(out_color.a, axes.z);
+ out_color.rgb = (axes.z < 1e-8) ? out_color.rgb : colorGridAxisZ.rgb;
+ }
+ }
+
+ float scene_depth = texelFetch(depth_tx, ivec2(gl_FragCoord.xy), 0).r;
+ if (flag_test(grid_flag, GRID_BACK)) {
+ fade *= (scene_depth == 1.0) ? 1.0 : 0.0;
+ }
+ else {
+ /* Add a small bias so the grid will always be below of a mesh with the same depth. */
+ float grid_depth = gl_FragCoord.z + 4.8e-7;
+ /* Manual, non hard, depth test:
+ * Progressively fade the grid below occluders
+ * (avoids popping visuals due to depth buffer precision) */
+ /* Harder settings tend to flicker more,
+ * but have less "see through" appearance. */
+ float bias = max(fwidth(gl_FragCoord.z), 2.4e-7);
+ fade *= linearstep(grid_depth, grid_depth + bias, scene_depth);
+ }
+
+ out_color.a *= fade;
+}