OpenGL_state.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>
  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 "OpenGL_state.h"
  9. #include "ViewerData.h"
  10. IGL_INLINE void igl::viewer::OpenGL_state::init_buffers()
  11. {
  12. // Mesh: Vertex Array Object & Buffer objects
  13. glGenVertexArrays(1, &vao_mesh);
  14. glBindVertexArray(vao_mesh);
  15. glGenBuffers(1, &vbo_V);
  16. glGenBuffers(1, &vbo_V_normals);
  17. glGenBuffers(1, &vbo_V_ambient);
  18. glGenBuffers(1, &vbo_V_diffuse);
  19. glGenBuffers(1, &vbo_V_specular);
  20. glGenBuffers(1, &vbo_V_uv);
  21. glGenBuffers(1, &vbo_F);
  22. glGenTextures(1, &vbo_tex);
  23. // Line overlay
  24. glGenVertexArrays(1, &vao_overlay_lines);
  25. glBindVertexArray(vao_overlay_lines);
  26. glGenBuffers(1, &vbo_lines_F);
  27. glGenBuffers(1, &vbo_lines_V);
  28. glGenBuffers(1, &vbo_lines_V_colors);
  29. // Point overlay
  30. glGenVertexArrays(1, &vao_overlay_points);
  31. glBindVertexArray(vao_overlay_points);
  32. glGenBuffers(1, &vbo_points_F);
  33. glGenBuffers(1, &vbo_points_V);
  34. glGenBuffers(1, &vbo_points_V_colors);
  35. dirty = ViewerData::DIRTY_ALL;
  36. }
  37. IGL_INLINE void igl::viewer::OpenGL_state::free_buffers()
  38. {
  39. glDeleteVertexArrays(1, &vao_mesh);
  40. glDeleteVertexArrays(1, &vao_overlay_lines);
  41. glDeleteVertexArrays(1, &vao_overlay_points);
  42. glDeleteBuffers(1, &vbo_V);
  43. glDeleteBuffers(1, &vbo_V_normals);
  44. glDeleteBuffers(1, &vbo_V_ambient);
  45. glDeleteBuffers(1, &vbo_V_diffuse);
  46. glDeleteBuffers(1, &vbo_V_specular);
  47. glDeleteBuffers(1, &vbo_V_uv);
  48. glDeleteBuffers(1, &vbo_F);
  49. glDeleteBuffers(1, &vbo_lines_F);
  50. glDeleteBuffers(1, &vbo_lines_V);
  51. glDeleteBuffers(1, &vbo_lines_V_colors);
  52. glDeleteBuffers(1, &vbo_points_F);
  53. glDeleteBuffers(1, &vbo_points_V);
  54. glDeleteBuffers(1, &vbo_points_V_colors);
  55. glDeleteTextures(1, &vbo_tex);
  56. }
  57. IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerData &data, bool invert_normals)
  58. {
  59. bool per_corner_uv = (data.F_uv.rows() == data.F.rows());
  60. bool per_corner_normals = (data.F_normals.rows() == 3 * data.F.rows());
  61. dirty |= data.dirty;
  62. if (!data.face_based)
  63. {
  64. if (!(per_corner_uv || per_corner_normals))
  65. {
  66. // Vertex positions
  67. if (dirty & ViewerData::DIRTY_POSITION)
  68. V_vbo = (data.V.transpose()).cast<float>();
  69. // Vertex normals
  70. if (dirty & ViewerData::DIRTY_NORMAL)
  71. {
  72. V_normals_vbo = (data.V_normals.transpose()).cast<float>();
  73. if (invert_normals)
  74. V_normals_vbo = -V_normals_vbo;
  75. }
  76. // Per-vertex material settings
  77. if (dirty & ViewerData::DIRTY_AMBIENT)
  78. V_ambient_vbo = (data.V_material_ambient.transpose()).cast<float>();
  79. if (dirty & ViewerData::DIRTY_DIFFUSE)
  80. V_diffuse_vbo = (data.V_material_diffuse.transpose()).cast<float>();
  81. if (dirty & ViewerData::DIRTY_SPECULAR)
  82. V_specular_vbo = (data.V_material_specular.transpose()).cast<float>();
  83. // Face indices
  84. if (dirty & ViewerData::DIRTY_FACE)
  85. F_vbo = (data.F.transpose()).cast<unsigned>();
  86. // Texture coordinates
  87. if (dirty & ViewerData::DIRTY_UV)
  88. V_uv_vbo = (data.V_uv.transpose()).cast<float>();
  89. }
  90. else
  91. {
  92. // Per vertex properties with per corner UVs
  93. if (dirty & ViewerData::DIRTY_POSITION)
  94. {
  95. V_vbo.resize(3,data.F.rows()*3);
  96. for (unsigned i=0; i<data.F.rows();++i)
  97. for (unsigned j=0;j<3;++j)
  98. V_vbo.col(i*3+j) = data.V.row(data.F(i,j)).transpose().cast<float>();
  99. }
  100. if (dirty & ViewerData::DIRTY_AMBIENT)
  101. {
  102. V_ambient_vbo.resize(4,data.F.rows()*3);
  103. for (unsigned i=0; i<data.F.rows();++i)
  104. for (unsigned j=0;j<3;++j)
  105. V_ambient_vbo.col (i*3+j) = data.V_material_ambient.row(data.F(i,j)).transpose().cast<float>();
  106. }
  107. if (dirty & ViewerData::DIRTY_DIFFUSE)
  108. {
  109. V_diffuse_vbo.resize(4,data.F.rows()*3);
  110. for (unsigned i=0; i<data.F.rows();++i)
  111. for (unsigned j=0;j<3;++j)
  112. V_diffuse_vbo.col (i*3+j) = data.V_material_diffuse.row(data.F(i,j)).transpose().cast<float>();
  113. }
  114. if (dirty & ViewerData::DIRTY_SPECULAR)
  115. {
  116. V_specular_vbo.resize(4,data.F.rows()*3);
  117. for (unsigned i=0; i<data.F.rows();++i)
  118. for (unsigned j=0;j<3;++j)
  119. V_specular_vbo.col(i*3+j) = data.V_material_specular.row(data.F(i,j)).transpose().cast<float>();
  120. }
  121. if (dirty & ViewerData::DIRTY_NORMAL)
  122. {
  123. V_normals_vbo.resize(3,data.F.rows()*3);
  124. for (unsigned i=0; i<data.F.rows();++i)
  125. for (unsigned j=0;j<3;++j)
  126. V_normals_vbo.col (i*3+j) =
  127. per_corner_normals ?
  128. data.F_normals.row(i*3+j).transpose().cast<float>() :
  129. data.V_normals.row(data.F(i,j)).transpose().cast<float>();
  130. if (invert_normals)
  131. V_normals_vbo = -V_normals_vbo;
  132. }
  133. if (dirty & ViewerData::DIRTY_FACE)
  134. {
  135. F_vbo.resize(3,data.F.rows());
  136. for (unsigned i=0; i<data.F.rows();++i)
  137. F_vbo.col(i) << i*3+0, i*3+1, i*3+2;
  138. }
  139. if (dirty & ViewerData::DIRTY_UV)
  140. {
  141. V_uv_vbo.resize(2,data.F.rows()*3);
  142. for (unsigned i=0; i<data.F.rows();++i)
  143. for (unsigned j=0;j<3;++j)
  144. V_uv_vbo.col(i*3+j) = data.V_uv.row(per_corner_uv ? data.F_uv(i,j) : data.F(i,j)).transpose().cast<float>();
  145. }
  146. }
  147. }
  148. else
  149. {
  150. if (dirty & ViewerData::DIRTY_POSITION)
  151. {
  152. V_vbo.resize(3,data.F.rows()*3);
  153. for (unsigned i=0; i<data.F.rows();++i)
  154. for (unsigned j=0;j<3;++j)
  155. V_vbo.col(i*3+j) = data.V.row(data.F(i,j)).transpose().cast<float>();
  156. }
  157. if (dirty & ViewerData::DIRTY_AMBIENT)
  158. {
  159. V_ambient_vbo.resize(4,data.F.rows()*3);
  160. for (unsigned i=0; i<data.F.rows();++i)
  161. for (unsigned j=0;j<3;++j)
  162. V_ambient_vbo.col (i*3+j) = data.F_material_ambient.row(i).transpose().cast<float>();
  163. }
  164. if (dirty & ViewerData::DIRTY_DIFFUSE)
  165. {
  166. V_diffuse_vbo.resize(4,data.F.rows()*3);
  167. for (unsigned i=0; i<data.F.rows();++i)
  168. for (unsigned j=0;j<3;++j)
  169. V_diffuse_vbo.col (i*3+j) = data.F_material_diffuse.row(i).transpose().cast<float>();
  170. }
  171. if (dirty & ViewerData::DIRTY_SPECULAR)
  172. {
  173. V_specular_vbo.resize(4,data.F.rows()*3);
  174. for (unsigned i=0; i<data.F.rows();++i)
  175. for (unsigned j=0;j<3;++j)
  176. V_specular_vbo.col(i*3+j) = data.F_material_specular.row(i).transpose().cast<float>();
  177. }
  178. if (dirty & ViewerData::DIRTY_NORMAL)
  179. {
  180. V_normals_vbo.resize(3,data.F.rows()*3);
  181. for (unsigned i=0; i<data.F.rows();++i)
  182. for (unsigned j=0;j<3;++j)
  183. V_normals_vbo.col (i*3+j) =
  184. per_corner_normals ?
  185. data.F_normals.row(i*3+j).transpose().cast<float>() :
  186. data.F_normals.row(i).transpose().cast<float>();
  187. if (invert_normals)
  188. V_normals_vbo = -V_normals_vbo;
  189. }
  190. if (dirty & ViewerData::DIRTY_FACE)
  191. {
  192. F_vbo.resize(3,data.F.rows());
  193. for (unsigned i=0; i<data.F.rows();++i)
  194. F_vbo.col(i) << i*3+0, i*3+1, i*3+2;
  195. }
  196. if (dirty & ViewerData::DIRTY_UV)
  197. {
  198. V_uv_vbo.resize(2,data.F.rows()*3);
  199. for (unsigned i=0; i<data.F.rows();++i)
  200. for (unsigned j=0;j<3;++j)
  201. V_uv_vbo.col(i*3+j) = data.V_uv.row(per_corner_uv ? data.F_uv(i,j) : data.F(i,j)).transpose().cast<float>();
  202. }
  203. }
  204. if (dirty & ViewerData::DIRTY_TEXTURE)
  205. {
  206. tex_u = data.texture_R.rows();
  207. tex_v = data.texture_R.cols();
  208. tex.resize(data.texture_R.size()*4);
  209. for (unsigned i=0;i<data.texture_R.size();++i)
  210. {
  211. tex(i*4+0) = data.texture_R(i);
  212. tex(i*4+1) = data.texture_G(i);
  213. tex(i*4+2) = data.texture_B(i);
  214. tex(i*4+3) = data.texture_A(i);
  215. }
  216. }
  217. if (dirty & ViewerData::DIRTY_OVERLAY_LINES)
  218. {
  219. lines_V_vbo.resize(3, data.lines.rows()*2);
  220. lines_V_colors_vbo.resize(3, data.lines.rows()*2);
  221. lines_F_vbo.resize(1, data.lines.rows()*2);
  222. for (unsigned i=0; i<data.lines.rows();++i)
  223. {
  224. lines_V_vbo.col(2*i+0) = data.lines.block<1, 3>(i, 0).transpose().cast<float>();
  225. lines_V_vbo.col(2*i+1) = data.lines.block<1, 3>(i, 3).transpose().cast<float>();
  226. lines_V_colors_vbo.col(2*i+0) = data.lines.block<1, 3>(i, 6).transpose().cast<float>();
  227. lines_V_colors_vbo.col(2*i+1) = data.lines.block<1, 3>(i, 6).transpose().cast<float>();
  228. lines_F_vbo(2*i+0) = 2*i+0;
  229. lines_F_vbo(2*i+1) = 2*i+1;
  230. }
  231. }
  232. if (dirty & ViewerData::DIRTY_OVERLAY_POINTS)
  233. {
  234. points_V_vbo.resize(3, data.points.rows());
  235. points_V_colors_vbo.resize(3, data.points.rows());
  236. points_F_vbo.resize(1, data.points.rows());
  237. for (unsigned i=0; i<data.points.rows();++i)
  238. {
  239. points_V_vbo.col(i) = data.points.block<1, 3>(i, 0).transpose().cast<float>();
  240. points_V_colors_vbo.col(i) = data.points.block<1, 3>(i, 3).transpose().cast<float>();
  241. points_F_vbo(i) = i;
  242. }
  243. }
  244. }
  245. IGL_INLINE void igl::viewer::OpenGL_state::bind_mesh()
  246. {
  247. glBindVertexArray(vao_mesh);
  248. shader_mesh.bind();
  249. shader_mesh.bindVertexAttribArray("position", vbo_V, V_vbo, dirty & ViewerData::DIRTY_POSITION);
  250. shader_mesh.bindVertexAttribArray("normal", vbo_V_normals, V_normals_vbo, dirty & ViewerData::DIRTY_NORMAL);
  251. shader_mesh.bindVertexAttribArray("Ka", vbo_V_ambient, V_ambient_vbo, dirty & ViewerData::DIRTY_AMBIENT);
  252. shader_mesh.bindVertexAttribArray("Kd", vbo_V_diffuse, V_diffuse_vbo, dirty & ViewerData::DIRTY_DIFFUSE);
  253. shader_mesh.bindVertexAttribArray("Ks", vbo_V_specular, V_specular_vbo, dirty & ViewerData::DIRTY_SPECULAR);
  254. shader_mesh.bindVertexAttribArray("texcoord", vbo_V_uv, V_uv_vbo, dirty & ViewerData::DIRTY_UV);
  255. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_F);
  256. if (dirty & ViewerData::DIRTY_FACE)
  257. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*F_vbo.size(), F_vbo.data(), GL_DYNAMIC_DRAW);
  258. glActiveTexture(GL_TEXTURE0);
  259. glBindTexture(GL_TEXTURE_2D, vbo_tex);
  260. if (dirty & ViewerData::DIRTY_TEXTURE)
  261. {
  262. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  263. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  264. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  265. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  266. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  267. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_u, tex_v, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.data());
  268. }
  269. glUniform1i(shader_mesh.uniform("tex"), 0);
  270. dirty &= ~ViewerData::DIRTY_MESH;
  271. }
  272. IGL_INLINE void igl::viewer::OpenGL_state::bind_overlay_lines()
  273. {
  274. bool is_dirty = dirty & ViewerData::DIRTY_OVERLAY_LINES;
  275. glBindVertexArray(vao_overlay_lines);
  276. shader_overlay_lines.bind();
  277. shader_overlay_lines.bindVertexAttribArray("position", vbo_lines_V, lines_V_vbo, is_dirty);
  278. shader_overlay_lines.bindVertexAttribArray("color", vbo_lines_V_colors, lines_V_colors_vbo, is_dirty);
  279. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_lines_F);
  280. if (is_dirty)
  281. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*lines_F_vbo.size(), lines_F_vbo.data(), GL_DYNAMIC_DRAW);
  282. dirty &= ~ViewerData::DIRTY_OVERLAY_LINES;
  283. }
  284. IGL_INLINE void igl::viewer::OpenGL_state::bind_overlay_points()
  285. {
  286. bool is_dirty = dirty & ViewerData::DIRTY_OVERLAY_POINTS;
  287. glBindVertexArray(vao_overlay_points);
  288. shader_overlay_points.bind();
  289. shader_overlay_points.bindVertexAttribArray("position", vbo_points_V, points_V_vbo, is_dirty);
  290. shader_overlay_points.bindVertexAttribArray("color", vbo_points_V_colors, points_V_colors_vbo, is_dirty);
  291. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_points_F);
  292. if (is_dirty)
  293. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*points_F_vbo.size(), points_F_vbo.data(), GL_DYNAMIC_DRAW);
  294. dirty &= ~ViewerData::DIRTY_OVERLAY_POINTS;
  295. }
  296. IGL_INLINE void igl::viewer::OpenGL_state::draw_mesh(bool solid)
  297. {
  298. glPolygonMode(GL_FRONT_AND_BACK, solid ? GL_FILL : GL_LINE);
  299. /* Avoid Z-buffer fighting between filled triangles & wireframe lines */
  300. if (solid)
  301. {
  302. glEnable(GL_POLYGON_OFFSET_FILL);
  303. glPolygonOffset(1.0, 1.0);
  304. }
  305. glDrawElements(GL_TRIANGLES, 3*F_vbo.cols(), GL_UNSIGNED_INT, 0);
  306. glDisable(GL_POLYGON_OFFSET_FILL);
  307. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  308. }
  309. IGL_INLINE void igl::viewer::OpenGL_state::draw_overlay_lines()
  310. {
  311. glDrawElements(GL_LINES, lines_F_vbo.cols(), GL_UNSIGNED_INT, 0);
  312. }
  313. IGL_INLINE void igl::viewer::OpenGL_state::draw_overlay_points()
  314. {
  315. glDrawElements(GL_POINTS, points_F_vbo.cols(), GL_UNSIGNED_INT, 0);
  316. }
  317. IGL_INLINE void igl::viewer::OpenGL_state::init()
  318. {
  319. std::string mesh_vertex_shader_string =
  320. "#version 150\n"
  321. "uniform mat4 model;"
  322. "uniform mat4 view;"
  323. "uniform mat4 proj;"
  324. "in vec3 position;"
  325. "in vec3 normal;"
  326. "out vec3 position_eye;"
  327. "out vec3 normal_eye;"
  328. "in vec4 Ka;"
  329. "in vec4 Kd;"
  330. "in vec4 Ks;"
  331. "in vec2 texcoord;"
  332. "out vec2 texcoordi;"
  333. "out vec4 Kai;"
  334. "out vec4 Kdi;"
  335. "out vec4 Ksi;"
  336. "void main()"
  337. "{"
  338. " position_eye = vec3 (view * model * vec4 (position, 1.0));"
  339. " normal_eye = vec3 (view * model * vec4 (normal, 0.0));"
  340. " normal_eye = normalize(normal_eye);"
  341. " gl_Position = proj * vec4 (position_eye, 1.0);" //proj * view * model * vec4(position, 1.0);"
  342. " Kai = Ka;"
  343. " Kdi = Kd;"
  344. " Ksi = Ks;"
  345. " texcoordi = texcoord;"
  346. "}";
  347. std::string mesh_fragment_shader_string =
  348. "#version 150\n"
  349. "uniform mat4 model;"
  350. "uniform mat4 view;"
  351. "uniform mat4 proj;"
  352. "uniform vec4 fixed_color;"
  353. "in vec3 position_eye;"
  354. "in vec3 normal_eye;"
  355. "uniform vec3 light_position_world;"
  356. "vec3 Ls = vec3 (1, 1, 1);"
  357. "vec3 Ld = vec3 (1, 1, 1);"
  358. "vec3 La = vec3 (1, 1, 1);"
  359. "in vec4 Ksi;"
  360. "in vec4 Kdi;"
  361. "in vec4 Kai;"
  362. "in vec2 texcoordi;"
  363. "uniform sampler2D tex;"
  364. "uniform float specular_exponent;"
  365. "uniform float lighting_factor;"
  366. "uniform float texture_factor;"
  367. "out vec4 outColor;"
  368. "void main()"
  369. "{"
  370. "vec3 Ia = La * vec3(Kai);" // ambient intensity
  371. "vec3 light_position_eye = vec3 (view * vec4 (light_position_world, 1.0));"
  372. "vec3 vector_to_light_eye = light_position_eye - position_eye;"
  373. "vec3 direction_to_light_eye = normalize (vector_to_light_eye);"
  374. "float dot_prod = dot (direction_to_light_eye, normal_eye);"
  375. "float clamped_dot_prod = max (dot_prod, 0.0);"
  376. "vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod;" // Diffuse intensity
  377. "vec3 reflection_eye = reflect (-direction_to_light_eye, normal_eye);"
  378. "vec3 surface_to_viewer_eye = normalize (-position_eye);"
  379. "float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);"
  380. "dot_prod_specular = float(abs(dot_prod)==dot_prod) * max (dot_prod_specular, 0.0);"
  381. "float specular_factor = pow (dot_prod_specular, specular_exponent);"
  382. "vec3 Is = Ls * vec3(Ksi) * specular_factor;" // specular intensity
  383. "vec4 color = vec4(lighting_factor * (Is + Id) + Ia + (1.0-lighting_factor) * vec3(Kdi),(Kai.a+Ksi.a+Kdi.a)/3);"
  384. "outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;"
  385. "if (fixed_color != vec4(0.0)) outColor = fixed_color;"
  386. "}";
  387. std::string overlay_vertex_shader_string =
  388. "#version 150\n"
  389. "uniform mat4 model;"
  390. "uniform mat4 view;"
  391. "uniform mat4 proj;"
  392. "in vec3 position;"
  393. "in vec3 color;"
  394. "out vec3 color_frag;"
  395. "void main()"
  396. "{"
  397. " gl_Position = proj * view * model * vec4 (position, 1.0);"
  398. " color_frag = color;"
  399. "}";
  400. std::string overlay_fragment_shader_string =
  401. "#version 150\n"
  402. "in vec3 color_frag;"
  403. "out vec4 outColor;"
  404. "void main()"
  405. "{"
  406. " outColor = vec4(color_frag, 1.0);"
  407. "}";
  408. std::string overlay_point_fragment_shader_string =
  409. "#version 150\n"
  410. "in vec3 color_frag;"
  411. "out vec4 outColor;"
  412. "void main()"
  413. "{"
  414. " if (length(gl_PointCoord - vec2(0.5)) > 0.5)"
  415. " discard;"
  416. " outColor = vec4(color_frag, 1.0);"
  417. "}";
  418. init_buffers();
  419. shader_mesh.init(mesh_vertex_shader_string,
  420. mesh_fragment_shader_string, "outColor");
  421. shader_overlay_lines.init(overlay_vertex_shader_string,
  422. overlay_fragment_shader_string, "outColor");
  423. shader_overlay_points.init(overlay_vertex_shader_string,
  424. overlay_point_fragment_shader_string, "outColor");
  425. }
  426. IGL_INLINE void igl::viewer::OpenGL_state::free()
  427. {
  428. shader_mesh.free();
  429. shader_overlay_lines.free();
  430. shader_overlay_points.free();
  431. free_buffers();
  432. }