map_texture.cpp 7.1 KB

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