3#include "common/maths/Vec.h"
12 Shader::Shader(
const String& filepathVertexShader,
const String& filepathPixelShader)
13 : m_FilePathVS(filepathVertexShader)
14 , m_FilePathPS(filepathPixelShader)
17 ShaderProgramSource source = parseShader(filepathVertexShader, filepathPixelShader);
19 m_RendererID = createShader(source.VertexSource, source.PixelSource);
21 GLCall(glUseProgram(m_RendererID));
23 if (m_RendererID == -1)
25 ERROR(
"Shader creation failed");
31 GLCall(glDeleteProgram(m_RendererID));
34 void Shader::Bind()
const
36 GLCall(glUseProgram(m_RendererID));
39 void Shader::Unbind()
const
41 GLCall(glUseProgram(0));
44 int Shader::getUniformLocation(
const std::string& name)
46 if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
47 return m_UniformLocationCache[name];
49 GLCall(
int location = glGetUniformLocation(m_RendererID, name.c_str()));
51 std::cout <<
"No active uniform variable with name " << name <<
" found" << std::endl;
53 m_UniformLocationCache[name] = location;
58 void Shader::SetUniform1i(
const std::string& name,
int value)
60 GLCall(glUniform1i(getUniformLocation(name), value));
63 void Shader::SetUniform1f(
const std::string& name,
float value)
65 GLCall(glUniform1f(getUniformLocation(name), value));
68 void Shader::SetUniform3f(
const std::string& name, Maths::Vec3& value)
70 GLCall(glUniform3f(getUniformLocation(name), (GLfloat)value.x, (GLfloat)value.y, (GLfloat)value.z));
73 void Shader::SetUniform4f(
const std::string& name,
float f0,
float f1,
float f2,
float f3)
75 GLCall(glUniform4f(getUniformLocation(name), f0, f1, f2, f3));
78 void Shader::SetUniform4f(
const std::string& name,
const glm::vec4& matrix)
80 GLCall(glUniform4f(getUniformLocation(name), matrix.x, matrix.y, matrix.z, matrix.w));
83 void Shader::SetUniformMat4f(
const std::string& name,
const glm::mat4& matrix)
85 GLCall(glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, &matrix[0][0]));
95 struct ShaderProgramSource
96 Shader::parseShader(const std::string& filepathVertexShader, const std::string& filepathPixelShader)
98 std::ifstream streamVS(filepathVertexShader);
99 std::ifstream streamPS(filepathPixelShader);
101 std::stringstream ss[2];
102 ShaderType type = NONE;
104 while (getline(streamVS, line))
106 ss[VERTEX] << line <<
'\n';
108 while (getline(streamPS, line))
110 ss[PIXEL] << line <<
'\n';
113 return { ss[0].str(), ss[1].str() };
116 unsigned int Shader::compileShader(
unsigned int type,
const std::string& source)
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));
125 GLCall(glGetShaderiv(
id, GL_COMPILE_STATUS, &result));
126 std::cout << (type == GL_VERTEX_SHADER ?
"vertex" :
"pixel") <<
" shader compile status: " << result
128 if (result == GL_FALSE)
131 GLCall(glGetShaderiv(
id, GL_INFO_LOG_LENGTH, &length));
132 char* message = (
char*)alloca(length *
sizeof(
char));
133 GLCall(glGetShaderInfoLog(
id, length, &length, message));
135 <<
"Failed to compile "
136 << (type == GL_VERTEX_SHADER ?
"vertex" :
"pixel")
139 std::cout << message << std::endl;
140 GLCall(glDeleteShader(
id));
147 unsigned int Shader::createShader(
const std::string& vertexShader,
const std::string& pixelShader)
149 unsigned int program = glCreateProgram();
150 unsigned int vs = compileShader(GL_VERTEX_SHADER, vertexShader);
151 unsigned int ps = compileShader(GL_FRAGMENT_SHADER, pixelShader);
153 if (vs == 0 || ps == 0)
158 GLCall(glAttachShader(program, vs));
159 GLCall(glAttachShader(program, ps));
161 GLCall(glLinkProgram(program));
163 GLint program_linked;
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)
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;
177 GLCall(glValidateProgram(program));
179 GLCall(glDeleteShader(vs));
180 GLCall(glDeleteShader(ps));
185 Ref<Shader> Shader::Create(
const std::string& filepathVertexShader,
const std::string& filepathPixelShader)
187 return MakeRef<Shader>(filepathVertexShader, filepathPixelShader);