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"
6
7namespace ogl {
8
9std::string_view opengl_get_error_name(GLenum t) {
10 switch(t) {
11 case GL_INVALID_ENUM:
12 return "GL_INVALID_ENUM";
13 case GL_INVALID_VALUE:
14 return "GL_INVALID_VALUE";
15 case GL_INVALID_OPERATION:
16 return "GL_INVALID_OPERATION";
17 case GL_INVALID_FRAMEBUFFER_OPERATION:
18 return "GL_INVALID_FRAMEBUFFER_OPERATION";
19 case GL_OUT_OF_MEMORY:
20 return "GL_OUT_OF_MEMORY";
21 case GL_STACK_UNDERFLOW:
22 return "GL_STACK_UNDERFLOW";
23 case GL_STACK_OVERFLOW:
24 return "GL_STACK_OVERFLOW";
25 case GL_NO_ERROR:
26 return "GL_NO_ERROR";
27 default:
28 return "Unknown";
29 }
30}
31
32void notify_user_of_fatal_opengl_error(std::string message) {
33 std::string full_message = message;
34 full_message += "\n";
35 full_message += opengl_get_error_name(glGetError());
36 window::emit_error_message("OpenGL error:" + full_message, true);
37}
38
39
40GLint compile_shader(std::string_view source, GLenum type) {
41 GLuint return_value = glCreateShader(type);
42
43 if(return_value == 0) {
44 notify_user_of_fatal_opengl_error("shader creation failed");
45 }
46
47 std::string s_source(source);
48 GLchar const* texts[] = {
49 "#version 140\r\n",
50 "#extension GL_ARB_explicit_uniform_location : enable\r\n",
51 "#extension GL_ARB_explicit_attrib_location : enable\r\n",
52 "#extension GL_ARB_shader_subroutine : enable\r\n",
53 "#extension GL_ARB_vertex_array_object : enable\r\n"
54 "#define M_PI 3.1415926535897932384626433832795\r\n",
55 "#define PI 3.1415926535897932384626433832795\r\n",
56 s_source.c_str()
57 };
58 glShaderSource(return_value, 7, texts, nullptr);
59 glCompileShader(return_value);
60
61 GLint result;
62 glGetShaderiv(return_value, GL_COMPILE_STATUS, &result);
63 if(result == GL_FALSE) {
64 GLint log_length = 0;
65 glGetShaderiv(return_value, GL_INFO_LOG_LENGTH, &log_length);
66
67 auto log = std::unique_ptr<char[]>(new char[static_cast<size_t>(log_length)]);
68 GLsizei written = 0;
69 glGetShaderInfoLog(return_value, log_length, &written, log.get());
70 notify_user_of_fatal_opengl_error(std::string("Shader failed to compile:\n") + log.get());
71 }
72 return return_value;
73}
74
75GLuint create_program(std::string_view vertex_shader, std::string_view fragment_shader) {
76 GLuint return_value = glCreateProgram();
77 if(return_value == 0) {
78 notify_user_of_fatal_opengl_error("program creation failed");
79 }
80
81 auto v_shader = compile_shader(vertex_shader, GL_VERTEX_SHADER);
82 auto f_shader = compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
83
84 glAttachShader(return_value, v_shader);
85 glAttachShader(return_value, f_shader);
86 glLinkProgram(return_value);
87
88 GLint result;
89 glGetProgramiv(return_value, GL_LINK_STATUS, &result);
90 if(result == GL_FALSE) {
91 GLint logLen;
92 glGetProgramiv(return_value, GL_INFO_LOG_LENGTH, &logLen);
93
94 char* log = new char[static_cast<size_t>(logLen)];
95 GLsizei written;
96 glGetProgramInfoLog(return_value, logLen, &written, log);
97 notify_user_of_fatal_opengl_error(std::string("Program failed to link:\n") + log);
98 }
99
100 glDeleteShader(v_shader);
101 glDeleteShader(f_shader);
102
103 return return_value;
104}
105
107 auto root = get_root(state.common_fs);
108 auto gfx_dir = simple_fs::open_directory(root, NATIVE("gfx"));
109
110 auto interface_dir = simple_fs::open_directory(gfx_dir, NATIVE("interface"));
111 auto money_dds = simple_fs::open_file(interface_dir, NATIVE("icon_money_big.dds"));
112 if(money_dds) {
113 auto content = simple_fs::view_contents(*money_dds);
114 uint32_t size_x, size_y;
115 state.open_gl.money_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(reinterpret_cast<uint8_t const*>(content.data),
116 content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
117 }
118
119 auto assets_dir = simple_fs::open_directory(root, NATIVE("assets"));
120 auto cross_dds = simple_fs::open_file(assets_dir, NATIVE("trigger_not.dds"));
121 if(cross_dds) {
122 auto content = simple_fs::view_contents(*cross_dds);
123 uint32_t size_x, size_y;
124 state.open_gl.cross_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(reinterpret_cast<uint8_t const*>(content.data),
125 content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
126 }
127 auto cb_cross_dds = simple_fs::open_file(assets_dir, NATIVE("trigger_not_cb.dds"));
128 if(cb_cross_dds) {
129 auto content = simple_fs::view_contents(*cb_cross_dds);
130 uint32_t size_x, size_y;
131 state.open_gl.color_blind_cross_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(reinterpret_cast<uint8_t const*>(content.data),
132 content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
133 }
134 auto checkmark_dds = simple_fs::open_file(assets_dir, NATIVE("trigger_yes.dds"));
135 if(checkmark_dds) {
136 auto content = simple_fs::view_contents(*checkmark_dds);
137 uint32_t size_x, size_y;
138 state.open_gl.checkmark_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(
139 reinterpret_cast<uint8_t const*>(content.data), content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
140 }
141
142 auto n_dds = simple_fs::open_file(interface_dir, NATIVE("politics_foreign_naval_units.dds"));
143 if(n_dds) {
144 auto content = simple_fs::view_contents(*n_dds);
145 uint32_t size_x, size_y;
146 state.open_gl.navy_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(
147 reinterpret_cast<uint8_t const*>(content.data), content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
148 }
149 auto a_dds = simple_fs::open_file(interface_dir, NATIVE("topbar_army.dds"));
150 if(a_dds) {
151 auto content = simple_fs::view_contents(*a_dds);
152 uint32_t size_x, size_y;
153 state.open_gl.army_icon_tex = GLuint(ogl::SOIL_direct_load_DDS_from_memory(
154 reinterpret_cast<uint8_t const*>(content.data), content.file_size, size_x, size_y, ogl::SOIL_FLAG_TEXTURE_REPEATS));
155 }
156}
157
158std::string_view framebuffer_error(GLenum e) {
159 switch(e) {
160 case GL_FRAMEBUFFER_UNDEFINED:
161 return "GL_FRAMEBUFFER_UNDEFINED";
162 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
163 return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
164 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
165 return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT ";
166 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
167 return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
168 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
169 return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
170 case GL_FRAMEBUFFER_UNSUPPORTED:
171 return "GL_FRAMEBUFFER_UNSUPPORTED";
172 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
173 return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
174 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
175 return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";
176 default:
177 break;
178 }
179 return "???";
180}
181
182void initialize_msaa(sys::state& state, int32_t size_x, int32_t size_y) {
183 if(state.user_settings.antialias_level == 0)
184 return;
185 if(!size_x || !size_y)
186 return;
187 glEnable(GL_MULTISAMPLE);
188 // setup screen VAO
189 static const float sq_vertices[] = {
190 // positions // texCoords
191 -1.0f, 1.0f, 0.0f, 1.0f,
192 -1.0f, -1.0f, 0.0f, 0.0f,
193 1.0f, -1.0f, 1.0f, 0.0f,
194 -1.0f, 1.0f, 0.0f, 1.0f,
195 1.0f, -1.0f, 1.0f, 0.0f,
196 1.0f, 1.0f, 1.0f, 1.0f
197 };
198 glGenVertexArrays(1, &state.open_gl.msaa_vao);
199 glGenBuffers(1, &state.open_gl.msaa_vbo);
200 glBindVertexArray(state.open_gl.msaa_vao);
201 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.msaa_vbo);
202 glBufferData(GL_ARRAY_BUFFER, sizeof(sq_vertices), &sq_vertices, GL_STATIC_DRAW);
203 glEnableVertexAttribArray(0);
204 glEnableVertexAttribArray(1);
205 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
206 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
207 // framebuffer
208 glGenFramebuffers(1, &state.open_gl.msaa_framebuffer);
209 glBindFramebuffer(GL_FRAMEBUFFER, state.open_gl.msaa_framebuffer);
210 // create a multisampled color attachment texture
211 glGenTextures(1, &state.open_gl.msaa_texcolorbuffer);
212 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, state.open_gl.msaa_texcolorbuffer);
213 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, GLsizei(state.user_settings.antialias_level), GL_RGBA, size_x, size_y, GL_TRUE);
214 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
215 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, state.open_gl.msaa_texcolorbuffer, 0);
216 // create a (also multisampled) renderbuffer object for depth and stencil attachments
217 glGenRenderbuffers(1, &state.open_gl.msaa_rbo);
218 glBindRenderbuffer(GL_RENDERBUFFER, state.open_gl.msaa_rbo);
219 glRenderbufferStorageMultisample(GL_RENDERBUFFER, GLsizei(state.user_settings.antialias_level), GL_DEPTH24_STENCIL8, size_x, size_y);
220 glBindRenderbuffer(GL_RENDERBUFFER, 0);
221 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, state.open_gl.msaa_rbo);
222 if(auto r = glCheckFramebufferStatus(GL_FRAMEBUFFER); r != GL_FRAMEBUFFER_COMPLETE) {
223 //notify_user_of_fatal_opengl_error("MSAA framebuffer wasn't completed: " + std::string(framebuffer_error(r)));
224 state.user_settings.antialias_level--;
225 deinitialize_msaa(state);
226 if(state.user_settings.antialias_level != 0) {
227 initialize_msaa(state, size_x, size_y);
228 } else {
229 state.open_gl.msaa_enabled = false;
230 }
231 return;
232 }
233 // configure second post-processing framebuffer
234 glGenFramebuffers(1, &state.open_gl.msaa_interbuffer);
235 glBindFramebuffer(GL_FRAMEBUFFER, state.open_gl.msaa_interbuffer);
236 // create a color attachment texture
237 glGenTextures(1, &state.open_gl.msaa_texture);
238 glBindTexture(GL_TEXTURE_2D, state.open_gl.msaa_texture);
239 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_x, size_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
242 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, state.open_gl.msaa_texture, 0); // we only need a color buffer
243 if(auto r = glCheckFramebufferStatus(GL_FRAMEBUFFER); r != GL_FRAMEBUFFER_COMPLETE) {
244 notify_user_of_fatal_opengl_error("MSAA post processing framebuffer wasn't completed: " + std::string(framebuffer_error(r)));
245 }
246 glBindFramebuffer(GL_FRAMEBUFFER, 0);
247
248 auto root = get_root(state.common_fs);
249 auto msaa_fshader = open_file(root, NATIVE("assets/shaders/glsl/msaa_f_shader.glsl"));
250 auto msaa_vshader = open_file(root, NATIVE("assets/shaders/glsl/msaa_v_shader.glsl"));
251 if(bool(msaa_fshader) && bool(msaa_vshader)) {
252 auto vertex_content = view_contents(*msaa_vshader);
253 auto fragment_content = view_contents(*msaa_fshader);
254 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));
255 state.open_gl.msaa_uniform_screen_size = glGetUniformLocation(state.open_gl.msaa_shader_program, "screen_size");
256 state.open_gl.msaa_uniform_gaussian_blur = glGetUniformLocation(state.open_gl.msaa_shader_program, "gaussian_radius");
257 } else {
258 notify_user_of_fatal_opengl_error("Unable to open a MSAA shaders file");
259 }
260 state.open_gl.msaa_enabled = true;
261}
262
263
265 if(!state.open_gl.msaa_enabled)
266 return;
267
268 state.open_gl.msaa_enabled = false;
269 if(state.open_gl.msaa_texture)
270 glDeleteTextures(1, &state.open_gl.msaa_texture);
271 if(state.open_gl.msaa_interbuffer)
272 glDeleteFramebuffers(1, &state.open_gl.msaa_framebuffer);
273 if(state.open_gl.msaa_rbo)
274 glDeleteRenderbuffers(1, &state.open_gl.msaa_rbo);
275 if(state.open_gl.msaa_texcolorbuffer)
276 glDeleteTextures(1, &state.open_gl.msaa_texcolorbuffer);
277 if(state.open_gl.msaa_framebuffer)
278 glDeleteFramebuffers(1, &state.open_gl.msaa_framebuffer);
279 if(state.open_gl.msaa_vbo)
280 glDeleteBuffers(1, &state.open_gl.msaa_vbo);
281 if(state.open_gl.msaa_vao)
282 glDeleteVertexArrays(1, &state.open_gl.msaa_vao);
283 if(state.open_gl.msaa_shader_program)
284 glDeleteProgram(state.open_gl.msaa_shader_program);
285 glDisable(GL_MULTISAMPLE);
286}
287
290
291 glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
292 glEnable(GL_LINE_SMOOTH);
293
294 load_shaders(state); // create shaders
295 load_global_squares(state); // create various squares to drive the shaders with
296
297 state.flag_type_map.resize(size_t(culture::flag_type::count), 0);
298 // Create the remapping for flags
299 state.world.for_each_national_identity([&](dcon::national_identity_id ident_id) {
300 auto fat_id = dcon::fatten(state.world, ident_id);
301 auto nat_id = fat_id.get_nation_from_identity_holder().id;
302 for(auto gov_id : state.world.in_government_type) {
303 state.flag_types.push_back(culture::flag_type(gov_id.get_flag()));
304 }
305 });
306 // Eliminate duplicates
307 std::sort(state.flag_types.begin(), state.flag_types.end());
308 state.flag_types.erase(std::unique(state.flag_types.begin(), state.flag_types.end()), state.flag_types.end());
309
310 // Automatically assign texture offsets to the flag_types
311 auto id = 0;
312 for(auto type : state.flag_types)
313 state.flag_type_map[uint32_t(type)] = uint8_t(id++);
314 assert(state.flag_type_map[0] == 0); // default_flag
315
316 // Allocate textures for the flags
317 state.open_gl.asset_textures.resize(
318 state.ui_defs.textures.size() + (state.world.national_identity_size() + 1) * state.flag_types.size());
319
320 state.map_state.load_map(state);
321
322 load_special_icons(state);
323
325}
326
327static const GLfloat global_square_data[] = {
328 0.0f, 0.0f, 0.0f, 0.0f,
329 0.0f, 1.0f, 0.0f, 1.0f,
330 1.0f, 1.0f, 1.0f, 1.0f,
331 1.0f, 0.0f, 1.0f, 0.0f
332};
333static const GLfloat global_square_right_data[] = {
334 0.0f, 0.0f, 0.0f, 1.0f,
335 0.0f, 1.0f, 1.0f, 1.0f,
336 1.0f, 1.0f, 1.0f, 0.0f,
337 1.0f, 0.0f, 0.0f, 0.0f
338};
339static const GLfloat global_square_left_data[] = {
340 0.0f, 0.0f, 1.0f, 0.0f,
341 0.0f, 1.0f, 0.0f, 0.0f,
342 1.0f, 1.0f, 0.0f, 1.0f,
343 1.0f, 0.0f, 1.0f, 1.0f
344};
345static const GLfloat global_square_flipped_data[] = {
346 0.0f, 0.0f, 0.0f, 1.0f,
347 0.0f, 1.0f, 0.0f, 0.0f,
348 1.0f, 1.0f, 1.0f, 0.0f,
349 1.0f, 0.0f, 1.0f, 1.0f
350};
351static const GLfloat global_square_right_flipped_data[] = {
352 0.0f, 0.0f, 0.0f, 0.0f,
353 0.0f, 1.0f, 1.0f, 0.0f,
354 1.0f, 1.0f, 1.0f, 1.0f,
355 1.0f, 0.0f, 0.0f, 1.0f
356};
357static const GLfloat global_square_left_flipped_data[] = {
358 0.0f, 0.0f, 1.0f, 1.0f,
359 0.0f, 1.0f, 0.0f, 1.0f,
360 1.0f, 1.0f, 0.0f, 0.0f,
361 1.0f, 0.0f, 1.0f, 0.0f
362};
363
364//RTL squares
365static const GLfloat global_rtl_square_data[] = {
366 0.0f, 0.0f, 1.0f, 0.0f,
367 0.0f, 1.0f, 1.0f, 1.0f,
368 1.0f, 1.0f, 0.0f, 1.0f,
369 1.0f, 0.0f, 0.0f, 0.0f
370};
371static const GLfloat global_rtl_square_right_data[] = {
372 0.0f, 1.0f, 1.0f, 0.0f,
373 0.0f, 0.0f, 0.0f, 0.0f,
374 1.0f, 0.0f, 0.0f, 1.0f,
375 1.0f, 1.0f, 1.0f, 1.0f
376};
377static const GLfloat global_rtl_square_left_data[] = {
378 0.0f, 0.0f, 0.0f, 0.0f,
379 0.0f, 1.0f, 1.0f, 0.0f,
380 1.0f, 1.0f, 1.0f, 1.0f,
381 1.0f, 0.0f, 0.0f, 1.0f
382};
383static const GLfloat global_rtl_square_flipped_data[] = {
384 0.0f, 0.0f, 1.0f, 1.0f,
385 0.0f, 1.0f, 1.0f, 0.0f,
386 1.0f, 1.0f, 0.0f, 0.0f,
387 1.0f, 0.0f, 0.0f, 1.0f
388};
389static const GLfloat global_rtl_square_right_flipped_data[] = {
390 0.0f, 0.0f, 1.0f, 0.0f,
391 0.0f, 1.0f, 0.0f, 0.0f,
392 1.0f, 1.0f, 0.0f, 1.0f,
393 1.0f, 0.0f, 1.0f, 1.0f
394};
395static const GLfloat global_rtl_square_left_flipped_data[] = {
396 0.0f, 0.0f, 0.0f, 1.0f,
397 0.0f, 1.0f, 1.0f, 1.0f,
398 1.0f, 1.0f, 1.0f, 0.0f,
399 1.0f, 0.0f, 0.0f, 0.0f
400};
401
403 auto root = get_root(state.common_fs);
404 auto ui_fshader = open_file(root, NATIVE("assets/shaders/glsl/ui_f_shader.glsl"));
405 auto ui_vshader = open_file(root, NATIVE("assets/shaders/glsl/ui_v_shader.glsl"));
406 if(bool(ui_fshader) && bool(ui_vshader)) {
407 auto vertex_content = view_contents(*ui_vshader);
408 auto fragment_content = view_contents(*ui_fshader);
409 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));
410
411 state.open_gl.ui_shader_texture_sampler_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "texture_sampler");
412 state.open_gl.ui_shader_secondary_texture_sampler_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "secondary_texture_sampler");
413 state.open_gl.ui_shader_screen_width_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "screen_width");
414 state.open_gl.ui_shader_screen_height_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "screen_height");
415 state.open_gl.ui_shader_gamma_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "gamma");
416
417 state.open_gl.ui_shader_d_rect_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "d_rect");
418 state.open_gl.ui_shader_subroutines_index_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "subroutines_index");
419 state.open_gl.ui_shader_inner_color_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "inner_color");
420 state.open_gl.ui_shader_subrect_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "subrect");
421 state.open_gl.ui_shader_border_size_uniform = glGetUniformLocation(state.open_gl.ui_shader_program, "border_size");
422 } else {
423 notify_user_of_fatal_opengl_error("Unable to open a necessary shader file");
424 }
425}
426
428 // Populate the position buffer
429 glGenBuffers(1, &state.open_gl.global_square_buffer);
430 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_buffer);
431 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_data, GL_STATIC_DRAW);
432 //RTL version
433 glGenBuffers(1, &state.open_gl.global_rtl_square_buffer);
434 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_buffer);
435 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_data, GL_STATIC_DRAW);
436
437 glGenVertexArrays(1, &state.open_gl.global_square_vao);
438 glBindVertexArray(state.open_gl.global_square_vao);
439 glEnableVertexAttribArray(0); // position
440 glEnableVertexAttribArray(1); // texture coordinates
441
442 glBindVertexBuffer(0, state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
443
444 glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, 0); // position
445 glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2); // texture coordinates
446 glVertexAttribBinding(0, 0); // position -> to array zero
447 glVertexAttribBinding(1, 0); // texture coordinates -> to array zero
448
449 glGenBuffers(1, &state.open_gl.global_square_left_buffer);
450 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_left_buffer);
451 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_left_data, GL_STATIC_DRAW);
452
453 glGenBuffers(1, &state.open_gl.global_square_right_buffer);
454 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_right_buffer);
455 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_right_data, GL_STATIC_DRAW);
456
457 glGenBuffers(1, &state.open_gl.global_square_right_flipped_buffer);
458 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_right_flipped_buffer);
459 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_right_flipped_data, GL_STATIC_DRAW);
460
461 glGenBuffers(1, &state.open_gl.global_square_left_flipped_buffer);
462 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_left_flipped_buffer);
463 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_left_flipped_data, GL_STATIC_DRAW);
464
465 glGenBuffers(1, &state.open_gl.global_square_flipped_buffer);
466 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_square_flipped_buffer);
467 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_square_flipped_data, GL_STATIC_DRAW);
468
469 //RTL mode squares
470 glGenBuffers(1, &state.open_gl.global_rtl_square_left_buffer);
471 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_left_buffer);
472 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_left_data, GL_STATIC_DRAW);
473
474 glGenBuffers(1, &state.open_gl.global_rtl_square_right_buffer);
475 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_right_buffer);
476 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_right_data, GL_STATIC_DRAW);
477
478 glGenBuffers(1, &state.open_gl.global_rtl_square_right_flipped_buffer);
479 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_right_flipped_buffer);
480 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_right_flipped_data, GL_STATIC_DRAW);
481
482 glGenBuffers(1, &state.open_gl.global_rtl_square_left_flipped_buffer);
483 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_left_flipped_buffer);
484 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_left_flipped_data, GL_STATIC_DRAW);
485
486 glGenBuffers(1, &state.open_gl.global_rtl_square_flipped_buffer);
487 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.global_rtl_square_flipped_buffer);
488 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_rtl_square_flipped_data, GL_STATIC_DRAW);
489
490 glGenBuffers(64, state.open_gl.sub_square_buffers);
491 for(uint32_t i = 0; i < 64; ++i) {
492 glBindBuffer(GL_ARRAY_BUFFER, state.open_gl.sub_square_buffers[i]);
493
494 float const cell_x = static_cast<float>(i & 7) / 8.0f;
495 float const cell_y = static_cast<float>((i >> 3) & 7) / 8.0f;
496
497 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,
498 cell_x + 1.0f / 8.0f, cell_y + 1.0f / 8.0f, 1.0f, 0.0f, cell_x + 1.0f / 8.0f, cell_y};
499
500 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, global_sub_square_data, GL_STATIC_DRAW);
501 }
502}
503
505 switch(e) {
512 default:
514 return parameters::enabled;
515 }
516}
517
518void bind_vertices_by_rotation(sys::state const& state, ui::rotation r, bool flipped, bool rtl) {
519 switch(r) {
521 if(!flipped)
522 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_buffer : state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
523 else
524 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_flipped_buffer : state.open_gl.global_square_flipped_buffer, 0, sizeof(GLfloat) * 4);
525 break;
527 if(!flipped)
528 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_left_buffer: state.open_gl.global_square_left_buffer, 0, sizeof(GLfloat) * 4);
529 else
530 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_left_flipped_buffer : state.open_gl.global_square_left_flipped_buffer, 0, sizeof(GLfloat) * 4);
531 break;
533 if(!flipped)
534 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_right_buffer : state.open_gl.global_square_right_buffer, 0, sizeof(GLfloat) * 4);
535 else
536 glBindVertexBuffer(0, rtl ? state.open_gl.global_rtl_square_right_flipped_buffer : state.open_gl.global_square_right_flipped_buffer, 0, sizeof(GLfloat) * 4);
537 break;
538 }
539}
540
541void render_simple_rect(sys::state const& state, float x, float y, float width, float height, ui::rotation r, bool flipped, bool rtl) {
542 glBindVertexArray(state.open_gl.global_square_vao);
543 bind_vertices_by_rotation(state, r, flipped, rtl);
544 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
546 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
547 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
548 glLineWidth(2.0f);
549 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 1.f, 0.f, 0.f);
550 glDrawArrays(GL_LINE_STRIP, 0, 4);
551}
552
553void render_textured_rect(sys::state const& state, color_modification enabled, float x, float y, float width, float height,
554 GLuint texture_handle, ui::rotation r, bool flipped, bool rtl) {
555 glBindVertexArray(state.open_gl.global_square_vao);
556
557 bind_vertices_by_rotation(state, r, flipped, rtl);
558
559 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
560 // glUniform4f(state.open_gl.ui_shader_d_rect_uniform, 0, 0, width, height);
561
562 glActiveTexture(GL_TEXTURE0);
563 glBindTexture(GL_TEXTURE_2D, texture_handle);
564
565 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::no_filter};
566 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
567 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
568
569 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
570}
571
572void render_textured_rect_direct(sys::state const& state, float x, float y, float width, float height, uint32_t handle) {
573 glBindVertexArray(state.open_gl.global_square_vao);
574
575 glBindVertexBuffer(0, state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
576
577 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
578
579 glActiveTexture(GL_TEXTURE0);
580 glBindTexture(GL_TEXTURE_2D, handle);
581
582 GLuint subroutines[2] = {parameters::enabled, parameters::no_filter};
583 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
584 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
585
586 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
587}
588
589void render_linegraph(sys::state const& state, color_modification enabled, float x, float y, float width, float height,
590 lines& l) {
591 glBindVertexArray(state.open_gl.global_square_vao);
592
593 l.bind_buffer();
594
595 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
596 GLuint subroutines[2] = { map_color_modification_to_index(enabled), parameters::linegraph };
597 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
598 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
599
600 if(state.user_settings.color_blind_mode != sys::color_blind_mode::none
601 && state.user_settings.color_blind_mode != sys::color_blind_mode::achroma) {
602 glLineWidth(4.0f);
603 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 0.f, 0.f, 0.f);
604 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
605 }
606 glLineWidth(2.0f);
607 if(state.user_settings.color_blind_mode == sys::color_blind_mode::achroma) {
608 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 0.f, 0.f, 0.f);
609 } else if(state.user_settings.color_blind_mode == sys::color_blind_mode::tritan) {
610 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 1.f, 1.f, 0.f);
611 } else if(state.user_settings.color_blind_mode == sys::color_blind_mode::deutan || state.user_settings.color_blind_mode == sys::color_blind_mode::protan) {
612 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 1.f, 1.f, 1.f);
613 } else {
614 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 1.f, 1.f, 0.f);
615 }
616 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
617}
618
619void render_linegraph(sys::state const& state, color_modification enabled, float x, float y, float width, float height, float r, float g, float b,
620 lines& l) {
621 glBindVertexArray(state.open_gl.global_square_vao);
622
623 l.bind_buffer();
624
625 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
626 GLuint subroutines[2] = { map_color_modification_to_index(enabled), parameters::linegraph_color };
627 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
628 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
629
630 if(state.user_settings.color_blind_mode != sys::color_blind_mode::none
631 && state.user_settings.color_blind_mode != sys::color_blind_mode::achroma) {
632 glLineWidth(4.0f);
633 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, 0.f, 0.f, 0.f);
634 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
635 }
636 glLineWidth(2.0f);
637 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, r, g, b);
638 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(l.count));
639}
640
641void render_barchart(sys::state const& state, color_modification enabled, float x, float y, float width, float height,
642 data_texture& t, ui::rotation r, bool flipped, bool rtl) {
643 glBindVertexArray(state.open_gl.global_square_vao);
644
645 bind_vertices_by_rotation(state, r, flipped, rtl);
646
647 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
648
649 glActiveTexture(GL_TEXTURE0);
650 glBindTexture(GL_TEXTURE_2D, t.handle());
651
652 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::barchart};
653 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
654 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
655
656 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
657}
658
659void render_piechart(sys::state const& state, color_modification enabled, float x, float y, float size, data_texture& t) {
660 glBindVertexArray(state.open_gl.global_square_vao);
661
662 glBindVertexBuffer(0, state.open_gl.global_square_buffer, 0, sizeof(GLfloat) * 4);
663
664 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, size, size);
665
666 glActiveTexture(GL_TEXTURE0);
667 glBindTexture(GL_TEXTURE_2D, t.handle());
668
669 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::piechart};
670 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
671 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
672
673 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
674}
675
676void render_bordered_rect(sys::state const& state, color_modification enabled, float border_size, float x, float y, float width,
677 float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl) {
678 glBindVertexArray(state.open_gl.global_square_vao);
679
680 bind_vertices_by_rotation(state, r, flipped, rtl);
681
682 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
683 glUniform1f(state.open_gl.ui_shader_border_size_uniform, border_size);
684
685 glActiveTexture(GL_TEXTURE0);
686 glBindTexture(GL_TEXTURE_2D, texture_handle);
687
688 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::frame_stretch};
689 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
690 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
691
692 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
693}
694
695void render_masked_rect(sys::state const& state, color_modification enabled, float x, float y, float width, float height,
696 GLuint texture_handle, GLuint mask_texture_handle, ui::rotation r, bool flipped, bool rtl) {
697 glBindVertexArray(state.open_gl.global_square_vao);
698
699 bind_vertices_by_rotation(state, r, flipped, rtl);
700
701 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
702
703 glActiveTexture(GL_TEXTURE0);
704 glBindTexture(GL_TEXTURE_2D, texture_handle);
705 glActiveTexture(GL_TEXTURE1);
706 glBindTexture(GL_TEXTURE_2D, mask_texture_handle);
707
708 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::use_mask};
709 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
710 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
711
712 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
713}
714
715void render_progress_bar(sys::state const& state, color_modification enabled, float progress, float x, float y, float width,
716 float height, GLuint left_texture_handle, GLuint right_texture_handle, ui::rotation r, bool flipped, bool rtl) {
717 glBindVertexArray(state.open_gl.global_square_vao);
718
719 bind_vertices_by_rotation(state, r, flipped, rtl);
720
721 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
722 glUniform1f(state.open_gl.ui_shader_border_size_uniform, progress);
723
724 glActiveTexture(GL_TEXTURE0);
725 glBindTexture(GL_TEXTURE_2D, left_texture_handle);
726 glActiveTexture(GL_TEXTURE1);
727 glBindTexture(GL_TEXTURE_2D, right_texture_handle);
728
729 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::progress_bar};
730 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
731 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
732
733 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
734}
735
736void render_tinted_textured_rect(sys::state const& state, float x, float y, float width, float height, float r, float g, float b,
737 GLuint texture_handle, ui::rotation rot, bool flipped, bool rtl) {
738 glBindVertexArray(state.open_gl.global_square_vao);
739
740 bind_vertices_by_rotation(state, rot, flipped, rtl);
741
742 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, r, g, b);
743 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
744
745 glActiveTexture(GL_TEXTURE0);
746 glBindTexture(GL_TEXTURE_2D, texture_handle);
747
748 GLuint subroutines[2] = {parameters::tint, parameters::no_filter};
749 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
750 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
751
752 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
753}
754
756 sys::state const& state,
757 float x, float y, float width, float height,
758 float r, float g, float b,
759 ui::rotation rot, bool flipped, bool rtl
760) {
761 glBindVertexArray(state.open_gl.global_square_vao);
762 bind_vertices_by_rotation(state, rot, flipped, rtl);
763 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, r, g, b);
764 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
765 GLuint subroutines[2] = { parameters::tint, parameters::transparent_color };
766 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
767 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
768}
769
770void render_tinted_subsprite(sys::state const& state, int frame, int total_frames, float x, float y,
771 float width, float height, float r, float g, float b, GLuint texture_handle, ui::rotation rot, bool flipped,
772 bool rtl) {
773 glBindVertexArray(state.open_gl.global_square_vao);
774
775 bind_vertices_by_rotation(state, rot, flipped, rtl);
776
777 auto const scale = 1.0f / static_cast<float>(total_frames);
778 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, static_cast<float>(frame) * scale, scale, 0.0f);
779 glUniform4f(state.open_gl.ui_shader_subrect_uniform, r, g, b, 0);
780 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
781
782 glActiveTexture(GL_TEXTURE0);
783 glBindTexture(GL_TEXTURE_2D, texture_handle);
784
785 GLuint subroutines[2] = { parameters::alternate_tint, parameters::sub_sprite };
786 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
787 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
788
789 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
790}
791
792void render_subsprite(sys::state const& state, color_modification enabled, int frame, int total_frames, float x, float y,
793 float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl) {
794 glBindVertexArray(state.open_gl.global_square_vao);
795
796 bind_vertices_by_rotation(state, r, flipped, rtl);
797
798 auto const scale = 1.0f / static_cast<float>(total_frames);
799 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, static_cast<float>(frame) * scale, scale, 0.0f);
800 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, y, width, height);
801
802 glActiveTexture(GL_TEXTURE0);
803 glBindTexture(GL_TEXTURE_2D, texture_handle);
804
805 GLuint subroutines[2] = {map_color_modification_to_index(enabled), parameters::sub_sprite};
806 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
807 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
808
809 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
810}
811
812
813GLuint get_flag_texture_handle_from_tag(sys::state& state, const char tag[3]) {
814 char ltag[3];
815 ltag[0] = char(toupper(tag[0]));
816 ltag[1] = char(toupper(tag[1]));
817 ltag[2] = char(toupper(tag[2]));
818 dcon::national_identity_id ident{};
819 state.world.for_each_national_identity([&](dcon::national_identity_id id) {
820 auto curr = nations::int_to_tag(state.world.national_identity_get_identifying_int(id));
821 if(curr[0] == ltag[0] && curr[1] == ltag[1] && curr[2] == ltag[2]) {
822 ident = id;
823 }
824 });
825 if(!bool(ident)) {
826 // QOL: We will print the text instead of displaying the flag, for ease of viewing invalid tags
827 return 0;
828 }
829 auto fat_id = dcon::fatten(state.world, ident);
830 auto nation = fat_id.get_nation_from_identity_holder();
832 if(bool(nation.id) && nation.get_owned_province_count() != 0) {
833 flag_type = culture::get_current_flag_type(state, nation.id);
834 } else {
835 flag_type = culture::get_current_flag_type(state, ident);
836 }
837 return ogl::get_flag_handle(state, ident, flag_type);
838}
839
840bool display_tag_is_valid(sys::state& state, char tag[3]) {
841 tag[0] = char(toupper(tag[0]));
842 tag[1] = char(toupper(tag[1]));
843 tag[2] = char(toupper(tag[2]));
844 dcon::national_identity_id ident{};
845 state.world.for_each_national_identity([&](dcon::national_identity_id id) {
846 auto curr = nations::int_to_tag(state.world.national_identity_get_identifying_int(id));
847 if(curr[0] == tag[0] && curr[1] == tag[1] && curr[2] == tag[2])
848 ident = id;
849 });
850 return bool(ident);
851}
852
853void 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) {
854 float scale = 1.f;
855 float icon_baseline = baseline_y + (f.internal_ascender / 64.f * font_size) - font_size;
856
858 glActiveTexture(GL_TEXTURE0);
859
860 switch(ico) {
862 scale = 1.3f;
863 glBindTexture(GL_TEXTURE_2D, state.open_gl.army_icon_tex );
864 break;
866 glBindTexture(GL_TEXTURE_2D, state.open_gl.navy_icon_tex);
867 scale = 1.3f;
868 break;
870 glBindTexture(GL_TEXTURE_2D, state.open_gl.checkmark_icon_tex);
871 icon_baseline += font_size * 0.1f;
872 break;
874 {
875 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)
876 ? state.open_gl.color_blind_cross_icon_tex
877 : state.open_gl.cross_icon_tex;
878 glBindTexture(GL_TEXTURE_2D, false_icon);
879 icon_baseline += font_size * 0.1f;
880 break;
881 }
882 }
883
884 GLuint icon_subroutines[2] = { map_color_modification_to_index(cmod), parameters::no_filter };
885 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, icon_subroutines[0], icon_subroutines[1]);
886 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, icon_subroutines); // must set all subroutines in one call
887 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x, icon_baseline, scale * font_size, scale * font_size);
888 glUniform4f(state.open_gl.ui_shader_subrect_uniform, 0.f, 1.f, 0.f, 1.f);
889 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
890}
891
892void 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) {
893 float icon_baseline = baseline_y + (f.internal_ascender / 64.f * font_size) - font_size;
894
895 auto fat_id = dcon::fatten(state.world, ico.tag);
896 auto nation = fat_id.get_nation_from_identity_holder();
898 if(bool(nation.id) && nation.get_owned_province_count() != 0) {
899 flag_type = culture::get_current_flag_type(state, nation.id);
900 } else {
901 flag_type = culture::get_current_flag_type(state, ico.tag);
902 }
903 GLuint flag_texture_handle = ogl::get_flag_handle(state, ico.tag, flag_type);
904
905 GLuint icon_subroutines[2] = { map_color_modification_to_index(cmod), parameters::no_filter };
906 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, icon_subroutines[0], icon_subroutines[1]);
907 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, icon_subroutines); // must set all subroutines in one call
909 glActiveTexture(GL_TEXTURE0);
910 glBindTexture(GL_TEXTURE_2D, flag_texture_handle);
911 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);
912 glUniform4f(state.open_gl.ui_shader_subrect_uniform, 0.f, 1.f, 0.f, 1.f);
913 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
914}
915
916void 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) {
917 float icon_baseline = baseline_y + (f.internal_ascender / 64.f * font_size) - font_size;
918
919 auto id = ico.unit_type;
920
921 auto gfx_id =
922 state.ui_defs.gui[
923 state.ui_state.defs_by_name.find(
924 state.lookup_key("gfx_storage_unit_types")
925 )->second.definition
926 ].data.image.gfx_object;
927
928 auto& gfx_def = state.ui_defs.gfx[gfx_id];
929
930 auto frame = state.military_definitions.unit_base_definitions[id].icon - 1;
931
933 state,
934 cmod,
935 frame,
936 gfx_def.number_of_frames,
937 float(x),
938 baseline_y,
939 font_size,
940 font_size,
941 ogl::get_texture_handle(state, gfx_def.primary_texture_handle, gfx_def.is_partially_transparent()),
943 gfx_def.is_vertically_flipped(),
944 false
945 );
946}
947
948void internal_text_render(sys::state& state, text::stored_glyphs const& txt, float x, float baseline_y, float size, text::font& f) {
950 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
951 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
952
953 unsigned int glyph_count = static_cast<unsigned int>(txt.glyph_info.size());
954 for(unsigned int i = 0; i < glyph_count; i++) {
955 hb_codepoint_t glyphid = txt.glyph_info[i].codepoint;
956 auto gso = f.glyph_positions[glyphid];
957 float x_advance = float(txt.glyph_info[i].x_advance) / (float((1 << 6) * text::magnification_factor));
958 float x_offset = float(txt.glyph_info[i].x_offset) / (float((1 << 6) * text::magnification_factor)) + float(gso.x);
959 float y_offset = float(gso.y) - float(txt.glyph_info[i].y_offset) / (float((1 << 6) * text::magnification_factor));
960 glBindVertexBuffer(0, state.open_gl.sub_square_buffers[gso.texture_slot & 63], 0, sizeof(GLfloat) * 4);
961 assert(uint32_t(gso.texture_slot >> 6) < f.textures.size());
962 assert(f.textures[gso.texture_slot >> 6]);
963 glActiveTexture(GL_TEXTURE0);
964 glBindTexture(GL_TEXTURE_2D, f.textures[gso.texture_slot >> 6]);
965 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, x + x_offset * size / 64.f, baseline_y + y_offset * size / 64.f, size, size);
966 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
967 x += x_advance * size / 64.f;
968 baseline_y -= (float(txt.glyph_info[i].y_advance) / (float((1 << 6) * text::magnification_factor))) * size / 64.f;
969 }
970}
971
972void 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) {
973 std::string codepoints = "";
974 for(uint32_t i = 0; i < uint32_t(txt.glyph_info.size()); i++) {
975 codepoints.push_back(char(txt.glyph_info[i].codepoint));
976 }
977 uint32_t count = uint32_t(codepoints.length());
978
979 float adv = 1.0f / font.width; // Font texture atlas spacing.
981 GLuint subroutines[2] = { map_color_modification_to_index(enabled), parameters::subsprite_b };
982 glUniform2ui(state.open_gl.ui_shader_subroutines_index_uniform, subroutines[0], subroutines[1]);
983 //glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 2, subroutines); // must set all subroutines in one call
984
985 // Set Text Color, all one color for now.
986 //------ FOR SCHOMBERT ------//
987 // Every iteration of this loop draws one character of the string 'fmt'.
988 //'texlst' contains information for each vertex of each rectangle for each character.
989 // Every 4 elements in 'texlst' is one complete rectangle, and one character.
990 //'texlst[i].texx' and 'texlst[i].texy' are the intended texture coordinates of a vertex on the texture.
991 //'texlst[i].x' and 'texlst[i].y' are the coordinates of a vertex of the rendered rectangle in the window.
992 // The color variables are unused currently.
993 //
994 // Spacing, kearning, etc. are already applied.
995 // Scaling (unintentionally) is also applied (by whatever part of Alice scales the normal fonts).
996
997 glActiveTexture(GL_TEXTURE0);
998 glBindTexture(GL_TEXTURE_2D, font.ftexid);
999
1000 for(uint32_t i = 0; i < count; ++i) {
1001 uint8_t ch = uint8_t(codepoints[i]);
1002 if(i != 0 && i < count - 1 && ch == 0xC2 && uint8_t(codepoints[i + 1]) == 0xA3) {
1003 ch = 0xA3;
1004 i++;
1005 } else if(ch == 0xA4) {
1006 ch = 0xA3;
1007 }
1008 auto const& f = font.chars[ch];
1009 float CurX = x + f.x_offset;
1010 float CurY = y + f.y_offset;
1011 glUniform4f(state.open_gl.ui_shader_d_rect_uniform, CurX, CurY, float(f.width), float(f.height));
1012 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, c.r, c.g, c.b);
1013 glUniform4f(state.open_gl.ui_shader_subrect_uniform, float(f.x) / float(font.width) /* x offset */,
1014 float(f.width) / float(font.width) /* x width */, float(f.y) / float(font.width) /* y offset */,
1015 float(f.height) / float(font.width) /* y height */
1016 );
1017 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1018 //float x_advance = float(txt.glyph_pos[i].x_advance) / (float((1 << 6) * text::magnification_factor));
1019 x += f.x_advance;
1020 }
1021}
1022
1023void 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) {
1024 glUniform3f(state.open_gl.ui_shader_inner_color_uniform, c.r, c.g, c.b);
1025 glUniform1f(state.open_gl.ui_shader_border_size_uniform, 0.08f * 16.0f / size);
1026 internal_text_render(state, txt, x, y + size, size, f);
1027}
1028
1029void render_text(sys::state& state, text::stored_glyphs const& txt, color_modification enabled, float x, float y, color3f const& c, uint16_t font_id) {
1030 auto& font = state.font_collection.get_font(state, text::font_index_from_font_id(state, font_id));
1031 if(state.user_settings.use_classic_fonts) {
1032 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);
1033 return;
1034 }
1035 render_new_text(state, txt, enabled, x, y, float(text::size_from_font_id(font_id)), c, font);
1036}
1037
1038void lines::set_y(float* v) {
1039 for(int32_t i = 0; i < static_cast<int32_t>(count); ++i) {
1040 buffer[i * 4] = static_cast<float>(i) / static_cast<float>(count - 1);
1041 buffer[i * 4 + 1] = 1.0f - v[i];
1042 buffer[i * 4 + 2] = 0.5f;
1043 buffer[i * 4 + 3] = v[i];
1044 }
1045 pending_data_update = true;
1046}
1047
1049 for(int32_t i = 0; i < static_cast<int32_t>(count); ++i) {
1050 buffer[i * 4] = static_cast<float>(i) / static_cast<float>(count - 1);
1051 buffer[i * 4 + 1] = 0.5f;
1052 buffer[i * 4 + 2] = 0.5f;
1053 buffer[i * 4 + 3] = 0.5f;
1054 }
1055 pending_data_update = true;
1056}
1057
1059 if(buffer_handle == 0) {
1060 glGenBuffers(1, &buffer_handle);
1061
1062 glBindBuffer(GL_ARRAY_BUFFER, buffer_handle);
1063 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * count * 4, nullptr, GL_DYNAMIC_DRAW);
1064 }
1065 if(buffer && pending_data_update) {
1066 glBindBuffer(GL_ARRAY_BUFFER, buffer_handle);
1067 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * count * 4, buffer);
1068 pending_data_update = false;
1069 }
1070
1071 glBindVertexBuffer(0, buffer_handle, 0, sizeof(GLfloat) * 4);
1072}
1073
1074bool msaa_enabled(sys::state const& state) {
1075 return state.open_gl.msaa_enabled;
1076}
1077
1079 int32_t file_channels = 4;
1080 int32_t size_x = 0;
1081 int32_t size_y = 0;
1082 auto content = simple_fs::view_contents(file);
1083 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);
1084 return image(data, size_x, size_y, 4);
1085}
1086
1087GLuint make_gl_texture(uint8_t* data, uint32_t size_x, uint32_t size_y, uint32_t channels) {
1088 GLuint texture_handle;
1089 glGenTextures(1, &texture_handle);
1090 const GLuint internalformats[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 };
1091 const GLuint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA };
1092 if(texture_handle) {
1093 glBindTexture(GL_TEXTURE_2D, texture_handle);
1094 glTexStorage2D(GL_TEXTURE_2D, 1, internalformats[channels - 1], size_x, size_y);
1095 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size_x, size_y, formats[channels - 1], GL_UNSIGNED_BYTE, data);
1096 glBindTexture(GL_TEXTURE_2D, 0);
1097 }
1098
1099 return texture_handle;
1100}
1102 auto file = open_file(dir, file_name);
1103 if(!file)
1104 return 0;
1105 auto image = load_stb_image(*file);
1107}
1108
1109void set_gltex_parameters(GLuint texture_handle, GLuint texture_type, GLuint filter, GLuint wrap) {
1110 glBindTexture(texture_type, texture_handle);
1111 if(filter == GL_LINEAR_MIPMAP_NEAREST || filter == GL_LINEAR_MIPMAP_LINEAR) {
1112 glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, filter);
1113 glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1114 glGenerateMipmap(texture_type);
1115 } else {
1116 glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, filter);
1117 glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1118 }
1119 glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap);
1120 glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap);
1121 glBindTexture(texture_type, 0);
1122}
1123
1124GLuint load_texture_array_from_file(simple_fs::file& file, int32_t tiles_x, int32_t tiles_y) {
1125 auto image = load_stb_image(file);
1126
1127 GLuint texture_handle = 0;
1128 glGenTextures(1, &texture_handle);
1129 if(texture_handle) {
1130 glBindTexture(GL_TEXTURE_2D_ARRAY, texture_handle);
1131
1132 size_t p_dx = image.size_x / tiles_x; // Pixels of each tile in x
1133 size_t p_dy = image.size_y / tiles_y; // Pixels of each tile in y
1134 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);
1135 glPixelStorei(GL_UNPACK_ROW_LENGTH, image.size_x);
1136 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image.size_y);
1137
1138 for(int32_t x = 0; x < tiles_x; x++)
1139 for(int32_t y = 0; y < tiles_y; y++)
1140 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));
1141
1142 set_gltex_parameters(texture_handle, GL_TEXTURE_2D_ARRAY, GL_LINEAR_MIPMAP_NEAREST, GL_REPEAT);
1143 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1144 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1145 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1146 }
1147 return texture_handle;
1148}
1149
1150} // namespace ogl
GLuint handle()
Definition: texture.cpp:619
uint32_t count
void set_y(float *v)
void set_default_y()
int32_t width
Definition: bmfont.hpp:91
GLuint ftexid
Definition: bmfont.hpp:96
std::array< char_descriptor, 256 > chars
Definition: bmfont.hpp:87
ankerl::unordered_dense::map< char32_t, glyph_sub_offset > glyph_positions
Definition: fonts.hpp:117
float internal_ascender
Definition: fonts.hpp:114
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:717
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:10
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 use_mask
constexpr GLuint subsprite_b
constexpr GLuint enabled
constexpr GLuint filter
constexpr GLuint barchart
constexpr GLuint disabled
constexpr GLuint linegraph
constexpr GLuint alternate_tint
constexpr GLuint interactable_disabled
constexpr GLuint sub_sprite
constexpr GLuint linegraph_color
Definition: color.hpp:6
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)
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 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)
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 set_gltex_parameters(GLuint texture_handle, GLuint texture_type, GLuint filter, GLuint wrap)
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:100
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:20
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)
GLuint get_texture_handle(sys::state &state, dcon::texture_id id, bool keep_data)
Definition: texture.cpp:577
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:544
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
dcon::national_identity_id tag
Definition: text.hpp:788
dcon::unit_type_id unit_type
Definition: text.hpp:785
std::vector< stored_glyph > glyph_info
Definition: fonts.hpp:82