-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShader.cpp
135 lines (121 loc) · 4.28 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
#include <fstream>
#include <iostream>
#include <sstream>
#include <glm/gtc/type_ptr.hpp>
#include "Shader.h"
Shader::Shader() {
handle = 0;
isLinked = false;
}
bool Shader::compileAndLink(const std::string &vertexShaderPath, const std::string &fragmentShaderPath) {
unsigned int vertexShader = 0;
unsigned int fragmentShader = 0;
if (!compileShader(vertexShaderPath, GL_VERTEX_SHADER, vertexShader)) {
return false;
}
if (!compileShader(fragmentShaderPath, GL_FRAGMENT_SHADER, fragmentShader)) {
return false;
}
handle = glCreateProgram();
glAttachShader(handle, vertexShader);
glAttachShader(handle, fragmentShader);
glBindFragDataLocation(handle, 0, "fragmentColor");
glLinkProgram(handle);
int status = 0;
glGetProgramiv(handle, GL_LINK_STATUS, &status);
isLinked = status != GL_FALSE;
if (!isLinked) {
std::cout << "Error: linking of shader program failed." << std::endl;
int infoLogLength = 0;
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
std::string infoLog(infoLogLength, ' ');
glGetProgramInfoLog(handle, infoLogLength, nullptr, &infoLog[0]);
std::cout << infoLog << std::endl;
}
}
glDetachShader(handle, vertexShader);
glDetachShader(handle, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
if (!isLinked) {
destroy();
}
return isLinked;
}
void Shader::use() const {
glUseProgram(handle);
}
void Shader::setInteger(const std::string &name, int value) const {
int location = glGetUniformLocation(handle, name.c_str());
glUniform1i(location, value);
}
void Shader::setFloat(const std::string &name, float value) const {
int location = glGetUniformLocation(handle, name.c_str());
glUniform1f(location, value);
}
void Shader::setVector3(const std::string &name, const glm::vec3 &vector) const {
int location = glGetUniformLocation(handle, name.c_str());
glUniform3fv(location, 1, glm::value_ptr(vector));
}
void Shader::setMatrix3(const std::string &name, const glm::mat3 &matrix) const {
int location = glGetUniformLocation(handle, name.c_str());
glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
}
void Shader::setMatrix4(const std::string &name, const glm::mat4 &matrix) const {
int location = glGetUniformLocation(handle, name.c_str());
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
}
void Shader::dispose() {
if (isLinked) {
destroy();
}
}
bool Shader::readFile(const std::string &shaderPath, std::string &shaderCode) {
std::ifstream shaderFile;
shaderFile.exceptions(std::ios::badbit | std::ios::failbit);
try {
shaderFile.open(shaderPath);
std::stringstream shaderStream;
shaderStream << shaderFile.rdbuf();
shaderFile.close();
shaderCode = shaderStream.str();
return true;
} catch (const std::ifstream::failure &failure) {
std::cout << "Error: unable to read shader file \"" << shaderPath << "\".\n" << failure.what() << std::endl;
}
return false;
}
bool Shader::compileShader(const std::string &shaderPath, GLenum shaderType, unsigned int &shader) {
std::string shaderCode;
if (!readFile(shaderPath, shaderCode)) {
return false;
}
const char *shaderSource = shaderCode.c_str();
int length = (int) shaderCode.length();
shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &shaderSource, &length);
glCompileShader(shader);
int status = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status) {
std::cout << "Error: compilation of shader \"" << shaderPath << "\" failed." << std::endl;
int infoLogLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
std::string infoLog(infoLogLength, ' ');
glGetShaderInfoLog(shader, infoLogLength, nullptr, &infoLog[0]);
std::cout << infoLog << std::endl;
}
glDeleteShader(shader);
shader = 0;
return false;
}
return true;
}
void Shader::destroy() {
glUseProgram(0);
glDeleteProgram(handle);
handle = 0;
isLinked = false;
}