91 lines
2.0 KiB
C++
Executable File
91 lines
2.0 KiB
C++
Executable File
|
|
#include "opengl/data/shader_program_data.hpp"
|
|
|
|
#include <fstream>
|
|
#include "GL/glew.h"
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
#include "util/for_each.hpp"
|
|
#include "util/logger.hpp"
|
|
#include "opengl/error.hpp"
|
|
|
|
namespace zgl
|
|
{
|
|
|
|
std::error_code shader_program_data::build_from(
|
|
const shader_handle& vertex_shader,
|
|
const shader_handle& geometry_shader,
|
|
const shader_handle& fragment_shader,
|
|
shader_program_data& data
|
|
) {
|
|
auto error = std::error_code{};
|
|
|
|
auto check_error = [&error, ec = static_cast<GLenum>(GL_NO_ERROR)]() mutable -> std::error_code&
|
|
{
|
|
ec = glGetError();
|
|
if (ec != GL_NO_ERROR) {
|
|
error = make_error_code(ec);
|
|
}
|
|
return error;
|
|
};
|
|
|
|
const auto program_id = glCreateProgram();
|
|
if (check_error()) return error;
|
|
|
|
using namespace std::string_view_literals;
|
|
|
|
constexpr auto shader_names = std::array{
|
|
"vertex"sv, "geometry"sv, "fragment"sv
|
|
};
|
|
|
|
for (const auto& [shader, name] : {
|
|
std::tie(vertex_shader, shader_names[0]),
|
|
std::tie(geometry_shader, shader_names[1]),
|
|
std::tie(fragment_shader, shader_names[2])
|
|
}) {
|
|
if (shader.shader_id) {
|
|
glAttachShader(program_id, shader.shader_id);
|
|
} else {
|
|
ztu::logger::warn("Using default % shader", name);
|
|
}
|
|
}
|
|
|
|
glLinkProgram(program_id);
|
|
if (check_error()) return error;
|
|
|
|
auto status = GLint{ GL_FALSE };
|
|
glGetProgramiv(program_id, GL_LINK_STATUS, &status);
|
|
if (check_error()) return error;
|
|
|
|
if (status == GL_FALSE) {
|
|
GLint log_length{};
|
|
glGetShaderiv(program_id, GL_INFO_LOG_LENGTH, &log_length);
|
|
|
|
auto log = std::string(log_length, ' ');
|
|
glGetProgramInfoLog(program_id, log_length, nullptr, log.data());
|
|
|
|
ztu::logger::warn("Error while linking program: [%] %", log_length, log);
|
|
|
|
return std::make_error_code(std::errc::io_error);
|
|
}
|
|
|
|
|
|
glUseProgram(0);
|
|
|
|
ztu::for_each::argument(
|
|
[&](const auto& shader)
|
|
{
|
|
if (shader.shader_id) {
|
|
glDetachShader(program_id, shader.shader_id);
|
|
}
|
|
return true;
|
|
},
|
|
vertex_shader, geometry_shader, fragment_shader
|
|
);
|
|
|
|
data = shader_program_data{ program_id };
|
|
|
|
return {};
|
|
}
|
|
}
|