-
Notifications
You must be signed in to change notification settings - Fork 0
/
shader.hpp
134 lines (101 loc) · 4.09 KB
/
shader.hpp
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
// VISIT THE FOLLOWING SITES FOR MORE INFORMATION ON...
// VAOs, VBOs, Vertex and Fragment Shaders: https://www.khronos.org/opengl/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_(C_/_SDL)
// ------------------------------------------------------------------------------------------------------------------------------------------------------
// Important reminder: The shader pipeline behaves as follows: Vertex Shaders -> Geometry Shaders -> (Rasterizing Engine) -> Fragment Shaders.
#pragma once
#include <string>
#include <GL/glew.h>
#include <fstream>
#include <iostream>
#include "transform.hpp"
#include "camera.hpp"
static std::string LoadShader(const std::string& fileName) {
std::ifstream file;
file.open((fileName).c_str());
std::string output;
std::string line;
if (file.is_open()) {
while(file.good()) {
getline(file, line);
output.append(line + "\n");
}
} else {
std::cerr << "Unable to load shader: " << fileName << std::endl;
}
return output;
}
void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage) {
GLint success = 0;
GLchar error[1024] = { 0 };
if(isProgram) {
glGetProgramiv(shader, flag, &success);
} else {
glGetShaderiv(shader, flag, &success);
}
if(success == GL_FALSE) {
if (isProgram) {
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
} else {
glGetShaderInfoLog(shader, sizeof(error), NULL, error);
}
std::cerr << errorMessage << ": '" << error << "'" << std::endl;
}
}
static GLuint CreateShader(const std::string& text, GLenum shaderType) {
GLuint shader = glCreateShader(shaderType);
if (shader == 0) {
std::cerr << "Error: Shader could not be created" << std::endl;
}
const GLchar* shaderSourceStrings[1];
GLint shaderSourceStringLenghts[1];
shaderSourceStrings[0] = text.c_str();
shaderSourceStringLenghts[0] = text.length();
glShaderSource(shader, 1, shaderSourceStrings, shaderSourceStringLenghts);
glCompileShader(shader);
CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed");
return shader;
}
class Shader {
public:
Shader(const std::string& fileName) {
m_program = glCreateProgram();
m_shaders[0] = CreateShader(LoadShader(fileName + ".vs"), GL_VERTEX_SHADER);
m_shaders[1] = CreateShader(LoadShader(fileName + ".fs"), GL_FRAGMENT_SHADER);
// Add shaders to the program
for(unsigned int i = 0; i < NUM_SHADERS; i++) {
glAttachShader(m_program, m_shaders[i]);
}
glBindAttribLocation(m_program, 0, "position");
glBindAttribLocation(m_program, 1, "textCoord");
glLinkProgram(m_program);
CheckShaderError(m_program, GL_LINK_STATUS, true, "Error: Shader program failed to link");
glValidateProgram(m_program);
CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Error: Shader program is invalid");
m_uniforms[TRANSFORM_U] = glGetUniformLocation(m_program, "transform");
}
void Bind() {
glUseProgram(m_program);
}
void Update(const Transform& transform, const Camera& camera) {
glm::mat4 model = camera.GetViewProjection() * transform.GetModel();
glUniformMatrix4fv(m_uniforms[TRANSFORM_U], 1, GL_FALSE, &model[0][0]);
}
virtual ~Shader() {
for(unsigned int i = 0; i < NUM_SHADERS; i++) {
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
private:
static const unsigned int NUM_SHADERS = 2;
Shader(const Shader& other) {}
void operator=(const Shader& other) {}
GLuint m_program;
GLuint m_shaders[NUM_SHADERS];
enum {
TRANSFORM_U,
NUM_UNIFORMS
};
GLuint m_uniforms[NUM_UNIFORMS];
};