Vivid
Loading...
Searching...
No Matches
Shader.cpp
1#include "Shader.h"
2#include "Renderer.h"
3#include "common/maths/Vec.h"
4
5#include <fstream>
6#include <iostream>
7#include <sstream>
8#include <string>
9
10namespace Vivid
11{
12 Shader::Shader(const String& filepathVertexShader, const String& filepathPixelShader)
13 : m_FilePathVS(filepathVertexShader)
14 , m_FilePathPS(filepathPixelShader)
15 , m_RendererID(0)
16 {
17 ShaderProgramSource source = parseShader(filepathVertexShader, filepathPixelShader);
18
19 m_RendererID = createShader(source.VertexSource, source.PixelSource);
20
21 GLCall(glUseProgram(m_RendererID));
22
23 if (m_RendererID == -1)
24 {
25 ERROR("Shader creation failed");
26 }
27 }
28
29 Shader::~Shader()
30 {
31 GLCall(glDeleteProgram(m_RendererID));
32 }
33
34 void Shader::Bind() const
35 {
36 GLCall(glUseProgram(m_RendererID));
37 }
38
39 void Shader::Unbind() const
40 {
41 GLCall(glUseProgram(0));
42 }
43
44 int Shader::getUniformLocation(const std::string& name)
45 {
46 if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
47 return m_UniformLocationCache[name];
48
49 GLCall(int location = glGetUniformLocation(m_RendererID, name.c_str()));
50 if (location == -1)
51 std::cout << "No active uniform variable with name " << name << " found" << std::endl;
52
53 m_UniformLocationCache[name] = location;
54
55 return location;
56 }
57
58 void Shader::SetUniform1i(const std::string& name, int value)
59 {
60 GLCall(glUniform1i(getUniformLocation(name), value));
61 }
62
63 void Shader::SetUniform1f(const std::string& name, float value)
64 {
65 GLCall(glUniform1f(getUniformLocation(name), value));
66 }
67
68 void Shader::SetUniform3f(const std::string& name, Maths::Vec3& value)
69 {
70 GLCall(glUniform3f(getUniformLocation(name), (GLfloat)value.x, (GLfloat)value.y, (GLfloat)value.z));
71 }
72
73 void Shader::SetUniform4f(const std::string& name, float f0, float f1, float f2, float f3)
74 {
75 GLCall(glUniform4f(getUniformLocation(name), f0, f1, f2, f3));
76 }
77
78 void Shader::SetUniform4f(const std::string& name, const glm::vec4& matrix)
79 {
80 GLCall(glUniform4f(getUniformLocation(name), matrix.x, matrix.y, matrix.z, matrix.w));
81 }
82
83 void Shader::SetUniformMat4f(const std::string& name, const glm::mat4& matrix)
84 {
85 GLCall(glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, &matrix[0][0]));
86 }
87
88 enum ShaderType
89 {
90 NONE = -1,
91 VERTEX = 0,
92 PIXEL = 1
93 };
94
95 struct ShaderProgramSource
96 Shader::parseShader(const std::string& filepathVertexShader, const std::string& filepathPixelShader)
97 {
98 std::ifstream streamVS(filepathVertexShader);
99 std::ifstream streamPS(filepathPixelShader);
100 std::string line;
101 std::stringstream ss[2];
102 ShaderType type = NONE;
103
104 while (getline(streamVS, line))
105 {
106 ss[VERTEX] << line << '\n';
107 }
108 while (getline(streamPS, line))
109 {
110 ss[PIXEL] << line << '\n';
111 }
112
113 return { ss[0].str(), ss[1].str() };
114 }
115
116 unsigned int Shader::compileShader(unsigned int type, const std::string& source)
117 {
118 GLCall(unsigned int id = glCreateShader(type));
119 const char* src = source.c_str();
120 GLCall(glShaderSource(id, 1, &src, nullptr));
121 GLCall(glCompileShader(id));
122
123 // Error handling
124 int result;
125 GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
126 std::cout << (type == GL_VERTEX_SHADER ? "vertex" : "pixel") << " shader compile status: " << result
127 << std::endl;
128 if (result == GL_FALSE)
129 {
130 int length;
131 GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
132 char* message = (char*)alloca(length * sizeof(char));
133 GLCall(glGetShaderInfoLog(id, length, &length, message));
134 std::cout
135 << "Failed to compile "
136 << (type == GL_VERTEX_SHADER ? "vertex" : "pixel")
137 << "shader"
138 << std::endl;
139 std::cout << message << std::endl;
140 GLCall(glDeleteShader(id));
141 return 0;
142 }
143
144 return id;
145 }
146
147 unsigned int Shader::createShader(const std::string& vertexShader, const std::string& pixelShader)
148 {
149 unsigned int program = glCreateProgram();
150 unsigned int vs = compileShader(GL_VERTEX_SHADER, vertexShader);
151 unsigned int ps = compileShader(GL_FRAGMENT_SHADER, pixelShader);
152
153 if (vs == 0 || ps == 0)
154 {
155 return -1;
156 }
157
158 GLCall(glAttachShader(program, vs));
159 GLCall(glAttachShader(program, ps));
160
161 GLCall(glLinkProgram(program));
162
163 GLint program_linked;
164
165 GLCall(glGetProgramiv(program, GL_LINK_STATUS, &program_linked));
166 std::cout << "Program link status: " << program_linked << std::endl;
167 if (program_linked != GL_TRUE)
168 {
169 GLsizei log_length = 0;
170 GLchar message[1024];
171 GLCall(glGetProgramInfoLog(program, 1024, &log_length, message));
172 std::cout << "Failed to link program" << std::endl;
173 std::cout << message << std::endl;
174 return -1;
175 }
176
177 GLCall(glValidateProgram(program));
178
179 GLCall(glDeleteShader(vs));
180 GLCall(glDeleteShader(ps));
181
182 return program;
183 }
184
185 Ref<Shader> Shader::Create(const std::string& filepathVertexShader, const std::string& filepathPixelShader)
186 {
187 return MakeRef<Shader>(filepathVertexShader, filepathPixelShader);
188 }
189}