115 lines
2.5 KiB
C++
115 lines
2.5 KiB
C++
|
#include "Shader.hpp"
|
||
|
|
||
|
namespace d2
|
||
|
{
|
||
|
/*explicit*/ Shader::Shader()
|
||
|
{
|
||
|
m_program = glCreateProgram();
|
||
|
|
||
|
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);
|
||
|
|
||
|
std::stringstream ss;
|
||
|
ss << "Cannot compile shader '"
|
||
|
<< source_path.string() << "'" << std::endl;
|
||
|
|
||
|
ss << msg << std::endl;
|
||
|
|
||
|
throw shader_error {ss.str()};
|
||
|
}
|
||
|
|
||
|
glAttachShader(m_program, shader);
|
||
|
|
||
|
return shader;
|
||
|
}
|
||
|
}
|