OpenGL_shader.cpp 5.0 KB

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