MeshGL.cpp 9.4 KB

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