MeshGL.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Daniele Panozzo <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "MeshGL.h"
  9. #include "bind_vertex_attrib_array.h"
  10. #include "create_shader_program.h"
  11. #include "destroy_shader_program.h"
  12. #include "verasansmono_compressed.h"
  13. #include <iostream>
  14. IGL_INLINE igl::opengl::MeshGL::MeshGL():
  15. tex_filter(GL_LINEAR),
  16. tex_wrap(GL_REPEAT)
  17. {
  18. }
  19. IGL_INLINE void igl::opengl::MeshGL::init_buffers()
  20. {
  21. // Mesh: Vertex Array Object & Buffer objects
  22. glGenVertexArrays(1, &vao_mesh);
  23. glBindVertexArray(vao_mesh);
  24. glGenBuffers(1, &vbo_V);
  25. glGenBuffers(1, &vbo_V_normals);
  26. glGenBuffers(1, &vbo_V_ambient);
  27. glGenBuffers(1, &vbo_V_diffuse);
  28. glGenBuffers(1, &vbo_V_specular);
  29. glGenBuffers(1, &vbo_V_uv);
  30. glGenBuffers(1, &vbo_F);
  31. glGenTextures(1, &vbo_tex);
  32. glGenTextures(1, &font_atlas);
  33. // Line overlay
  34. glGenVertexArrays(1, &vao_overlay_lines);
  35. glBindVertexArray(vao_overlay_lines);
  36. glGenBuffers(1, &vbo_lines_F);
  37. glGenBuffers(1, &vbo_lines_V);
  38. glGenBuffers(1, &vbo_lines_V_colors);
  39. // Point overlay
  40. glGenVertexArrays(1, &vao_overlay_points);
  41. glBindVertexArray(vao_overlay_points);
  42. glGenBuffers(1, &vbo_points_F);
  43. glGenBuffers(1, &vbo_points_V);
  44. glGenBuffers(1, &vbo_points_V_colors);
  45. // Text Labels
  46. vertex_labels.init_buffers();
  47. face_labels.init_buffers();
  48. custom_labels.init_buffers();
  49. dirty = MeshGL::DIRTY_ALL;
  50. }
  51. IGL_INLINE void igl::opengl::MeshGL::free_buffers()
  52. {
  53. if (is_initialized)
  54. {
  55. glDeleteVertexArrays(1, &vao_mesh);
  56. glDeleteVertexArrays(1, &vao_overlay_lines);
  57. glDeleteVertexArrays(1, &vao_overlay_points);
  58. glDeleteBuffers(1, &vbo_V);
  59. glDeleteBuffers(1, &vbo_V_normals);
  60. glDeleteBuffers(1, &vbo_V_ambient);
  61. glDeleteBuffers(1, &vbo_V_diffuse);
  62. glDeleteBuffers(1, &vbo_V_specular);
  63. glDeleteBuffers(1, &vbo_V_uv);
  64. glDeleteBuffers(1, &vbo_F);
  65. glDeleteBuffers(1, &vbo_lines_F);
  66. glDeleteBuffers(1, &vbo_lines_V);
  67. glDeleteBuffers(1, &vbo_lines_V_colors);
  68. glDeleteBuffers(1, &vbo_points_F);
  69. glDeleteBuffers(1, &vbo_points_V);
  70. glDeleteBuffers(1, &vbo_points_V_colors);
  71. // Text Labels
  72. vertex_labels.free_buffers();
  73. face_labels.free_buffers();
  74. custom_labels.free_buffers();
  75. glDeleteTextures(1, &vbo_tex);
  76. glDeleteTextures(1, &font_atlas);
  77. }
  78. }
  79. IGL_INLINE void igl::opengl::MeshGL::TextGL::init_buffers()
  80. {
  81. glGenVertexArrays(1, &vao_labels);
  82. glBindVertexArray(vao_labels);
  83. glGenBuffers(1, &vbo_labels_pos);
  84. glGenBuffers(1, &vbo_labels_characters);
  85. glGenBuffers(1, &vbo_labels_offset);
  86. glGenBuffers(1, &vbo_labels_indices);
  87. }
  88. IGL_INLINE void igl::opengl::MeshGL::TextGL::free_buffers()
  89. {
  90. glDeleteBuffers(1, &vbo_labels_pos);
  91. glDeleteBuffers(1, &vbo_labels_characters);
  92. glDeleteBuffers(1, &vbo_labels_offset);
  93. glDeleteBuffers(1, &vbo_labels_indices);
  94. }
  95. IGL_INLINE void igl::opengl::MeshGL::bind_mesh()
  96. {
  97. glBindVertexArray(vao_mesh);
  98. glUseProgram(shader_mesh);
  99. bind_vertex_attrib_array(shader_mesh,"position", vbo_V, V_vbo, dirty & MeshGL::DIRTY_POSITION);
  100. bind_vertex_attrib_array(shader_mesh,"normal", vbo_V_normals, V_normals_vbo, dirty & MeshGL::DIRTY_NORMAL);
  101. bind_vertex_attrib_array(shader_mesh,"Ka", vbo_V_ambient, V_ambient_vbo, dirty & MeshGL::DIRTY_AMBIENT);
  102. bind_vertex_attrib_array(shader_mesh,"Kd", vbo_V_diffuse, V_diffuse_vbo, dirty & MeshGL::DIRTY_DIFFUSE);
  103. bind_vertex_attrib_array(shader_mesh,"Ks", vbo_V_specular, V_specular_vbo, dirty & MeshGL::DIRTY_SPECULAR);
  104. bind_vertex_attrib_array(shader_mesh,"texcoord", vbo_V_uv, V_uv_vbo, dirty & MeshGL::DIRTY_UV);
  105. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_F);
  106. if (dirty & MeshGL::DIRTY_FACE)
  107. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*F_vbo.size(), F_vbo.data(), GL_DYNAMIC_DRAW);
  108. glActiveTexture(GL_TEXTURE0);
  109. glBindTexture(GL_TEXTURE_2D, vbo_tex);
  110. if (dirty & MeshGL::DIRTY_TEXTURE)
  111. {
  112. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex_wrap);
  113. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex_wrap);
  114. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex_filter);
  115. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex_filter);
  116. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  117. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_u, tex_v, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.data());
  118. }
  119. glUniform1i(glGetUniformLocation(shader_mesh,"tex"), 0);
  120. dirty &= ~MeshGL::DIRTY_MESH;
  121. }
  122. IGL_INLINE void igl::opengl::MeshGL::bind_overlay_lines()
  123. {
  124. bool is_dirty = dirty & MeshGL::DIRTY_OVERLAY_LINES;
  125. glBindVertexArray(vao_overlay_lines);
  126. glUseProgram(shader_overlay_lines);
  127. bind_vertex_attrib_array(shader_overlay_lines,"position", vbo_lines_V, lines_V_vbo, is_dirty);
  128. bind_vertex_attrib_array(shader_overlay_lines,"color", vbo_lines_V_colors, lines_V_colors_vbo, is_dirty);
  129. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_lines_F);
  130. if (is_dirty)
  131. {
  132. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*lines_F_vbo.size(), lines_F_vbo.data(), GL_DYNAMIC_DRAW);
  133. }
  134. dirty &= ~MeshGL::DIRTY_OVERLAY_LINES;
  135. }
  136. IGL_INLINE void igl::opengl::MeshGL::bind_overlay_points()
  137. {
  138. bool is_dirty = dirty & MeshGL::DIRTY_OVERLAY_POINTS;
  139. glBindVertexArray(vao_overlay_points);
  140. glUseProgram(shader_overlay_points);
  141. bind_vertex_attrib_array(shader_overlay_points,"position", vbo_points_V, points_V_vbo, is_dirty);
  142. bind_vertex_attrib_array(shader_overlay_points,"color", vbo_points_V_colors, points_V_colors_vbo, is_dirty);
  143. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_points_F);
  144. if (is_dirty)
  145. {
  146. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*points_F_vbo.size(), points_F_vbo.data(), GL_DYNAMIC_DRAW);
  147. }
  148. dirty &= ~MeshGL::DIRTY_OVERLAY_POINTS;
  149. }
  150. IGL_INLINE void igl::opengl::MeshGL::init_text_rendering()
  151. {
  152. // Decompress the png of the font atlas
  153. unsigned char verasansmono_font_atlas[256*256];
  154. decompress_verasansmono_atlas(verasansmono_font_atlas);
  155. // Bind atlas
  156. glBindTexture(GL_TEXTURE_2D, font_atlas);
  157. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  158. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  159. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  160. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  161. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 256, 256, 0, GL_RED, GL_UNSIGNED_BYTE, verasansmono_font_atlas);
  162. // TextGL initialization
  163. vertex_labels.dirty_flag = MeshGL::DIRTY_VERTEX_LABELS;
  164. face_labels.dirty_flag = MeshGL::DIRTY_FACE_LABELS;
  165. custom_labels.dirty_flag = MeshGL::DIRTY_CUSTOM_LABELS;
  166. }
  167. IGL_INLINE void igl::opengl::MeshGL::bind_labels(const TextGL& labels)
  168. {
  169. bool is_dirty = dirty & labels.dirty_flag;
  170. glBindTexture(GL_TEXTURE_2D, font_atlas);
  171. glBindVertexArray(labels.vao_labels);
  172. glUseProgram(shader_text);
  173. bind_vertex_attrib_array(shader_text, "position" , labels.vbo_labels_pos , labels.label_pos_vbo , is_dirty);
  174. bind_vertex_attrib_array(shader_text, "character", labels.vbo_labels_characters, labels.label_char_vbo , is_dirty);
  175. bind_vertex_attrib_array(shader_text, "offset" , labels.vbo_labels_offset , labels.label_offset_vbo, is_dirty);
  176. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, labels.vbo_labels_indices);
  177. if (is_dirty)
  178. {
  179. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*labels.label_indices_vbo.size(), labels.label_indices_vbo.data(), GL_DYNAMIC_DRAW);
  180. }
  181. dirty &= ~labels.dirty_flag;
  182. }
  183. IGL_INLINE void igl::opengl::MeshGL::draw_mesh(bool solid)
  184. {
  185. glPolygonMode(GL_FRONT_AND_BACK, solid ? GL_FILL : GL_LINE);
  186. /* Avoid Z-buffer fighting between filled triangles & wireframe lines */
  187. if (solid)
  188. {
  189. glEnable(GL_POLYGON_OFFSET_FILL);
  190. glPolygonOffset(1.0, 1.0);
  191. }
  192. glDrawElements(GL_TRIANGLES, 3*F_vbo.rows(), GL_UNSIGNED_INT, 0);
  193. glDisable(GL_POLYGON_OFFSET_FILL);
  194. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  195. }
  196. IGL_INLINE void igl::opengl::MeshGL::draw_overlay_lines()
  197. {
  198. glDrawElements(GL_LINES, lines_F_vbo.rows(), GL_UNSIGNED_INT, 0);
  199. }
  200. IGL_INLINE void igl::opengl::MeshGL::draw_overlay_points()
  201. {
  202. glDrawElements(GL_POINTS, points_F_vbo.rows(), GL_UNSIGNED_INT, 0);
  203. }
  204. IGL_INLINE void igl::opengl::MeshGL::draw_labels(const TextGL& labels)
  205. {
  206. glDrawElements(GL_POINTS, labels.label_indices_vbo.rows(), GL_UNSIGNED_INT, 0);
  207. }
  208. IGL_INLINE void igl::opengl::MeshGL::init()
  209. {
  210. if(is_initialized)
  211. {
  212. return;
  213. }
  214. is_initialized = true;
  215. std::string mesh_vertex_shader_string =
  216. R"(#version 150
  217. uniform mat4 view;
  218. uniform mat4 proj;
  219. uniform mat4 normal_matrix;
  220. in vec3 position;
  221. in vec3 normal;
  222. out vec3 position_eye;
  223. out vec3 normal_eye;
  224. in vec4 Ka;
  225. in vec4 Kd;
  226. in vec4 Ks;
  227. in vec2 texcoord;
  228. out vec2 texcoordi;
  229. out vec4 Kai;
  230. out vec4 Kdi;
  231. out vec4 Ksi;
  232. uniform mat4 shadow_view;
  233. uniform mat4 shadow_proj;
  234. uniform bool shadow_pass;
  235. uniform bool is_shadow_mapping;
  236. out vec4 position_shadow;
  237. void main()
  238. {
  239. position_eye = vec3 (view * vec4 (position, 1.0));
  240. if(!shadow_pass)
  241. {
  242. if(is_shadow_mapping)
  243. {
  244. position_shadow = shadow_proj * shadow_view * vec4(position, 1.0);
  245. }
  246. normal_eye = vec3 (normal_matrix * vec4 (normal, 0.0));
  247. normal_eye = normalize(normal_eye);
  248. Kai = Ka;
  249. Kdi = Kd;
  250. Ksi = Ks;
  251. texcoordi = texcoord;
  252. }
  253. gl_Position = proj * vec4 (position_eye, 1.0); //proj * view * vec4(position, 1.0);
  254. }
  255. )";
  256. std::string mesh_fragment_shader_string =
  257. R"(#version 150
  258. uniform mat4 view;
  259. uniform mat4 proj;
  260. uniform vec4 fixed_color;
  261. in vec3 position_eye;
  262. in vec3 normal_eye;
  263. uniform bool is_directional_light;
  264. uniform bool is_shadow_mapping;
  265. uniform bool shadow_pass;
  266. uniform vec3 light_position_eye;
  267. vec3 Ls = vec3 (1, 1, 1);
  268. vec3 Ld = vec3 (1, 1, 1);
  269. vec3 La = vec3 (1, 1, 1);
  270. in vec4 Ksi;
  271. in vec4 Kdi;
  272. in vec4 Kai;
  273. in vec2 texcoordi;
  274. uniform sampler2D tex;
  275. uniform float specular_exponent;
  276. uniform float lighting_factor;
  277. uniform float texture_factor;
  278. uniform float matcap_factor;
  279. uniform float double_sided;
  280. uniform bool pseudocolor_with_normals;
  281. uniform sampler2D shadow_tex;
  282. in vec4 position_shadow;
  283. out vec4 outColor;
  284. void main()
  285. {
  286. if(shadow_pass)
  287. {
  288. // Would it be better to have a separate no-op frag shader?
  289. outColor = vec4(0.56,0.85,0.77,1.);
  290. return;
  291. }
  292. if(pseudocolor_with_normals)
  293. {
  294. outColor = vec4(normalize(normal_eye) * 0.5 + 0.5, 1.0);
  295. return;
  296. }
  297. // If is_directional_light then assume normalized
  298. vec3 direction_to_light_eye = light_position_eye;
  299. if(! is_directional_light)
  300. {
  301. vec3 vector_to_light_eye = light_position_eye - position_eye;
  302. direction_to_light_eye = normalize(vector_to_light_eye);
  303. }
  304. float shadow = 1.0;
  305. if(is_shadow_mapping)
  306. {
  307. vec3 shadow_pos = (position_shadow.xyz / position_shadow.w) * 0.5 + 0.5;
  308. float currentDepth = shadow_pos.z;
  309. //float bias = 0.005;
  310. float ddd = max(dot(normalize(normal_eye), direction_to_light_eye),0);
  311. float bias = max(0.02 * (1.0 - ddd), 0.005);
  312. // 5-point stencil
  313. if(shadow_pos.z < 1.0)
  314. {
  315. float closestDepth = texture( shadow_tex , shadow_pos.xy).r;
  316. shadow = currentDepth - bias >= closestDepth ? 0.0 : 1.0;
  317. vec2 texelSize = 1.0 / textureSize(shadow_tex, 0);
  318. for(int x = -1; x <= 1; x+=2)
  319. {
  320. for(int y = -1; y <= 1; y+=2)
  321. {
  322. float pcfDepth = texture(shadow_tex, shadow_pos.xy + vec2(x, y) * texelSize).r;
  323. shadow += currentDepth - bias >= pcfDepth ? 0.0 : 1.0;
  324. }
  325. }
  326. shadow /= 5.0;
  327. }
  328. }
  329. if(matcap_factor == 1.0f)
  330. {
  331. vec2 uv = normalize(normal_eye).xy * 0.5 + 0.5;
  332. outColor = mix(Kai,texture(tex, uv),shadow);
  333. }else
  334. {
  335. vec3 Ia = La * vec3(Kai); // ambient intensity
  336. float dot_prod = dot (direction_to_light_eye, normalize(normal_eye));
  337. float clamped_dot_prod = abs(max (dot_prod, -double_sided));
  338. vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod; // Diffuse intensity
  339. vec3 reflection_eye = reflect (-direction_to_light_eye, normalize(normal_eye));
  340. vec3 surface_to_viewer_eye = normalize (-position_eye);
  341. float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);
  342. dot_prod_specular = float(abs(dot_prod)==dot_prod) * abs(max (dot_prod_specular, -double_sided));
  343. float specular_factor = pow (dot_prod_specular, specular_exponent);
  344. vec3 Is = Ls * vec3(Ksi) * specular_factor; // specular intensity
  345. vec4 color = vec4(Ia + shadow*(lighting_factor * (Is + Id) + (1.0-lighting_factor) * vec3(Kdi)),(Kai.a+Ksi.a+Kdi.a)/3);
  346. outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;
  347. if (fixed_color != vec4(0.0)) outColor = fixed_color;
  348. }
  349. }
  350. )";
  351. std::string overlay_vertex_shader_string =
  352. R"(#version 150
  353. uniform mat4 view;
  354. uniform mat4 proj;
  355. in vec3 position;
  356. in vec3 color;
  357. out vec3 color_frag;
  358. void main()
  359. {
  360. gl_Position = proj * view * vec4 (position, 1.0);
  361. color_frag = color;
  362. }
  363. )";
  364. std::string overlay_fragment_shader_string =
  365. R"(#version 150
  366. in vec3 color_frag;
  367. out vec4 outColor;
  368. void main()
  369. {
  370. outColor = vec4(color_frag, 1.0);
  371. }
  372. )";
  373. std::string overlay_point_fragment_shader_string =
  374. R"(#version 150
  375. in vec3 color_frag;
  376. out vec4 outColor;
  377. void main()
  378. {
  379. if (length(gl_PointCoord - vec2(0.5)) > 0.5)
  380. discard;
  381. outColor = vec4(color_frag, 1.0);
  382. }
  383. )";
  384. std::string text_vert_shader =
  385. R"(#version 330
  386. in vec3 position;
  387. in float character;
  388. in float offset;
  389. uniform mat4 view;
  390. uniform mat4 proj;
  391. out int vCharacter;
  392. out float vOffset;
  393. void main()
  394. {
  395. vCharacter = int(character);
  396. vOffset = offset;
  397. gl_Position = proj * view * vec4(position, 1.0);
  398. }
  399. )";
  400. std::string text_geom_shader =
  401. R"(#version 150 core
  402. layout(points) in;
  403. layout(triangle_strip, max_vertices = 4) out;
  404. out vec2 gTexCoord;
  405. uniform mat4 view;
  406. uniform mat4 proj;
  407. uniform vec2 CellSize;
  408. uniform vec2 CellOffset;
  409. uniform vec2 RenderSize;
  410. uniform vec2 RenderOrigin;
  411. uniform float TextShiftFactor;
  412. in int vCharacter[1];
  413. in float vOffset[1];
  414. void main()
  415. {
  416. // Code taken from https://prideout.net/strings-inside-vertex-buffers
  417. // Determine the final quad's position and size:
  418. vec4 P = gl_in[0].gl_Position + vec4( vOffset[0]*TextShiftFactor, 0.0, 0.0, 0.0 ); // 0.04
  419. vec4 U = vec4(1, 0, 0, 0) * RenderSize.x; // 1.0
  420. vec4 V = vec4(0, 1, 0, 0) * RenderSize.y; // 1.0
  421. // Determine the texture coordinates:
  422. int letter = vCharacter[0]; // used to be the character
  423. letter = clamp(letter - 32, 0, 96);
  424. int row = letter / 16 + 1;
  425. int col = letter % 16;
  426. float S0 = CellOffset.x + CellSize.x * col;
  427. float T0 = CellOffset.y + 1 - CellSize.y * row;
  428. float S1 = S0 + CellSize.x - CellOffset.x;
  429. float T1 = T0 + CellSize.y;
  430. // Output the quad's vertices:
  431. gTexCoord = vec2(S0, T1); gl_Position = P - U - V; EmitVertex();
  432. gTexCoord = vec2(S1, T1); gl_Position = P + U - V; EmitVertex();
  433. gTexCoord = vec2(S0, T0); gl_Position = P - U + V; EmitVertex();
  434. gTexCoord = vec2(S1, T0); gl_Position = P + U + V; EmitVertex();
  435. EndPrimitive();
  436. }
  437. )";
  438. std::string text_frag_shader =
  439. R"(#version 330
  440. out vec4 outColor;
  441. in vec2 gTexCoord;
  442. uniform sampler2D font_atlas;
  443. uniform vec3 TextColor;
  444. void main()
  445. {
  446. float A = texture(font_atlas, gTexCoord).r;
  447. outColor = vec4(TextColor, A);
  448. }
  449. )";
  450. init_buffers();
  451. init_text_rendering();
  452. create_shader_program(
  453. mesh_vertex_shader_string,
  454. mesh_fragment_shader_string,
  455. {},
  456. shader_mesh);
  457. create_shader_program(
  458. overlay_vertex_shader_string,
  459. overlay_fragment_shader_string,
  460. {},
  461. shader_overlay_lines);
  462. create_shader_program(
  463. overlay_vertex_shader_string,
  464. overlay_point_fragment_shader_string,
  465. {},
  466. shader_overlay_points);
  467. create_shader_program(
  468. text_geom_shader,
  469. text_vert_shader,
  470. text_frag_shader,
  471. {},
  472. shader_text);
  473. }
  474. IGL_INLINE void igl::opengl::MeshGL::free()
  475. {
  476. const auto free = [](GLuint & id)
  477. {
  478. if(id)
  479. {
  480. destroy_shader_program(id);
  481. id = 0;
  482. }
  483. };
  484. if (is_initialized)
  485. {
  486. free(shader_mesh);
  487. free(shader_overlay_lines);
  488. free(shader_overlay_points);
  489. free(shader_text);
  490. free_buffers();
  491. }
  492. }