-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShaderManager.cpp
181 lines (144 loc) · 4.8 KB
/
ShaderManager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include "ShaderManager.h"
#include <fstream>
#include <iostream>
static GLint compileShader(const char* shaderPath, GLenum type)
{
std::ifstream fs(shaderPath, std::ios::binary | std::ios::ate);
if (!fs || !fs.is_open())
{
std::cerr << "Failed to open shader file " << shaderPath << std::endl;
return 0;
}
std::streampos fileSize = fs.tellg();
fs.seekg(std::ios::beg);
std::string sShaderCode(static_cast<unsigned int>(fileSize), 0);
fs.read(&sShaderCode[0], fileSize);
const GLchar* shaderSource = sShaderCode.c_str();
const GLint shader = glCreateShader(type);
if (!shader)
{
std::cerr << "Failed to create a shader of type " << type << std::endl;
abort();
}
glShaderSource(shader, 1, &shaderSource, NULL);
glCompileShader(shader);
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled)
{
std::cerr << "Failed to compile shader " << shaderPath << std::endl;
GLint errorLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &errorLength);
GLchar* errorString = new GLchar[errorLength];
std::vector<GLchar> errorLog(errorLength);
glGetShaderInfoLog(shader, errorLength, &errorLength, &errorLog[0]);
std::cerr << (char*)&errorLog[0] << std::endl;
abort();
}
return shader;
}
static GLint compileShaderProgram(const char* vertexShaderPath, const char* fragmentShaderPath)
{
const GLint shaderProgram = glCreateProgram();
if (!shaderProgram)
{
std::cerr << "Failed to create shader program" << std::endl;
abort();
}
glAttachShader(shaderProgram, compileShader(vertexShaderPath, GL_VERTEX_SHADER));
glAttachShader(shaderProgram, compileShader(fragmentShaderPath, GL_FRAGMENT_SHADER));
glLinkProgram(shaderProgram);
GLint linked;
glGetShaderiv(shaderProgram, GL_LINK_STATUS, &linked);
if (!linked)
{
std::cerr << "Failed to link shader program with shaders " << vertexShaderPath << " and " << fragmentShaderPath << std::endl;
abort();
}
return shaderProgram;
}
ShaderManager::ShaderManager() :
m_activeShader(0)
{
}
ShaderManager::~ShaderManager()
{
}
void ShaderManager::AddShader(std::string const& name, const char* sVertexFile, const char* sFragmentFile)
{
GLuint programID = compileShaderProgram(sVertexFile, sFragmentFile);
Shader newShader(name, sVertexFile, sFragmentFile);
newShader.programId = programID;
m_shaderPrograms.insert({ name, newShader });
}
void ShaderManager::UseShader(std::string const& name)
{
auto result = m_shaderPrograms.find(name);
if (result == m_shaderPrograms.end())
{
std::cerr << "Shader \"" << name << "\" could not be found" << std::endl;
abort();
}
m_activeShader = &result->second;
glUseProgram(m_activeShader->programId);
}
void ShaderManager::SetUniform1i(const char* uniformName, int value)
{
GLuint uniformLocation = GetUniformLocation(uniformName);
glUniform1i(uniformLocation, value);
}
void ShaderManager::SetUniform1f(const char* uniformName, float value)
{
GLuint uniformLocation = GetUniformLocation(uniformName);
glUniform1f(uniformLocation, value);
}
void ShaderManager::SetUniform3f(const char* uniformName, glm::vec3 const& value)
{
GLuint uniformLocation = GetUniformLocation(uniformName);
glUniform3fv(uniformLocation, 1, &value[0]);
}
void ShaderManager::SetUniformMatrix(const char* uniformName, glm::mat4 const& value)
{
GLuint uniformLocation = GetUniformLocation(uniformName);
glUniformMatrix4fv(uniformLocation, 1, GL_FALSE, &value[0][0]);
}
void ShaderManager::Recompile()
{
// Recompile shaders to allow editing
glUseProgram(GL_NONE);
m_activeShader = nullptr;
for (auto& entry : m_shaderPrograms)
{
Shader& shader = entry.second;
glDeleteProgram(shader.programId);
shader.programId = compileShaderProgram(shader.vertexFile.c_str(), shader.fragmentFile.c_str());
}
}
GLuint ShaderManager::GetProgramID(std::string const& name)
{
auto result = m_shaderPrograms.find(name);
if (result == m_shaderPrograms.end())
{
std::cerr << "Shader \"" << name << "\" could not be found" << std::endl;
abort();
}
return result->second.programId;
}
GLuint ShaderManager::GetUniformLocation(std::string const& uniformName)
{
// Lookup uniform locations from a hashed map.
// If not found, try to add them and raise an error if the uniform doesn't exist
auto result = m_activeShader->uniformLocations.find(uniformName);
if (result == m_activeShader->uniformLocations.end())
{
GLuint uniformLocation = glGetUniformLocation(m_activeShader->programId, uniformName.c_str());
if (uniformLocation == -1)
{
std::cerr << "Uniform \"" << uniformName << "\" does not exist in " << m_activeShader->name << std::endl;
abort();
}
m_activeShader->uniformLocations.emplace(uniformName, uniformLocation);
return uniformLocation;
}
return result->second;
}