duck2d/src/Shader.cpp

115 lines
2.5 KiB
C++
Raw Normal View History

2023-10-29 17:37:22 +00:00
#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;
}
}