-
Notifications
You must be signed in to change notification settings - Fork 0
/
Shader.cpp
143 lines (134 loc) · 4.07 KB
/
Shader.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
#include "Shader.h"
void Shader::unload() noexcept {
if (this->shaderID_ != 0) {
glDeleteShader(shaderID_);
shaderID_ = 0;
}
}
bool Shader::compile(std::string shaderSource) {
// assign shader source code
const char* shaderSourceCstring = shaderSource.c_str();
int shaderLength = static_cast<int>(shaderSource.length());
glShaderSource(shaderID_, 1, &shaderSourceCstring, &shaderLength);
// compile shader
glCompileShader(shaderID_);
// check for compilation errors
GLint is_compiled;
glGetShaderiv(shaderID_, GL_COMPILE_STATUS, &is_compiled);
if(is_compiled != GL_TRUE) return false;
else return true;
}
std::string Shader::readFile(const std::string& filepath) {
std::ifstream file(filepath.c_str(), std::ifstream::in);
if (!file) {
throw std::runtime_error("Program exits because reading shader file failed.");
}
std::string line;
std::stringstream content;
while (file.good()) {
std::getline(file, line);
content << line << std::endl;
}
file.close();
return content.str();
}
void Shader::printLog(std::string path, std::string shaderSource) {
GLsizei log_length = 0;
GLchar message[1024];
glGetShaderInfoLog(shaderID_, 1024, &log_length, message);
printf("\nSHADER INFO LOG\n===============\n");
printf("%s\n", path.c_str());
printf("%s", message);
std::string str(message);
std::size_t pos_colon1 = str.find(":");
std::string str2 = str.substr(pos_colon1+2);
std::size_t pos_colon2 = str2.find(":");
std::string col_num_str = str2.substr(0,pos_colon2);
std::string str3 = str2.substr(pos_colon2+1);
std::size_t pos_colon3 = str3.find(":");
std::string row_num_str = str3.substr(0,pos_colon3);
int col_num = atoi(col_num_str.c_str());
int row_num = atoi(row_num_str.c_str());
int row_cnt = 0;
for(unsigned int i = 0; i < shaderSource.length(); i++) {
if(i==0) printf("|%*d | ", 3, 1);
if(shaderSource[i]=='\n') row_cnt++;
printf("%c", shaderSource[i]); // print source code character
if(shaderSource[i]=='\n') {
if(row_cnt==row_num) {
printf("|%*s | ", 3, " ");
for(int j = 0; j < col_num; j++) printf("-");
if(col_num!=0) printf("^");
printf("\n");
}
if(row_cnt==row_num-1) {
printf("|%*s |\n|%*d!| ", 3, " ", 3, row_cnt+1);
} else {
printf("|%*d | ", 3, row_cnt+1);
}
}
}
printf("\n\n");
glDeleteShader(shaderID_);
throw std::runtime_error("Program exits because shader compilation failed.");
}
//public:
Shader::Shader(const std::string& name, GLenum type) {
type_ = type;
filepath_ = config::shader_dir+name;
shaderID_ = 0;
shaderID_ = glCreateShader(type);
if (shaderID_ == 0) {
throw std::runtime_error("Program exits because OpenGL failed to create shader.");
} else {
std::string source = readFile(filepath_);
bool success = compile(source);
if(!success) printLog(filepath_, source);
}
}
Shader::Shader(std::initializer_list<std::string> source_lines, GLenum type) {
type_= type;
shaderID_ = 0;
shaderID_ = glCreateShader(type);
if(shaderID_ == 0) {
throw std::runtime_error("Program exits because OpenGL failed to create shader.");
} else {
std::string source;
for(std::string line : source_lines) {
source += line + '\n';
}
bool success = compile(source);
if(!success) printLog("", source);
}
}
Shader::~Shader() {
unload();
}
GLuint Shader::link(std::initializer_list<Shader> shaders) {
// create gpu program
GLuint program = glCreateProgram();
if (program == 0) {
throw std::runtime_error("Program exits because OpenGL failed to create GPU program.");
}
// attach the shaders
for(Shader s : shaders) {
glAttachShader(program, s.opengl_id());
}
// link
glLinkProgram(program);
// check for linking errors
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
for(Shader s : shaders) {
glDetachShader(program, s.opengl_id());
}
glDeleteProgram(program);
// further information possible via glGetShaderInfoLog
throw std::runtime_error("Program exits because shaders linking failed."); // exit
}
for(Shader s : shaders) {
//glDetachShader(program, s.opengl_id()); // TODO OpenGL Error 1281 Invalid Value why?
}
return program;
}