Regular measurement lines

Simple, flat shader intended for a ColorRect for creating lines at regular intervals, no textures required. The color is set by the modulation from the Control node.

please note that some of the functionality is broken right now (namely, actually configuring the length of the lines). if you have any ideas how to solve it, or even just a general optimization, please comment below and i will update it accordingly.

Settings include:

  • `Spacing_Factor`: the given number of lines to be shown. the first of every N lines will be a major line;
  • `Height`: the absolute height to be pointed at;
    • a major line should be guaranteed to be centered at the zero point with the default settings. 
  • `Height_Per_Major`: the distance to be covered by each interval between any given major line;
  • (`Major`/`Minor`)`_Line_Size`: proportion of the length relative to the width of the ColorRect;
    • where 0 should make the line hidden, and 1 should cover the whole width.
  • `Thickness`: proportion of the size of each and every line;
    • where 0 will hide all lines, and 1 will make them into one continuous shape along the height.
Shader code
shader_type canvas_item;
render_mode unshaded;

uniform lowp float Spacing_Factor = 4;
uniform lowp float Height = 0.0;
uniform lowp float Height_Per_Major = 5.0;
uniform lowp float Minor_Line_Size : hint_range(0, 1) = 0.25;
uniform lowp float Major_Line_Size : hint_range(0, 1) = 0.75;
uniform lowp float Thickness : hint_range(0, 1) = 0.4;

void fragment() {
    if (Minor_Line_Size < 0.0001 && Major_Line_Size < 0.0001) discard;
    if (Thickness < 0.0001) discard;
    lowp float centering_offset = Thickness * 0.5 * Spacing_Factor;
    // `-UV.y` makes the lines go downwards as the height increases.
    lowp float h = -UV.y * Spacing_Factor + centering_offset + (Height/(Height_Per_Major/Spacing_Factor));

    // `-UV.x` makes the lines rest on the right side.
    // invert this sign to change direction.
    lowp vec2 pos = vec2(-UV.x, h);
    pos -= floor(pos); //fract() is avoided so to improve OpenGL compatibility.

    //setting up between which lines are major and which ones are minor.
    lowp vec2 interval = vec2(
        mod(h-(Thickness*(Spacing_Factor))-1.0, Spacing_Factor),
        mod(h-(Thickness*(Spacing_Factor))-1.0, Spacing_Factor)
    );
    if (pos.y >= interval.r) pos.x -= 1.0-Major_Line_Size;
    else pos.x += 1.0-Minor_Line_Size;
    
    lowp vec2 pos_major = pos;
    pos_major.y / Spacing_Factor;
    
    //vertical crop
    bool vgap = pos.y < 1.0-Thickness;
    if (vgap) discard;

    //horizontal crop
    bvec2 hgap = bvec2(
        pos_major.x > Major_Line_Size,
        pos.x > Minor_Line_Size
    );
    if (hgap.x && hgap.y) discard;
}
Tags
ColorRect, compatibility, height, imperial, interval, intervals, line, lines, major lines, measure, measurement, measures, metric, minor lines, no texture, no textures, régua, regular interval, ruler, ruller, spacing, textureless, thickness, unit, units
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Lines Screen Transition

Speed Lines Shader for Godot 4

Motion Lines

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Suvius
3 months ago

shader_type canvas_item;
render_mode unshaded;

uniform lowp float Spacing_Factor : hint_range(1, 100, 1) = 4;
uniform lowp float Height : hint_range(0, 20) = 0.0;
uniform lowp float Height_Per_Major : hint_range(1, 100) = 5.0;
uniform lowp float Minor_Line_Size : hint_range(0, 1) = 0.25;
uniform lowp float Major_Line_Size : hint_range(0, 1) = 0.75;
uniform lowp float Thickness : hint_range(0, 1) = 0.4;

void fragment() {
  if (Minor_Line_Size < 0.0001 && Major_Line_Size < 0.0001) discard;
  if (Thickness < 0.0001) discard;
   
  lowp float centering_offset = Thickness * 0.5 * Spacing_Factor;
  // -UV.y makes the lines go downwards as the height increases.
  lowp float h = -UV.y * Spacing_Factor + centering_offset + (Height / (Height_Per_Major / Spacing_Factor));

  // -UV.x makes the lines rest on the right side.
  // invert this sign to change direction.
  lowp vec2 pos = vec2(-UV.x, h);
  pos -= floor(pos); // fract() is avoided to improve OpenGL compatibility.

  // setting up between which lines are major and which ones are minor.
  lowp vec2 interval = vec2(
    mod(h – (Thickness * (Spacing_Factor)) – 1.0, Spacing_Factor),
    mod(h – (Thickness * (Spacing_Factor)) – 1.0, Spacing_Factor)
  );

  if (pos.y >= interval.r) 
    pos.x += 1.0 – Major_Line_Size;
  else 
    pos.x += 1.0 – Minor_Line_Size;

  lowp vec2 pos_major = pos;
  pos_major.y /= Spacing_Factor;

  // vertical crop
  bool vgap = pos.y < 1.0 – Thickness;
  if (vgap) 
    discard;

  // horizontal crop
  bvec2 hgap = bvec2(
    pos_major.x > (1.0 – Major_Line_Size),
    pos.x > (1.0 – Minor_Line_Size)
  );
  if (hgap.x && hgap.y) 
    discard;
}

better hint for Spacing_Factor and “fixed” line sizes