map_texture.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "map_texture.h"
  2. #include "background_window.h"
  3. #include "../create_shader_program.h"
  4. #include "../bind_vertex_attrib_array.h"
  5. #include "../gl.h"
  6. #include <GLFW/glfw3.h>
  7. #include <iostream>
  8. #include <string>
  9. template <typename DerivedV, typename DerivedF, typename DerivedU>
  10. IGL_INLINE bool igl::opengl::glfw::map_texture(
  11. const Eigen::MatrixBase<DerivedV> & _V,
  12. const Eigen::MatrixBase<DerivedF> & _F,
  13. const Eigen::MatrixBase<DerivedU> & _U,
  14. const unsigned char * in_data,
  15. const int w,
  16. const int h,
  17. const int nc,
  18. std::vector<unsigned char> & out_data)
  19. {
  20. int out_w = w;
  21. int out_h = h;
  22. int out_nc = nc;
  23. return map_texture(_V,_F,_U,in_data,w,h,nc,out_data,out_w,out_h,out_nc);
  24. }
  25. template <typename DerivedV, typename DerivedF, typename DerivedU>
  26. IGL_INLINE bool igl::opengl::glfw::map_texture(
  27. const Eigen::MatrixBase<DerivedV> & V,
  28. const Eigen::MatrixBase<DerivedF> & F,
  29. const Eigen::MatrixBase<DerivedU> & U,
  30. const unsigned char * in_data,
  31. const int in_w,
  32. const int in_h,
  33. const int in_nc,
  34. std::vector<unsigned char> & out_data,
  35. int & out_w,
  36. int & out_h,
  37. int & out_nc)
  38. {
  39. GLenum format = -1;
  40. switch(in_nc)
  41. {
  42. case 1: format = GL_RED; break;
  43. case 2: format = GL_RG; break;
  44. case 3: format = GL_RGB; break;
  45. case 4: format = GL_RGBA; break;
  46. default: assert(false && "Unsupported number of channels"); break;
  47. }
  48. GLFWwindow * window = nullptr;
  49. igl::opengl::glfw::background_window(window);
  50. // Compile each shader
  51. std::string vertex_shader = R"(
  52. #version 400
  53. layout(location = 0) in vec3 position;
  54. layout(location = 1) in vec2 tex_coord_v;
  55. out vec2 tex_coord_f;
  56. void main()
  57. {
  58. tex_coord_f = vec2(tex_coord_v.x,1.-tex_coord_v.y);
  59. gl_Position = vec4(2.*position.x-1.,2.*(1.-position.y)-1., position.z,1.);
  60. }
  61. )"
  62. ;
  63. std::string fragment_shader = R"(
  64. #version 400
  65. layout(location = 0) out vec3 color;
  66. uniform sampler2D tex;
  67. in vec2 tex_coord_f;
  68. void main()
  69. {
  70. color = texture(tex,tex_coord_f).rgb;
  71. }
  72. )";
  73. GLuint prog_id =
  74. igl::opengl::create_shader_program(vertex_shader,fragment_shader,{});
  75. using Scalar = float;
  76. using MatrixXS3 = Eigen::Matrix<Scalar,Eigen::Dynamic,3,Eigen::RowMajor>;
  77. MatrixXS3 V_vbo = MatrixXS3::Zero(V.rows(),3);
  78. V_vbo.leftCols(V.cols()) = V.template cast<Scalar>();
  79. MatrixXS3 U_vbo = MatrixXS3::Zero(U.rows(),3);
  80. U_vbo.leftCols(U.cols()) = U.template cast<Scalar>();
  81. Eigen::Matrix<unsigned, Eigen::Dynamic, 3, Eigen::RowMajor> F_vbo =
  82. F.template cast<unsigned>();
  83. // Generate and attach buffers to vertex array
  84. glDisable(GL_CULL_FACE);
  85. GLuint VAO = 0;
  86. glGenVertexArrays(1,&VAO);
  87. glBindVertexArray(VAO);
  88. GLuint ibo,vbo,tbo,tex;
  89. glGenBuffers(1,&ibo);
  90. glGenBuffers(1,&vbo);
  91. glGenBuffers(1,&tbo);
  92. glGenTextures(1,&tex);
  93. out_w = in_w;
  94. out_h = in_h;
  95. glClearColor(0,0,1,1);
  96. glClear(GL_COLOR_BUFFER_BIT);
  97. glViewport(0,0,out_w,out_h);
  98. // Prepare framebuffer
  99. GLuint fb = 0;
  100. GLuint out_tex;
  101. glGenFramebuffers(1, &fb);
  102. glBindFramebuffer(GL_FRAMEBUFFER, fb);
  103. glGenTextures(1, &out_tex);
  104. glBindTexture(GL_TEXTURE_2D, out_tex);
  105. // always use float for internal storage
  106. glTexImage2D(GL_TEXTURE_2D, 0,format, out_w, out_h, 0,format, GL_FLOAT, 0);
  107. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  108. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  109. glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, out_tex, 0);
  110. {
  111. GLenum bufs[1] = {GL_COLOR_ATTACHMENT0};
  112. glDrawBuffers(1, bufs);
  113. }
  114. if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  115. {
  116. glfwTerminate();
  117. return false;
  118. }
  119. glBindFramebuffer(GL_FRAMEBUFFER, fb);
  120. glUseProgram(prog_id);
  121. glActiveTexture(GL_TEXTURE0);
  122. glBindTexture(GL_TEXTURE_2D, tex);
  123. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  124. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  125. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  126. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  127. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  128. glTexImage2D(GL_TEXTURE_2D, 0, format, in_w, in_h, 0, format, GL_UNSIGNED_BYTE, in_data);
  129. glUniform1i(glGetUniformLocation(prog_id,"tex"), 0);
  130. igl::opengl::bind_vertex_attrib_array(prog_id,"position", vbo, U_vbo, true);
  131. igl::opengl::bind_vertex_attrib_array(prog_id,"tex_coord_v", tbo, V_vbo, true);
  132. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  133. glBindVertexArray(VAO);
  134. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
  135. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*F_vbo.size(), F_vbo.data(), GL_DYNAMIC_DRAW);
  136. glDrawElements(GL_TRIANGLES, F.size(), GL_UNSIGNED_INT, 0);
  137. out_nc = in_nc;
  138. out_data.resize(out_nc*out_w*out_h);
  139. glBindTexture(GL_TEXTURE_2D, out_tex);
  140. glGetTexImage(GL_TEXTURE_2D, 0, format, GL_UNSIGNED_BYTE, out_data.data());
  141. glfwDestroyWindow(window);
  142. glfwTerminate();
  143. return true;
  144. }
  145. #ifdef IGL_STATIC_LIBRARY
  146. // Explicit template instantiation
  147. // generated by autoexplicit.sh
  148. 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> >&);
  149. template bool igl::opengl::glfw::map_texture<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned char const*, int, int, int, std::vector<unsigned char, std::allocator<unsigned char> >&, int&, int&, int&);
  150. #endif