Project Alice
Loading...
Searching...
No Matches
opengl_wrapper.cpp
Go to the documentation of this file.
1#include "opengl_wrapper.hpp"
2#include "system_state.hpp"
3#include "simple_fs.hpp"
4#include "fonts.hpp"
5#include "bmfont.hpp"
7
8namespace ogl {
9
10std::string_view opengl_get_error_name(GLenum t) {
11 switch(t) {
12 case GL_INVALID_ENUM:
13 return "GL_INVALID_ENUM";
14 case GL_INVALID_VALUE:
15 return "GL_INVALID_VALUE";
16 case GL_INVALID_OPERATION:
17 return "GL_INVALID_OPERATION";
18 case GL_INVALID_FRAMEBUFFER_OPERATION:
19 return "GL_INVALID_FRAMEBUFFER_OPERATION";
20 case GL_OUT_OF_MEMORY:
21 return "GL_OUT_OF_MEMORY";
22 case GL_STACK_UNDERFLOW:
23 return "GL_STACK_UNDERFLOW";
24 case GL_STACK_OVERFLOW:
25 return "GL_STACK_OVERFLOW";
26 case GL_NO_ERROR:
27 return "GL_NO_ERROR";
28 default:
29 return "Unknown";
30 }
31}
32
33void notify_user_of_fatal_opengl_error(std::string message) {
34 std::string full_message = message;
35 full_message += "\n";
36 full_message += opengl_get_error_name(glGetError());
37 window::emit_error_message("OpenGL error:" + full_message, true);
38}
39
40
41GLint compile_shader(std::string_view source, GLenum type) {
42 GLuint return_value = glCreateShader(type);
43
44 if(return_value == 0) {
45 notify_user_of_fatal_opengl_error("shader creation failed");
46 }
47
48 std::string s_source(source);
49 GLchar const* texts[] = {
50 "#version 140\r\n",
51 "#extension GL_ARB_explicit_uniform_location : enable\r\n",
52 "#extension GL_ARB_explicit_attrib_location : enable\r\n",
53 "#extension GL_ARB_shader_subroutine : enable\r\n",
54 "#extension GL_ARB_vertex_array_object : enable\r\n"
55 "#define M_PI 3.1415926535897932384626433832795\r\n",
56 "#define PI 3.1415926535897932384626433832795\r\n",
57 s_source.c_str()
58 };
59 glShaderSource(return_value, 7, texts, nullptr);
60 glCompileShader(return_value);
61
62 GLint result;
63 glGetShaderiv(return_value, GL_COMPILE_STATUS, &result);
64 if(result == GL_FALSE) {
65 GLint log_length = 0;
66 glGetShaderiv(return_value, GL_INFO_LOG_LENGTH, &log_length);
67
68 auto log = std::unique_ptr<char[]>(new char[static_cast<size_t>(log_length)]);
69 GLsizei written = 0;
70 glGetShaderInfoLog(return_value, log_length, &written, log.get());
71 notify_user_of_fatal_opengl_error(std::string("Shader failed to compile:\n") + log.get());
72 }
73 return return_value;
74}
75
76GLuint create_program(std::string_view vertex_shader, std::string_view fragment_shader) {
77 GLuint return_value = glCreateProgram();
78 if(return_value == 0) {
79 notify_user_of_fatal_opengl_error("program creation failed");
80 }
81
82 auto v_shader = compile_shader(vertex_shader, GL_VERTEX_SHADER);
83 auto f_shader = compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
84
85 glAttachShader(return_value, v_shader);
86 glAttachShader(return_value, f_shader);
87 glLinkProgram(return_value);
88
89 GLint result;
90 glGetProgramiv(return_value, GL_LINK_STATUS, &result);
91 if(result == GL_FALSE) {
92 GLint logLen;
93 glGetProgramiv(return_value, GL_INFO_LOG_LENGTH, &logLen);
94
95 char* log = new char[static_cast<size_t>(logLen)];
96 GLsizei written;
97 glGetProgramInfoLog(return_value, logLen, &written, log);
98 notify_user_of_fatal_opengl_error(std::string("Program failed to link:\n") + log);
99 }
100
101 glDeleteShader(v_shader);
102 glDeleteShader(f_shader);
103
104 return return_value;
105}
106
108 auto root = get_root(state.common_fs);
109 auto gfx_dir = simple_fs::open_directory(root, NATIVE("gfx"));
110
111 auto interface_dir = simple_fs::open_directory(gfx_dir, NATIVE("interface"));
112 auto money_dds = simple_fs::open_file(interface_dir, NATIVE("icon_money_big.dds"));
113 if(money_dds) {
114 auto content = simple_fs::view_contents(*money_dds);
115 uint32_t size_x, size_y;
116 state.open_gl.money_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(reinterpret_cast<uint8_t const*>(content.data),
117 content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
118 }
119
120 auto assets_dir = simple_fs::open_directory(root, NATIVE("assets"));
121 auto cross_dds = simple_fs::open_file(assets_dir, NATIVE("trigger_not.dds"));
122 if(cross_dds) {
123 auto content = simple_fs::view_contents(*cross_dds);
124 uint32_t size_x, size_y;
125 state.open_gl.cross_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(reinterpret_cast<uint8_t const*>(content.data),
126 content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
127 }
128 auto cb_cross_dds = simple_fs::open_file(assets_dir, NATIVE("trigger_not_cb.dds"));
129 if(cb_cross_dds) {
130 auto content = simple_fs::view_contents(*cb_cross_dds);
131 uint32_t size_x, size_y;
132 state.open_gl.color_blind_cross_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(reinterpret_cast<uint8_t const*>(content.data),
133 content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
134 }
135 auto checkmark_dds = simple_fs::open_file(assets_dir, NATIVE("trigger_yes.dds"));
136 if(checkmark_dds) {
137 auto content = simple_fs::view_contents(*checkmark_dds);
138 uint32_t size_x, size_y;
139 state.open_gl.checkmark_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(
140 reinterpret_cast<uint8_t const*>(content.data), content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
141 }
142
143 auto n_dds = simple_fs::open_file(interface_dir, NATIVE("politics_foreign_naval_units.dds"));
144 if(n_dds) {
145 auto content = simple_fs::view_contents(*n_dds);
146 uint32_t size_x, size_y;
147 state.open_gl.navy_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(
148 reinterpret_cast<uint8_t const*>(content.data), content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
149 }
150 auto a_dds = simple_fs::open_file(interface_dir, NATIVE("topbar_army.dds"));
151 if(a_dds) {
152 auto content = simple_fs::view_contents(*a_dds);
153 uint32_t size_x, size_y;
154 state.open_gl.army_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(
155 reinterpret_cast<uint8_t const*>(content.data), content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
156 }
157}
158
159std::string_view framebuffer_error(GLenum e) {
160 switch(e) {
161 case GL_FRAMEBUFFER_UNDEFINED:
162 return "GL_FRAMEBUFFER_UNDEFINED";
163 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
164 return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
165 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
166 return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT ";
167 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
168 return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
169 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
170 return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
171 case GL_FRAMEBUFFER_UNSUPPORTED:
172 return "GL_FRAMEBUFFER_UNSUPPORTED";
173 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
174 return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
175 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
176 return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";
177 default:
178 break;
179 }
180 return "???";
181}
182
183void initialize_msaa(sys::state& state, int32_t size_x, int32_t size_y) {
184 if(state.user_settings.antialias_level == 0)
185 return;
186 if(!size_x || !size_y)
187 return;
188 glEnable(GL_MULTISAMPLE);
189 // setup screen VAO
190 static const float sq_vertices[] = {
191 // positions // texCoords
192 -1.0f, 1.0f, 0.0f, 1.0f,
193 -1.0f, -1.0f, 0.0f, 0.0f,
194 1.0f, -1.0f, 1.0f, 0.0f,
195 -1.0f, 1.0f, 0.0f, 1.0f,
196 1.0f, -1.0f, 1.0f, 0.0f,
197 1.0f, 1.0f, 1.0f, 1.0f
198 };
199 glGenVertexArrays(1, &state.open_gl.msaa_vao);
200 glGenBuffers(1, &state.open_gl.msaa_vbo);
201 glBindVertexArray(state.open_gl.msaa_vao);
202 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.msaa_vbo);
203 glBufferData(GL_ARRAY_BUFFER, sizeof(sq_vertices), &sq_vertices, GL_STATIC_DRAW);
204 glEnableVertexAttribArray(0);
205 glEnableVertexAttribArray(1);
206 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
207 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
208 // framebuffer
209 glGenFramebuffers(1, &state.open_gl.msaa_framebuffer);
210 glBindFramebuffer(GL_FRAMEBUFFER, state.open_gl.msaa_framebuffer);
211 // create a multisampled color attachment texture
212 glGenTextures(1, &state.open_gl.msaa_texcolorbuffer);
213 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, state.open_gl.msaa_texcolorbuffer);
214 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, GLsizei(state.user_settings.antialias_level), GL_RGBA, size_x, size_y, GL_TRUE);
215 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
216 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, state.open_gl.msaa_texcolorbuffer, 0);
217 // create a (also multisampled) renderbuffer object for depth and stencil attachments
218 glGenRenderbuffers(1, &state.open_gl.msaa_rbo);
219 glBindRenderbuffer(GL_RENDERBUFFER, state.open_gl.msaa_rbo);
220 glRenderbufferStorageMultisample(GL_RENDERBUFFER, GLsizei(state.user_settings.antialias_level), GL_DEPTH24_STENCIL8, size_x, size_y);
221 glBindRenderbuffer(GL_RENDERBUFFER, 0);
222 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, state.open_gl.msaa_rbo);
223 if(auto r = glCheckFramebufferStatus(GL_FRAMEBUFFER); r != GL_FRAMEBUFFER_COMPLETE) {
224 //notify_user_of_fatal_opengl_error("MSAA framebuffer wasn't completed: " + std::string(framebuffer_error(r)));
225 state.user_settings.antialias_level--;
226 deinitialize_msaa(state);
227 if(state.user_settings.antialias_level != 0) {
228 initialize_msaa(state, size_x, size_y);
229 } else {
230 state.open_gl.msaa_enabled = false;
231 }
232 return;
233 }
234 // configure second post-processing framebuffer
235 glGenFramebuffers(1, &state.open_gl.msaa_interbuffer);
236 glBindFramebuffer(GL_FRAMEBUFFER, state.open_gl.msaa_interbuffer);
237 // create a color attachment texture
238 glGenTextures(1, &state.open_gl.msaa_texture);
239 glBindTexture(GL_TEXTURE_2D, state.open_gl.msaa_texture);
240 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_x, size_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
243 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, state.open_gl.msaa_texture, 0); // we only need a color buffer
244 if(auto r = glCheckFramebufferStatus(GL_FRAMEBUFFER); r != GL_FRAMEBUFFER_COMPLETE) {
245 notify_user_of_fatal_opengl_error("MSAA post processing framebuffer wasn't completed: " + std::string(framebuffer_error(r)));
246 }
247 glBindFramebuffer(GL_FRAMEBUFFER, 0);
248
249 auto root = get_root(state.common_fs);
250 auto msaa_fshader = open_file(root, NATIVE("assets/shaders/glsl/msaa_f_shader.glsl"));
251 auto msaa_vshader = open_file(root, NATIVE("assets/shaders/glsl/msaa_v_shader.glsl"));
252 if(bool(msaa_fshader) && bool(msaa_vshader)) {
253 auto vertex_content = view_contents(*msaa_vshader);
254 auto fragment_content = view_contents(*msaa_fshader);
255 state.open_gl.msaa_shader_program = create_program(std::string_view(vertex_content.data, vertex_content.file_size), std::string_view(fragment_content.data, fragment_content.file_size));
256 state.open_gl.msaa_uniform_screen_size = glGetUniformLocation(state.open_gl.msaa_shader_program, "screen_size");
257 state.open_gl.msaa_uniform_gaussian_blur = glGetUniformLocation(state.open_gl.msaa_shader_program, "gaussian_radius");
258 } else {
259 notify_user_of_fatal_opengl_error("Unable to open a MSAA shaders file");
260 }
261 state.open_gl.msaa_enabled = true;
262}
263
264
266 if(!state.open_gl.msaa_enabled)
267 return;
268
269 state.open_gl.msaa_enabled = false;
270 if(state.open_gl.msaa_texture)
271 glDeleteTextures(1, &state.open_gl.msaa_texture);
272 if(state.open_gl.msaa_interbuffer)
273 glDeleteFramebuffers(1, &state.open_gl.msaa_framebuffer);
274 if(state.open_gl.msaa_rbo)
275 glDeleteRenderbuffers(1, &state.open_gl.msaa_rbo);
276 if(state.open_gl.msaa_texcolorbuffer)
277 glDeleteTextures(1, &state.open_gl.msaa_texcolorbuffer);
278 if(state.open_gl.msaa_framebuffer)
279 glDeleteFramebuffers(1, &state.open_gl.msaa_framebuffer);
280 if(state.open_gl.msaa_vbo)
281 glDeleteBuffers(1, &state.open_gl.msaa_vbo);
282 if(state.open_gl.msaa_vao)
283 glDeleteVertexArrays(1, &state.open_gl.msaa_vao);
284 if(state.open_gl.msaa_shader_program)
285 glDeleteProgram(state.open_gl.msaa_shader_program);
286 glDisable(GL_MULTISAMPLE);
287}
288
291
292 glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
293 glEnable(GL_LINE_SMOOTH);
294
295 load_shaders(state); // create shaders
296 load_global_squares(state); // create various squares to drive the shaders with
297
298 state.flag_type_map.resize(size_t(culture::flag_type::count), 0);
299 // Create the remapping for flags
300 state.world.for_each_national_identity([&](dcon::national_identity_id ident_id) {
301 auto fat_id = dcon::fatten(state.world, ident_id);
302 auto nat_id = fat_id.get_nation_from_identity_holder().id;
303 for(auto gov_id : state.world.in_government_type) {
304 state.flag_types.push_back(culture::flag_type(gov_id.get_flag()));
305 }
306 });
307 // Eliminate duplicates
308 std::sort(state.flag_types.begin(), state.flag_types.end());
309 state.flag_types.erase(std::unique(state.flag_types.begin(), state.flag_types.end()), state.flag_types.end());
310
311 // Automatically assign texture offsets to the flag_types
312 auto id = 0;
313 for(auto type : state.flag_types)
314 state.flag_type_map[uint32_t(type)] = uint8_t(id++);
315 assert(state.flag_type_map[0] == 0); // default_flag
316
317 // Allocate textures for the flags
318 state.open_gl.asset_textures.resize(
319 state.ui_defs.textures.size() + (state.world.national_identity_size() + 1) * state.flag_types.size());
320
321 state.map_state.load_map(state);
322
323 load_special_icons(state);
324
326}
327
328static const GLfloat global_square_data[] = {
329 0.0f, 0.0f, 0.0f, 0.0f,
330 0.0f, 1.0f, 0.0f, 1.0f,
331 1.0f, 1.0f, 1.0f, 1.0f,
332 1.0f, 0.0f, 1.0f, 0.0f
333};
334static const GLfloat global_square_right_data[] = {
335 0.0f, 0.0f, 0.0f, 1.0f,
336 0.0f, 1.0f, 1.0f, 1.0f,
337 1.0f, 1.0f, 1.0f, 0.0f,
338 1.0f, 0.0f, 0.0f, 0.0f
339};
340static const GLfloat global_square_left_data[] = {
341 0.0f, 0.0f, 1.0f, 0.0f,
342 0.0f, 1.0f, 0.0f, 0.0f,
343 1.0f, 1.0f, 0.0f, 1.0f,
344 1.0f, 0.0f, 1.0f, 1.0f
345};
346static const GLfloat global_square_flipped_data[] = {
347 0.0f, 0.0f, 0.0f, 1.0f,
348 0.0f, 1.0f, 0.0f, 0.0f,
349 1.0f, 1.0f, 1.0f, 0.0f,
350 1.0f, 0.0f, 1.0f, 1.0f
351};
352static const GLfloat global_square_right_flipped_data[] = {
353 0.0f, 0.0f, 0.0f, 0.0f,
354 0.0f, 1.0f, 1.0f, 0.0f,
355 1.0f, 1.0f, 1.0f, 1.0f,
356 1.0f, 0.0f, 0.0f, 1.0f
357};
358static const GLfloat global_square_left_flipped_data[] = {
359 0.0f, 0.0f, 1.0f, 1.0f,
360 0.0f, 1.0f, 0.0f, 1.0f,
361 1.0f, 1.0f, 0.0f, 0.0f,
362 1.0f, 0.0f, 1.0f, 0.0f
363};
364
365//RTL squares
366static const GLfloat global_rtl_square_data[] = {
367 0.0f, 0.0f, 1.0f, 0.0f,
368 0.0f, 1.0f, 1.0f, 1.0f,
369 1.0f, 1.0f, 0.0f, 1.0f,
370 1.0f, 0.0f, 0.0f, 0.0f
371};
372static const GLfloat global_rtl_square_right_data[] = {
373 0.0f, 1.0f, 1.0f, 0.0f,
374 0.0f, 0.0f, 0.0f, 0.0f,
375 1.0f, 0.0f, 0.0f, 1.0f,
376 1.0f, 1.0f, 1.0f, 1.0f
377};
378static const GLfloat global_rtl_square_left_data[] = {
379 0.0f, 0.0f, 0.0f, 0.0f,
380 0.0f, 1.0f, 1.0f, 0.0f,
381 1.0f, 1.0f, 1.0f, 1.0f,
382 1.0f, 0.0f, 0.0f, 1.0f
383};
384static const GLfloat global_rtl_square_flipped_data[] = {
385 0.0f, 0.0f, 1.0f, 1.0f,
386 0.0f, 1.0f, 1.0f, 0.0f,
387 1.0f, 1.0f, 0.0f, 0.0f,
388 1.0f, 0.0f, 0.0f, 1.0f
389};
390static const GLfloat global_rtl_square_right_flipped_data[] = {
391 0.0f, 0.0f, 1.0f, 0.0f,
392 0.0f, 1.0f, 0.0f, 0.0f,
393 1.0f, 1.0f, 0.0f, 1.0f,
394 1.0f, 0.0f, 1.0f, 1.0f
395};
396static const GLfloat global_rtl_square_left_flipped_data[] = {
397 0.0f, 0.0f, 0.0f, 1.0f,
398 0.0f, 1.0f, 1.0f, 1.0f,
399 1.0f, 1.0f, 1.0f, 0.0f,
400 1.0f, 0.0f, 0.0f, 0.0f
401};
402
404 auto root = get_root(state.common_fs);
405 auto ui_fshader = open_file(root, NATIVE("assets/shaders/glsl/ui_f_shader.glsl"));
406 auto ui_vshader = open_file(root, NATIVE("assets/shaders/glsl/ui_v_shader.glsl"));
407 if(bool(ui_fshader) && bool(ui_vshader)) {
408 auto vertex_content = view_contents(*ui_vshader);
409 auto fragment_content = view_contents(*ui_fshader);
410 state.open_gl.ui_shader_program = create_program(std::string_view(vertex_content.data, vertex_content.file_size), std::string_view(fragment_content.data, fragment_content.file_size));
411
412 state.open_gl.ui_shader_texture_sampler_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "texture_sampler");
413 state.open_gl.ui_shader_secondary_texture_sampler_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "secondary_texture_sampler");
414 state.open_gl.ui_shader_screen_width_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "screen_width");
415 state.open_gl.ui_shader_screen_height_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "screen_height");
416 state.open_gl.ui_shader_gamma_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "gamma");
417
418 state.open_gl.ui_shader_d_rect_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "d_rect");
419 state.open_gl.ui_shader_subroutines_index_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "subroutines_index");
420 state.open_gl.ui_shader_inner_color_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "inner_color");
421 state.open_gl.ui_shader_subrect_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "subrect");
422 state.open_gl.ui_shader_border_size_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "border_size");
423 } else {
424 notify_user_of_fatal_opengl_error("Unable to open a necessary shader file");
425 }
426}
427
429 // Populate the position buffer
430 glGenBuffers(1, &state.open_gl.global_square_buffer);
431 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_buffer);
432 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_data, GL_STATIC_DRAW);
433 //RTL version
434 glGenBuffers(1, &state.open_gl.global_rtl_square_buffer);
435 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_buffer);
436 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_data, GL_STATIC_DRAW);
437
438 glGenVertexArrays(1, &state.open_gl.global_square_vao);
439 glBindVertexArray(state.open_gl.global_square_vao);
440 glEnableVertexAttribArray(0); // position
441 glEnableVertexAttribArray(1); // texture coordinates
442
443 glBindVertexBuffer(0, state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
444
445 glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, 0); // position
446 glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2); // texture coordinates
447 glVertexAttribBinding(0, 0); // position -> to array zero
448 glVertexAttribBinding(1, 0); // texture coordinates -> to array zero
449
450 glGenBuffers(1, &state.open_gl.global_square_left_buffer);
451 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_left_buffer);
452 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_left_data, GL_STATIC_DRAW);
453
454 glGenBuffers(1, &state.open_gl.global_square_right_buffer);
455 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_right_buffer);
456 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_right_data, GL_STATIC_DRAW);
457
458 glGenBuffers(1, &state.open_gl.global_square_right_flipped_buffer);
459 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_right_flipped_buffer);
460 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_right_flipped_data, GL_STATIC_DRAW);
461
462 glGenBuffers(1, &state.open_gl.global_square_left_flipped_buffer);
463 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_left_flipped_buffer);
464 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_left_flipped_data, GL_STATIC_DRAW);
465
466 glGenBuffers(1, &state.open_gl.global_square_flipped_buffer);
467 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_flipped_buffer);
468 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_flipped_data, GL_STATIC_DRAW);
469
470 //RTL mode squares
471 glGenBuffers(1, &state.open_gl.global_rtl_square_left_buffer);
472 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_left_buffer);
473 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_left_data, GL_STATIC_DRAW);
474
475 glGenBuffers(1, &state.open_gl.global_rtl_square_right_buffer);
476 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_right_buffer);
477 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_right_data, GL_STATIC_DRAW);
478
479 glGenBuffers(1, &state.open_gl.global_rtl_square_right_flipped_buffer);
480 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_right_flipped_buffer);
481 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_right_flipped_data, GL_STATIC_DRAW);
482
483 glGenBuffers(1, &state.open_gl.global_rtl_square_left_flipped_buffer);
484 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_left_flipped_buffer);
485 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_left_flipped_data, GL_STATIC_DRAW);
486
487 glGenBuffers(1, &state.open_gl.global_rtl_square_flipped_buffer);
488 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_flipped_buffer);
489 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_flipped_data, GL_STATIC_DRAW);
490
491 glGenBuffers(64, state.open_gl.sub_square_buffers);
492 for(uint32_t i = 0; i < 64; ++i) {
493 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.sub_square_buffers[i]);
494
495 float const cell_x = static_cast<float>(i & 7) / 8.0f;
496 float const cell_y = static_cast<float>((i >> 3) & 7) / 8.0f;
497
498 GLfloat global_sub_square_data[] = {0.0f, 0.0f, cell_x, cell_y, 0.0f, 1.0f, cell_x, cell_y + 1.0f / 8.0f, 1.0f, 1.0f,
499 cell_x + 1.0f / 8.0f, cell_y + 1.0f / 8.0f, 1.0f, 0.0f, cell_x + 1.0f / 8.0f, cell_y};
500
501 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_sub_square_data, GL_STATIC_DRAW);
502 }
503}
504
506 switch(e) {
513 default:
515 return parameters::enabled;
516 }
517}
518
519void bind_vertices_by_rotation(sys::state const& state, ui::rotation r, bool flipped, bool rtl) {
520 switch(r) {
522 if(!flipped)
523 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_buffer : state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
524 else
525 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_flipped_buffer : state.open_gl.global_square_flipped_buffer, 0, sizeof(GLfloat) * 4);
526 break;
528 if(!flipped)
529 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_left_buffer: state.open_gl.global_square_left_buffer, 0, sizeof(GLfloat) * 4);
530 else
531 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_left_flipped_buffer : state.open_gl.global_square_left_flipped_buffer, 0, sizeof(GLfloat) * 4);
532 break;
534 if(!flipped)
535 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_right_buffer : state.open_gl.global_square_right_buffer, 0, sizeof(GLfloat) * 4);
536 else
537 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_right_flipped_buffer : state.open_gl.global_square_right_flipped_buffer, 0, sizeof(GLfloat) * 4);
538 break;
539 }
540}
541
543 sys::state const& state,
544 float x, float y, float width, float height,
545 float red, float green, float blue,
546 ui::rotation r, bool flipped, bool rtl
547) {
548 glBindVertexArray(state.open_gl.global_square_vao);
549 bind_vertices_by_rotation(state, r, flipped, rtl);
550 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
552 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
553 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, red, green, blue);
554 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
555 glLineWidth(2.0f);
556 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
557}
558
560 sys::state const& state,
561 float x, float y, float width, float height,
562 float red, float green, float blue, float alpha
563) {
564 glBindVertexArray(state.open_gl.global_square_vao);
565 glBindVertexBuffer(0, state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
566 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
568 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
569 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, red, green, blue);
570 glUniform1f(state.open_gl.ui_shader_border_size_uniform, alpha);
571 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
572 glLineWidth(2.0f);
573 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
574}
575
576void render_simple_rect(sys::state const& state, float x, float y, float width, float height, ui::rotation r, bool flipped, bool rtl) {
578 state, x, y, width, height, 1.0f, 1.0f, 1.0f, r, flipped, rtl
579 );
580}
581
582void render_textured_rect(sys::state const& state, color_modification enabled, float x, float y, float width, float height,
583 GLuint texture_handle, ui::rotation r, bool flipped, bool rtl) {
584 glBindVertexArray(state.open_gl.global_square_vao);
585
586 bind_vertices_by_rotation(state, r, flipped, rtl);
587
588 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
589 // glUniform4f(state.open_gl.ui_shader_d_rect_uniform, 0, 0, width, height);
590
591 glActiveTexture(GL_TEXTURE0);
592 glBindTexture(GL_TEXTURE_2D, texture_handle);
593
594 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::no_filter};
595 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
596 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
597
598 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
599}
600
601void render_textured_rect_direct(sys::state const& state, float x, float y, float width, float height, uint32_t handle) {
602 glBindVertexArray(state.open_gl.global_square_vao);
603
604 glBindVertexBuffer(0, state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
605
606 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
607
608 glActiveTexture(GL_TEXTURE0);
609 glBindTexture(GL_TEXTURE_2D, handle);
610
611 GLuint subroutines[2] = {parameters::enabled, parameters::no_filter};
612 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
613 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
614
615 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
616}
617
618void render_linegraph(sys::state const& state, color_modification enabled, float x, float y, float width, float height,
619 lines& l) {
620 glBindVertexArray(state.open_gl.global_square_vao);
621
622 l.bind_buffer();
623
624 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
625 GLuint subroutines[2] = { map_color_modification_to_index(enabled), parameters::linegraph };
626 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
627 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
628
629 if(state.user_settings.color_blind_mode != sys::color_blind_mode::none
630 && state.user_settings.color_blind_mode != sys::color_blind_mode::achroma) {
631 glLineWidth(4.0f);
632 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 0.f, 0.f, 0.f);
633 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
634 }
635 glLineWidth(2.0f);
636 if(state.user_settings.color_blind_mode == sys::color_blind_mode::achroma) {
637 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 0.f, 0.f, 0.f);
638 } else if(state.user_settings.color_blind_mode == sys::color_blind_mode::tritan) {
639 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 1.f, 1.f, 0.f);
640 } else if(state.user_settings.color_blind_mode == sys::color_blind_mode::deutan || state.user_settings.color_blind_mode == sys::color_blind_mode::protan) {
641 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 1.f, 1.f, 1.f);
642 } else {
643 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 1.f, 1.f, 0.f);
644 }
645 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
646}
647
648void render_linegraph(sys::state const& state, color_modification enabled, float x, float y, float width, float height, float r, float g, float b,
649 lines& l) {
650 glBindVertexArray(state.open_gl.global_square_vao);
651
652 l.bind_buffer();
653
654 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
655 GLuint subroutines[2] = { map_color_modification_to_index(enabled), parameters::linegraph_color };
656 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
657 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
658
659 if(state.user_settings.color_blind_mode != sys::color_blind_mode::none
660 && state.user_settings.color_blind_mode != sys::color_blind_mode::achroma) {
661 glLineWidth(4.0f);
662 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 0.f, 0.f, 0.f);
663 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
664 }
665 glLineWidth(2.0f);
666 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, r, g, b);
667 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
668}
669
670void render_linegraph(sys::state const& state, color_modification enabled, float x, float y, float width, float height, float r, float g, float b, float a, lines& l) {
671 glBindVertexArray(state.open_gl.global_square_vao);
672
673 l.bind_buffer();
674
675 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
676 GLuint subroutines[2] = { map_color_modification_to_index(enabled), parameters::linegraph_acolor };
677 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
678 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
679
680 glUniform1f(state.open_gl.ui_shader_border_size_uniform, a);
681
682 if(state.user_settings.color_blind_mode != sys::color_blind_mode::none
683 && state.user_settings.color_blind_mode != sys::color_blind_mode::achroma) {
684 glLineWidth(2.0f + 2.0f * state.user_settings.ui_scale);
685 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 0.f, 0.f, 0.f);
686 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
687 }
688 glLineWidth(2.0f * state.user_settings.ui_scale);
689 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, r, g, b);
690 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
691}
692
693void render_barchart(sys::state const& state, color_modification enabled, float x, float y, float width, float height,
694 data_texture& t, ui::rotation r, bool flipped, bool rtl) {
695 glBindVertexArray(state.open_gl.global_square_vao);
696
697 bind_vertices_by_rotation(state, r, flipped, rtl);
698
699 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
700
701 glActiveTexture(GL_TEXTURE0);
702 glBindTexture(GL_TEXTURE_2D, t.handle());
703
704 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::barchart};
705 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
706 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
707
708 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
709}
710
711void render_piechart(sys::state const& state, color_modification enabled, float x, float y, float size, data_texture& t) {
712 glBindVertexArray(state.open_gl.global_square_vao);
713
714 glBindVertexBuffer(0, state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
715
716 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, size, size);
717
718 glActiveTexture(GL_TEXTURE0);
719 glBindTexture(GL_TEXTURE_2D, t.handle());
720
721 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::piechart};
722 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
723 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
724
725 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
726}
727void render_stripchart(sys::state const& state, color_modification enabled, float x, float y, float sizex, float sizey, data_texture& t) {
728 glBindVertexArray(state.open_gl.global_square_vao);
729
730 glBindVertexBuffer(0, state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
731
732 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, sizex, sizey);
733
734 glActiveTexture(GL_TEXTURE0);
735 glBindTexture(GL_TEXTURE_2D, t.handle());
736
737 GLuint subroutines[2] = { map_color_modification_to_index(enabled), parameters::stripchart };
738 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
739 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
740
741 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
742}
743void render_bordered_rect(sys::state const& state, color_modification enabled, float border_size, float x, float y, float width,
744 float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl) {
745 glBindVertexArray(state.open_gl.global_square_vao);
746
747 bind_vertices_by_rotation(state, r, flipped, rtl);
748
749 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
750 glUniform1f(state.open_gl.ui_shader_border_size_uniform, border_size);
751
752 glActiveTexture(GL_TEXTURE0);
753 glBindTexture(GL_TEXTURE_2D, texture_handle);
754
755 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::frame_stretch};
756 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
757 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
758
759 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
760}
761
762void render_masked_rect(sys::state const& state, color_modification enabled, float x, float y, float width, float height,
763 GLuint texture_handle, GLuint mask_texture_handle, ui::rotation r, bool flipped, bool rtl) {
764 glBindVertexArray(state.open_gl.global_square_vao);
765
766 bind_vertices_by_rotation(state, r, flipped, rtl);
767
768 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
769
770 glActiveTexture(GL_TEXTURE0);
771 glBindTexture(GL_TEXTURE_2D, texture_handle);
772 glActiveTexture(GL_TEXTURE1);
773 glBindTexture(GL_TEXTURE_2D, mask_texture_handle);
774
775 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::use_mask};
776 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
777 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
778
779 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
780}
781
782void render_progress_bar(sys::state const& state, color_modification enabled, float progress, float x, float y, float width,
783 float height, GLuint left_texture_handle, GLuint right_texture_handle, ui::rotation r, bool flipped, bool rtl) {
784 glBindVertexArray(state.open_gl.global_square_vao);
785
786 bind_vertices_by_rotation(state, r, flipped, rtl);
787
788 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
789 glUniform1f(state.open_gl.ui_shader_border_size_uniform, progress);
790
791 glActiveTexture(GL_TEXTURE0);
792 glBindTexture(GL_TEXTURE_2D, left_texture_handle);
793 glActiveTexture(GL_TEXTURE1);
794 glBindTexture(GL_TEXTURE_2D, right_texture_handle);
795
796 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::progress_bar};
797 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
798 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
799
800 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
801}
802
803void render_tinted_textured_rect(sys::state const& state, float x, float y, float width, float height, float r, float g, float b,
804 GLuint texture_handle, ui::rotation rot, bool flipped, bool rtl) {
805 glBindVertexArray(state.open_gl.global_square_vao);
806
807 bind_vertices_by_rotation(state, rot, flipped, rtl);
808
809 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, r, g, b);
810 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
811
812 glActiveTexture(GL_TEXTURE0);
813 glBindTexture(GL_TEXTURE_2D, texture_handle);
814
815 GLuint subroutines[2] = {parameters::tint, parameters::no_filter};
816 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
817 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
818
819 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
820}
821
823 sys::state const& state,
824 float x, float y, float width, float height,
825 float r, float g, float b,
826 ui::rotation rot, bool flipped, bool rtl
827) {
828 glBindVertexArray(state.open_gl.global_square_vao);
829 bind_vertices_by_rotation(state, rot, flipped, rtl);
830 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, r, g, b);
831 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
832 GLuint subroutines[2] = { parameters::tint, parameters::transparent_color };
833 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
834 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
835}
836
837void render_tinted_subsprite(sys::state const& state, int frame, int total_frames, float x, float y,
838 float width, float height, float r, float g, float b, GLuint texture_handle, ui::rotation rot, bool flipped,
839 bool rtl) {
840 glBindVertexArray(state.open_gl.global_square_vao);
841
842 bind_vertices_by_rotation(state, rot, flipped, rtl);
843
844 auto const scale = 1.0f / static_cast<float>(total_frames);
845 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, static_cast<float>(frame) * scale, scale, 0.0f);
846 glUniform4f(state.open_gl.ui_shader_subrect_uniform, r, g, b, 0);
847 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
848
849 glActiveTexture(GL_TEXTURE0);
850 glBindTexture(GL_TEXTURE_2D, texture_handle);
851
852 GLuint subroutines[2] = { parameters::alternate_tint, parameters::sub_sprite };
853 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
854 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
855
856 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
857}
858
859void render_subsprite(sys::state const& state, color_modification enabled, int frame, int total_frames, float x, float y,
860 float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl) {
861 glBindVertexArray(state.open_gl.global_square_vao);
862
863 bind_vertices_by_rotation(state, r, flipped, rtl);
864
865 auto const scale = 1.0f / static_cast<float>(total_frames);
866 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, static_cast<float>(frame) * scale, scale, 0.0f);
867 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
868
869 glActiveTexture(GL_TEXTURE0);
870 glBindTexture(GL_TEXTURE_2D, texture_handle);
871
872 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::sub_sprite};
873 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
874 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
875
876 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
877}
878
879
880GLuint get_flag_texture_handle_from_tag(sys::state& state, const char tag[3]) {
881 char ltag[3];
882 ltag[0] = char(toupper(tag[0]));
883 ltag[1] = char(toupper(tag[1]));
884 ltag[2] = char(toupper(tag[2]));
885 dcon::national_identity_id ident{};
886 state.world.for_each_national_identity([&](dcon::national_identity_id id) {
887 auto curr = nations::int_to_tag(state.world.national_identity_get_identifying_int(id));
888 if(curr[0] == ltag[0] && curr[1] == ltag[1] && curr[2] == ltag[2]) {
889 ident = id;
890 }
891 });
892 if(!bool(ident)) {
893 // QOL: We will print the text instead of displaying the flag, for ease of viewing invalid tags
894 return 0;
895 }
896 auto fat_id = dcon::fatten(state.world, ident);
897 auto nation = fat_id.get_nation_from_identity_holder();
899 if(bool(nation.id) && nation.get_owned_province_count() != 0) {
900 flag_type = culture::get_current_flag_type(state, nation.id);
901 } else {
902 flag_type = culture::get_current_flag_type(state, ident);
903 }
904 return ogl::get_flag_handle(state, ident, flag_type);
905}
906
907bool display_tag_is_valid(sys::state& state, char tag[3]) {
908 tag[0] = char(toupper(tag[0]));
909 tag[1] = char(toupper(tag[1]));
910 tag[2] = char(toupper(tag[2]));
911 dcon::national_identity_id ident{};
912 state.world.for_each_national_identity([&](dcon::national_identity_id id) {
913 auto curr = nations::int_to_tag(state.world.national_identity_get_identifying_int(id));
914 if(curr[0] == tag[0] && curr[1] == tag[1] && curr[2] == tag[2])
915 ident = id;
916 });
917 return bool(ident);
918}
919
920void render_text_icon(sys::state& state, text::embedded_icon ico, float x, float baseline_y, float font_size, text::font& f, ogl::color_modification cmod) {
921 float scale = 1.f;
922 float icon_baseline = baseline_y + (f.internal_ascender / 64.f * font_size) - font_size;
923
925 glActiveTexture(GL_TEXTURE0);
926
927 switch(ico) {
929 scale = 1.3f;
930 glBindTexture(GL_TEXTURE_2D, state.open_gl.army_icon_tex );
931 break;
933 glBindTexture(GL_TEXTURE_2D, state.open_gl.navy_icon_tex);
934 scale = 1.3f;
935 break;
937 glBindTexture(GL_TEXTURE_2D, state.open_gl.checkmark_icon_tex);
938 icon_baseline += font_size * 0.1f;
939 break;
941 {
942 GLuint false_icon = (state.user_settings.color_blind_mode == sys::color_blind_mode::deutan || state.user_settings.color_blind_mode == sys::color_blind_mode::protan)
943 ? state.open_gl.color_blind_cross_icon_tex
944 : state.open_gl.cross_icon_tex;
945 glBindTexture(GL_TEXTURE_2D, false_icon);
946 icon_baseline += font_size * 0.1f;
947 break;
948 }
949 }
950
951 GLuint icon_subroutines[2] = { map_color_modification_to_index(cmod), parameters::no_filter };
952 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, icon_subroutines[0], icon_subroutines[1]);
953 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, icon_subroutines); // must set all subroutines in one call
954 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, icon_baseline, scale * font_size, scale * font_size);
955 glUniform4f(state.open_gl.ui_shader_subrect_uniform, 0.f, 1.f, 0.f, 1.f);
956 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
957}
958
959void render_text_flag(sys::state& state, text::embedded_flag ico, float x, float baseline_y, float font_size, text::font& f, ogl::color_modification cmod) {
960 float icon_baseline = baseline_y + (f.internal_ascender / 64.f * font_size) - font_size;
961
962 auto fat_id = dcon::fatten(state.world, ico.tag);
963 auto nation = fat_id.get_nation_from_identity_holder();
965 if(bool(nation.id) && nation.get_owned_province_count() != 0) {
966 flag_type = culture::get_current_flag_type(state, nation.id);
967 } else {
968 flag_type = culture::get_current_flag_type(state, ico.tag);
969 }
970 GLuint flag_texture_handle = ogl::get_flag_handle(state, ico.tag, flag_type);
971
972 GLuint icon_subroutines[2] = { map_color_modification_to_index(cmod), parameters::no_filter };
973 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, icon_subroutines[0], icon_subroutines[1]);
974 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, icon_subroutines); // must set all subroutines in one call
976 glActiveTexture(GL_TEXTURE0);
977 glBindTexture(GL_TEXTURE_2D, flag_texture_handle);
978 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, icon_baseline + font_size * 0.15f, 1.5f * font_size * 0.9f, font_size * 0.9f);
979 glUniform4f(state.open_gl.ui_shader_subrect_uniform, 0.f, 1.f, 0.f, 1.f);
980 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
981}
982
983void render_text_unit_icon(sys::state& state, text::embedded_unit_icon ico, float x, float baseline_y, float font_size, text::font& f, ogl::color_modification cmod) {
984 auto ascender_size = f.ascender(int32_t(font_size));
985 auto top_adj = f.top_adjustment(int32_t(font_size));
986 float icon_baseline = baseline_y + top_adj + ascender_size;
987 //float icon_baseline = baseline_y + (f.internal_ascender / 64.f * font_size) - font_size;
988
989 auto id = ico.unit_type;
990
991 auto gfx_id =
992 state.ui_defs.gui[
993 state.ui_state.defs_by_name.find(
994 state.lookup_key("gfx_storage_unit_types")
995 )->second.definition
996 ].data.image.gfx_object;
997
998 auto& gfx_def = state.ui_defs.gfx[gfx_id];
999
1000 auto frame = state.military_definitions.unit_base_definitions[id].icon - 1;
1001
1003 state,
1004 cmod,
1005 frame,
1006 gfx_def.number_of_frames,
1007 float(x) - ascender_size * 0.125f,
1008 icon_baseline - ascender_size,
1009 ascender_size * 1.25f,
1010 ascender_size * 1.25f,
1011 ogl::get_texture_handle(state, gfx_def.primary_texture_handle, gfx_def.is_partially_transparent()),
1013 gfx_def.is_vertically_flipped(),
1014 false
1015 );
1016}
1017
1019 sys::state& state, dcon::commodity_id cid,
1020 float x, float y, float w, float h
1021) {
1022 auto gfx_id =
1023 state.ui_defs.gui[
1024 state.ui_state.defs_by_name.find(
1025 state.lookup_key("gfx_storage_commodity")
1026 )->second.definition
1027 ].data.image.gfx_object;
1028
1029 auto& gfx_def = state.ui_defs.gfx[gfx_id];
1030
1031 auto frame = state.world.commodity_get_icon(cid);
1032
1034 state,
1036 frame,
1037 gfx_def.number_of_frames,
1038 x,
1039 y,
1040 w,
1041 h,
1042 ogl::get_texture_handle(state, gfx_def.primary_texture_handle, gfx_def.is_partially_transparent()),
1044 gfx_def.is_vertically_flipped(),
1045 false
1046 );
1047}
1048
1051 float x, float baseline_y,
1052 float font_size, text::font& f
1053) {
1054 float icon_baseline = baseline_y + (f.internal_ascender / 64.f * font_size) - font_size;
1055
1057 state, ico.commodity,
1058 x, baseline_y,
1059 font_size, font_size
1060 );
1061}
1062
1063void internal_text_render(sys::state& state, text::stored_glyphs const& txt, float x, float baseline_y, float size, text::font& f) {
1065 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
1066 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
1067
1068 unsigned int glyph_count = static_cast<unsigned int>(txt.glyph_info.size());
1069 for(unsigned int i = 0; i < glyph_count; i++) {
1070 hb_codepoint_t glyphid = txt.glyph_info[i].codepoint;
1071 auto gso = f.glyph_positions[glyphid];
1072 float x_advance = float(txt.glyph_info[i].x_advance) / (float((1 << 6) * text::magnification_factor));
1073 float x_offset = float(txt.glyph_info[i].x_offset) / (float((1 << 6) * text::magnification_factor)) + float(gso.x);
1074 float y_offset = float(gso.y) - float(txt.glyph_info[i].y_offset) / (float((1 << 6) * text::magnification_factor));
1075 glBindVertexBuffer(0, state.open_gl.sub_square_buffers[gso.texture_slot & 63], 0, sizeof(GLfloat) * 4);
1076 assert(uint32_t(gso.texture_slot >> 6) < f.textures.size());
1077 assert(f.textures[gso.texture_slot >> 6]);
1078 glActiveTexture(GL_TEXTURE0);
1079 glBindTexture(GL_TEXTURE_2D, f.textures[gso.texture_slot >> 6]);
1080 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x + x_offset * size / 64.f, baseline_y + y_offset * size / 64.f, size, size);
1081 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1082 x += x_advance * size / 64.f;
1083 baseline_y -= (float(txt.glyph_info[i].y_advance) / (float((1 << 6) * text::magnification_factor))) * size / 64.f;
1084 }
1085}
1086
1087void render_classic_text(sys::state& state, text::stored_glyphs const& txt, float x, float y, float size, color_modification enabled, color3f const& c, text::bm_font const& font, text::font& base_font) {
1088 std::string codepoints = "";
1089 for(uint32_t i = 0; i < uint32_t(txt.glyph_info.size()); i++) {
1090 codepoints.push_back(char(txt.glyph_info[i].codepoint));
1091 }
1092 uint32_t count = uint32_t(codepoints.length());
1093
1094 float adv = 1.0f / font.width; // Font texture atlas spacing.
1096 GLuint subroutines[2] = { map_color_modification_to_index(enabled), parameters::subsprite_b };
1097 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
1098 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
1099
1100 // Set Text Color, all one color for now.
1101 //------ FOR SCHOMBERT ------//
1102 // Every iteration of this loop draws one character of the string 'fmt'.
1103 //'texlst' contains information for each vertex of each rectangle for each character.
1104 // Every 4 elements in 'texlst' is one complete rectangle, and one character.
1105 //'texlst[i].texx' and 'texlst[i].texy' are the intended texture coordinates of a vertex on the texture.
1106 //'texlst[i].x' and 'texlst[i].y' are the coordinates of a vertex of the rendered rectangle in the window.
1107 // The color variables are unused currently.
1108 //
1109 // Spacing, kearning, etc. are already applied.
1110 // Scaling (unintentionally) is also applied (by whatever part of Alice scales the normal fonts).
1111
1112 glActiveTexture(GL_TEXTURE0);
1113 glBindTexture(GL_TEXTURE_2D, font.ftexid);
1114
1115 for(uint32_t i = 0; i < count; ++i) {
1116 uint8_t ch = uint8_t(codepoints[i]);
1117 if(i != 0 && i < count - 1 && ch == 0xC2 && uint8_t(codepoints[i + 1]) == 0xA3) {
1118 ch = 0xA3;
1119 i++;
1120 } else if(ch == 0xA4) {
1121 ch = 0xA3;
1122 }
1123 auto const& f = font.chars[ch];
1124 float CurX = x + f.x_offset;
1125 float CurY = y + f.y_offset;
1126 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, CurX, CurY, float(f.width), float(f.height));
1127 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, c.r, c.g, c.b);
1128 glUniform4f(state.open_gl.ui_shader_subrect_uniform, float(f.x) / float(font.width) /* x offset */,
1129 float(f.width) / float(font.width) /* x width */, float(f.y) / float(font.width) /* y offset */,
1130 float(f.height) / float(font.width) /* y height */
1131 );
1132 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1133 //float x_advance = float(txt.glyph_pos[i].x_advance) / (float((1 << 6) * text::magnification_factor));
1134 x += f.x_advance;
1135 }
1136}
1137
1138void render_new_text(sys::state& state, text::stored_glyphs const& txt, color_modification enabled, float x, float y, float size, color3f const& c, text::font& f) {
1139 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, c.r, c.g, c.b);
1140 glUniform1f(state.open_gl.ui_shader_border_size_uniform, 0.08f * 16.0f / size);
1141 internal_text_render(state, txt, x, y + size, size, f);
1142}
1143
1144void render_text(sys::state& state, text::stored_glyphs const& txt, color_modification enabled, float x, float y, color3f const& c, uint16_t font_id) {
1145 auto& font = state.font_collection.get_font(state, text::font_index_from_font_id(state, font_id));
1146 if(state.user_settings.use_classic_fonts) {
1147 render_classic_text(state, txt, x, y, float(text::size_from_font_id(font_id)), enabled, c, text::get_bm_font(state, font_id), font);
1148 return;
1149 }
1150 render_new_text(state, txt, enabled, x, y, float(text::size_from_font_id(font_id)), c, font);
1151}
1152
1153void lines::set_y(float* v) {
1154 for(int32_t i = 0; i < static_cast<int32_t>(count); ++i) {
1155 buffer[i * 4] = static_cast<float>(i) / static_cast<float>(count - 1);
1156 buffer[i * 4 + 1] = 1.0f - v[i];
1157 buffer[i * 4 + 2] = 0.5f;
1158 buffer[i * 4 + 3] = v[i];
1159 }
1160 pending_data_update = true;
1161}
1162
1164 for(int32_t i = 0; i < static_cast<int32_t>(count); ++i) {
1165 buffer[i * 4] = static_cast<float>(i) / static_cast<float>(count - 1);
1166 buffer[i * 4 + 1] = 0.5f;
1167 buffer[i * 4 + 2] = 0.5f;
1168 buffer[i * 4 + 3] = 0.5f;
1169 }
1170 pending_data_update = true;
1171}
1172
1174 if(buffer_handle == 0) {
1175 glGenBuffers(1, &buffer_handle);
1176
1177 glBindBuffer(GL_ARRAY_BUFFER, buffer_handle);
1178 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * count * 4, nullptr, GL_DYNAMIC_DRAW);
1179 }
1180 if(buffer && pending_data_update) {
1181 glBindBuffer(GL_ARRAY_BUFFER, buffer_handle);
1182 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * count * 4, buffer);
1183 pending_data_update = false;
1184 }
1185
1186 glBindVertexBuffer(0, buffer_handle, 0, sizeof(GLfloat) * 4);
1187}
1188
1189bool msaa_enabled(sys::state const& state) {
1190 return state.open_gl.msaa_enabled;
1191}
1192
1194 int32_t file_channels = 4;
1195 int32_t size_x = 0;
1196 int32_t size_y = 0;
1197 auto content = simple_fs::view_contents(file);
1198 auto data = stbi_load_from_memory(reinterpret_cast<uint8_t const*>(content.data), int32_t(content.file_size), &size_x, &size_y, &file_channels, 4);
1199 return image(data, size_x, size_y, 4);
1200}
1201
1202GLuint make_gl_texture(uint8_t* data, uint32_t size_x, uint32_t size_y, uint32_t channels) {
1203 GLuint texture_handle;
1204 glGenTextures(1, &texture_handle);
1205 const GLuint internalformats[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 };
1206 const GLuint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA };
1207 if(texture_handle) {
1208 glBindTexture(GL_TEXTURE_2D, texture_handle);
1209 glTexStorage2D(GL_TEXTURE_2D, 1, internalformats[channels - 1], size_x, size_y);
1210 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size_x, size_y, formats[channels - 1], GL_UNSIGNED_BYTE, data);
1211 glBindTexture(GL_TEXTURE_2D, 0);
1212 }
1213
1214 return texture_handle;
1215}
1217 auto file = open_file(dir, file_name);
1218 if(!file)
1219 return 0;
1220 auto image = load_stb_image(*file);
1222}
1223
1224void set_gltex_parameters(GLuint texture_handle, GLuint texture_type, GLuint filter, GLuint wrap) {
1225 glBindTexture(texture_type, texture_handle);
1226 if(filter == GL_LINEAR_MIPMAP_NEAREST || filter == GL_LINEAR_MIPMAP_LINEAR) {
1227 glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, filter);
1228 glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1229 glGenerateMipmap(texture_type);
1230 } else {
1231 glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, filter);
1232 glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1233 }
1234 glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap);
1235 glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap);
1236 glBindTexture(texture_type, 0);
1237}
1238
1239GLuint load_texture_array_from_file(simple_fs::file& file, int32_t tiles_x, int32_t tiles_y) {
1240 auto image = load_stb_image(file);
1241
1242 GLuint texture_handle = 0;
1243 glGenTextures(1, &texture_handle);
1244 if(texture_handle) {
1245 glBindTexture(GL_TEXTURE_2D_ARRAY, texture_handle);
1246
1247 size_t p_dx = image.size_x / tiles_x; // Pixels of each tile in x
1248 size_t p_dy = image.size_y / tiles_y; // Pixels of each tile in y
1249 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GLsizei(p_dx), GLsizei(p_dy), GLsizei(tiles_x * tiles_y), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1250 glPixelStorei(GL_UNPACK_ROW_LENGTH, image.size_x);
1251 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image.size_y);
1252
1253 for(int32_t x = 0; x < tiles_x; x++)
1254 for(int32_t y = 0; y < tiles_y; y++)
1255 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, GLint(x * tiles_x + y), GLsizei(p_dx), GLsizei(p_dy), 1, GL_RGBA, GL_UNSIGNED_BYTE, ((uint32_t const*)image.data) + (x * p_dy * image.size_x + y * p_dx));
1256
1257 set_gltex_parameters(texture_handle, GL_TEXTURE_2D_ARRAY, GL_LINEAR_MIPMAP_NEAREST, GL_REPEAT);
1258 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1259 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1260 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1261 }
1262 return texture_handle;
1263}
1264
1266 if(state.x_size > max_x || state.y_size > max_y) {
1267 max_x = std::max(max_x, state.x_size);
1268 max_y = std::max(max_y, state.y_size);
1269
1270 if(texture_handle)
1271 glDeleteTextures(1, &texture_handle);
1272 if(framebuffer)
1273 glDeleteFramebuffers(1, &framebuffer);
1274
1275 glGenFramebuffers(1, &framebuffer);
1276 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1277
1278 glGenTextures(1, &texture_handle);
1279 glBindTexture(GL_TEXTURE_2D, texture_handle);
1280 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, max_x, max_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1283
1284 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_handle, 0);
1285
1286 GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
1287 glDrawBuffers(1, DrawBuffers);
1288
1289 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1290 glClear(GL_COLOR_BUFFER_BIT);
1291 glEnable(GL_BLEND);
1292 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1293 glUseProgram(state.open_gl.ui_shader_program);
1294 glUniform1i(state.open_gl.ui_shader_texture_sampler_uniform, 0);
1295 glUniform1i(state.open_gl.ui_shader_secondary_texture_sampler_uniform, 1);
1296 glUniform1f(state.open_gl.ui_shader_screen_width_uniform, float(max_x) / state.user_settings.ui_scale);
1297 glUniform1f(state.open_gl.ui_shader_screen_height_uniform, float(max_y) / state.user_settings.ui_scale);
1298 glUniform1f(state.open_gl.ui_shader_gamma_uniform, state.user_settings.gamma);
1299 glViewport(0, 0, max_x, max_y);
1300 glDepthRange(-1.0f, 1.0f);
1301 } else {
1302 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1303
1304 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1305 glClear(GL_COLOR_BUFFER_BIT);
1306 glEnable(GL_BLEND);
1307 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1308 glUseProgram(state.open_gl.ui_shader_program);
1309 glUniform1i(state.open_gl.ui_shader_texture_sampler_uniform, 0);
1310 glUniform1i(state.open_gl.ui_shader_secondary_texture_sampler_uniform, 1);
1311 glUniform1f(state.open_gl.ui_shader_screen_width_uniform, float(max_x) / state.user_settings.ui_scale);
1312 glUniform1f(state.open_gl.ui_shader_screen_height_uniform, float(max_y) / state.user_settings.ui_scale);
1313 glUniform1f(state.open_gl.ui_shader_gamma_uniform, state.user_settings.gamma);
1314 glViewport(0, 0, max_x, max_y);
1315 glDepthRange(-1.0f, 1.0f);
1316 }
1317}
1319 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1320}
1322 return texture_handle;
1323}
1325 if(texture_handle)
1326 glDeleteTextures(1, &texture_handle);
1327 if(framebuffer)
1328 glDeleteFramebuffers(1, &framebuffer);
1329}
1330void render_subrect(sys::state const& state, float target_x, float target_y, float target_width, float target_height, float source_x, float source_y, float source_width, float source_height, GLuint texture_handle) {
1332 GLuint subroutines[2] = { parameters::enabled, parameters::subsprite_c };
1333 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
1334
1335 glActiveTexture(GL_TEXTURE0);
1336 glBindTexture(GL_TEXTURE_2D, texture_handle);
1337
1338 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, target_x, target_y, target_width, target_height);
1339 glUniform4f(state.open_gl.ui_shader_subrect_uniform, source_x /* x offset */, source_width /* x width */, source_y /* y offset */, source_height /* y height */);
1340 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1341}
1342
1343void animation::start_animation(sys::state& state, int32_t x, int32_t y, int32_t w, int32_t h, type t, int32_t runtime) {
1344 start_state.ready(state);
1345 state.current_scene.get_root(state)->impl_render(state, 0, 0);
1346 start_state.finish(state);
1347 ani_type = t;
1348 x_pos = x;
1349 y_pos = y;
1350 x_size = w;
1351 y_size = h;
1352 ms_run_time = runtime;
1353 start_time = std::chrono::steady_clock::now();
1354 running = true;
1355}
1357 if(running) {
1358 bool needs_new_state = (ani_type == type::page_flip_left_rev || ani_type == type::page_flip_right_rev || ani_type == type::page_flip_up_rev);
1359 if(needs_new_state) {
1360 end_state.ready(state);
1361 state.current_scene.get_root(state)->impl_render(state, 0, 0);
1362 end_state.finish(state);
1363 }
1364 }
1365}
1367 if(!running)
1368 return;
1369 auto entry_time = std::chrono::steady_clock::now();
1370 auto ms_count = std::chrono::duration_cast<std::chrono::milliseconds>(entry_time - start_time).count();
1371 if(ms_count > ms_run_time) {
1372 running = false;
1373 } else {
1374 float percent = float(ms_count) / float(ms_run_time);
1375 switch(ani_type) {
1377 {
1378 float extent = cos((percent) * 3.14159f / 2.0f);
1379 render_subrect(state, float(x_pos), float(y_pos), float(x_size * extent), float(y_size),
1380 float(x_pos) * state.user_settings.ui_scale / float(start_state.max_x), float(start_state.max_y - y_pos) * state.user_settings.ui_scale / float(start_state.max_y), float(x_size) * state.user_settings.ui_scale / float(start_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(start_state.max_y),
1381 start_state.get());
1382 }
1383 break;
1385 {
1386 float extent = cos((percent) * 3.14159f / 2.0f);
1387 render_subrect(state, float(x_pos + (x_size * (1.0f - extent))), float(y_pos), float(x_size * extent), float(y_size),
1388 float(x_pos) * state.user_settings.ui_scale / float(start_state.max_x), float(start_state.max_y - y_pos) * state.user_settings.ui_scale / float(start_state.max_y), float(x_size) * state.user_settings.ui_scale / float(start_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(start_state.max_y),
1389 start_state.get());
1390 }
1391 break;
1392 case type::page_flip_up:
1393 {
1394 float extent = cos((percent) * 3.14159f / 2.0f);
1395 render_subrect(state, float(x_pos), float(y_pos), float(x_size), float(y_size * extent),
1396 float(x_pos) * state.user_settings.ui_scale / float(start_state.max_x), float(start_state.max_y - y_pos) * state.user_settings.ui_scale / float(start_state.max_y), float(x_size) * state.user_settings.ui_scale / float(start_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(start_state.max_y),
1397 start_state.get());
1398 }
1399 break;
1401 {
1402 float extent = cos((1.0f - percent) * 3.14159f / 2.0f);
1403 render_subrect(state, float(x_pos), float(y_pos), float(x_size), float(y_size),
1404 float(x_pos) * state.user_settings.ui_scale / float(start_state.max_x), float(start_state.max_y - y_pos) * state.user_settings.ui_scale / float(start_state.max_y), float(x_size) * state.user_settings.ui_scale / float(start_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(start_state.max_y),
1405 start_state.get());
1406 render_subrect(state, float(x_pos), float(y_pos), float(x_size * extent), float(y_size),
1407 float(x_pos) * state.user_settings.ui_scale / float(end_state.max_x), float(start_state.max_y - y_pos) * state.user_settings.ui_scale / float(end_state.max_y), float(x_size) * state.user_settings.ui_scale / float(end_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(end_state.max_y),
1408 end_state.get());
1409 }
1410 break;
1412 {
1413 float extent = cos((1.0f - percent) * 3.14159f / 2.0f);
1414 render_subrect(state, float(x_pos), float(y_pos), float(x_size), float(y_size),
1415 float(x_pos) * state.user_settings.ui_scale / float(start_state.max_x), float(start_state.max_y - y_pos) * state.user_settings.ui_scale / float(start_state.max_y), float(x_size) * state.user_settings.ui_scale / float(start_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(start_state.max_y),
1416 start_state.get());
1417 render_subrect(state, float(x_pos + (x_size * (1.0f - extent))), float(y_pos), float(x_size * extent), float(y_size),
1418 float(x_pos) * state.user_settings.ui_scale / float(end_state.max_x), float(end_state.max_y - y_pos) * state.user_settings.ui_scale / float(end_state.max_y), float(x_size) * state.user_settings.ui_scale / float(end_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(end_state.max_y),
1419 end_state.get());
1420 }
1421 break;
1423 {
1424 float extent = cos((1.0f - percent) * 3.14159f / 2.0f);
1425 render_subrect(state, float(x_pos), float(y_pos), float(x_size), float(y_size),
1426 float(x_pos) * state.user_settings.ui_scale / float(start_state.max_x), float(start_state.max_y - y_pos) * state.user_settings.ui_scale / float(start_state.max_y), float(x_size) * state.user_settings.ui_scale / float(start_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(start_state.max_y),
1427 start_state.get());
1428 render_subrect(state, float(x_pos), float(y_pos), float(x_size), float(y_size * extent),
1429 float(x_pos) * state.user_settings.ui_scale / float(end_state.max_x), float(end_state.max_y - y_pos) * state.user_settings.ui_scale / float(end_state.max_y), float(x_size) * state.user_settings.ui_scale / float(end_state.max_x), float(-y_size) * state.user_settings.ui_scale / float(end_state.max_y),
1430 end_state.get());
1431 }
1432 break;
1433 }
1434 }
1435}
1436
1437} // namespace ogl
void start_animation(sys::state &state, int32_t x, int32_t y, int32_t w, int32_t h, type t, int32_t runtime)
void post_update_frame(sys::state &state)
void render(sys::state &state)
uint32_t count
void set_y(float *v)
void set_default_y()
void ready(sys::state &state)
void finish(sys::state &state)
int32_t width
Definition: bmfont.hpp:91
GLuint ftexid
Definition: bmfont.hpp:96
std::array< char_descriptor, 256 > chars
Definition: bmfont.hpp:87
float top_adjustment(int32_t size) const
Definition: fonts.cpp:463
ankerl::unordered_dense::map< char32_t, glyph_sub_offset > glyph_positions
Definition: fonts.hpp:117
float internal_ascender
Definition: fonts.hpp:114
float ascender(int32_t size) const
Definition: fonts.cpp:457
std::vector< uint32_t > textures
Definition: fonts.hpp:118
#define assert(condition)
Definition: debug.h:74
flag_type get_current_flag_type(sys::state const &state, dcon::nation_id target_nation)
Definition: culture.cpp:782
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
std::string int_to_tag(uint32_t v)
Definition: nations.hpp:14
constexpr GLuint piechart
constexpr GLuint tint
constexpr GLuint interactable
constexpr GLuint frame_stretch
constexpr GLuint no_filter
constexpr GLuint transparent_color
constexpr GLuint progress_bar
constexpr GLuint alpha_color
constexpr GLuint use_mask
constexpr GLuint stripchart
constexpr GLuint linegraph_acolor
constexpr GLuint subsprite_b
constexpr GLuint enabled
constexpr GLuint filter
constexpr GLuint barchart
constexpr GLuint disabled
constexpr GLuint linegraph
constexpr GLuint subsprite_c
constexpr GLuint alternate_tint
constexpr GLuint interactable_disabled
constexpr GLuint solid_color
constexpr GLuint sub_sprite
constexpr GLuint linegraph_color
void render_tinted_subsprite(sys::state const &state, int frame, int total_frames, float x, float y, float width, float height, float r, float g, float b, GLuint texture_handle, ui::rotation rot, bool flipped, bool rtl)
color_modification
std::string_view opengl_get_error_name(GLenum t)
void initialize_opengl(sys::state &state)
GLuint make_gl_texture(uint8_t *data, uint32_t size_x, uint32_t size_y, uint32_t channels)
void create_opengl_context(sys::state &state)
void render_barchart(sys::state const &state, color_modification enabled, float x, float y, float width, float height, data_texture &t, ui::rotation r, bool flipped, bool rtl)
void initialize_msaa(sys::state &state, int32_t size_x, int32_t size_y)
void render_colored_rect(sys::state const &state, float x, float y, float width, float height, float red, float green, float blue, ui::rotation r, bool flipped, bool rtl)
bool msaa_enabled(sys::state const &state)
void load_shaders(sys::state &state)
void render_bordered_rect(sys::state const &state, color_modification enabled, float border_size, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
void render_alpha_colored_rect(sys::state const &state, float x, float y, float width, float height, float red, float green, float blue, float alpha)
void internal_text_render(sys::state &state, text::stored_glyphs const &txt, float x, float baseline_y, float size, text::font &f)
void render_piechart(sys::state const &state, color_modification enabled, float x, float y, float size, data_texture &t)
void render_masked_rect(sys::state const &state, color_modification enabled, float x, float y, float width, float height, GLuint texture_handle, GLuint mask_texture_handle, ui::rotation r, bool flipped, bool rtl)
void load_global_squares(sys::state &state)
void deinitialize_msaa(sys::state &state)
void render_new_text(sys::state &state, text::stored_glyphs const &txt, color_modification enabled, float x, float y, float size, color3f const &c, text::font &f)
void render_text_commodity_icon(sys::state &state, text::embedded_commodity_icon ico, float x, float baseline_y, float font_size, text::font &f)
auto map_color_modification_to_index(color_modification e)
void render_subsprite(sys::state const &state, color_modification enabled, int frame, int total_frames, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
void render_text(sys::state &state, text::stored_glyphs const &txt, color_modification enabled, float x, float y, color3f const &c, uint16_t font_id)
void render_linegraph(sys::state const &state, color_modification enabled, float x, float y, float width, float height, lines &l)
void render_text_flag(sys::state &state, text::embedded_flag ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
GLuint load_texture_array_from_file(simple_fs::file &file, int32_t tiles_x, int32_t tiles_y)
void bind_vertices_by_rotation(sys::state const &state, ui::rotation r, bool flipped, bool rtl)
void render_simple_rect(sys::state const &state, float x, float y, float width, float height, ui::rotation r, bool flipped, bool rtl)
void render_subrect(sys::state const &state, float target_x, float target_y, float target_width, float target_height, float source_x, float source_y, float source_width, float source_height, GLuint texture_handle)
void set_gltex_parameters(GLuint texture_handle, GLuint texture_type, GLuint filter, GLuint wrap)
void render_commodity_icon(sys::state &state, dcon::commodity_id cid, float x, float y, float w, float h)
image load_stb_image(simple_fs::file &file)
GLuint create_program(std::string_view vertex_shader, std::string_view fragment_shader)
void render_textured_rect(sys::state const &state, color_modification enabled, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
GLuint SOIL_direct_load_DDS_from_memory(unsigned char const *const buffer, uint32_t buffer_length, uint32_t &width, uint32_t &height, int soil_flags)
Definition: texture.cpp:101
bool display_tag_is_valid(sys::state &state, char tag[3])
void render_tinted_rect(sys::state const &state, float x, float y, float width, float height, float r, float g, float b, ui::rotation rot, bool flipped, bool rtl)
@ SOIL_FLAG_TEXTURE_REPEATS
Definition: texture.hpp:23
void load_special_icons(sys::state &state)
void render_classic_text(sys::state &state, text::stored_glyphs const &txt, float x, float y, float size, color_modification enabled, color3f const &c, text::bm_font const &font, text::font &base_font)
void render_stripchart(sys::state const &state, color_modification enabled, float x, float y, float sizex, float sizey, data_texture &t)
GLuint get_texture_handle(sys::state &state, dcon::texture_id id, bool keep_data)
Definition: texture.cpp:1066
std::string_view framebuffer_error(GLenum e)
void render_text_icon(sys::state &state, text::embedded_icon ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
GLint compile_shader(std::string_view source, GLenum type)
void render_tinted_textured_rect(sys::state const &state, float x, float y, float width, float height, float r, float g, float b, GLuint texture_handle, ui::rotation rot, bool flipped, bool rtl)
void render_text_unit_icon(sys::state &state, text::embedded_unit_icon ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
GLuint get_flag_texture_handle_from_tag(sys::state &state, const char tag[3])
void render_textured_rect_direct(sys::state const &state, float x, float y, float width, float height, uint32_t handle)
void notify_user_of_fatal_opengl_error(std::string message)
void render_progress_bar(sys::state const &state, color_modification enabled, float progress, float x, float y, float width, float height, GLuint left_texture_handle, GLuint right_texture_handle, ui::rotation r, bool flipped, bool rtl)
GLuint get_flag_handle(sys::state &state, dcon::national_identity_id nat_id, culture::flag_type type)
Definition: texture.cpp:977
directory open_directory(directory const &dir, native_string_view directory_name)
std::optional< file > open_file(directory const &dir, native_string_view file_name)
file_contents view_contents(file const &f)
constexpr int magnification_factor
Definition: fonts.hpp:17
int32_t size_from_font_id(uint16_t id)
Definition: fonts.cpp:119
embedded_icon
Definition: text.hpp:781
bm_font const & get_bm_font(sys::state &state, uint16_t font_handle)
Definition: bmfont.cpp:162
font_selection font_index_from_font_id(sys::state &state, uint16_t id)
Definition: fonts.cpp:130
void emit_error_message(std::string const &content, bool fatal)
Definition: window_nix.cpp:355
#define NATIVE(X)
std::string_view native_string_view
uint uint32_t
uchar uint8_t
@ ident
int32_t channels
int32_t size_y
int32_t size_x
uint8_t * data
Holds important data about the game world, state, and other data regarding windowing,...
dcon::commodity_id commodity
Definition: text.hpp:788
dcon::national_identity_id tag
Definition: text.hpp:791
dcon::unit_type_id unit_type
Definition: text.hpp:785
std::vector< stored_glyph > glyph_info
Definition: fonts.hpp:82