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.glsl103
1 files changed, 44 insertions, 59 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
index 54a4231590e..b401c3e7b2e 100644
--- a/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl
@@ -1,6 +1,6 @@
/**
* Infinite grid:
- * Draw antialiazed grid and axes of different sizes with smooth blending between Level of details.
+ * Draw antialiased grid and axes of different sizes with smooth blending between levels of detail.
* We draw multiple triangles to avoid float precision issues due to perspective interpolation.
**/
@@ -8,29 +8,33 @@
#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.
+ * We want to know how much of a pixel is covered by a line.
+ * Here, we imagine the square pixel is a circle with the same area and try to find the
+ * intersection area. The overlap area is a circular segment.
+ * https://en.wikipedia.org/wiki/Circular_segment The formula for the area uses inverse trig
+ * function and is quite complex. Instead, we approximate it by using the smoothstep function and
+ * a 1.05 factor to the disc radius.
+ *
+ * For an alternate approach, see:
+ * https://developer.nvidia.com/gpugems/gpugems2/part-iii-high-quality-rendering/chapter-22-fast-prefiltered-lines
*/
#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_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 get_grid(vec2 co, vec2 fwidthCos, vec2 grid_scale)
{
- float half_size = grid_scale / 2.0;
+ vec2 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);
+ vec2 grid_domain = abs(mod(co + half_size, 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);
+ return GRID_LINE_STEP(line_dist - grid_buf.line_size);
}
vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size)
@@ -39,7 +43,7 @@ vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size)
/* 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));
+ return 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))
@@ -91,9 +95,9 @@ void main()
}
if (flag_test(grid_flag, SHOW_GRID)) {
- /* Using `max(dot(dFdxPos, screenVecs[0]), dot(dFdyPos, screenVecs[1]))`
+ /* Using `max(dot(dFdxPos, ViewMatrixInverse[0]), dot(dFdyPos, ViewMatrixInverse[1]))`
* would be more accurate, but not really necessary. */
- float grid_res = dot(dFdxPos, screenVecs[0].xyz);
+ float grid_res = dot(dFdxPos, ViewMatrixInverse[0].xyz);
/* The grid begins to appear when it comprises 4 pixels. */
grid_res *= 4;
@@ -106,49 +110,30 @@ void main()
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));
+/** Keep in sync with `SI_GRID_STEPS_LEN` in `DNA_space_types.h`. */
+#define STEPS_LEN 8
+ int step_id_x = STEPS_LEN - 1;
+ int step_id_y = STEPS_LEN - 1;
+
+ /* Loop backwards a compile-time-constant number of steps. */
+ for (int i = STEPS_LEN - 2; i >= 0; --i) {
+ step_id_x = (grid_res < grid_buf.steps[i].x) ? i : step_id_x; /* Branchless. */
+ step_id_y = (grid_res < grid_buf.steps[i].y) ? i : step_id_y;
}
-#endif
-#undef grid_step
- float blend = 1.0 - linearstep(scale[0], scale[1], grid_res);
+ /* From biggest to smallest. */
+ float scale0x = step_id_x > 0 ? grid_buf.steps[step_id_x - 1].x : 0.0;
+ float scaleAx = grid_buf.steps[step_id_x].x;
+ float scaleBx = grid_buf.steps[min(step_id_x + 1, STEPS_LEN - 1)].x;
+ float scaleCx = grid_buf.steps[min(step_id_x + 2, STEPS_LEN - 1)].x;
+
+ float scale0y = step_id_y > 0 ? grid_buf.steps[step_id_y - 1].y : 0.0;
+ float scaleAy = grid_buf.steps[step_id_y].y;
+ float scaleBy = grid_buf.steps[min(step_id_y + 1, STEPS_LEN - 1)].y;
+ float scaleCy = grid_buf.steps[min(step_id_y + 2, STEPS_LEN - 1)].y;
+
+ /* Subtract from 1.0 to fix blending when `scale0x == scaleAx`. */
+ float blend = 1.0 - linearstep(scale0x + scale0y, scaleAx + scaleAy, grid_res + grid_res);
blend = blend * blend * blend;
vec2 grid_pos, grid_fwidth;
@@ -165,9 +150,9 @@ void main()
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]);
+ float gridA = get_grid(grid_pos, grid_fwidth, vec2(scaleAx, scaleAy));
+ float gridB = get_grid(grid_pos, grid_fwidth, vec2(scaleBx, scaleBy));
+ float gridC = get_grid(grid_pos, grid_fwidth, vec2(scaleCx, scaleCy));
out_color = colorGrid;
out_color.a *= gridA * blend;