OpenGL_shader.cpp 4.6 KB

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