clean up some headers

This commit is contained in:
Hartmut Seichter 2024-07-14 11:23:04 +02:00
parent c70c18e41c
commit a5d42995b2
5 changed files with 251 additions and 358 deletions

View file

@ -14,6 +14,13 @@ struct geometry_n {
std::vector<std::size_t> indices{}; std::vector<std::size_t> indices{};
}; };
struct mesh_n {
geometry_n geometry{};
};
} // namespace pw } // namespace pw
auto main() -> int { auto main() -> int {
@ -27,6 +34,8 @@ auto main() -> int {
std::print("({}) ",pw::serialize::to_string(geom.vertices[i])); std::print("({}) ",pw::serialize::to_string(geom.vertices[i]));
} }
// pw::geometry geo; // pw::geometry geo;
// pw::vector3_array vs = { // pw::vector3_array vs = {

View file

@ -1,19 +1,17 @@
#ifndef PW_VISUAL_MESH_RENDERER_HPP #ifndef PW_VISUAL_MESH_RENDERER_HPP
#define PW_VISUAL_MESH_RENDERER_HPP #define PW_VISUAL_MESH_RENDERER_HPP
#include <memory>
#include <map> #include <map>
#include <memory>
namespace pw { namespace pw {
class geometry; struct geometry;
/** /**
* @brief builds a renderer for geometry * @brief builds a renderer for geometry
*/ */
class renderer { struct renderer final {
public:
renderer(); renderer();
renderer(const geometry& m); renderer(const geometry& m);
@ -27,13 +25,12 @@ public:
uint64_t change_count() const; uint64_t change_count() const;
void set_change_count(uint64_t n); void set_change_count(uint64_t n);
protected:
protected:
struct impl; struct impl;
std::unique_ptr<impl> _impl; std::unique_ptr<impl> _impl;
}; };
} } // namespace pw
#endif #endif

View file

@ -1,11 +1,10 @@
#ifndef PW_VISUAL_SHADER_HPP #ifndef PW_VISUAL_SHADER_HPP
#define PW_VISUAL_SHADER_HPP #define PW_VISUAL_SHADER_HPP
#include <pw/core/debug.hpp>
#include <pw/core/globals.hpp> #include <pw/core/globals.hpp>
#include <pw/core/matrix.hpp> #include <pw/core/matrix.hpp>
#include <pw/core/vector.hpp> #include <pw/core/vector.hpp>
#include <pw/core/debug.hpp>
#include <pw/visual/texture.hpp> #include <pw/visual/texture.hpp>
#include <map> #include <map>
@ -13,18 +12,11 @@
namespace pw { namespace pw {
class shader { struct shader final {
public:
shader(); shader();
~shader(); ~shader();
enum class code_type { enum class code_type { vertex, fragment, geometry, compute };
vertex,
fragment,
geometry,
compute
};
void set_source(code_type t, const std::string& c) { _source[t] = c; } void set_source(code_type t, const std::string& c) { _source[t] = c; }
std::string source(code_type t) { return _source[t]; } std::string source(code_type t) { return _source[t]; }
@ -50,22 +42,25 @@ public:
* @param name of the uniform * @param name of the uniform
* @return true if found * @return true if found
*/ */
bool has_uniform(std::string const &name) const { return uniform_location(name) >= 0; } bool has_uniform(std::string const& name) const {
return uniform_location(name) >= 0;
}
/** /**
* sets data of the * sets data of the
*/ */
template <typename T> template <typename T>
shader & set_uniform(std::string const & name, T &&value) shader& set_uniform(std::string const& name, T&& value) {
{ return set_uniform_at_location(uniform_location(name),
return set_uniform_at_location( uniform_location(name), std::forward<T>(value) ); std::forward<T>(value));
} }
bool build(); bool build();
void use(); void use();
using uniform_t = std::variant<bool,int,float,double,vector2f,vector3f,vector4f,matrix4x4f>; using uniform_t = std::variant<bool, int, float, double, vector2f, vector3f,
vector4f, matrix4x4f>;
using uniform_entry_t = std::tuple<std::string, uniform_t, int>; using uniform_entry_t = std::tuple<std::string, uniform_t, int>;
using uniform_cache_t = std::vector<uniform_entry_t>; using uniform_cache_t = std::vector<uniform_entry_t>;
@ -75,15 +70,12 @@ public:
uint32_t native_handle() const; uint32_t native_handle() const;
protected: protected:
std::unordered_map<code_type, std::string> _source; std::unordered_map<code_type, std::string> _source;
struct impl; struct impl;
std::unique_ptr<impl> _impl; std::unique_ptr<impl> _impl;
}; };
} // namespace pw
}
#endif #endif

View file

@ -1,15 +1,14 @@
#include "pw/visual/renderer.hpp" #include "pw/visual/renderer.hpp"
#include "pw/core/geometry.hpp"
#include "pw/core/size.hpp"
#include "pw/core/debug.hpp" #include "pw/core/debug.hpp"
#include "pw/core/geometry.hpp"
#include "pw/core/matrix.hpp" #include "pw/core/matrix.hpp"
#include "pw/core/size.hpp"
#include "glad/glad.h" #include "glad/glad.h"
#include <algorithm> #include <algorithm>
namespace pw { namespace pw {
struct renderer::impl { struct renderer::impl {
@ -20,23 +19,17 @@ struct renderer::impl {
uint32_t _ebo{0}; uint32_t _ebo{0};
std::vector<uint32_t> _vbos{}; std::vector<uint32_t> _vbos{};
GLint _mesh_elements = {0}; GLint _mesh_elements = {0};
impl() = default; impl() = default;
~impl() ~impl() { release(); }
{
release();
}
bool ready() const bool ready() const {
{
return glIsVertexArray != nullptr && GL_TRUE == glIsVertexArray(_vao); return glIsVertexArray != nullptr && GL_TRUE == glIsVertexArray(_vao);
} }
bool update(const geometry& m) bool update(const geometry& m) {
{
if (_change_count == m.change_count()) if (_change_count == m.change_count())
return false; return false;
@ -52,65 +45,54 @@ struct renderer::impl {
glGenBuffers(1, &_ebo); glGenBuffers(1, &_ebo);
// TODO binding separate VBOs to the // TODO binding separate VBOs to the
// vertexarray should be avoided // vertexarray should be avoided
// indices // indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, glBufferData(GL_ELEMENT_ARRAY_BUFFER,
m.indices().size() * sizeof (uint32_t), m.indices().size() * sizeof(uint32_t), m.indices().data(),
m.indices().data(),
GL_STATIC_DRAW); GL_STATIC_DRAW);
_vbos.resize(_vbos.size() + 1); _vbos.resize(_vbos.size() + 1);
glGenBuffers(1, &_vbos.back()); glGenBuffers(1, &_vbos.back());
// vertices // vertices
glBindBuffer(GL_ARRAY_BUFFER, _vbos.back()); glBindBuffer(GL_ARRAY_BUFFER, _vbos.back());
glVertexAttribPointer(_vbos.size()-1, vector3::coefficients, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(_vbos.size() - 1, vector3::coefficients, GL_FLOAT,
glBufferData(GL_ARRAY_BUFFER, GL_FALSE, 0, nullptr);
m.vertices().size() * sizeof(vector3), glBufferData(GL_ARRAY_BUFFER, m.vertices().size() * sizeof(vector3),
m.vertices().data(), m.vertices().data(), GL_STATIC_DRAW);
GL_STATIC_DRAW);
glEnableVertexAttribArray(_vbos.size() - 1); glEnableVertexAttribArray(_vbos.size() - 1);
debug::d() << "vertices at " << _vbos.size() - 1; debug::d() << "vertices at " << _vbos.size() - 1;
if (!m.normals().empty()) if (!m.normals().empty()) {
{
_vbos.resize(_vbos.size() + 1); _vbos.resize(_vbos.size() + 1);
glGenBuffers(1, &_vbos.back()); glGenBuffers(1, &_vbos.back());
// normals // normals
glBindBuffer(GL_ARRAY_BUFFER, _vbos.back()); glBindBuffer(GL_ARRAY_BUFFER, _vbos.back());
glVertexAttribPointer(_vbos.size()-1, vector3::coefficients, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(_vbos.size() - 1, vector3::coefficients,
glBufferData(GL_ARRAY_BUFFER, GL_FLOAT, GL_FALSE, 0, nullptr);
m.normals().size() * sizeof(vector3), glBufferData(GL_ARRAY_BUFFER, m.normals().size() * sizeof(vector3),
m.normals().data(), m.normals().data(), GL_STATIC_DRAW);
GL_STATIC_DRAW);
glEnableVertexAttribArray(_vbos.size() - 1); glEnableVertexAttribArray(_vbos.size() - 1);
debug::d() << "normals at " << _vbos.size() - 1; debug::d() << "normals at " << _vbos.size() - 1;
} }
if (!m.texture_coordinates().empty()) if (!m.texture_coordinates().empty()) {
{ for (const auto& tc : m.texture_coordinates()) {
for (const auto& tc : m.texture_coordinates())
{
_vbos.resize(_vbos.size() + 1); _vbos.resize(_vbos.size() + 1);
glGenBuffers(1, &_vbos.back()); glGenBuffers(1, &_vbos.back());
// texture coordinates // texture coordinates
glBindBuffer(GL_ARRAY_BUFFER, _vbos.back()); glBindBuffer(GL_ARRAY_BUFFER, _vbos.back());
glVertexAttribPointer(_vbos.size()-1, vector2::coefficients, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(_vbos.size() - 1, vector2::coefficients,
glBufferData(GL_ARRAY_BUFFER, GL_FLOAT, GL_FALSE, 0, nullptr);
tc.size() * sizeof(vector2), glBufferData(GL_ARRAY_BUFFER, tc.size() * sizeof(vector2),
tc.data(), tc.data(), GL_STATIC_DRAW);
GL_STATIC_DRAW);
glEnableVertexAttribArray(_vbos.size() - 1); glEnableVertexAttribArray(_vbos.size() - 1);
debug::d() << "texture coordinates at " << _vbos.size() - 1; debug::d() << "texture coordinates at " << _vbos.size() - 1;
@ -120,10 +102,8 @@ struct renderer::impl {
// stop binding // stop binding
glBindVertexArray(0); glBindVertexArray(0);
this->_change_count = m.change_count(); this->_change_count = m.change_count();
#if 1 #if 1
// get errors // get errors
auto error = glGetError(); auto error = glGetError();
@ -136,19 +116,16 @@ struct renderer::impl {
return ready(); return ready();
} }
void release() {
void release() for (auto & vbo : _vbos)
{
for (auto vbo : _vbos)
glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &_ebo); glDeleteBuffers(1, &_ebo);
glDeleteVertexArrays(1, &_vao); glDeleteVertexArrays(1, &_vao);
} }
void draw() void draw() {
{
glBindVertexArray(_vao); glBindVertexArray(_vao);
glDrawElements(GL_TRIANGLES, _mesh_elements, GL_UNSIGNED_INT, nullptr); glDrawElements(GL_TRIANGLES, _mesh_elements, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0); glBindVertexArray(0);
@ -163,57 +140,32 @@ struct renderer::impl {
} }
// GLint get_mode(vertex_array::) // GLint get_mode(vertex_array::)
}; };
// //
// Outer wrapper // Outer wrapper
// //
renderer::renderer() renderer::renderer() : _impl(std::make_unique<renderer::impl>()) {}
: _impl(std::make_unique<renderer::impl>())
{
}
renderer::renderer(const geometry &m) renderer::renderer(const geometry& m) {
{
renderer(); renderer();
// directly update // directly update
_impl->update(m); _impl->update(m);
} }
renderer::~renderer() renderer::~renderer() = default;
{
}
bool renderer::ready() const bool renderer::ready() const { return _impl->ready(); }
{
return _impl->ready();
}
bool renderer::update(const geometry &m) bool renderer::update(const geometry& m) { return _impl->update(m); }
{
return _impl->update(m);
}
void renderer::release() void renderer::release() { _impl->release(); }
{
_impl->release();
}
void renderer::draw() void renderer::draw() { _impl->draw(); }
{
_impl->draw();
}
uint64_t renderer::change_count() const uint64_t renderer::change_count() const { return _impl->_change_count; }
{
return _impl->_change_count;
}
void renderer::set_change_count(uint64_t n) void renderer::set_change_count(uint64_t n) { _impl->_change_count = n; }
{
_impl->_change_count = n;
}
} } // namespace pw

View file

@ -6,35 +6,25 @@
namespace pw { namespace pw {
struct shader::impl struct shader::impl {
{
shader& _shader; shader& _shader;
GLuint _shader_program; GLuint _shader_program;
std::vector<GLuint> _shader_stages; std::vector<GLuint> _shader_stages;
impl(shader& s) impl(shader& s) : _shader(s) {}
: _shader(s)
{
}
~impl() ~impl() { destroy(); }
{
destroy();
}
bool is_valid() bool is_valid() {
{
// we potentially haul in is_valid while no context is given // we potentially haul in is_valid while no context is given
return glIsProgram != nullptr && glIsProgram(_shader_program); return glIsProgram != nullptr && glIsProgram(_shader_program);
} }
bool build() bool build() {
{
// if (!is_valid()) return false; // if (!is_valid()) return false;
for (const auto & [type,code] : _shader._source) for (const auto& [type, code] : _shader._source) {
{
GLuint shader_type = 0; GLuint shader_type = 0;
switch (type) { switch (type) {
case shader::code_type::vertex: case shader::code_type::vertex:
@ -64,8 +54,7 @@ struct shader::impl
GLint is_compiled = GL_FALSE; GLint is_compiled = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &is_compiled); glGetShaderiv(shaderId, GL_COMPILE_STATUS, &is_compiled);
if(is_compiled == GL_FALSE) if (is_compiled == GL_FALSE) {
{
GLint log_length; GLint log_length;
@ -73,7 +62,8 @@ struct shader::impl
std::vector<char> log_buffer(static_cast<size_t>(log_length)); std::vector<char> log_buffer(static_cast<size_t>(log_length));
glGetShaderInfoLog(shaderId, log_length, &log_length, log_buffer.data()); glGetShaderInfoLog(shaderId, log_length, &log_length,
log_buffer.data());
// TODO - handle errors! // TODO - handle errors!
debug::e() << log_buffer.data(); debug::e() << log_buffer.data();
@ -82,19 +72,17 @@ struct shader::impl
} }
_shader_stages.push_back(shaderId); _shader_stages.push_back(shaderId);
} }
_shader_program = glCreateProgram(); _shader_program = glCreateProgram();
for (auto s : _shader_stages) for (auto s : _shader_stages)
glAttachShader(_shader_program, s); glAttachShader(_shader_program, s);
// TODO attribute binding ... // TODO attribute binding ...
/* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */ /* Bind attribute index 0 (coordinates) to in_Position and attribute
* index 1 (color) to in_Color */
/* Attribute locations must be setup before calling glLinkProgram. */ /* Attribute locations must be setup before calling glLinkProgram. */
// glBindAttribLocation(shaderprogram, 0, "in_Position"); // glBindAttribLocation(shaderprogram, 0, "in_Position");
// glBindAttribLocation(shaderprogram, 1, "in_Color"); // glBindAttribLocation(shaderprogram, 1, "in_Color");
@ -103,23 +91,25 @@ struct shader::impl
GLint is_linked = 0; GLint is_linked = 0;
glGetProgramiv(_shader_program, GL_LINK_STATUS, &is_linked); glGetProgramiv(_shader_program, GL_LINK_STATUS, &is_linked);
if(is_linked == GL_FALSE) if (is_linked == GL_FALSE) {
{
GLint log_length; GLint log_length;
/* Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. */ /* Noticed that glGetProgramiv is used to get the length for a
* shader program, not glGetShaderiv. */
glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &log_length); glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &log_length);
/* The maxLength includes the NULL character */ /* The maxLength includes the NULL character */
std::vector<char> info_log(static_cast<size_t>(log_length)); std::vector<char> info_log(static_cast<size_t>(log_length));
/* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */ /* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */
glGetProgramInfoLog(_shader_program, log_length, &log_length, info_log.data()); glGetProgramInfoLog(_shader_program, log_length, &log_length,
info_log.data());
debug::e() << info_log.data(); debug::e() << info_log.data();
/* Handle the error in an appropriate way such as displaying a message or writing to a log file. */ /* Handle the error in an appropriate way such as displaying a
* message or writing to a log file. */
/* In this simple program, we'll just leave */ /* In this simple program, we'll just leave */
return false; return false;
@ -128,21 +118,15 @@ struct shader::impl
return true; return true;
} }
void use() { glUseProgram(_shader_program); }
void use() void destroy() {
{
glUseProgram(_shader_program);
}
void destroy()
{
// potentially the GL driver hasn't been loaded // potentially the GL driver hasn't been loaded
if (is_valid()) { if (is_valid()) {
// deleting and detaching should happen much earlier // deleting and detaching should happen much earlier
for (auto s : _shader_stages) for (auto s : _shader_stages) {
{
glDeleteShader(s); glDeleteShader(s);
} }
@ -152,109 +136,74 @@ struct shader::impl
} }
} }
int uniform_location(std::string const& name) const int uniform_location(std::string const& name) const {
{
return glGetUniformLocation(_shader_program, name.c_str()); return glGetUniformLocation(_shader_program, name.c_str());
} }
void bind(int location,const matrix3x3f& m) void bind(int location, const matrix3x3f& m) {
{
glUniformMatrix3fv(location, 1, GL_FALSE, m.ptr()); glUniformMatrix3fv(location, 1, GL_FALSE, m.ptr());
} }
void bind(int location,const matrix4x4f& m) void bind(int location, const matrix4x4f& m) {
{
glUniformMatrix4fv(location, 1, GL_FALSE, m.ptr()); glUniformMatrix4fv(location, 1, GL_FALSE, m.ptr());
} }
void bind(int location,const vector4f& v) void bind(int location, const vector4f& v) {
{
glUniform4fv(location, 1, v.ptr()); glUniform4fv(location, 1, v.ptr());
} }
void bind(int location,const float& v) void bind(int location, const float& v) { glUniform1f(location, v); }
{
glUniform1f(location,v);
}
void bind(int location,const uint32_t& i) void bind(int location, const uint32_t& i) { glUniform1ui(location, i); }
{
glUniform1ui(location,i);
}
void bind(int location,const int32_t& i) void bind(int location, const int32_t& i) { glUniform1i(location, i); }
{
glUniform1i(location,i);
}
void bind(int location,const texture& v) void bind(int location, const texture& v) {
{
this->bind(location, (int)v.native_handle()); this->bind(location, (int)v.native_handle());
} }
}; };
shader::shader() { _impl = make_unique<impl>(*this); }
shader::shader() shader::~shader() {}
{
_impl = make_unique<impl>(*this);
}
shader::~shader() bool shader::ready() const { return _impl->is_valid(); }
{
} shader& shader::set_uniform_at_location(int location, float v) {
bool shader::ready() const
{
return _impl->is_valid();
}
shader &shader::set_uniform_at_location(int location, float v)
{
_impl->bind(location, v); _impl->bind(location, v);
return *this; return *this;
} }
shader &shader::set_uniform_at_location(int location, uint32_t v) shader& shader::set_uniform_at_location(int location, uint32_t v) {
{ _impl->bind(location, v);
_impl->bind(location,v); return *this; return *this;
} }
shader &shader::set_uniform_at_location(int location, int32_t v) shader& shader::set_uniform_at_location(int location, int32_t v) {
{ _impl->bind(location, v);
_impl->bind(location,v); return *this; return *this;
} }
shader& shader::set_uniform_at_location(int location, vector4f const& v) {
shader &shader::set_uniform_at_location(int location, vector4f const &v) _impl->bind(location, v);
{ return *this;
_impl->bind(location,v); return *this;
} }
shader &shader::set_uniform_at_location(int location, matrix4x4f const &v) shader& shader::set_uniform_at_location(int location, matrix4x4f const& v) {
{ _impl->bind(location, v);
_impl->bind(location,v); return *this; return *this;
} }
shader& shader::set_uniform_at_location(int location, texture const& v) {
shader &shader::set_uniform_at_location(int location, texture const &v) _impl->bind(location, v);
{ return *this;
_impl->bind(location,v); return *this;
} }
bool shader::build() bool shader::build() { return _impl->build(); }
{
return _impl->build();
}
void shader::use() void shader::use() { _impl->use(); }
{
_impl->use();
}
void shader::set_uniforms(uniform_cache_t c) void shader::set_uniforms(uniform_cache_t c) {
{
// TODO rewrite in proper C++17 // TODO rewrite in proper C++17
for (auto& u : c) { for (auto& u : c) {
@ -272,7 +221,6 @@ void shader::set_uniforms(uniform_cache_t c)
auto var = std::get<1>(u); auto var = std::get<1>(u);
std::visit([this, loc](auto&& arg) { std::visit([this, loc](auto&& arg) {
using T = std::decay_t<decltype(arg)>; using T = std::decay_t<decltype(arg)>;
// TODO query the std::variant of uniform_t // TODO query the std::variant of uniform_t
@ -288,15 +236,10 @@ void shader::set_uniforms(uniform_cache_t c)
} }
} }
uint32_t shader::native_handle() const uint32_t shader::native_handle() const { return _impl->_shader_program; }
{
return _impl->_shader_program;
}
int shader::uniform_location(const std::string &name) const int shader::uniform_location(const std::string& name) const {
{
return _impl->uniform_location(name); return _impl->uniform_location(name);
} }
} // namespace pw
}