jubilant-funicular
GLSLProgram.cpp
1 #include <fstream>
2 #include <queue>
3 
4 #include <GL/glew.h>
5 
6 #include "nta/GLSLProgram.h"
7 #include "nta/Logger.h"
8 
9 namespace nta {
11  }
12  GLSLProgram::~GLSLProgram() {
13  if (m_programID != 0) {
14  glDeleteProgram(m_programID);
15  }
16  m_programID = 0;
17  }
18  GLuint GLSLProgram::compileShader(crstring shaderFileName, GLenum shaderType) const {
19  GLuint retID = 0;
20  retID = glCreateShader(shaderType);
21  if (retID == 0) {
22  Logger::writeErrorToLog("Failed to create shader", GL_FAILURE);
23  }
24  std::ifstream shaderFile(shaderFileName);
25  if (shaderFile.fail()) {
26  Logger::writeErrorToLog("Failed to open shader file: " + shaderFileName,
27  MISSING_RESOURCE);
28  }
29  std::string fileContents = "";
30  std::string line;
31  while (getline(shaderFile, line)) {
32  fileContents += line + '\n';
33  }
34  shaderFile.close();
35  const char* contentsPtr = fileContents.c_str();
36  glShaderSource(retID, 1, &contentsPtr, nullptr);
37  glCompileShader(retID);
38  GLint compileStatus = 0;
39  glGetShaderiv(retID, GL_COMPILE_STATUS, &compileStatus);
40  if (compileStatus == GL_FALSE) {
41  GLint maxLength = 0;
42  glGetShaderiv(retID, GL_INFO_LOG_LENGTH, &maxLength);
43  char* log = new char[maxLength];
44  glGetShaderInfoLog(retID, maxLength, &maxLength, log);
45  if (maxLength > 0) {
46  glDeleteShader(retID);
47  Logger::writeToLog(shaderFileName + " log:");
48  Logger::writeErrorToLog(log, GL_FAILURE);
49  }
50  }
51  return retID;
52  }
53  GLint GLSLProgram::getUniformLocation(crstring uniformName) const {
54  GLint ret = glGetUniformLocation(m_programID, uniformName.c_str());
55  if (ret == GL_INVALID_INDEX) {
56  Logger::writeErrorToLog("Could not find uniform in shader: " + uniformName,
57  GL_FAILURE);
58  }
59  return ret;
60  }
61  bool GLSLProgram::isLinked() const {
62  return m_isLinked;
63  }
64  void GLSLProgram::compileShaders(crstring shaderProgName) {
65  Logger::writeToLog("Compiling shaders: " + shaderProgName + "...");
66  m_programID = glCreateProgram();
67  m_vert = shaderProgName + ".vert";
68  m_vertShaderID = compileShader(m_vert.to_string(), GL_VERTEX_SHADER);
69  m_frag = shaderProgName + ".frag";
70  m_fragShaderID = compileShader(m_frag.to_string(), GL_FRAGMENT_SHADER);
71  Logger::writeToLog("Compiled shaders");
72  }
73  void GLSLProgram::compileShaders(crstring vert, crstring frag) {
74  Logger::writeToLog("Compiling shaders: " + vert + " | " + frag + "...");
75  m_programID = glCreateProgram();
76  std::tie(m_vert, m_frag) = std::make_tuple(vert, frag);
77  m_vertShaderID = compileShader(vert, GL_VERTEX_SHADER);
78  m_fragShaderID = compileShader(frag, GL_FRAGMENT_SHADER);
79  Logger::writeToLog("Compiled shaders");
80  }
81  void GLSLProgram::addAttribute(crstring attributeName) {
82  Logger::writeToLog("Adding attribute \"" + attributeName + "\" to program...");
83  glBindAttribLocation(m_programID, m_numAttributes++, attributeName.c_str());
84  }
86  Logger::writeToLog("Linking shaders to program...");
87  glAttachShader(m_programID, m_vertShaderID);
88  glAttachShader(m_programID, m_fragShaderID);
89  glLinkProgram(m_programID);
90  GLint linkStatus;
91  glGetProgramiv(m_programID, GL_LINK_STATUS, &linkStatus);
92  if (linkStatus == GL_FALSE) {
93  GLint maxLength = 0;
94  glGetProgramiv(m_programID, GL_INFO_LOG_LENGTH, &maxLength);
95  char* log = new char[maxLength];
96  glGetProgramInfoLog(m_programID, maxLength, &maxLength, log);
97  if (maxLength > 0) {
98  glDeleteShader(m_vertShaderID);
99  glDeleteShader(m_fragShaderID);
100  glDeleteProgram(m_programID);
101  Logger::writeToLog("GLSLProgram log:");
102  Logger::writeErrorToLog(log, GL_FAILURE);
103  }
104  }
105  glDetachShader(m_programID, m_vertShaderID);
106  glDetachShader(m_programID, m_fragShaderID);
107  glDeleteShader(m_vertShaderID);
108  glDeleteShader(m_fragShaderID);
109  m_isLinked = true;
110  Logger::writeToLog("Linked shaders");
111  }
112  void GLSLProgram::use() const {
113  glUseProgram(m_programID);
114  for (int i = 0; i < m_numAttributes; i++) {
115  glEnableVertexAttribArray(i);
116  }
117  }
118  void GLSLProgram::unuse() const {
119  glUseProgram(0);
120  for (int i = 0; i < m_numAttributes; i++) {
121  glDisableVertexAttribArray(i);
122  }
123  }
125  glDeleteProgram(m_programID);
126  m_programID = 0;
127  m_numAttributes = 0;
128  m_isLinked = false;
129  }
131  static const std::size_t MAX_ATTRIB_NAME_SIZE = 64;
132  Logger::writeToLog("Reloading shaders: " + m_vert.to_string() + " | " + m_frag.to_string() + "...");
133  Logger::indent();
134 
135  std::vector<std::string> attribs(m_numAttributes);
136  for (int i = 0; i < m_numAttributes; i++) {
137  char attribName[MAX_ATTRIB_NAME_SIZE];
138  GLint size;
139  GLenum type;
140  glGetActiveAttrib(m_programID, i, MAX_ATTRIB_NAME_SIZE, nullptr,
141  &size, &type, attribName);
142  attribs[glGetAttribLocation(m_programID, attribName)] = attribName;
143  }
144 
145  destroy();
146  compileShaders(m_vert.to_string(), m_frag.to_string());
147  for (auto& attrib : attribs) {
148  addAttribute(attrib);
149  }
150  linkShaders();
151 
153  Logger::writeToLog("Reloaded shaders");
154  }
155 }
nta::GLSLProgram::reload
void reload()
Reloads the program.
Definition: GLSLProgram.cpp:130
nta::GLSLProgram::m_numAttributes
int m_numAttributes
the number of attributes used by the vertex shader
Definition: GLSLProgram.h:28
nta::Logger::writeToLog
static void writeToLog(crstring entry)
writes an entry in the log
Definition: Logger.cpp:17
nta::Logger::unindent
static void unindent(size_t tab_size=TAB_SIZE)
unindents entries
Definition: Logger.cpp:46
nta::GLSLProgram::compileShaders
void compileShaders(crstring shaderProgName)
compiles both the vertex and fragment shaders given their name
Definition: GLSLProgram.cpp:64
nta::GLSLProgram::linkShaders
void linkShaders()
links the compiled shaders to this program
Definition: GLSLProgram.cpp:85
nta::GLSLProgram::m_isLinked
bool m_isLinked
keeps track of whether or not the shaders have been linked
Definition: GLSLProgram.h:30
nta
Definition: Animation2D.h:6
nta::GLSLProgram::m_vert
utils::Path m_vert
The files containing the vertex and fragment shaders.
Definition: GLSLProgram.h:26
nta::GLSLProgram::destroy
void destroy()
deletes this program
Definition: GLSLProgram.cpp:124
nta::GLSLProgram::addAttribute
void addAttribute(crstring attributeName)
makes an attribute useful and assigns it the next available location
Definition: GLSLProgram.cpp:81
nta::GLSLProgram::GLSLProgram
GLSLProgram()
constructor and destructor
Definition: GLSLProgram.cpp:10
nta::GLSLProgram::isLinked
bool isLinked() const
returns whether or not the shaders have been linked
Definition: GLSLProgram.cpp:61
nta::GLSLProgram::unuse
void unuse() const
unbinds this program
Definition: GLSLProgram.cpp:118
nta::GLSLProgram::getUniformLocation
GLint getUniformLocation(crstring uniformName) const
returns the location of a uniform in the shaders
Definition: GLSLProgram.cpp:53
nta::Logger::writeErrorToLog
static Error writeErrorToLog(crstring error, ErrorType type=OTHER)
writes entry in log and then notifies ErrorManager
Definition: Logger.cpp:31
nta::GLSLProgram::m_programID
GLuint m_programID
the id for the program
Definition: GLSLProgram.h:22
nta::GLSLProgram::m_vertShaderID
GLuint m_vertShaderID
the ids for the vertex and fragment shaders
Definition: GLSLProgram.h:24
nta::Logger::indent
static void indent(size_t tab_size=TAB_SIZE)
indents entries
Definition: Logger.cpp:43
nta::GLSLProgram::use
void use() const
binds this program
Definition: GLSLProgram.cpp:112
nta::GLSLProgram::compileShader
GLuint compileShader(crstring shaderFileName, GLenum shaderType) const
compiles a shader from a file and returns its id
Definition: GLSLProgram.cpp:18