OpenGL_shader.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Wenzel Jacob <wenzel@inf.ethz.ch>
  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 "OpenGL_shader.h"
  9. #include <iostream>
  10. #include <fstream>
  11. IGL_INLINE bool igl::viewer::OpenGL_shader::init_from_files(
  12. const std::string &vertex_shader_filename,
  13. const std::string &fragment_shader_filename,
  14. const std::string &fragment_data_name,
  15. const std::string &geometry_shader_filename,
  16. int geometry_shader_max_vertices)
  17. {
  18. auto file_to_string = [](const std::string &filename)->std::string
  19. {
  20. std::ifstream t(filename);
  21. return std::string((std::istreambuf_iterator<char>(t)),
  22. std::istreambuf_iterator<char>());
  23. };
  24. return init(
  25. file_to_string(vertex_shader_filename),
  26. file_to_string(fragment_shader_filename),
  27. fragment_data_name,
  28. file_to_string(geometry_shader_filename),
  29. geometry_shader_max_vertices
  30. );
  31. }
  32. IGL_INLINE bool igl::viewer::OpenGL_shader::init(
  33. const std::string &vertex_shader_string,
  34. const std::string &fragment_shader_string,
  35. const std::string &fragment_data_name,
  36. const std::string &geometry_shader_string,
  37. int geometry_shader_max_vertices)
  38. {
  39. using namespace std;
  40. vertex_shader = create_shader_helper(GL_VERTEX_SHADER, vertex_shader_string);
  41. geometry_shader = create_shader_helper(GL_GEOMETRY_SHADER, geometry_shader_string);
  42. fragment_shader = create_shader_helper(GL_FRAGMENT_SHADER, fragment_shader_string);
  43. if (!vertex_shader || !fragment_shader)
  44. return false;
  45. program_shader = glCreateProgram();
  46. glAttachShader(program_shader, vertex_shader);
  47. glAttachShader(program_shader, fragment_shader);
  48. if (geometry_shader)
  49. {
  50. glAttachShader(program_shader, geometry_shader);
  51. /* This covers only basic cases and may need to be modified */
  52. glProgramParameteri(program_shader, GL_GEOMETRY_INPUT_TYPE, GL_TRIANGLES);
  53. glProgramParameteri(program_shader, GL_GEOMETRY_OUTPUT_TYPE, GL_TRIANGLES);
  54. glProgramParameteri(program_shader, GL_GEOMETRY_VERTICES_OUT, geometry_shader_max_vertices);
  55. }
  56. glBindFragDataLocation(program_shader, 0, fragment_data_name.c_str());
  57. glLinkProgram(program_shader);
  58. GLint status;
  59. glGetProgramiv(program_shader, GL_LINK_STATUS, &status);
  60. if (status != GL_TRUE)
  61. {
  62. char buffer[512];
  63. glGetProgramInfoLog(program_shader, 512, NULL, buffer);
  64. cerr << "Linker error: " << endl << buffer << endl;
  65. program_shader = 0;
  66. return false;
  67. }
  68. return true;
  69. }
  70. IGL_INLINE void igl::viewer::OpenGL_shader::bind()
  71. {
  72. glUseProgram(program_shader);
  73. }
  74. IGL_INLINE GLint igl::viewer::OpenGL_shader::attrib(const std::string &name) const
  75. {
  76. return glGetAttribLocation(program_shader, name.c_str());
  77. }
  78. IGL_INLINE GLint igl::viewer::OpenGL_shader::uniform(const std::string &name) const
  79. {
  80. return glGetUniformLocation(program_shader, name.c_str());
  81. }
  82. IGL_INLINE GLint igl::viewer::OpenGL_shader::bindVertexAttribArray(
  83. const std::string &name, GLuint bufferID, const Eigen::MatrixXf &M, bool refresh) const
  84. {
  85. GLint id = attrib(name);
  86. if (id < 0)
  87. return id;
  88. if (M.size() == 0)
  89. {
  90. glDisableVertexAttribArray(id);
  91. return id;
  92. }
  93. glBindBuffer(GL_ARRAY_BUFFER, bufferID);
  94. if (refresh)
  95. glBufferData(GL_ARRAY_BUFFER, sizeof(float)*M.size(), M.data(), GL_DYNAMIC_DRAW);
  96. glVertexAttribPointer(id, M.rows(), GL_FLOAT, GL_FALSE, 0, 0);
  97. glEnableVertexAttribArray(id);
  98. return id;
  99. }
  100. IGL_INLINE void igl::viewer::OpenGL_shader::free()
  101. {
  102. if (program_shader)
  103. {
  104. glDeleteProgram(program_shader);
  105. program_shader = 0;
  106. }
  107. if (vertex_shader)
  108. {
  109. glDeleteShader(vertex_shader);
  110. vertex_shader = 0;
  111. }
  112. if (fragment_shader)
  113. {
  114. glDeleteShader(fragment_shader);
  115. fragment_shader = 0;
  116. }
  117. if (geometry_shader)
  118. {
  119. glDeleteShader(geometry_shader);
  120. geometry_shader = 0;
  121. }
  122. }
  123. IGL_INLINE GLuint igl::viewer::OpenGL_shader::create_shader_helper(GLint type, const std::string &shader_string)
  124. {
  125. using namespace std;
  126. if (shader_string.empty())
  127. return (GLuint) 0;
  128. GLuint id = glCreateShader(type);
  129. const char *shader_string_const = shader_string.c_str();
  130. glShaderSource(id, 1, &shader_string_const, NULL);
  131. glCompileShader(id);
  132. GLint status;
  133. glGetShaderiv(id, GL_COMPILE_STATUS, &status);
  134. if (status != GL_TRUE)
  135. {
  136. char buffer[512];
  137. if (type == GL_VERTEX_SHADER)
  138. cerr << "Vertex shader:" << endl;
  139. else if (type == GL_FRAGMENT_SHADER)
  140. cerr << "Fragment shader:" << endl;
  141. else if (type == GL_GEOMETRY_SHADER)
  142. cerr << "Geometry shader:" << endl;
  143. cerr << shader_string << endl << endl;
  144. glGetShaderInfoLog(id, 512, NULL, buffer);
  145. cerr << "Error: " << endl << buffer << endl;
  146. return (GLuint) 0;
  147. }
  148. return id;
  149. }