MeshGL.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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. "#version 150\n"
  144. "uniform mat4 model;"
  145. "uniform mat4 view;"
  146. "uniform mat4 proj;"
  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 * model * vec4 (position, 1.0));"
  162. " normal_eye = vec3 (view * model * vec4 (normal, 0.0));"
  163. " normal_eye = normalize(normal_eye);"
  164. " gl_Position = proj * vec4 (position_eye, 1.0);" //proj * view * model * vec4(position, 1.0);"
  165. " Kai = Ka;"
  166. " Kdi = Kd;"
  167. " Ksi = Ks;"
  168. " texcoordi = texcoord;"
  169. "}";
  170. std::string mesh_fragment_shader_string =
  171. "#version 150\n"
  172. "uniform mat4 model;"
  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_world;"
  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 light_position_eye = vec3 (view * vec4 (light_position_world, 1.0));"
  195. "vec3 vector_to_light_eye = light_position_eye - position_eye;"
  196. "vec3 direction_to_light_eye = normalize (vector_to_light_eye);"
  197. "float dot_prod = dot (direction_to_light_eye, normal_eye);"
  198. "float clamped_dot_prod = max (dot_prod, 0.0);"
  199. "vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod;" // Diffuse intensity
  200. "vec3 reflection_eye = reflect (-direction_to_light_eye, normal_eye);"
  201. "vec3 surface_to_viewer_eye = normalize (-position_eye);"
  202. "float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);"
  203. "dot_prod_specular = float(abs(dot_prod)==dot_prod) * max (dot_prod_specular, 0.0);"
  204. "float specular_factor = pow (dot_prod_specular, specular_exponent);"
  205. "vec3 Is = Ls * vec3(Ksi) * specular_factor;" // specular intensity
  206. "vec4 color = vec4(lighting_factor * (Is + Id) + Ia + (1.0-lighting_factor) * vec3(Kdi),(Kai.a+Ksi.a+Kdi.a)/3);"
  207. "outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;"
  208. "if (fixed_color != vec4(0.0)) outColor = fixed_color;"
  209. "}";
  210. std::string overlay_vertex_shader_string =
  211. "#version 150\n"
  212. "uniform mat4 model;"
  213. "uniform mat4 view;"
  214. "uniform mat4 proj;"
  215. "in vec3 position;"
  216. "in vec3 color;"
  217. "out vec3 color_frag;"
  218. "void main()"
  219. "{"
  220. " gl_Position = proj * view * model * vec4 (position, 1.0);"
  221. " color_frag = color;"
  222. "}";
  223. std::string overlay_fragment_shader_string =
  224. "#version 150\n"
  225. "in vec3 color_frag;"
  226. "out vec4 outColor;"
  227. "void main()"
  228. "{"
  229. " outColor = vec4(color_frag, 1.0);"
  230. "}";
  231. std::string overlay_point_fragment_shader_string =
  232. "#version 150\n"
  233. "in vec3 color_frag;"
  234. "out vec4 outColor;"
  235. "void main()"
  236. "{"
  237. " if (length(gl_PointCoord - vec2(0.5)) > 0.5)"
  238. " discard;"
  239. " outColor = vec4(color_frag, 1.0);"
  240. "}";
  241. init_buffers();
  242. create_shader_program(
  243. mesh_vertex_shader_string,
  244. mesh_fragment_shader_string,
  245. {},
  246. shader_mesh);
  247. create_shader_program(
  248. overlay_vertex_shader_string,
  249. overlay_fragment_shader_string,
  250. {},
  251. shader_overlay_lines);
  252. create_shader_program(
  253. overlay_vertex_shader_string,
  254. overlay_point_fragment_shader_string,
  255. {},
  256. shader_overlay_points);
  257. }
  258. IGL_INLINE void igl::opengl::MeshGL::free()
  259. {
  260. const auto free = [](GLuint & id)
  261. {
  262. if(id)
  263. {
  264. destroy_shader_program(id);
  265. id = 0;
  266. }
  267. };
  268. if (is_initialized)
  269. {
  270. free(shader_mesh);
  271. free(shader_overlay_lines);
  272. free(shader_overlay_points);
  273. free_buffers();
  274. }
  275. }