92 lines
2.5 KiB
C++
92 lines
2.5 KiB
C++
#include "graphics/opengl/shader.hpp"
|
|
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
using namespace kuiper::gl;
|
|
|
|
shader::s_ptr shader::make(shader_type type) noexcept {
|
|
|
|
GLenum gl_type = 0;
|
|
switch (type) {
|
|
case shader_type::vertex:
|
|
gl_type = GL_VERTEX_SHADER;
|
|
break;
|
|
case shader_type::fragment:
|
|
gl_type = GL_FRAGMENT_SHADER;
|
|
break;
|
|
case shader_type::compute:
|
|
gl_type = GL_COMPUTE_SHADER;
|
|
break;
|
|
default:
|
|
return nullptr;
|
|
}
|
|
|
|
GLuint name = glCreateShader(gl_type);
|
|
|
|
if (!name)
|
|
return nullptr;
|
|
|
|
return std::make_shared<shader>(name, gl_type);
|
|
}
|
|
|
|
shader::s_ptr shader::from_path(const std::filesystem::path& shader_path, shader_type type) noexcept {
|
|
if (shader_path.empty() || !std::filesystem::is_regular_file(shader_path) || !std::filesystem::exists(shader_path))
|
|
return nullptr;
|
|
|
|
const auto file_size = std::filesystem::file_size(shader_path);
|
|
std::vector<char> read_buf(file_size + 1); // +1 for NUL terminator
|
|
std::ifstream in_file(shader_path); // TODO: std::ios::ate & tellg() trick
|
|
|
|
if (!in_file.is_open())
|
|
return nullptr;
|
|
|
|
in_file.read(read_buf.data(), file_size);
|
|
|
|
std::string_view file_ext(shader_path.extension().c_str());
|
|
|
|
if (type == shader_type::none) {
|
|
if (file_ext.compare(".vs") == 0 || file_ext.compare(".vert") == 0) {
|
|
type = shader_type::vertex;
|
|
} else if (file_ext.compare(".fs") == 0 || file_ext.compare(".frag") == 0) {
|
|
type = shader_type::fragment;
|
|
} else if (file_ext.compare(".cs") == 0 || file_ext.compare(".comp") == 0) {
|
|
type = shader_type::compute;
|
|
}
|
|
}
|
|
|
|
return shader::from_source(read_buf.data(), type);
|
|
}
|
|
|
|
shader::s_ptr shader::from_source(std::string_view source, shader_type type) noexcept {
|
|
auto shader = shader::make(type);
|
|
shader->attach_source(source);
|
|
shader->compile();
|
|
|
|
return shader;
|
|
}
|
|
|
|
void shader::destroy() noexcept {
|
|
if (m_id) {
|
|
glDeleteShader(m_id);
|
|
m_id = 0;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void shader::attach_source(std::string_view source) noexcept {
|
|
const GLint n_shader_sources = 1;
|
|
const char* const s = source.data();
|
|
const GLint s_len = static_cast<GLint>(source.size());
|
|
|
|
return glShaderSource(m_id, n_shader_sources, &s, &s_len);
|
|
}
|
|
|
|
void shader::compile() noexcept {
|
|
|
|
return glCompileShader(m_id);
|
|
}
|