-
Notifications
You must be signed in to change notification settings - Fork 0
/
GLSH_Shaders.cpp
133 lines (108 loc) · 3.67 KB
/
GLSH_Shaders.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
#include "GLSH_Shaders.h"
#include "GLSH_Util.h"
#include <iostream>
#include <map>
#include <set>
namespace glsh {
GLuint CompileShader(GLenum shaderType, const std::string& path)
{
// load shader source code from a text file
std::string source = glsh::ReadTextFile(path);
// create shader object of the appropriate type
GLuint so = glCreateShader(shaderType);
if (!so) {
std::cerr << "*** Poop: Failed to create shader object" << std::endl;
return GL_NONE;
}
// attach shader source code
const char* cSource = source.c_str();
glShaderSource(so, 1, &cSource, NULL);
// compile the shader
glCompileShader(so);
// check result of compilation
GLint result;
glGetShaderiv(so, GL_COMPILE_STATUS, &result);
if (!result) {
std::cerr << "*** Poop: failed to compile shader " << path << ":\n";
GLint infoLogLength = 0;
glGetShaderiv(so, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
char* infoLog = new char[infoLogLength];
glGetShaderInfoLog(so, infoLogLength, NULL, infoLog);
std::cerr << infoLog << std::endl;
delete [] infoLog;
}
return GL_NONE;
}
// return shader object id
return so;
}
GLuint BuildShaderProgram(const std::string& vsPath, const std::string& fsPath)
{
// load and compile vertex shader
GLuint vs = CompileVertexShader(vsPath);
if (!vs)
return GL_NONE;
// load and compile fragment shader
GLuint fs = CompileFragmentShader(fsPath);
if (!fs) {
glDeleteShader(vs); // cleanup
return GL_NONE;
}
// create shader program object
GLuint prog = glCreateProgram();
if (!prog) {
std::cerr << "*** Poop: Failed to create program object" << std::endl;
glDeleteShader(vs);
glDeleteShader(fs);
return GL_NONE;
}
// attach vertex and fragment shaders to the program object
glAttachShader(prog, vs);
glAttachShader(prog, fs);
// link program
glLinkProgram(prog);
// shader objects no longer needed once program is linked
glDeleteShader(vs);
glDeleteShader(fs);
// check link status
GLint linkStatus;
glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus);
if (!linkStatus) {
std::cerr << "*** Poop: Failed to vertex shader " << vsPath << " with fragment shader " << fsPath << std::endl;
glDeleteProgram(prog);
return GL_NONE;
}
// check for GL errors
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
std::cout << "*** Poop: GL Error in function " __FUNCTION__ " on line " << __LINE__ << ": " << gluErrorString(err) << std::endl;
glDeleteProgram(prog);
return GL_NONE;
}
// return program id
return prog;
}
GLint GetActiveShaderUniformLocation(const std::string& name)
{
// first, get the currently active program id
GLint prog = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, &prog);
if (!prog) {
std::cerr << "*** Can't get shader uniform location - no active program" << std::endl;
return -1;
}
// next, get the location of the named uniform in the currently active program
GLint loc = glGetUniformLocation(prog, name.c_str());
if (loc < 0) {
// only report missing name errors once
static std::map<GLint, std::set<std::string>> missingUniforms;
if (missingUniforms[prog].find(name) == missingUniforms[prog].end()) {
std::cerr << "*** Currently active program does not have a uniform named '" << name << "'" << std::endl;
missingUniforms[prog].insert(name);
}
return loc;
}
return loc;
}
}