Zen 0.3.0
Loading...
Searching...
No Matches
ZEN_Shader.cpp
1#include <glm/gtc/type_ptr.hpp>
2#include <zen/renderer/ZEN_Shader.h>
3
4namespace Zen {
5 Shader::Shader(const char *vertexPath, const char *fragmentPath) {
6 // Read our shaders into the appropriate buffers
7 // Create an empty vertex shader handle
8 // 1. retrieve the vertex/fragment source code from filePath
9 std::string vertexCode;
10 std::string fragmentCode;
11 std::ifstream vShaderFile;
12 std::ifstream fShaderFile;
13 // ensure ifstream objects can throw exceptions:
14 vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
15 fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
16 try {
17 // open files
18 vShaderFile.open(vertexPath);
19 fShaderFile.open(fragmentPath);
20 std::stringstream vShaderStream, fShaderStream;
21 // read file's buffer contents into streams
22 vShaderStream << vShaderFile.rdbuf();
23 fShaderStream << fShaderFile.rdbuf();
24 // close file handlers
25 vShaderFile.close();
26 fShaderFile.close();
27 // convert stream into string
28 vertexCode = vShaderStream.str();
29 fragmentCode = fShaderStream.str();
30
31 // ZEN_LOG_DEBUG("{}", vertexCode);
32 // ZEN_LOG_DEBUG("{}", fragmentCode);
33 // ZEN_LOG_DEBUG("{}", vertexPath);
34 // ZEN_LOG_DEBUG("{}", fragmentPath);
35 } catch (std::ifstream::failure e) {
36 ZEN_LOG_ERROR("ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ");
37 throw std::runtime_error("shader file read failed");
38 }
39 const char *vShaderCode = vertexCode.c_str();
40 const char *fShaderCode = fragmentCode.c_str();
41
42 uint32_t vertexShader, fragmentShader;
43
44 vertexShader = glCreateShader(GL_VERTEX_SHADER);
45 glShaderSource(vertexShader, 1, &vShaderCode, nullptr);
46
47 // Compile the vertex shader
48 glCompileShader(vertexShader);
49
50 GLint isCompiled = 0;
51 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
52 if (isCompiled == GL_FALSE) {
53 GLint maxLength = 0;
54 glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
55
56 // The maxLength includes the NULL character
57 std::vector<GLchar> infoLog(maxLength);
58 glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);
59
60 // We don't need the shader anymore.
61 glDeleteShader(vertexShader);
62
63 ZEN_LOG_ERROR("{}", infoLog.data());
64 return;
65 }
66
67 // Create an empty fragment shader handle
68 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
69 glShaderSource(fragmentShader, 1, &fShaderCode, nullptr);
70
71 // Compile the fragment shader
72 glCompileShader(fragmentShader);
73
74 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);
75 if (isCompiled == GL_FALSE) {
76 GLint maxLength = 0;
77 glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
78
79 // The maxLength includes the NULL character
80 std::vector<GLchar> infoLog(maxLength);
81 glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);
82
83 // We don't need the shader anymore.
84 glDeleteShader(fragmentShader);
85 // Either of them. Don't leak shaders.
86 glDeleteShader(vertexShader);
87
88 // Use the infoLog as you see fit.
89
90 // In this simple program, we'll just leave
91 ZEN_LOG_ERROR("{}", infoLog.data());
92 return;
93 }
94
95 // Vertex and fragment shaders are successfully compiled.
96 // Now time to link them together into a program.
97 // Get a program object.
98 m_rendererID = glCreateProgram();
99 GLuint program = m_rendererID;
100
101 // Attach our shaders to our program
102 glAttachShader(program, vertexShader);
103 glAttachShader(program, fragmentShader);
104
105 // Link our program
106 glLinkProgram(program);
107
108 // Note the different functions here: glGetProgram* instead of glGetShader*.
109 GLint isLinked = 0;
110 glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
111 if (isLinked == GL_FALSE) {
112 GLint maxLength = 0;
113 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
114
115 // The maxLength includes the NULL character
116 std::vector<GLchar> infoLog(maxLength);
117 glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
118
119 // We don't need the program anymore.
120 glDeleteProgram(program);
121 // Don't leak shaders either.
122 glDeleteShader(vertexShader);
123 glDeleteShader(fragmentShader);
124
125 // Use the infoLog as you see fit.
126
127 // In this simple program, we'll just leave
128 ZEN_LOG_ERROR("{}", infoLog.data());
129 return;
130 }
131
132 // Always detach shaders after a successful link.
133 glDetachShader(program, vertexShader);
134 glDetachShader(program, fragmentShader);
135 }
136
137 Shader::~Shader() {
138 ZEN_LOG_DEBUG("Shader deconstructed");
139 glDeleteProgram(m_rendererID);
140 }
141
142 void Shader::bind() const {
143 // ZEN_LOG_DEBUG("Shader binded");
144 glUseProgram(m_rendererID);
145 }
146
147 void Shader::unBind() const {
148 ZEN_LOG_DEBUG("Shader unbinded");
149 glUseProgram(0);
150 }
151
152 void Shader::uploadUniformMat4(const std::string &name, const glm::mat4 &matrix) {
153 GLint location = glGetUniformLocation(m_rendererID, name.c_str());
154 glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
155 }
156}; // namespace Zen