map_texture.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "map_texture.h"
  2. #include "../create_shader_program.h"
  3. // Hopefully OpenGL/gl.h hasn't been included already
  4. #include <OpenGL/gl3.h>
  5. #define __gl_h_
  6. #define GLFW_INCLUDE_GLU
  7. #include <GLFW/glfw3.h>
  8. #include <iostream>
  9. #include <string>
  10. template <typename DerivedV, typename DerivedF, typename DerivedU>
  11. IGL_INLINE bool igl::opengl::glfw::map_texture(
  12. const Eigen::MatrixBase<DerivedV> & _V,
  13. const Eigen::MatrixBase<DerivedF> & _F,
  14. const Eigen::MatrixBase<DerivedU> & _U,
  15. const unsigned char * in_data,
  16. const int w,
  17. const int h,
  18. const int nc,
  19. std::vector<unsigned char> & out_data)
  20. {
  21. const auto fail = [](const std::string msg)
  22. {
  23. std::cerr<<msg<<std::endl;
  24. glfwTerminate();
  25. return false;
  26. };
  27. // Force inputs to be RowMajor at the cost of a copy
  28. Eigen::Matrix<
  29. double,
  30. DerivedV::RowsAtCompileTime,
  31. DerivedV::ColsAtCompileTime,
  32. Eigen::RowMajor> V = _V.template cast<double>();
  33. Eigen::Matrix<
  34. double,
  35. DerivedU::RowsAtCompileTime,
  36. DerivedU::ColsAtCompileTime,
  37. Eigen::RowMajor> U = _U.template cast<double>();
  38. Eigen::Matrix<
  39. int,
  40. DerivedF::RowsAtCompileTime,
  41. DerivedF::ColsAtCompileTime,
  42. Eigen::RowMajor> F = _F.template cast<int>();
  43. // Set up glfw
  44. if(!glfwInit()) fail("Could not initialize glfw");
  45. glfwSetErrorCallback([](int id,const char* m){std::cerr<<m<<std::endl;});
  46. glfwWindowHint(GLFW_SAMPLES, 4);
  47. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  48. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
  49. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  50. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  51. glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
  52. GLFWwindow* window = glfwCreateWindow(1, 1,"", NULL, NULL);
  53. if(!window) fail("Could not create glfw window");
  54. glfwMakeContextCurrent(window);
  55. // Compile each shader
  56. std::string vertex_shader = R"(
  57. #version 330 core
  58. layout(location = 0) in vec2 position;
  59. layout(location = 1) in vec2 tex_coord_v;
  60. out vec2 tex_coord_f;
  61. void main()
  62. {
  63. tex_coord_f = vec2(tex_coord_v.x,1.-tex_coord_v.y);
  64. gl_Position = vec4( 2.*position.x-1., 2.*(1.-position.y)-1., 0.,1.);
  65. }
  66. )";
  67. std::string fragment_shader = R"(
  68. #version 330 core
  69. layout(location = 0) out vec3 color;
  70. uniform sampler2D tex;
  71. in vec2 tex_coord_f;
  72. void main()
  73. {
  74. color = texture(tex,tex_coord_f).rgb;
  75. }
  76. )";
  77. GLuint prog_id =
  78. igl::opengl::create_shader_program(vertex_shader,fragment_shader,{});
  79. glUniform1i(glGetUniformLocation(prog_id, "tex"),0);
  80. // Generate and attach buffers to vertex array
  81. glDisable(GL_CULL_FACE);
  82. GLuint VAO = 0;
  83. glGenVertexArrays(1,&VAO);
  84. glBindVertexArray(VAO);
  85. GLuint ibo,vbo,tbo;
  86. glGenBuffers(1,&ibo);
  87. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
  88. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*F.size(), F.data(), GL_STATIC_DRAW);
  89. glGenBuffers(1,&vbo);
  90. glEnableVertexAttribArray(0);
  91. glBindBuffer(GL_ARRAY_BUFFER,vbo);
  92. glBufferData(GL_ARRAY_BUFFER, sizeof(double)*U.size(), U.data(), GL_STATIC_DRAW);
  93. glVertexAttribLPointer(0, U.cols(), GL_DOUBLE, V.cols() * sizeof(GLdouble), (GLvoid*)0);
  94. glGenBuffers(1,&tbo);
  95. glEnableVertexAttribArray(1);
  96. glBindBuffer(GL_ARRAY_BUFFER,tbo);
  97. glBufferData(GL_ARRAY_BUFFER, sizeof(double)*V.size(), V.data(), GL_STATIC_DRAW);
  98. glVertexAttribLPointer(1, V.cols(), GL_DOUBLE, V.cols() * sizeof(GLdouble), (GLvoid*)0);
  99. glBindVertexArray(0);
  100. glBindBuffer(GL_ARRAY_BUFFER, 0);
  101. glBindVertexArray(0);
  102. // Prepare texture
  103. GLuint in_tex;
  104. GLenum format;
  105. {
  106. format = nc==1 ? GL_RED : (nc==3 ? GL_RGB : (nc == 4 ? GL_RGBA : GL_FALSE));
  107. glGenTextures(1, &in_tex);
  108. glBindTexture(GL_TEXTURE_2D, in_tex);
  109. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  110. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  111. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  112. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  113. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  114. glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w, h, 0,format, GL_UNSIGNED_BYTE, in_data);
  115. }
  116. // Prepare framebuffer
  117. GLuint fb = 0;
  118. glGenFramebuffers(1, &fb);
  119. glBindFramebuffer(GL_FRAMEBUFFER, fb);
  120. GLuint out_tex;
  121. glGenTextures(1, &out_tex);
  122. glBindTexture(GL_TEXTURE_2D, out_tex);
  123. // always use float for internal storage
  124. glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w, h, 0,GL_RGB, GL_FLOAT, 0);
  125. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  126. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  127. glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, out_tex, 0);
  128. {
  129. GLenum bufs[1] = {GL_COLOR_ATTACHMENT0};
  130. glDrawBuffers(1, bufs);
  131. }
  132. if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  133. {
  134. fail("framebuffer setup failed.");
  135. }
  136. glBindFramebuffer(GL_FRAMEBUFFER, fb);
  137. // clear screen and set viewport
  138. glClearColor(0.0,1.0,0.0,0.);
  139. glClear(GL_COLOR_BUFFER_BIT);
  140. glViewport(0,0,w,h);
  141. // Attach shader program
  142. glUseProgram(prog_id);
  143. glActiveTexture(GL_TEXTURE0 + 0);
  144. glBindTexture(GL_TEXTURE_2D, in_tex);
  145. // Draw mesh as wireframe
  146. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  147. glBindVertexArray(VAO);
  148. glDrawElements(GL_TRIANGLES, F.size(), GL_UNSIGNED_INT, 0);
  149. glBindVertexArray(0);
  150. // Write into memory
  151. out_data.resize(nc*w*h);
  152. glBindTexture(GL_TEXTURE_2D, out_tex);
  153. glGetTexImage(GL_TEXTURE_2D, 0, format, GL_UNSIGNED_BYTE, &out_data[0]);
  154. // OpenGL cleanup
  155. glDeleteBuffers(1,&fb);
  156. glDeleteBuffers(1,&ibo);
  157. glDeleteBuffers(1,&vbo);
  158. glDeleteBuffers(1,&tbo);
  159. glDeleteTextures(1,&in_tex);
  160. glDeleteTextures(1,&out_tex);
  161. glDeleteVertexArrays(1,&VAO);
  162. glUseProgram(0);
  163. glDeleteProgram(prog_id);
  164. // GLFW cleanup
  165. glfwDestroyWindow(window);
  166. glfwTerminate();
  167. return true;
  168. }
  169. #ifdef IGL_STATIC_LIBRARY
  170. // Explicit template instantiation
  171. // generated by autoexplicit.sh
  172. template bool igl::opengl::glfw::map_texture<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, -1, 1, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, unsigned char const*, int, int, int, std::vector<unsigned char, std::allocator<unsigned char> >&);
  173. #endif