2023-10-29 17:37:22 +00:00
|
|
|
#include "Shader.hpp"
|
|
|
|
|
|
|
|
namespace d2
|
|
|
|
{
|
|
|
|
/*explicit*/ Shader::Shader()
|
|
|
|
{
|
|
|
|
load_shader(GL_VERTEX_SHADER,
|
|
|
|
DUCK_ASSETS / "shaders" / "vertex.glsl");
|
|
|
|
|
|
|
|
load_shader(GL_FRAGMENT_SHADER,
|
|
|
|
DUCK_ASSETS / "shaders" / "fragment.glsl");
|
|
|
|
|
|
|
|
glLinkProgram(m_program);
|
|
|
|
|
|
|
|
GLint status = GL_FALSE;
|
|
|
|
glGetProgramiv(m_program, GL_LINK_STATUS, &status);
|
|
|
|
|
|
|
|
if (status == GL_FALSE)
|
|
|
|
{
|
|
|
|
size_t const SZ = 1024;
|
|
|
|
char msg[SZ];
|
|
|
|
glGetProgramInfoLog(m_program, SZ, nullptr, msg);
|
|
|
|
throw shader_error {"Cannot link program."};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*virtual*/ Shader::~Shader()
|
|
|
|
{
|
|
|
|
glDeleteProgram(m_program);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Shader::use() const
|
|
|
|
{
|
|
|
|
glUseProgram(m_program);
|
|
|
|
}
|
|
|
|
|
|
|
|
GLint Shader::attr(std::string const& name) const
|
|
|
|
{
|
|
|
|
use();
|
|
|
|
return glGetAttribLocation(m_program, name.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
GLint Shader::uniform(std::string const& name) const
|
|
|
|
{
|
|
|
|
use();
|
|
|
|
return glGetUniformLocation(m_program, name.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Shader::set_matrix(std::string const& name, glm::mat4 matrix) const
|
|
|
|
{
|
|
|
|
use();
|
|
|
|
glUniformMatrix4fv(uniform(name), 1, false, glm::value_ptr(matrix));
|
|
|
|
}
|
|
|
|
|
|
|
|
GLuint Shader::load_shader(GLenum type,
|
|
|
|
std::filesystem::path source_path)
|
|
|
|
{
|
|
|
|
// Load source
|
|
|
|
// -----------
|
|
|
|
if (!std::filesystem::is_regular_file(source_path))
|
|
|
|
{
|
|
|
|
throw shader_error {"Cannot find shader '"
|
|
|
|
+ source_path.string() + "'."};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::stringstream ss;
|
|
|
|
std::ifstream file { source_path };
|
|
|
|
|
|
|
|
if (!file)
|
|
|
|
{
|
|
|
|
throw shader_error {"Cannot open shader '"
|
|
|
|
+ source_path.string()
|
|
|
|
+ "'"};
|
|
|
|
}
|
|
|
|
|
|
|
|
ss << file.rdbuf();
|
|
|
|
|
|
|
|
// Compile source
|
|
|
|
// --------------
|
|
|
|
std::string source = ss.str();
|
|
|
|
char const* c_source[] = {source.c_str()};
|
|
|
|
|
|
|
|
GLuint shader = glCreateShader(type);
|
|
|
|
glShaderSource(shader, 1, c_source, nullptr);
|
|
|
|
|
|
|
|
glCompileShader(shader);
|
|
|
|
|
|
|
|
// check compilation status
|
|
|
|
// ------------------------
|
|
|
|
GLint status = GL_FALSE;
|
|
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
|
|
|
|
|
|
|
if (status == GL_FALSE)
|
|
|
|
{
|
|
|
|
size_t const SZ = 1024;
|
|
|
|
char msg[SZ];
|
|
|
|
glGetShaderInfoLog(shader, SZ, nullptr, msg);
|
|
|
|
|
2023-10-29 20:19:09 +00:00
|
|
|
std::stringstream ss2;
|
|
|
|
ss2 << "Cannot compile shader '"
|
2023-10-29 17:37:22 +00:00
|
|
|
<< source_path.string() << "'" << std::endl;
|
|
|
|
|
2023-10-29 20:19:09 +00:00
|
|
|
ss2 << msg << std::endl;
|
2023-10-29 17:37:22 +00:00
|
|
|
|
2023-10-29 20:19:09 +00:00
|
|
|
throw shader_error {ss2.str()};
|
2023-10-29 17:37:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
glAttachShader(m_program, shader);
|
|
|
|
|
|
|
|
return shader;
|
|
|
|
}
|
|
|
|
}
|