Vital
Loading...
Searching...
No Matches
open_gl_line_renderer.cpp
Go to the documentation of this file.
2
3#include "shaders.h"
4#include "utils.h"
5
6namespace {
7 constexpr float kLoopWidth = 2.001f;
8 constexpr float kDefaultLineWidth = 7.0f;
9
10 force_inline float inverseSqrt(float value) {
11 // Fast inverse square root approximation
12 static constexpr float kThreeHalves = 1.5f;
13 int i;
14 float x2, y;
15
16 x2 = value * 0.5f;
17 y = value;
18 i = *(int *)&y;
19 i = 0x5f3759df - (i >> 1);
20 y = *(float *)&i;
21 y = y * (kThreeHalves - (x2 * y * y));
22 y = y * (kThreeHalves - (x2 * y * y));
23 return y;
24 }
25
26 force_inline float inverseMagnitudeOfPoint(Point<float> point) {
27 return inverseSqrt(point.x * point.x + point.y * point.y);
28 }
29
30 force_inline Point<float> normalize(Point<float> point) {
31 return point * inverseMagnitudeOfPoint(point);
32 }
33}
34
35OpenGlLineRenderer::OpenGlLineRenderer(int num_points, bool loop) :
36 num_points_(num_points), boost_(0.0f), fill_(false), fill_center_(0.0f), fit_(false),
37 boost_amount_(0.0f), fill_boost_amount_(0.0f), enable_backward_boost_(true),
38 index_(0), dirty_(false), last_drawn_left_(false), loop_(loop), any_boost_value_(false),
39 shader_(nullptr), fill_shader_(nullptr) {
41 num_padding_ = 1;
42 if (loop)
43 num_padding_ = 2;
44
45 num_line_vertices_ = kLineVerticesPerPoint * (num_points_ + 2 * num_padding_);
46 num_fill_vertices_ = kFillVerticesPerPoint * (num_points_ + 2 * num_padding_);
47 num_line_floats_ = kLineFloatsPerVertex * num_line_vertices_;
48 num_fill_floats_ = kFillFloatsPerVertex * num_fill_vertices_;
49
50 line_width_ = kDefaultLineWidth;
51
52 x_ = std::make_unique<float[]>(num_points_);
53 y_ = std::make_unique<float[]>(num_points_);
54 boost_left_ = std::make_unique<float[]>(num_points_);
55 boost_right_ = std::make_unique<float[]>(num_points_);
56
57 line_data_ = std::make_unique<float[]>(num_line_floats_);
58 fill_data_ = std::make_unique<float[]>(num_fill_floats_);
59 indices_data_ = std::make_unique<int[]>(num_line_vertices_);
60 vertex_array_object_ = 0;
61 line_buffer_ = 0;
62 fill_buffer_ = 0;
63 indices_buffer_ = 0;
64 last_negative_boost_ = false;
65
66 for (int i = 0; i < num_line_vertices_; ++i)
67 indices_data_[i] = i;
68
69 for (int i = 0; i < num_line_floats_; i += 2 * kLineFloatsPerVertex)
70 line_data_[i + 2] = 1.0f;
71
72 for (int i = 0; i < num_points_; ++i)
73 setXAt(i, 2.0f * i / (num_points_ - 1.0f) - 1.0f);
74}
75
77
79 OpenGlComponent::init(open_gl);
80
81 open_gl.context.extensions.glGenVertexArrays(1, &vertex_array_object_);
82 open_gl.context.extensions.glBindVertexArray(vertex_array_object_);
83
84 open_gl.context.extensions.glGenBuffers(1, &line_buffer_);
85 open_gl.context.extensions.glBindBuffer(GL_ARRAY_BUFFER, line_buffer_);
86
87 GLsizeiptr line_vert_size = static_cast<GLsizeiptr>(num_line_floats_ * sizeof(float));
88 open_gl.context.extensions.glBufferData(GL_ARRAY_BUFFER, line_vert_size, line_data_.get(), GL_STATIC_DRAW);
89
90 open_gl.context.extensions.glGenBuffers(1, &fill_buffer_);
91 open_gl.context.extensions.glBindBuffer(GL_ARRAY_BUFFER, fill_buffer_);
92
93 GLsizeiptr fill_vert_size = static_cast<GLsizeiptr>(num_fill_floats_ * sizeof(float));
94 open_gl.context.extensions.glBufferData(GL_ARRAY_BUFFER, fill_vert_size, fill_data_.get(), GL_STATIC_DRAW);
95
96 open_gl.context.extensions.glGenBuffers(1, &indices_buffer_);
97 open_gl.context.extensions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer_);
98
99 GLsizeiptr line_size = static_cast<GLsizeiptr>(num_line_vertices_ * sizeof(int));
100 open_gl.context.extensions.glBufferData(GL_ELEMENT_ARRAY_BUFFER, line_size, indices_data_.get(), GL_STATIC_DRAW);
101
103 shader_->use();
104 color_uniform_ = getUniform(open_gl, *shader_, "color");
105 scale_uniform_ = getUniform(open_gl, *shader_, "scale");
106 boost_uniform_ = getUniform(open_gl, *shader_, "boost");
107 line_width_uniform_ = getUniform(open_gl, *shader_, "line_width");
108 position_ = getAttribute(open_gl, *shader_, "position");
109
111 fill_shader_->use();
112 fill_color_from_uniform_ = getUniform(open_gl, *fill_shader_, "color_from");
113 fill_color_to_uniform_ = getUniform(open_gl, *fill_shader_, "color_to");
114 fill_center_uniform_ = getUniform(open_gl, *fill_shader_, "center_position");
115 fill_boost_amount_uniform_ = getUniform(open_gl, *fill_shader_, "boost_amount");
116 fill_scale_uniform_ = getUniform(open_gl, *fill_shader_, "scale");
117 fill_position_ = getAttribute(open_gl, *fill_shader_, "position");
118}
119
120void OpenGlLineRenderer::boostLeftRange(float start, float end, int buffer_vertices, float min) {
121 boostRange(boost_left_.get(), start, end, buffer_vertices, min);
122}
123
124void OpenGlLineRenderer::boostRightRange(float start, float end, int buffer_vertices, float min) {
125 boostRange(boost_right_.get(), start, end, buffer_vertices, min);
126}
127
128void OpenGlLineRenderer::boostRange(float* boosts, float start, float end, int buffer_vertices, float min) {
129 any_boost_value_ = true;
130 dirty_ = true;
131
132 int active_points = num_points_ - 2 * buffer_vertices;
133 int start_index = std::max((int)std::ceil(start * (active_points - 1)), 0);
134 float end_position = end * (active_points - 1);
135 int end_index = std::max(std::ceil(end_position), 0.0f);
136 float progress = end_position - (int)end_position;
137
138 start_index %= active_points;
139 end_index %= active_points;
140 int num_points = end_index - start_index;
141 int direction = 1;
142 if (enable_backward_boost_) {
143 if ((num_points < 0 && num_points > -num_points_ / 2) || (num_points == 0 && last_negative_boost_)) {
144 num_points = -num_points;
145 direction = -1;
146 }
147 else if (num_points > num_points_ / 2) {
148 num_points -= active_points;
149 num_points = -num_points;
150 direction = -1;
151 }
152 }
153
154 last_negative_boost_ = direction < 0;
155 if (last_negative_boost_) {
156 start_index = std::max((int)std::floor(start * (active_points - 1)), 0);
157 end_index = std::max(std::floor(end_position), 0.0f);
158 start_index %= active_points;
159 end_index %= active_points;
160
161 num_points = start_index - end_index;
162 progress = 1.0f - progress;
163 }
164
165 float delta = (1.0f - min) / num_points;
166 float val = min;
167
168 for (int i = start_index; i != end_index; i = (i + active_points + direction) % active_points) {
169 val += delta;
170 val = std::min(1.0f, val);
171 float last_value = boosts[i + buffer_vertices];
172 boosts[i + buffer_vertices] = std::max(last_value, val);
173 }
174
175 float end_value = boosts[end_index + buffer_vertices];
176 boosts[end_index + buffer_vertices] = std::max(end_value, progress * progress);
177}
178
180 int buffer_vertices, vital::poly_float min) {
181 boostLeftRange(start[0], end[0], buffer_vertices, min[0]);
182 boostRightRange(start[1], end[1], buffer_vertices, min[1]);
183}
184
186 bool any_boost = false;
187 for (int i = 0; i < num_points_; ++i) {
188 boost_left_[i] *= mult[0];
189 boost_right_[i] *= mult[1];
190 any_boost = any_boost || boost_left_[i] || boost_right_[i];
191 }
192
193 any_boost_value_ = any_boost;
194}
195
197 float* boosts = left ? boost_left_.get() : boost_right_.get();
198 float x_adjust = 2.0f / getWidth();
199 float y_adjust = 2.0f / getHeight();
200
201 for (int i = 0; i < num_points_; ++i) {
202 int index_top = (i + num_padding_) * kFillFloatsPerPoint;
203 int index_bottom = index_top + kFillFloatsPerVertex;
204 float x = x_adjust * x_[i] - 1.0f;
205 float y = 1.0f - y_adjust * y_[i];
206 fill_data_[index_top] = x;
207 fill_data_[index_top + 1] = y;
208 fill_data_[index_top + 2] = boosts[i];
209 fill_data_[index_bottom] = x;
210 fill_data_[index_bottom + 1] = fill_center_;
211 fill_data_[index_bottom + 2] = boosts[i];
212 }
213
214 int padding_copy_size = num_padding_ * kFillFloatsPerPoint * sizeof(float);
215 int begin_copy_source = num_padding_ * kFillFloatsPerPoint;
216 int end_copy_source = num_points_ * kFillFloatsPerPoint;
217 if (loop_ && num_points_ >= 2) {
218 memcpy(fill_data_.get(), fill_data_.get() + end_copy_source, padding_copy_size);
219 int begin_copy_dest = (num_padding_ + num_points_) * kFillFloatsPerPoint;
220 memcpy(fill_data_.get() + begin_copy_dest, fill_data_.get() + begin_copy_source, padding_copy_size);
221
222 for (int i = 0; i < num_padding_; ++i) {
223 fill_data_[i * kFillFloatsPerPoint] -= kLoopWidth;
224 fill_data_[i * kFillFloatsPerPoint + kFillFloatsPerVertex] -= kLoopWidth;
225 fill_data_[begin_copy_dest + i * kFillFloatsPerPoint] += kLoopWidth;
226 fill_data_[begin_copy_dest + i * kFillFloatsPerPoint + kFillFloatsPerVertex] += kLoopWidth;
227 }
228 }
229 else {
230 int end_copy_dest = (num_padding_ + num_points_) * kFillFloatsPerPoint;
231 memcpy(fill_data_.get() + end_copy_dest, fill_data_.get() + end_copy_source, padding_copy_size);
232 memcpy(fill_data_.get(), fill_data_.get() + begin_copy_source, padding_copy_size);
233 }
234}
235
237 float* boosts = left ? boost_left_.get() : boost_right_.get();
238
239 Point<float> prev_normalized_delta;
240 for (int i = 0; i < num_points_ - 1; ++i) {
241 if (x_[i] != x_[i + 1] || y_[i] != y_[i + 1]) {
242 prev_normalized_delta = normalize(Point<float>(x_[i + 1] - x_[i], y_[i + 1] - y_[i]));
243 break;
244 }
245 }
246
247 Point<float> prev_delta_normal(-prev_normalized_delta.y, prev_normalized_delta.x);
248 float line_radius = line_width_ / 2.0f + 0.5f;
249 float prev_magnitude = line_radius;
250
251 float x_adjust = 2.0f / getWidth();
252 float y_adjust = 2.0f / getHeight();
253
254 for (int i = 0; i < num_points_; ++i) {
255 float radius = line_radius * (1.0f + boost_amount_ * boosts[i]);
256 Point<float> point(x_[i], y_[i]);
257 int next_index = i + 1;
258 int clamped_next_index = std::min(next_index, num_points_ - 1);
259
260 Point<float> next_point(x_[clamped_next_index], y_[clamped_next_index]);
261 Point<float> delta = next_point - point;
262 if (point == next_point) {
263 delta = prev_normalized_delta;
264 next_point = point + delta;
265 }
266
267 float inverse_magnitude = inverseMagnitudeOfPoint(delta);
268 float magnitude = 1.0f / std::max(0.00001f, inverse_magnitude);
269 Point<float> normalized_delta(delta.x * inverse_magnitude, delta.y * inverse_magnitude);
270 Point<float> delta_normal = Point<float>(-normalized_delta.y, normalized_delta.x);
271
272 Point<float> angle_bisect_delta = normalized_delta - prev_normalized_delta;
273 Point<float> bisect_line;
274 bool straight = angle_bisect_delta.x < 0.001f && angle_bisect_delta.x > -0.001f &&
275 angle_bisect_delta.y < 0.001f && angle_bisect_delta.y > -0.001f;
276 if (straight)
277 bisect_line = delta_normal;
278 else
279 bisect_line = normalize(angle_bisect_delta);
280
281 float x1, x2, x3, x4, x5, x6;
282 float y1, y2, y3, y4, y5, y6;
283
284 float max_inner_radius = std::max(radius, 0.5f * (magnitude + prev_magnitude));
285 prev_magnitude = magnitude;
286
287 float bisect_normal_dot_product = bisect_line.getDotProduct(delta_normal);
288 float inner_mult = 1.0f / std::max(0.1f, std::fabs(bisect_normal_dot_product));
289 Point<float> inner_point = point + std::min(inner_mult * radius, max_inner_radius) * bisect_line;
290 Point<float> outer_point = point - bisect_line * radius;
291
292 if (bisect_normal_dot_product < 0.0f) {
293 Point<float> outer_point_start = outer_point;
294 Point<float> outer_point_end = outer_point;
295 if (!straight) {
296 outer_point_start = point + prev_delta_normal * radius;
297 outer_point_end = point + delta_normal * radius;
298 }
299 x1 = outer_point_start.x;
300 y1 = outer_point_start.y;
301 x3 = outer_point.x;
302 y3 = outer_point.y;
303 x5 = outer_point_end.x;
304 y5 = outer_point_end.y;
305 x2 = x4 = x6 = inner_point.x;
306 y2 = y4 = y6 = inner_point.y;
307 }
308 else {
309 Point<float> outer_point_start = outer_point;
310 Point<float> outer_point_end = outer_point;
311 if (!straight) {
312 outer_point_start = point - prev_delta_normal * radius;
313 outer_point_end = point - delta_normal * radius;
314 }
315 x2 = outer_point_start.x;
316 y2 = outer_point_start.y;
317 x4 = outer_point.x;
318 y4 = outer_point.y;
319 x6 = outer_point_end.x;
320 y6 = outer_point_end.y;
321 x1 = x3 = x5 = inner_point.x;
322 y1 = y3 = y5 = inner_point.y;
323 }
324
325 int first = (i + num_padding_) * kLineFloatsPerPoint;
326 int second = first + kLineFloatsPerVertex;
327 int third = second + kLineFloatsPerVertex;
328 int fourth = third + kLineFloatsPerVertex;
329 int fifth = fourth + kLineFloatsPerVertex;
330 int sixth = fifth + kLineFloatsPerVertex;
331
332 line_data_[first] = x_adjust * x1 - 1.0f;
333 line_data_[first + 1] = 1.0f - y_adjust * y1;
334
335 line_data_[second] = x_adjust * x2 - 1.0f;
336 line_data_[second + 1] = 1.0f - y_adjust * y2;
337
338 line_data_[third] = x_adjust * x3 - 1.0f;
339 line_data_[third + 1] = 1.0f - y_adjust * y3;
340
341 line_data_[fourth] = x_adjust * x4 - 1.0f;
342 line_data_[fourth + 1] = 1.0f - y_adjust * y4;
343
344 line_data_[fifth] = x_adjust * x5 - 1.0f;
345 line_data_[fifth + 1] = 1.0f - y_adjust * y5;
346
347 line_data_[sixth] = x_adjust * x6 - 1.0f;
348 line_data_[sixth + 1] = 1.0f - y_adjust * y6;
349
350 prev_delta_normal = delta_normal;
351 prev_normalized_delta = normalized_delta;
352 }
353
354 int begin_copy_dest = (num_padding_ + num_points_) * kLineFloatsPerPoint;
355 if (loop_ && num_points_ >= 2) {
356 int padding_copy_size = num_padding_ * kLineFloatsPerPoint * sizeof(float);
357 int begin_copy_source = num_padding_ * kLineFloatsPerPoint;
358 int end_copy_source = num_points_ * kLineFloatsPerPoint;
359
360 memcpy(line_data_.get(), line_data_.get() + end_copy_source, padding_copy_size);
361 memcpy(line_data_.get() + begin_copy_dest, line_data_.get() + begin_copy_source, padding_copy_size);
362
363 for (int i = 0; i < num_padding_ * kLineVerticesPerPoint; ++i) {
364 line_data_[i * kLineFloatsPerVertex] -= kLoopWidth;
365 line_data_[begin_copy_dest + i * kLineFloatsPerVertex] += kLoopWidth;
366 }
367 }
368 else {
369 Point<float> delta_start(xAt(0) - xAt(1), yAt(0) - yAt(1));
370 Point<float> delta_start_offset = normalize(delta_start) * line_radius;
371 Point<float> delta_end(xAt(num_points_ - 1) - xAt(num_points_ - 2), yAt(num_points_ - 1) - yAt(num_points_ - 2));
372 Point<float> delta_end_offset = normalize(delta_end) * line_radius;
373 for (int i = 0; i < kLineVerticesPerPoint; ++i) {
374 line_data_[i * kLineFloatsPerVertex] = (xAt(0) + delta_start_offset.x) * x_adjust - 1.0f;
375 line_data_[i * kLineFloatsPerVertex + 1] = 1.0f - (yAt(0) + delta_start_offset.y) * y_adjust;
376 line_data_[i * kLineFloatsPerVertex + 2] = boosts[0];
377
378 int copy_index_start = begin_copy_dest + i * kLineFloatsPerVertex;
379 line_data_[copy_index_start] = (xAt(num_points_ - 1) + delta_end_offset.x) * x_adjust - 1.0f;
380 line_data_[copy_index_start + 1] = 1.0f - (yAt(num_points_ - 1) + delta_end_offset.y) * y_adjust;
381 line_data_[copy_index_start + 2] = boosts[num_points_ - 1];
382 }
383 }
384}
385
387 if (!setViewPort(open_gl))
388 return;
389
390 if (fill_shader_ == nullptr)
391 init(open_gl);
392
393 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
394 glEnable(GL_BLEND);
395 glEnable(GL_SCISSOR_TEST);
396
397 open_gl.context.extensions.glBindVertexArray(vertex_array_object_);
398
399 if (dirty_ || last_drawn_left_ != left) {
400 dirty_ = false;
401 last_drawn_left_ = left;
402 setLineVertices(left);
403 setFillVertices(left);
404
405 open_gl.context.extensions.glBindBuffer(GL_ARRAY_BUFFER, line_buffer_);
406
407 GLsizeiptr line_vert_size = static_cast<GLsizeiptr>(num_line_floats_ * sizeof(float));
408 open_gl.context.extensions.glBufferData(GL_ARRAY_BUFFER, line_vert_size, line_data_.get(), GL_STATIC_DRAW);
409
410 open_gl.context.extensions.glBindBuffer(GL_ARRAY_BUFFER, fill_buffer_);
411
412 GLsizeiptr fill_vert_size = static_cast<GLsizeiptr>(num_fill_floats_ * sizeof(float));
413 open_gl.context.extensions.glBufferData(GL_ARRAY_BUFFER, fill_vert_size, fill_data_.get(), GL_STATIC_DRAW);
414
415 open_gl.context.extensions.glBindBuffer(GL_ARRAY_BUFFER, 0);
416 }
417
418 open_gl.context.extensions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer_);
419
420 float x_shrink = 1.0f;
421 float y_shrink = 1.0f;
422 if (fit_) {
423 x_shrink = 1.0f - 0.33f * line_width_ / getWidth();
424 y_shrink = 1.0f - 0.33f * line_width_ / getHeight();
425 }
426
427 if (fill_) {
428 open_gl.context.extensions.glBindBuffer(GL_ARRAY_BUFFER, fill_buffer_);
429 fill_shader_->use();
430 fill_color_from_uniform_->set(fill_color_from_.getFloatRed(), fill_color_from_.getFloatGreen(),
431 fill_color_from_.getFloatBlue(), fill_color_from_.getFloatAlpha());
432 fill_color_to_uniform_->set(fill_color_to_.getFloatRed(), fill_color_to_.getFloatGreen(),
433 fill_color_to_.getFloatBlue(), fill_color_to_.getFloatAlpha());
434 fill_center_uniform_->set(fill_center_);
435 fill_boost_amount_uniform_->set(fill_boost_amount_);
436 fill_scale_uniform_->set(x_shrink, y_shrink);
437
438 open_gl.context.extensions.glVertexAttribPointer(fill_position_->attributeID, kFillFloatsPerVertex, GL_FLOAT,
439 GL_FALSE, kFillFloatsPerVertex * sizeof(float), nullptr);
440 open_gl.context.extensions.glEnableVertexAttribArray(fill_position_->attributeID);
441 glDrawElements(GL_TRIANGLE_STRIP, num_fill_vertices_, GL_UNSIGNED_INT, nullptr);
442 }
443
444 open_gl.context.extensions.glBindBuffer(GL_ARRAY_BUFFER, line_buffer_);
445 shader_->use();
446 open_gl.context.extensions.glVertexAttribPointer(position_->attributeID, kLineFloatsPerVertex, GL_FLOAT,
447 GL_FALSE, kLineFloatsPerVertex * sizeof(float), nullptr);
448 open_gl.context.extensions.glEnableVertexAttribArray(position_->attributeID);
449 color_uniform_->set(color_.getFloatRed(), color_.getFloatGreen(), color_.getFloatBlue(), color_.getFloatAlpha());
450
451 scale_uniform_->set(x_shrink, y_shrink);
452 boost_uniform_->set(boost_);
453 line_width_uniform_->set(line_width_);
454
455 glDrawElements(GL_TRIANGLE_STRIP, num_line_vertices_, GL_UNSIGNED_INT, nullptr);
456
457 open_gl.context.extensions.glDisableVertexAttribArray(position_->attributeID);
458 open_gl.context.extensions.glBindBuffer(GL_ARRAY_BUFFER, 0);
459 open_gl.context.extensions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
460 glDisable(GL_BLEND);
461 glDisable(GL_SCISSOR_TEST);
462}
463
464void OpenGlLineRenderer::render(OpenGlWrapper& open_gl, bool animate) {
465 drawLines(open_gl, true);
466}
467
470
471 shader_ = nullptr;
472 position_ = nullptr;
473 color_uniform_ = nullptr;
474 scale_uniform_ = nullptr;
475 boost_uniform_ = nullptr;
476 line_width_uniform_ = nullptr;
477
478 fill_shader_ = nullptr;
479 fill_color_from_uniform_ = nullptr;
480 fill_color_to_uniform_ = nullptr;
481 fill_center_uniform_ = nullptr;
482 fill_boost_amount_uniform_ = nullptr;
483 fill_scale_uniform_ = nullptr;
484 fill_position_ = nullptr;
485
486 open_gl.context.extensions.glDeleteBuffers(1, &line_buffer_);
487 open_gl.context.extensions.glDeleteBuffers(1, &fill_buffer_);
488 open_gl.context.extensions.glDeleteBuffers(1, &indices_buffer_);
489
490 vertex_array_object_ = 0;
491 line_buffer_ = 0;
492 fill_buffer_ = 0;
493 indices_buffer_ = 0;
494}
static bool setViewPort(Component *component, Rectangle< int > bounds, OpenGlWrapper &open_gl)
Sets the OpenGL viewport to match a specified rectangle within a component.
Definition open_gl_component.cpp:42
void addRoundedCorners()
Adds rounded corners to the component's edges.
Definition open_gl_component.cpp:138
static std::unique_ptr< OpenGLShaderProgram::Attribute > getAttribute(const OpenGlWrapper &open_gl, const OpenGLShaderProgram &program, const char *name)
Retrieves an attribute from the shader program if it exists.
Definition open_gl_component.h:79
virtual void destroy(OpenGlWrapper &open_gl)
Destroys any OpenGL-specific resources allocated by this component.
Definition open_gl_component.cpp:168
static std::unique_ptr< OpenGLShaderProgram::Uniform > getUniform(const OpenGlWrapper &open_gl, const OpenGLShaderProgram &program, const char *name)
Retrieves a uniform from the shader program if it exists.
Definition open_gl_component.h:64
virtual void init(OpenGlWrapper &open_gl)
Initializes any OpenGL-specific resources needed by the component.
Definition open_gl_component.cpp:148
virtual void init(OpenGlWrapper &open_gl) override
Initializes OpenGL resources for rendering the line.
Definition open_gl_line_renderer.cpp:78
virtual void destroy(OpenGlWrapper &open_gl) override
Destroys OpenGL resources allocated by this line renderer.
Definition open_gl_line_renderer.cpp:468
force_inline float xAt(int index) const
Gets the x-coordinate of a point at a given index.
Definition open_gl_line_renderer.h:81
virtual void render(OpenGlWrapper &open_gl, bool animate) override
Renders the line using OpenGL.
Definition open_gl_line_renderer.cpp:464
void decayBoosts(vital::poly_float mult)
Decays all boosts by a multiplicative factor, allowing animated damping.
Definition open_gl_line_renderer.cpp:185
static constexpr int kLineFloatsPerVertex
Floats per vertex in the line data (x, y, and potentially others).
Definition open_gl_line_renderer.h:19
static constexpr int kFillVerticesPerPoint
Number of vertices per point in the fill representation.
Definition open_gl_line_renderer.h:25
virtual ~OpenGlLineRenderer()
Destructor.
Definition open_gl_line_renderer.cpp:76
force_inline void setXAt(int index, float val)
Sets the x-coordinate of a point, marking data as dirty.
Definition open_gl_line_renderer.h:105
void boostRightRange(float start, float end, int buffer_vertices, float min)
Boosts right-side range of the line.
Definition open_gl_line_renderer.cpp:124
static constexpr int kFillFloatsPerVertex
Floats per vertex in the fill data (x, y, and boost value).
Definition open_gl_line_renderer.h:21
static constexpr int kLineVerticesPerPoint
Number of vertices per point in the line representation.
Definition open_gl_line_renderer.h:23
void setLineVertices(bool left)
Sets line vertices according to the current line and boost data.
Definition open_gl_line_renderer.cpp:236
void setFillVertices(bool left)
Sets fill vertices according to the current line and boost data.
Definition open_gl_line_renderer.cpp:196
static constexpr int kLineFloatsPerPoint
Floats per point in the line data (6 vertices * 3 floats each).
Definition open_gl_line_renderer.h:27
OpenGlLineRenderer(int num_points, bool loop=false)
Constructs an OpenGlLineRenderer for a given number of points.
Definition open_gl_line_renderer.cpp:35
static constexpr int kFillFloatsPerPoint
Floats per point in the fill data (2 vertices * 4 floats each).
Definition open_gl_line_renderer.h:29
force_inline float yAt(int index) const
Gets the y-coordinate of a point at a given index.
Definition open_gl_line_renderer.h:78
void boostRange(float *boosts, float start, float end, int buffer_vertices, float min)
Boosts a range for the given boost array.
Definition open_gl_line_renderer.cpp:128
void drawLines(OpenGlWrapper &open_gl, bool left)
Draws the line and optional fill using OpenGL.
Definition open_gl_line_renderer.cpp:386
void boostLeftRange(float start, float end, int buffer_vertices, float min)
Boosts left-side range of the line.
Definition open_gl_line_renderer.cpp:120
@ kFillVertex
Definition shaders.h:46
@ kLineVertex
Definition shaders.h:45
@ kLineFragment
Definition shaders.h:77
@ kFillFragment
Definition shaders.h:78
OpenGLShaderProgram * getShaderProgram(VertexShader vertex_shader, FragmentShader fragment_shader, const GLchar **varyings=nullptr)
Retrieves or creates an OpenGLShaderProgram from a given vertex and fragment shader pair.
Definition shaders.cpp:953
#define force_inline
Definition common.h:23
A helper struct containing references to OpenGL context, shaders, and display scale.
Definition shaders.h:174
OpenGLContext & context
The OpenGLContext for current rendering.
Definition shaders.h:181
Shaders * shaders
Pointer to the Shaders instance providing compiled shaders.
Definition shaders.h:182
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
Provides various utility functions, classes, and constants for audio, math, and general-purpose opera...