MeshGL.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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 "MeshGL.h"
  9. #include "bind_vertex_attrib_array.h"
  10. #include "create_shader_program.h"
  11. #include "destroy_shader_program.h"
  12. #include <iostream>
  13. IGL_INLINE void igl::opengl::MeshGL::init_buffers()
  14. {
  15. // Mesh: Vertex Array Object & Buffer objects
  16. glGenVertexArrays(1, &vao_mesh);
  17. glBindVertexArray(vao_mesh);
  18. glGenBuffers(1, &vbo_V);
  19. glGenBuffers(1, &vbo_V_normals);
  20. glGenBuffers(1, &vbo_V_ambient);
  21. glGenBuffers(1, &vbo_V_diffuse);
  22. glGenBuffers(1, &vbo_V_specular);
  23. glGenBuffers(1, &vbo_V_uv);
  24. glGenBuffers(1, &vbo_F);
  25. glGenTextures(1, &vbo_tex);
  26. // Line overlay
  27. glGenVertexArrays(1, &vao_overlay_lines);
  28. glBindVertexArray(vao_overlay_lines);
  29. glGenBuffers(1, &vbo_lines_F);
  30. glGenBuffers(1, &vbo_lines_V);
  31. glGenBuffers(1, &vbo_lines_V_colors);
  32. // Point overlay
  33. glGenVertexArrays(1, &vao_overlay_points);
  34. glBindVertexArray(vao_overlay_points);
  35. glGenBuffers(1, &vbo_points_F);
  36. glGenBuffers(1, &vbo_points_V);
  37. glGenBuffers(1, &vbo_points_V_colors);
  38. dirty = MeshGL::DIRTY_ALL;
  39. }
  40. IGL_INLINE void igl::opengl::MeshGL::free_buffers()
  41. {
  42. if (is_initialized)
  43. {
  44. glDeleteVertexArrays(1, &vao_mesh);
  45. glDeleteVertexArrays(1, &vao_overlay_lines);
  46. glDeleteVertexArrays(1, &vao_overlay_points);
  47. glDeleteBuffers(1, &vbo_V);
  48. glDeleteBuffers(1, &vbo_V_normals);
  49. glDeleteBuffers(1, &vbo_V_ambient);
  50. glDeleteBuffers(1, &vbo_V_diffuse);
  51. glDeleteBuffers(1, &vbo_V_specular);
  52. glDeleteBuffers(1, &vbo_V_uv);
  53. glDeleteBuffers(1, &vbo_F);
  54. glDeleteBuffers(1, &vbo_lines_F);
  55. glDeleteBuffers(1, &vbo_lines_V);
  56. glDeleteBuffers(1, &vbo_lines_V_colors);
  57. glDeleteBuffers(1, &vbo_points_F);
  58. glDeleteBuffers(1, &vbo_points_V);
  59. glDeleteBuffers(1, &vbo_points_V_colors);
  60. glDeleteTextures(1, &vbo_tex);
  61. }
  62. }
  63. IGL_INLINE void igl::opengl::MeshGL::bind_mesh()
  64. {
  65. glBindVertexArray(vao_mesh);
  66. glUseProgram(shader_mesh);
  67. bind_vertex_attrib_array(shader_mesh,"position", vbo_V, V_vbo, dirty & MeshGL::DIRTY_POSITION);
  68. bind_vertex_attrib_array(shader_mesh,"normal", vbo_V_normals, V_normals_vbo, dirty & MeshGL::DIRTY_NORMAL);
  69. bind_vertex_attrib_array(shader_mesh,"Ka", vbo_V_ambient, V_ambient_vbo, dirty & MeshGL::DIRTY_AMBIENT);
  70. bind_vertex_attrib_array(shader_mesh,"Kd", vbo_V_diffuse, V_diffuse_vbo, dirty & MeshGL::DIRTY_DIFFUSE);
  71. bind_vertex_attrib_array(shader_mesh,"Ks", vbo_V_specular, V_specular_vbo, dirty & MeshGL::DIRTY_SPECULAR);
  72. bind_vertex_attrib_array(shader_mesh,"texcoord", vbo_V_uv, V_uv_vbo, dirty & MeshGL::DIRTY_UV);
  73. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_F);
  74. if (dirty & MeshGL::DIRTY_FACE)
  75. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*F_vbo.size(), F_vbo.data(), GL_DYNAMIC_DRAW);
  76. glActiveTexture(GL_TEXTURE0);
  77. glBindTexture(GL_TEXTURE_2D, vbo_tex);
  78. if (dirty & MeshGL::DIRTY_TEXTURE)
  79. {
  80. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  81. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  82. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  83. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  84. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  85. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_u, tex_v, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.data());
  86. }
  87. glUniform1i(glGetUniformLocation(shader_mesh,"tex"), 0);
  88. dirty &= ~MeshGL::DIRTY_MESH;
  89. }
  90. IGL_INLINE void igl::opengl::MeshGL::bind_overlay_lines()
  91. {
  92. bool is_dirty = dirty & MeshGL::DIRTY_OVERLAY_LINES;
  93. glBindVertexArray(vao_overlay_lines);
  94. glUseProgram(shader_overlay_lines);
  95. bind_vertex_attrib_array(shader_overlay_lines,"position", vbo_lines_V, lines_V_vbo, is_dirty);
  96. bind_vertex_attrib_array(shader_overlay_lines,"color", vbo_lines_V_colors, lines_V_colors_vbo, is_dirty);
  97. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_lines_F);
  98. if (is_dirty)
  99. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*lines_F_vbo.size(), lines_F_vbo.data(), GL_DYNAMIC_DRAW);
  100. dirty &= ~MeshGL::DIRTY_OVERLAY_LINES;
  101. }
  102. IGL_INLINE void igl::opengl::MeshGL::bind_overlay_points()
  103. {
  104. bool is_dirty = dirty & MeshGL::DIRTY_OVERLAY_POINTS;
  105. glBindVertexArray(vao_overlay_points);
  106. glUseProgram(shader_overlay_points);
  107. bind_vertex_attrib_array(shader_overlay_points,"position", vbo_points_V, points_V_vbo, is_dirty);
  108. bind_vertex_attrib_array(shader_overlay_points,"color", vbo_points_V_colors, points_V_colors_vbo, is_dirty);
  109. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_points_F);
  110. if (is_dirty)
  111. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*points_F_vbo.size(), points_F_vbo.data(), GL_DYNAMIC_DRAW);
  112. dirty &= ~MeshGL::DIRTY_OVERLAY_POINTS;
  113. }
  114. IGL_INLINE void igl::opengl::MeshGL::draw_mesh(bool solid)
  115. {
  116. glPolygonMode(GL_FRONT_AND_BACK, solid ? GL_FILL : GL_LINE);
  117. /* Avoid Z-buffer fighting between filled triangles & wireframe lines */
  118. if (solid)
  119. {
  120. glEnable(GL_POLYGON_OFFSET_FILL);
  121. glPolygonOffset(1.0, 1.0);
  122. }
  123. glDrawElements(GL_TRIANGLES, 3*F_vbo.rows(), GL_UNSIGNED_INT, 0);
  124. glDisable(GL_POLYGON_OFFSET_FILL);
  125. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  126. }
  127. IGL_INLINE void igl::opengl::MeshGL::draw_overlay_lines()
  128. {
  129. glDrawElements(GL_LINES, lines_F_vbo.rows(), GL_UNSIGNED_INT, 0);
  130. }
  131. IGL_INLINE void igl::opengl::MeshGL::draw_overlay_points()
  132. {
  133. glDrawElements(GL_POINTS, points_F_vbo.rows(), GL_UNSIGNED_INT, 0);
  134. }
  135. IGL_INLINE void igl::opengl::MeshGL::init()
  136. {
  137. if(is_initialized)
  138. {
  139. return;
  140. }
  141. is_initialized = true;
  142. std::string mesh_vertex_shader_string =
  143. R"(#version 150
  144. uniform mat4 view;
  145. uniform mat4 proj;
  146. uniform mat4 normal_matrix;
  147. in vec3 position;
  148. in vec3 normal;
  149. out vec3 position_eye;
  150. out vec3 normal_eye;
  151. in vec4 Ka;
  152. in vec4 Kd;
  153. in vec4 Ks;
  154. in vec2 texcoord;
  155. out vec2 texcoordi;
  156. out vec4 Kai;
  157. out vec4 Kdi;
  158. out vec4 Ksi;
  159. void main()
  160. {
  161. position_eye = vec3 (view * vec4 (position, 1.0));
  162. normal_eye = vec3 (normal_matrix * vec4 (normal, 0.0));
  163. normal_eye = normalize(normal_eye);
  164. gl_Position = proj * vec4 (position_eye, 1.0); //proj * view * vec4(position, 1.0);"
  165. Kai = Ka;
  166. Kdi = Kd;
  167. Ksi = Ks;
  168. texcoordi = texcoord;
  169. }
  170. )";
  171. std::string mesh_fragment_shader_string =
  172. R"(#version 150
  173. uniform mat4 view;
  174. uniform mat4 proj;
  175. uniform vec4 fixed_color;
  176. in vec3 position_eye;
  177. in vec3 normal_eye;
  178. uniform vec3 light_position_eye;
  179. vec3 Ls = vec3 (1, 1, 1);
  180. vec3 Ld = vec3 (1, 1, 1);
  181. vec3 La = vec3 (1, 1, 1);
  182. in vec4 Ksi;
  183. in vec4 Kdi;
  184. in vec4 Kai;
  185. in vec2 texcoordi;
  186. uniform sampler2D tex;
  187. uniform float specular_exponent;
  188. uniform float lighting_factor;
  189. uniform float texture_factor;
  190. out vec4 outColor;
  191. void main()
  192. {
  193. vec3 Ia = La * vec3(Kai); // ambient intensity
  194. vec3 vector_to_light_eye = light_position_eye - position_eye;
  195. vec3 direction_to_light_eye = normalize (vector_to_light_eye);
  196. float dot_prod = dot (direction_to_light_eye, normalize(normal_eye));
  197. float clamped_dot_prod = max (dot_prod, 0.0);
  198. vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod; // Diffuse intensity
  199. vec3 reflection_eye = reflect (-direction_to_light_eye, normalize(normal_eye));
  200. vec3 surface_to_viewer_eye = normalize (-position_eye);
  201. float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);
  202. dot_prod_specular = float(abs(dot_prod)==dot_prod) * max (dot_prod_specular, 0.0);
  203. float specular_factor = pow (dot_prod_specular, specular_exponent);
  204. vec3 Is = Ls * vec3(Ksi) * specular_factor; // specular intensity
  205. vec4 color = vec4(lighting_factor * (Is + Id) + Ia + (1.0-lighting_factor) * vec3(Kdi),(Kai.a+Ksi.a+Kdi.a)/3);
  206. outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;
  207. if (fixed_color != vec4(0.0)) outColor = fixed_color;
  208. }
  209. )";
  210. std::string overlay_vertex_shader_string =
  211. R"(#version 150
  212. uniform mat4 view;
  213. uniform mat4 proj;
  214. in vec3 position;
  215. in vec3 color;
  216. out vec3 color_frag;
  217. void main()
  218. {
  219. gl_Position = proj * view * vec4 (position, 1.0);
  220. color_frag = color;
  221. }
  222. )";
  223. std::string overlay_fragment_shader_string =
  224. R"(#version 150
  225. in vec3 color_frag;
  226. out vec4 outColor;
  227. void main()
  228. {
  229. outColor = vec4(color_frag, 1.0);
  230. }
  231. )";
  232. std::string overlay_point_fragment_shader_string =
  233. R"(#version 150
  234. in vec3 color_frag;
  235. out vec4 outColor;
  236. void main()
  237. {
  238. if (length(gl_PointCoord - vec2(0.5)) > 0.5)
  239. discard;
  240. outColor = vec4(color_frag, 1.0);
  241. }
  242. )";
  243. init_buffers();
  244. create_shader_program(
  245. mesh_vertex_shader_string,
  246. mesh_fragment_shader_string,
  247. {},
  248. shader_mesh);
  249. create_shader_program(
  250. overlay_vertex_shader_string,
  251. overlay_fragment_shader_string,
  252. {},
  253. shader_overlay_lines);
  254. create_shader_program(
  255. overlay_vertex_shader_string,
  256. overlay_point_fragment_shader_string,
  257. {},
  258. shader_overlay_points);
  259. }
  260. IGL_INLINE void igl::opengl::MeshGL::free()
  261. {
  262. const auto free = [](GLuint & id)
  263. {
  264. if(id)
  265. {
  266. destroy_shader_program(id);
  267. id = 0;
  268. }
  269. };
  270. if (is_initialized)
  271. {
  272. free(shader_mesh);
  273. free(shader_overlay_lines);
  274. free(shader_overlay_points);
  275. free_buffers();
  276. }
  277. }