OpenGL_state.cpp 15 KB

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