fixes
This commit is contained in:
129
source/opengl/data/material_data.ipp
Normal file
129
source/opengl/data/material_data.ipp
Normal file
@@ -0,0 +1,129 @@
|
||||
#ifndef INCLUDE_MATERIAL_DATA_IMPLEMENTATION
|
||||
# error Never include this file directly include 'material_data.hpp'
|
||||
#endif
|
||||
|
||||
namespace zgl
|
||||
{
|
||||
inline material_data::material_data(
|
||||
const std::optional<texture_handle>& texture_handle,
|
||||
const std::optional<surface_properties_handle>& surface_properties_handle,
|
||||
const std::optional<alpha_handle>& alpha_handle,
|
||||
std::optional<texture_data>&& texture_data,
|
||||
const material_component::flags components
|
||||
) :
|
||||
m_handle{
|
||||
.texture = texture_handle,
|
||||
.surface_properties = surface_properties_handle,
|
||||
.alpha = alpha_handle
|
||||
},
|
||||
m_texture_data{ std::move(texture_data) },
|
||||
m_component_types{ components } {}
|
||||
|
||||
inline material_data::material_data(material_data&& other) noexcept
|
||||
{
|
||||
m_handle = other.m_handle;
|
||||
m_texture_data = std::move(other.m_texture_data);
|
||||
m_component_types = other.m_component_types;
|
||||
|
||||
other.m_handle.texture = std::nullopt;
|
||||
other.m_handle.surface_properties = std::nullopt;
|
||||
other.m_handle.alpha = std::nullopt;
|
||||
other.m_component_types = material_component::flags::none;
|
||||
}
|
||||
|
||||
inline material_data& material_data::operator=(material_data&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->~material_data();
|
||||
|
||||
m_handle = other.m_handle;
|
||||
m_texture_data = std::move(other.m_texture_data);
|
||||
m_component_types = other.m_component_types;
|
||||
|
||||
other.m_handle.texture = std::nullopt;
|
||||
other.m_handle.surface_properties = std::nullopt;
|
||||
other.m_handle.alpha = std::nullopt;
|
||||
other.m_component_types = material_component::flags::none;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline material_handle material_data::handle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
inline material_component::flags material_data::components() const
|
||||
{
|
||||
return m_component_types;
|
||||
}
|
||||
|
||||
|
||||
inline std::error_code material_data::build_from(
|
||||
const std::optional<material_component::texture::value_type>& texture_opt,
|
||||
const std::optional<material_component::surface_properties::value_type>& surface_properties_opt,
|
||||
const std::optional<material_component::transparency::value_type>& transparency_opt,
|
||||
const material_component::flags components,
|
||||
material_data& dst_data
|
||||
) {
|
||||
|
||||
auto texture_data_opt = std::optional<texture_data>{ std::nullopt };
|
||||
auto texture_handle_opt = std::optional<texture_handle>{ std::nullopt };
|
||||
if (texture_opt)
|
||||
{
|
||||
const auto& texture = *texture_opt;
|
||||
auto texture_data = zgl::texture_data{};
|
||||
|
||||
if (const auto e = texture_data::build_from(
|
||||
std::span(texture.cbegin(), texture.cend()),
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
texture.width(),
|
||||
texture.height(),
|
||||
texture_data
|
||||
)) {
|
||||
return e;
|
||||
}
|
||||
|
||||
texture_handle_opt.emplace(texture_data.handle());
|
||||
texture_data_opt.emplace(std::move(texture_data));
|
||||
}
|
||||
|
||||
auto surface_properties_data_opt = std::optional<surface_properties_handle>{ std::nullopt };
|
||||
if (surface_properties_opt)
|
||||
{
|
||||
const auto& [ ambient, diffuse, specular, shininess ] = *surface_properties_opt;
|
||||
surface_properties_data_opt.emplace(
|
||||
glm::vec3{ ambient[0], ambient[1], ambient[2] },
|
||||
glm::vec3{ diffuse[0], diffuse[1], diffuse[2] },
|
||||
glm::vec3{ specular[0], specular[1], specular[2] },
|
||||
shininess
|
||||
);
|
||||
}
|
||||
|
||||
auto alpha_data_opt = std::optional<alpha_handle>{ std::nullopt };
|
||||
if (transparency_opt)
|
||||
{
|
||||
alpha_data_opt.emplace(1.0f - *transparency_opt);
|
||||
}
|
||||
|
||||
|
||||
/*dst_data = material_data{
|
||||
texture_handle_opt,
|
||||
surface_properties_data_opt,
|
||||
alpha_data_opt,
|
||||
std::move(texture_data_opt),
|
||||
components
|
||||
};*/
|
||||
|
||||
dst_data.m_handle.texture = texture_handle_opt;
|
||||
dst_data.m_handle.surface_properties = surface_properties_data_opt;
|
||||
dst_data.m_handle.alpha = alpha_data_opt;
|
||||
dst_data.m_texture_data = std::move(texture_data_opt);
|
||||
dst_data.m_component_types = components;
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
119
source/opengl/data/mesh_data.cpp
Normal file
119
source/opengl/data/mesh_data.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#include "opengl/data/mesh_data.hpp"
|
||||
|
||||
#include "opengl/type_utils.hpp"
|
||||
#include "opengl/error.hpp"
|
||||
|
||||
#include "GL/glew.h"
|
||||
#include <algorithm>
|
||||
#include "util/logger.hpp" // TODO remove
|
||||
|
||||
|
||||
std::error_code zgl::mesh_data::build_from(
|
||||
const std::span<const ztu::u8> vertex_buffer,
|
||||
const std::span<const GLenum> component_types,
|
||||
const std::span<const GLint> component_lengths,
|
||||
const GLsizei stride,
|
||||
const std::span<const ztu::u32> index_buffer,
|
||||
const ztu::u32 material_id,
|
||||
const components::mesh_vertex::flags components,
|
||||
mesh_data& data
|
||||
) {
|
||||
if (not std::ranges::all_of(component_types, type_utils::is_valid_type))
|
||||
{
|
||||
ztu::logger::debug("not all types valid.");
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
const auto vertices_byte_count = vertex_buffer.size() * sizeof(std::uint8_t);
|
||||
if (vertices_byte_count > std::numeric_limits<GLsizeiptr>::max())
|
||||
{
|
||||
return std::make_error_code(std::errc::value_too_large);
|
||||
}
|
||||
|
||||
const auto indices_byte_count = index_buffer.size() * sizeof(ztu::u32);
|
||||
if (indices_byte_count > std::numeric_limits<GLsizeiptr>::max())
|
||||
{
|
||||
return std::make_error_code(std::errc::value_too_large);
|
||||
}
|
||||
|
||||
auto error = std::error_code{};
|
||||
|
||||
auto check_error = [&error, ec = static_cast<GLenum>(GL_NO_ERROR)]() mutable -> const std::error_code&
|
||||
{
|
||||
ec = glGetError();
|
||||
if (ec != GL_NO_ERROR)
|
||||
{
|
||||
error = make_error_code(ec);
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
GLuint vao_id;
|
||||
glGenVertexArrays(1, &vao_id);
|
||||
glBindVertexArray(vao_id);
|
||||
if (check_error()) return error;
|
||||
|
||||
ztu::logger::debug("Created mesh vao: % valid: %", vao_id, (bool)glIsVertexArray(vao_id));
|
||||
|
||||
GLuint vertex_buffer_id;
|
||||
glGenBuffers(1, &vertex_buffer_id);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
static_cast<GLsizeiptr>(vertices_byte_count),
|
||||
vertex_buffer.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
if (check_error()) return error;
|
||||
|
||||
GLuint index_buffer_id;
|
||||
glGenBuffers(1, &index_buffer_id);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id);
|
||||
glBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
static_cast<GLsizeiptr>(indices_byte_count),
|
||||
index_buffer.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
if (check_error()) return error;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
|
||||
if (check_error()) return error;
|
||||
|
||||
auto offset = GLsizei{ 0 };
|
||||
|
||||
for (std::size_t i{}; i != component_types.size(); ++i)
|
||||
{
|
||||
const auto type = component_types[i];
|
||||
const auto length = component_lengths[i];
|
||||
const auto byte_count = type_utils::size_of(type);
|
||||
|
||||
glVertexAttribPointer(
|
||||
i,
|
||||
length,
|
||||
type,
|
||||
GL_FALSE,
|
||||
stride,
|
||||
reinterpret_cast<GLvoid*>(offset)
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(i);
|
||||
if (check_error()) return error;
|
||||
|
||||
offset += length * byte_count;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
data = mesh_data(
|
||||
vertex_buffer_id,
|
||||
index_buffer_id,
|
||||
vao_id,
|
||||
material_id,
|
||||
components,
|
||||
index_buffer.size()
|
||||
);
|
||||
|
||||
return {};
|
||||
}
|
||||
90
source/opengl/data/mesh_data.ipp
Normal file
90
source/opengl/data/mesh_data.ipp
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef INCLUDE_MESH_DATA_IMPLEMENTATION
|
||||
# error Never include this file directly include 'mesh_data.hpp'
|
||||
#endif
|
||||
|
||||
namespace zgl
|
||||
{
|
||||
inline mesh_data::mesh_data(
|
||||
const GLuint vertex_vbo_id,
|
||||
const GLuint index_vbo_id,
|
||||
const GLuint vao_id,
|
||||
const ztu::u32 material_id,
|
||||
const components::mesh_vertex::flags components,
|
||||
const GLsizei index_count
|
||||
) :
|
||||
m_handle{
|
||||
.vao_id = vao_id,
|
||||
.index_count = index_count
|
||||
},
|
||||
m_vertex_vbo_id{ vertex_vbo_id },
|
||||
m_index_vbo_id{ index_vbo_id },
|
||||
m_material_id{ material_id },
|
||||
m_component_types{ components } {}
|
||||
|
||||
inline mesh_data& mesh_data::operator=(mesh_data&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->~mesh_data();
|
||||
|
||||
m_handle = other.m_handle;
|
||||
m_vertex_vbo_id = other.m_vertex_vbo_id;
|
||||
m_index_vbo_id = other.m_index_vbo_id;
|
||||
m_material_id = other.m_material_id;
|
||||
m_component_types = other.m_component_types;
|
||||
|
||||
other.m_handle.vao_id = 0;
|
||||
other.m_handle.index_count = 0;
|
||||
other.m_vertex_vbo_id = 0;
|
||||
other.m_index_vbo_id = 0;
|
||||
other.m_material_id = 0;
|
||||
other.m_component_types = components::mesh_vertex::flags::none;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline mesh_data::mesh_data(mesh_data&& other) noexcept :
|
||||
m_handle{ other.m_handle },
|
||||
m_vertex_vbo_id{ other.m_vertex_vbo_id },
|
||||
m_index_vbo_id{ other.m_index_vbo_id },
|
||||
m_material_id{ other.m_material_id },
|
||||
m_component_types{ other.m_component_types }
|
||||
{
|
||||
other.m_handle.vao_id = 0;
|
||||
other.m_handle.index_count = 0;
|
||||
other.m_vertex_vbo_id = 0;
|
||||
other.m_index_vbo_id = 0;
|
||||
other.m_material_id = 0;
|
||||
other.m_component_types = components::mesh_vertex::flags::none;
|
||||
}
|
||||
|
||||
inline mesh_data::~mesh_data() {
|
||||
if (m_vertex_vbo_id) {
|
||||
glDeleteBuffers(1, &m_vertex_vbo_id);
|
||||
}
|
||||
if (m_index_vbo_id) {
|
||||
glDeleteBuffers(1, &m_index_vbo_id);
|
||||
}
|
||||
if (m_handle.vao_id) {
|
||||
glDeleteVertexArrays(1, &m_handle.vao_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline mesh_handle mesh_data::handle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
inline components::mesh_vertex::flags mesh_data::components() const
|
||||
{
|
||||
return m_component_types;
|
||||
}
|
||||
|
||||
inline ztu::u32 mesh_data::material_id() const
|
||||
{
|
||||
return m_material_id;
|
||||
}
|
||||
|
||||
}
|
||||
99
source/opengl/data/point_cloud_data.cpp
Normal file
99
source/opengl/data/point_cloud_data.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "opengl/data/point_cloud_data.hpp"
|
||||
|
||||
#include "opengl/type_utils.hpp"
|
||||
#include "opengl/error.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include "GL/glew.h"
|
||||
|
||||
std::error_code zgl::point_cloud_data::build_from(
|
||||
std::span<const std::uint8_t> point_buffer,
|
||||
std::span<const GLenum> component_types,
|
||||
std::span<const GLint> component_lengths,
|
||||
GLsizei stride,
|
||||
point_cloud_data& data
|
||||
) {
|
||||
if (not std::ranges::all_of(component_types, type_utils::is_valid_type))
|
||||
{
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
const auto points_byte_count = point_buffer.size() * sizeof(std::uint8_t);
|
||||
if (points_byte_count > std::numeric_limits<GLsizeiptr>::max())
|
||||
{
|
||||
return std::make_error_code(std::errc::value_too_large);
|
||||
}
|
||||
|
||||
auto error = std::error_code{};
|
||||
|
||||
auto check_error = [&error, ec = static_cast<GLenum>(GL_NO_ERROR)]() mutable -> const std::error_code&
|
||||
{
|
||||
ec = glGetError();
|
||||
if (ec != GL_NO_ERROR) {
|
||||
error = make_error_code(ec);
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
ztu::u32 vao_id;
|
||||
glGenVertexArrays(1, &vao_id);
|
||||
if (check_error()) return error;
|
||||
|
||||
glBindVertexArray(vao_id);
|
||||
if (check_error()) return error;
|
||||
|
||||
ztu::u32 vertex_buffer_id;
|
||||
glGenBuffers(1, &vertex_buffer_id);
|
||||
if (check_error()) return error;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
|
||||
if (check_error()) return error;
|
||||
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
static_cast<GLsizeiptr>(points_byte_count),
|
||||
point_buffer.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
if (check_error()) return error;
|
||||
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
|
||||
if (check_error()) return error;
|
||||
|
||||
auto offset = GLsizei{ 0 };
|
||||
|
||||
for (std::size_t i{}; i != component_types.size(); ++i)
|
||||
{
|
||||
const auto type = component_types[i];
|
||||
const auto length = component_lengths[i];
|
||||
const auto byte_count = type_utils::size_of(type);
|
||||
|
||||
glVertexAttribPointer(
|
||||
i,
|
||||
length,
|
||||
type,
|
||||
GL_FALSE,
|
||||
stride,
|
||||
reinterpret_cast<GLvoid*>(offset)
|
||||
);
|
||||
if (check_error()) return error;
|
||||
glEnableVertexAttribArray(i);
|
||||
if (check_error()) return error;
|
||||
|
||||
offset += length * byte_count;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
if (check_error()) return error;
|
||||
glBindVertexArray(0);
|
||||
if (check_error()) return error;
|
||||
|
||||
data = point_cloud_data(
|
||||
vertex_buffer_id,
|
||||
vao_id,
|
||||
point_buffer.size()
|
||||
);
|
||||
|
||||
return {};
|
||||
}
|
||||
66
source/opengl/data/point_cloud_data.ipp
Normal file
66
source/opengl/data/point_cloud_data.ipp
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef INCLUDE_POINT_CLOUD_DATA_IMPLEMENTATION
|
||||
# error Never include this file directly include 'point_cloud_data.hpp'
|
||||
#endif
|
||||
|
||||
|
||||
namespace zgl
|
||||
{
|
||||
inline point_cloud_data::point_cloud_data(
|
||||
const GLuint vertex_vbo_id,
|
||||
const GLuint vao_id,
|
||||
const GLsizei point_count
|
||||
) :
|
||||
m_handle{
|
||||
.vao_id = vao_id,
|
||||
.point_count = point_count
|
||||
},
|
||||
m_vertex_vbo_id{ vertex_vbo_id } {}
|
||||
|
||||
inline point_cloud_data::point_cloud_data(point_cloud_data&& other) noexcept :
|
||||
m_handle{ other.m_handle },
|
||||
m_vertex_vbo_id{ other.m_vertex_vbo_id }
|
||||
{
|
||||
other.m_handle.vao_id = 0;
|
||||
other.m_handle.point_count = 0;
|
||||
other.m_vertex_vbo_id = 0;
|
||||
}
|
||||
|
||||
inline point_cloud_data& point_cloud_data::operator=(point_cloud_data&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->~point_cloud_data();
|
||||
|
||||
m_handle = other.m_handle;
|
||||
m_vertex_vbo_id = other.m_vertex_vbo_id;
|
||||
|
||||
other.m_handle.vao_id = 0;
|
||||
other.m_handle.point_count = 0;
|
||||
other.m_vertex_vbo_id = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline point_cloud_data::~point_cloud_data()
|
||||
{
|
||||
if (m_vertex_vbo_id)
|
||||
{
|
||||
glDeleteBuffers(1, &m_vertex_vbo_id);
|
||||
}
|
||||
if (m_handle.vao_id)
|
||||
{
|
||||
glDeleteVertexArrays(1, &m_handle.vao_id);
|
||||
}
|
||||
}
|
||||
|
||||
inline point_cloud_handle point_cloud_data::handle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
inline components::point_cloud_vertex::flags point_cloud_data::components() const
|
||||
{
|
||||
return m_component_types;
|
||||
}
|
||||
}
|
||||
46
source/opengl/data/shader_data.cpp
Executable file
46
source/opengl/data/shader_data.cpp
Executable file
@@ -0,0 +1,46 @@
|
||||
#include "opengl/data/shader_data.hpp"
|
||||
|
||||
#include "GL/glew.h"
|
||||
#include "opengl/error.hpp"
|
||||
#include "util/logger.hpp"
|
||||
|
||||
namespace zgl
|
||||
{
|
||||
std::error_code shader_data::build_from(
|
||||
const GLenum type,
|
||||
const std::string& source,
|
||||
shader_data& data
|
||||
) {
|
||||
auto shader_id = GLuint{ 0 };
|
||||
|
||||
if (not source.empty())
|
||||
{
|
||||
shader_id = glCreateShader(type);
|
||||
|
||||
// Curious choice to take lists as parameters...
|
||||
const auto first_list_element = source.c_str();
|
||||
const auto first_list_element_len = static_cast<GLint>(source.length());
|
||||
glShaderSource(shader_id, 1, &first_list_element, &first_list_element_len);
|
||||
glCompileShader(shader_id);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &success);
|
||||
if (not success)
|
||||
{
|
||||
GLint log_length{};
|
||||
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
|
||||
|
||||
auto log = std::string(log_length, ' ');
|
||||
glGetShaderInfoLog(shader_id, log_length, nullptr, log.data());
|
||||
|
||||
ztu::logger::warn("Error while compiling shader:\n%", log);
|
||||
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
}
|
||||
|
||||
data = shader_data{ shader_id, type };
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
47
source/opengl/data/shader_data.ipp
Normal file
47
source/opengl/data/shader_data.ipp
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef INCLUDE_SHADER_DATA_IMPLEMENTATION
|
||||
# error Never include this file directly include 'shader_data.hpp'
|
||||
#endif
|
||||
|
||||
namespace zgl
|
||||
{
|
||||
inline shader_data::shader_data(const GLuint shader_id, const GLenum type)
|
||||
: m_handle{ shader_id }, m_type{ type } {}
|
||||
|
||||
|
||||
inline shader_data::shader_data(shader_data&& other) noexcept
|
||||
{
|
||||
m_handle = other.m_handle;
|
||||
m_type = other.m_type;
|
||||
other.m_handle.shader_id = 0;
|
||||
other.m_type = GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
inline shader_data& shader_data::operator=(shader_data&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->~shader_data();
|
||||
|
||||
m_handle = other.m_handle;
|
||||
m_type = other.m_type;
|
||||
other.m_handle.shader_id = 0;
|
||||
other.m_type = GL_INVALID_ENUM;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline shader_data::~shader_data()
|
||||
{
|
||||
if (m_handle.shader_id)
|
||||
{
|
||||
glDeleteShader(m_handle.shader_id);
|
||||
}
|
||||
m_type = GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
inline shader_handle shader_data::handle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
}
|
||||
90
source/opengl/data/shader_program_data.cpp
Executable file
90
source/opengl/data/shader_program_data.cpp
Executable file
@@ -0,0 +1,90 @@
|
||||
|
||||
#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 {};
|
||||
}
|
||||
}
|
||||
45
source/opengl/data/shader_program_data.ipp
Executable file
45
source/opengl/data/shader_program_data.ipp
Executable file
@@ -0,0 +1,45 @@
|
||||
#ifndef INCLUDE_SHADER_PROGRAM_DATA_IMPLEMENTATION
|
||||
# error Never include this file directly include 'shader_program_data.hpp'
|
||||
#endif
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "util/for_each.hpp"
|
||||
#include "util/logger.hpp"
|
||||
#include "opengl/error.hpp"
|
||||
|
||||
namespace zgl
|
||||
{
|
||||
inline shader_program_data::shader_program_data(GLuint program_id)
|
||||
: m_handle{ program_id } {}
|
||||
|
||||
|
||||
inline shader_program_data::shader_program_data(shader_program_data&& other) noexcept
|
||||
{
|
||||
m_handle = other.m_handle;
|
||||
other.m_handle.program_id = 0;
|
||||
}
|
||||
|
||||
inline shader_program_data& shader_program_data::operator=(shader_program_data&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->~shader_program_data();
|
||||
m_handle = other.m_handle;
|
||||
other.m_handle.program_id = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline shader_program_data::~shader_program_data()
|
||||
{
|
||||
if (m_handle.program_id) {
|
||||
glDeleteProgram(m_handle.program_id);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] inline shader_program_handle shader_program_data::handle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
}
|
||||
79
source/opengl/data/texture_data.ipp
Normal file
79
source/opengl/data/texture_data.ipp
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef INCLUDE_TEXTURE_DATA_IMPLEMENTATION
|
||||
# error Never include this file directly include 'texture_data.hpp'
|
||||
#endif
|
||||
|
||||
namespace zgl
|
||||
{
|
||||
inline texture_data::texture_data(const GLuint texture_id)
|
||||
: m_handle{ texture_id } {}
|
||||
|
||||
inline texture_data::texture_data(texture_data&& other) noexcept
|
||||
: m_handle{ other.m_handle }
|
||||
{
|
||||
other.m_handle.texture_id = 0;
|
||||
}
|
||||
|
||||
inline texture_data& texture_data::operator=(texture_data&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->~texture_data();
|
||||
|
||||
m_handle = other.m_handle;
|
||||
|
||||
other.m_handle.texture_id = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::error_code texture_data::build_from(
|
||||
std::span<const T> buffer,
|
||||
const GLenum format,
|
||||
const GLenum type,
|
||||
const GLsizei width,
|
||||
const GLsizei height,
|
||||
texture_data& data
|
||||
) {
|
||||
GLuint texture_id;
|
||||
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0,
|
||||
GL_RGBA8,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
format, type,
|
||||
buffer.data()
|
||||
);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
data = texture_data(texture_id);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline texture_data::~texture_data()
|
||||
{
|
||||
if (m_handle.texture_id)
|
||||
{
|
||||
glDeleteTextures(1, &m_handle.texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
inline texture_handle texture_data::handle() const
|
||||
{
|
||||
return { m_handle.texture_id };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user