Skip to main content

sge_debug_visualisations/
grid.rs

1use glium::{IndexBuffer, ProgramCreationError, VertexBuffer, implement_vertex};
2use sge_api::shapes_2d::draw_line_world;
3use sge_camera::{get_camera_2d, get_camera_2d_mut};
4use sge_color::Color;
5use sge_error_union::ErrorUnion;
6use sge_math::transform::Transform3D;
7use sge_programs::{ProgramRef, load_program_sync};
8use sge_rendering::{
9    materials::Material,
10    object_3d::{Mesh, Object3D, Object3DRef},
11};
12use sge_types::MaterialVertex3D;
13use sge_vectors::Vec2;
14use sge_window::get_display;
15
16implement_vertex!(GridVertex, position);
17#[derive(Copy, Clone, Debug)]
18pub struct GridVertex {
19    pub position: [f32; 3],
20}
21
22#[derive(ErrorUnion, Debug)]
23pub enum GridCreationError {
24    VertexBuffer(glium::vertex::BufferCreationError),
25    IndexBuffer(glium::index::BufferCreationError),
26    Program(glium::program::ProgramCreationError),
27}
28
29pub fn create_infinite_grid() -> Result<Object3DRef, GridCreationError> {
30    let display = get_display();
31
32    let size = 1000.0;
33    let vertices = vec![
34        MaterialVertex3D {
35            position: [-size, 0.0, -size],
36            normal: [0.0, 1.0, 0.0],
37            tex_coords: [0.0, 0.0],
38        },
39        MaterialVertex3D {
40            position: [size, 0.0, -size],
41            normal: [0.0, 1.0, 0.0],
42            tex_coords: [1.0, 0.0],
43        },
44        MaterialVertex3D {
45            position: [size, 0.0, size],
46            normal: [0.0, 1.0, 0.0],
47            tex_coords: [1.0, 1.0],
48        },
49        MaterialVertex3D {
50            position: [-size, 0.0, size],
51            normal: [0.0, 1.0, 0.0],
52            tex_coords: [0.0, 1.0],
53        },
54    ];
55
56    let indices = vec![0, 1, 2, 0, 2, 3];
57
58    let vertex_buffer = VertexBuffer::new(display, &vertices)?;
59    let index_buffer = IndexBuffer::new(
60        display,
61        glium::index::PrimitiveType::TrianglesList,
62        &indices,
63    )?;
64
65    let program = load_grid_program()?;
66
67    let draw_params = glium::DrawParameters {
68        blend: glium::Blend::alpha_blending(),
69        depth: glium::Depth {
70            test: glium::DepthTest::IfLess,
71            write: false,
72            ..Default::default()
73        },
74        ..Default::default()
75    };
76
77    let material = Material::new(program)
78        .with_float("grid_scale", 1.0)
79        .with_float("grid_size", 10.0)
80        .with_color("grid_color_thin", Color::NEUTRAL_500.with_alpha(0.4))
81        .with_color("grid_color_thick", Color::NEUTRAL_500.with_alpha(0.8))
82        .with_color("x_axis_color", Color::RED_200)
83        .with_color("z_axis_color", Color::BLUE_200)
84        .with_float("axis_width", 0.02)
85        .with_draw_param_overrides(draw_params)
86        .create();
87
88    let object = Object3D {
89        mesh: Mesh {
90            vertices: vertex_buffer,
91            indices: index_buffer,
92        }
93        .create(),
94        material,
95        transform: Transform3D::IDENTITY,
96        flip_normals: false,
97    };
98
99    Ok(object.create())
100}
101
102fn load_grid_program() -> Result<ProgramRef, ProgramCreationError> {
103    let vertex_shader = include_str!("../assets/vertex.glsl");
104    let fragment_shader = include_str!("../assets/fragment.glsl");
105
106    load_program_sync(vertex_shader, fragment_shader)
107}
108
109pub fn draw_2d_grid_world(color: Color) {
110    let (min, max) = get_camera_2d_mut().visible_bounds();
111    let size = max - min;
112
113    let rough_spacing = size.x.min(size.y) / 5.0;
114    let log = rough_spacing.log10();
115    let large_scale = 10_f32.powi(log.ceil() as i32);
116    let small_scale = 10_f32.powi(log.floor() as i32);
117
118    let t = ((1.0 - log.fract().rem_euclid(1.0)) * 2.0).clamp(0.0, 1.0);
119
120    let small_alpha = t;
121    let large_alpha = 1.0;
122
123    draw_grid(min, max, large_scale, large_alpha, 2.0, color);
124    draw_grid(min, max, small_scale, small_alpha, 1.0, color);
125}
126
127fn draw_grid(min: Vec2, max: Vec2, scale: f32, alpha: f32, thickness_mult: f32, color: Color) {
128    let size = max - min;
129    let width = (size.x / scale).ceil() as usize + 1;
130    let height = (size.y / scale).ceil() as usize + 1;
131    let tl = (min / scale).floor() * scale;
132
133    let faded = Color::from_rgba(color.r, color.g, color.b, color.a * alpha);
134    let thickness = thickness_mult / get_camera_2d().scale();
135
136    for x in 0..width {
137        let x = x as f32 * scale + tl.x;
138        draw_line_world(Vec2::new(x, min.y), Vec2::new(x, max.y), thickness, faded);
139    }
140    for y in 0..height {
141        let y = y as f32 * scale + tl.y;
142        draw_line_world(Vec2::new(min.x, y), Vec2::new(max.x, y), thickness, faded);
143    }
144}