GCC Code Coverage Report


./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 of 95, 0 excluded
0.0%
Functions:
0 of 10, 0 excluded
0.0%
Branches:
0 of 126, 0 excluded
0.0%

libs/render/src/eu/render/linebatch.cc
Line Branch Exec Source
1 #include "eu/render/linebatch.h"
2
3 #include "eu/assert/assert.h"
4
5 #include "eu/render/opengl_utils.h"
6 #include "eu/render/camera.h"
7
8 #include "eu/render/dependency_glad.h"
9
10 constexpr auto vertices_per_line = 2;
11
12 namespace eu::render
13 {
14 LineDrawer::LineDrawer()
15 // todo(Gustav): expand shader with stipple pattern https://stackoverflow.com/questions/52928678/dashed-line-in-opengl3/54543267#54543267
16 // todo(Gustav): move `description` and `layout` to a separate setup
17 : description({{.type = core::VertexType::position3, .name = "a_world_position"}, {.type = core::VertexType::color3, .name = "a_color"}})
18 , layout(compile_shader_layout(core::compile_attribute_layouts({description}), description, std::nullopt, std::nullopt))
19 , shader(
20 USE_DEBUG_LABEL_MANY("debug line")
21 R"glsl(
22 #version 430 core
23 in vec3 a_world_position;
24 in vec3 a_color;
25
26 uniform mat4 u_clip_from_view;
27 uniform mat4 u_view_from_world;
28
29 out vec4 v_color;
30 out vec4 v_vert_pos;
31 flat out vec4 v_start_pos;
32
33 void main()
34 {
35 v_color = vec4(a_color, 1.0);
36 vec4 pos = u_clip_from_view * u_view_from_world * vec4(a_world_position.xyz, 1.0);
37 gl_Position = pos;
38 v_vert_pos = pos;
39 v_start_pos = v_vert_pos;
40 }
41 )glsl",
42 R"glsl(
43 #version 430 core
44
45 in vec4 v_color;
46 flat in vec4 v_start_pos;
47 in vec4 v_vert_pos;
48
49 uniform float u_dash_size;
50 uniform float u_gap_size;
51 uniform vec2 u_resolution;
52
53 out vec4 color;
54
55 vec2 pixel(vec4 pos)
56 {
57 return ((pos.xy / pos.w) + 1)/2.0 * u_resolution;
58 }
59
60 void main()
61 {
62 if(u_resolution.x > 0.0)
63 {
64 float seg_len = u_dash_size + u_gap_size;
65
66 float dash_seg = u_dash_size/seg_len;
67
68 float cur = length(pixel(v_vert_pos) - pixel(v_start_pos));
69 float cur_seg = fract(cur / seg_len);
70 if(cur_seg > dash_seg)
71 {
72 discard;
73 }
74 color = v_color;
75 }
76 else
77 {
78 color = v_color;
79 }
80 }
81 )glsl",
82 layout
83 )
84 , clip_from_view_uni(shader.get_uniform("u_clip_from_view"))
85 , view_from_world_uni(shader.get_uniform("u_view_from_world"))
86 , resolution_uni(shader.get_uniform("u_resolution"))
87 , dash_size_uni(shader.get_uniform("u_dash_size"))
88 , gap_size_uni(shader.get_uniform("u_gap_size"))
89 , va(create_vertex_array())
90 , vb(create_buffer())
91 , ib(create_buffer())
92 {
93 shader.use();
94
95 glBindVertexArray(va);
96 SET_DEBUG_LABEL_NAMED(va, DebugLabelFor::VertexArray, "VERT line batch"sv);
97
98 constexpr auto attributes_per_vertex = 2;
99 constexpr auto float_per_attribute = 3;
100
101 constexpr auto floats_per_vertex = float_per_attribute * attributes_per_vertex;
102 constexpr auto vertex_size = floats_per_vertex * sizeof(float);
103 constexpr auto max_vertices = vertices_per_line * max_lines;
104 constexpr auto max_indices = vertices_per_line * max_lines;
105
106 glBindBuffer(GL_ARRAY_BUFFER, vb);
107 SET_DEBUG_LABEL_NAMED(vb, DebugLabelFor::Buffer, "ARR BUF line batch"sv);
108 glBufferData(GL_ARRAY_BUFFER, vertex_size * max_vertices, nullptr, GL_DYNAMIC_DRAW);
109
110 auto relative_offset = [](unsigned int i)
111 {
112 return reinterpret_cast<void*>(i * sizeof(float));
113 };
114
115 unsigned int offset = 0;
116
117 glEnableVertexAttribArray(0);
118 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, relative_offset(offset));
119 offset += 3;
120
121 glEnableVertexAttribArray(1);
122 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertex_size, relative_offset(offset));
123 offset += 3;
124 ASSERT(offset == floats_per_vertex);
125
126 std::vector<u32> indices;
127 indices.reserve(max_indices);
128
129 for (auto quad_index = 0; quad_index < max_lines; quad_index += 1)
130 {
131 const auto base = quad_index * vertices_per_line;
132 indices.emplace_back(base + 0);
133 indices.emplace_back(base + 1);
134 }
135
136 ASSERT(max_indices == indices.size());
137
138 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib);
139 SET_DEBUG_LABEL_NAMED(ib, DebugLabelFor::Buffer, "IND BUF line batch"sv);
140 glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_indices * sizeof(u32), indices.data(), GL_STATIC_DRAW);
141 }
142
143 LineDrawer::~LineDrawer()
144 {
145 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
146 destroy_buffer(ib);
147
148 glBindBuffer(GL_ARRAY_BUFFER, 0);
149 destroy_buffer(vb);
150
151 glBindVertexArray(0);
152 destroy_vertex_array(va);
153 }
154
155 void LineDrawer::set_line_to_dash(const v2& resolution, float dash_size, float gap_size)
156 {
157 submit();
158 shader.set_vec2(resolution_uni, resolution);
159 shader.set_float(dash_size_uni, dash_size);
160 shader.set_float(gap_size_uni, gap_size);
161 }
162
163 void LineDrawer::set_line_to_solid()
164 {
165 submit();
166 shader.set_vec2(resolution_uni, {-1.0f, -1.0f});
167 }
168
169 bool LineDrawer::is_loaded() const
170 {
171 return shader.is_loaded();
172 }
173
174 void LineDrawer::line(const v3& world_from, const v3& world_to, const Lin_rgb& color)
175 {
176 if (lines == max_lines)
177 {
178 submit();
179 }
180
181 lines += 1;
182
183 const auto add_vertex = [this,color](const v3& world_position)
184 {
185 data.push_back(world_position.x);
186 data.push_back(world_position.y);
187 data.push_back(world_position.z);
188
189 data.push_back(color.r);
190 data.push_back(color.g);
191 data.push_back(color.b);
192 };
193
194 add_vertex(world_from);
195 add_vertex(world_to);
196 }
197
198 void LineDrawer::set_camera(const CompiledCamera& compiled_camera)
199 {
200 shader.set_mat(clip_from_view_uni, compiled_camera.clip_from_view);
201 shader.set_mat(view_from_world_uni, compiled_camera.view_from_world);
202 }
203
204 void LineDrawer::submit()
205 {
206 if (lines == 0)
207 {
208 return;
209 }
210
211 // note: this assumes set_camera has been called
212
213 glBindVertexArray(va);
214
215 glBindBuffer(GL_ARRAY_BUFFER, vb);
216 glBufferSubData(
217 GL_ARRAY_BUFFER, 0, static_cast<GLsizeiptr>(sizeof(float) * data.size()), static_cast<const void*>(data.data())
218 );
219 glDrawElements(GL_LINES, vertices_per_line * lines, GL_UNSIGNED_INT, nullptr);
220
221 data.resize(0);
222 lines = 0;
223 }
224
225 } // namespace eu::render
226