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

View file

@ -1,39 +1,36 @@
#ifndef PW_VISUAL_MESH_RENDERER_HPP
#define PW_VISUAL_MESH_RENDERER_HPP
#include <memory>
#include <map>
#include <memory>
namespace pw {
class geometry;
struct geometry;
/**
* @brief builds a renderer for geometry
*/
class renderer {
public:
struct renderer final {
renderer();
renderer(const geometry& m);
~renderer();
bool update(const geometry &m);
void release();
bool update(const geometry& m);
void release();
void draw();
bool ready() const;
void draw();
bool ready() const;
uint64_t change_count() const;
void set_change_count(uint64_t n);
protected:
struct impl;
std::unique_ptr<impl> _impl;
protected:
struct impl;
std::unique_ptr<impl> _impl;
};
}
} // namespace pw
#endif

View file

@ -1,11 +1,10 @@
#ifndef PW_VISUAL_SHADER_HPP
#define PW_VISUAL_SHADER_HPP
#include <pw/core/debug.hpp>
#include <pw/core/globals.hpp>
#include <pw/core/matrix.hpp>
#include <pw/core/vector.hpp>
#include <pw/core/debug.hpp>
#include <pw/visual/texture.hpp>
#include <map>
@ -13,77 +12,70 @@
namespace pw {
class shader {
public:
shader();
struct shader final {
shader();
~shader();
enum class code_type {
vertex,
fragment,
geometry,
compute
};
enum class code_type { vertex, fragment, geometry, compute };
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]; }
bool ready() const;
bool ready() const;
shader& set_uniform_at_location(int location,float v);
shader& set_uniform_at_location(int location, float v);
shader& set_uniform_at_location(int location, uint32_t v);
shader &set_uniform_at_location(int location, int32_t v);
shader& set_uniform_at_location(int location,matrix4x4f const &v);
shader& set_uniform_at_location(int location,vector4f const &v);
shader& set_uniform_at_location(int location,texture const &t);
shader& set_uniform_at_location(int location, int32_t v);
shader& set_uniform_at_location(int location, matrix4x4f const& v);
shader& set_uniform_at_location(int location, vector4f const& v);
shader& set_uniform_at_location(int location, texture const& t);
/**
* @brief retrieves the position of a uniform
* @param name of the uniform
* @return position of the uniform or negative if it doesn't exist
*/
int uniform_location(std::string const & name) const;
int uniform_location(std::string const& name) const;
/**
* @brief check if a uniform with the given name exists
* @param name of the uniform
* @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
*/
template<typename T>
shader & set_uniform(std::string const & name, T &&value)
{
return set_uniform_at_location( uniform_location(name), std::forward<T>(value) );
}
template <typename T>
shader& set_uniform(std::string const& name, T&& value) {
return set_uniform_at_location(uniform_location(name),
std::forward<T>(value));
}
bool build();
bool build();
void use();
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_t = std::variant<bool, int, float, double, vector2f, vector3f,
vector4f, matrix4x4f>;
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>;
void set_uniforms(uniform_cache_t c);
void set_uniforms(uniform_cache_t c);
uint32_t native_handle() const;
protected:
std::unordered_map<code_type,std::string> _source;
struct impl;
std::unique_ptr<impl> _impl;
protected:
std::unordered_map<code_type, std::string> _source;
struct impl;
std::unique_ptr<impl> _impl;
};
}
} // namespace pw
#endif

View file

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

View file

@ -6,297 +6,240 @@
namespace pw {
struct shader::impl
{
shader& _shader;
struct shader::impl {
shader& _shader;
GLuint _shader_program;
std::vector<GLuint> _shader_stages;
GLuint _shader_program;
std::vector<GLuint> _shader_stages;
impl(shader& s)
: _shader(s)
{
}
impl(shader& s) : _shader(s) {}
~impl()
{
destroy();
}
~impl() { destroy(); }
bool is_valid()
{
bool is_valid() {
// we potentially haul in is_valid while no context is given
return glIsProgram != nullptr && glIsProgram(_shader_program);
}
}
bool build()
{
// if (!is_valid()) return false;
bool build() {
// if (!is_valid()) return false;
for (const auto & [type,code] : _shader._source)
{
GLuint shader_type = 0;
for (const auto& [type, code] : _shader._source) {
GLuint shader_type = 0;
switch (type) {
case shader::code_type::vertex:
shader_type = GL_VERTEX_SHADER;
break;
case shader::code_type::compute:
shader_type = GL_COMPUTE_SHADER;
break;
case shader::code_type::geometry:
shader_type = GL_GEOMETRY_SHADER;
break;
case shader::code_type::fragment:
shader_type = GL_FRAGMENT_SHADER;
break;
case shader::code_type::vertex:
shader_type = GL_VERTEX_SHADER;
break;
case shader::code_type::compute:
shader_type = GL_COMPUTE_SHADER;
break;
case shader::code_type::geometry:
shader_type = GL_GEOMETRY_SHADER;
break;
case shader::code_type::fragment:
shader_type = GL_FRAGMENT_SHADER;
break;
default:
debug::w() << " unknown shader type";
}
}
GLuint shaderId = glCreateShader(shader_type);
GLuint shaderId = glCreateShader(shader_type);
char* src = const_cast<char*>(code.c_str());
char* src = const_cast<char*>(code.c_str());
GLint size = static_cast<GLint>(code.length());
glShaderSource(shaderId , 1, &src, &size);
glShaderSource(shaderId, 1, &src, &size);
glCompileShader(shaderId);
glCompileShader(shaderId);
GLint is_compiled = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &is_compiled);
if(is_compiled == GL_FALSE)
{
GLint is_compiled = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &is_compiled);
if (is_compiled == GL_FALSE) {
GLint log_length;
GLint log_length;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &log_length);
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &log_length);
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!
debug::e() << log_buffer.data();
// TODO - handle errors!
debug::e() << log_buffer.data();
return false;
}
return false;
}
_shader_stages.push_back(shaderId);
_shader_stages.push_back(shaderId);
}
}
_shader_program = glCreateProgram();
for (auto s : _shader_stages)
glAttachShader(_shader_program,s);
_shader_program = glCreateProgram();
for (auto s : _shader_stages)
glAttachShader(_shader_program, s);
// TODO attribute binding ...
/* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */
/* Attribute locations must be setup before calling glLinkProgram. */
// glBindAttribLocation(shaderprogram, 0, "in_Position");
// glBindAttribLocation(shaderprogram, 1, "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. */
// glBindAttribLocation(shaderprogram, 0, "in_Position");
// glBindAttribLocation(shaderprogram, 1, "in_Color");
glLinkProgram(_shader_program);
glLinkProgram(_shader_program);
GLint is_linked = 0;
glGetProgramiv(_shader_program, GL_LINK_STATUS, &is_linked);
if(is_linked == GL_FALSE)
{
GLint is_linked = 0;
glGetProgramiv(_shader_program, GL_LINK_STATUS, &is_linked);
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. */
glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &log_length);
/* Noticed that glGetProgramiv is used to get the length for a
* shader program, not glGetShaderiv. */
glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &log_length);
/* The maxLength includes the NULL character */
std::vector<char> info_log(static_cast<size_t>(log_length));
/* The maxLength includes the NULL character */
std::vector<char> info_log(static_cast<size_t>(log_length));
/* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */
glGetProgramInfoLog(_shader_program, log_length, &log_length, info_log.data());
/* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */
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. */
/* In this simple program, we'll just leave */
/* 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 */
return false;
}
return false;
}
return true;
}
return true;
}
void use() { glUseProgram(_shader_program); }
void use()
{
glUseProgram(_shader_program);
}
void destroy()
{
void destroy() {
// potentially the GL driver hasn't been loaded
if (is_valid()) {
// deleting and detaching should happen much earlier
for (auto s : _shader_stages)
{
glDeleteShader(s);
for (auto s : _shader_stages) {
glDeleteShader(s);
}
// only program needs to be deleted
glDeleteProgram(_shader_program);
}
}
int uniform_location(std::string const& name) const
{
return glGetUniformLocation(_shader_program,name.c_str());
}
void bind(int location,const matrix3x3f& m)
{
glUniformMatrix3fv(location,1,GL_FALSE,m.ptr());
}
void bind(int location,const matrix4x4f& m)
{
glUniformMatrix4fv(location,1,GL_FALSE,m.ptr());
}
void bind(int location,const vector4f& v)
{
glUniform4fv(location,1,v.ptr());
}
void bind(int location,const float& v)
{
glUniform1f(location,v);
}
void bind(int location,const uint32_t& i)
{
glUniform1ui(location,i);
}
void bind(int location,const int32_t& i)
{
glUniform1i(location,i);
int uniform_location(std::string const& name) const {
return glGetUniformLocation(_shader_program, name.c_str());
}
void bind(int location,const texture& v)
{
this->bind(location,(int)v.native_handle());
void bind(int location, const matrix3x3f& m) {
glUniformMatrix3fv(location, 1, GL_FALSE, m.ptr());
}
void bind(int location, const matrix4x4f& m) {
glUniformMatrix4fv(location, 1, GL_FALSE, m.ptr());
}
void bind(int location, const vector4f& v) {
glUniform4fv(location, 1, v.ptr());
}
void bind(int location, const float& v) { glUniform1f(location, v); }
void bind(int location, const uint32_t& i) { glUniform1ui(location, i); }
void bind(int location, const int32_t& i) { glUniform1i(location, i); }
void bind(int location, const texture& v) {
this->bind(location, (int)v.native_handle());
}
};
shader::shader() { _impl = make_unique<impl>(*this); }
shader::shader()
{
_impl = make_unique<impl>(*this);
}
shader::~shader() {}
shader::~shader()
{
bool shader::ready() const { return _impl->is_valid(); }
}
bool shader::ready() const
{
return _impl->is_valid();
}
shader &shader::set_uniform_at_location(int location, float v)
{
_impl->bind(location,v);
shader& shader::set_uniform_at_location(int location, float v) {
_impl->bind(location, v);
return *this;
}
shader &shader::set_uniform_at_location(int location, uint32_t v)
{
_impl->bind(location,v); return *this;
shader& shader::set_uniform_at_location(int location, uint32_t v) {
_impl->bind(location, v);
return *this;
}
shader &shader::set_uniform_at_location(int location, int32_t v)
{
_impl->bind(location,v); return *this;
shader& shader::set_uniform_at_location(int location, int32_t v) {
_impl->bind(location, v);
return *this;
}
shader &shader::set_uniform_at_location(int location, vector4f const &v)
{
_impl->bind(location,v); return *this;
shader& shader::set_uniform_at_location(int location, vector4f const& v) {
_impl->bind(location, v);
return *this;
}
shader &shader::set_uniform_at_location(int location, matrix4x4f const &v)
{
_impl->bind(location,v); return *this;
shader& shader::set_uniform_at_location(int location, matrix4x4f const& v) {
_impl->bind(location, v);
return *this;
}
shader &shader::set_uniform_at_location(int location, texture const &v)
{
_impl->bind(location,v); return *this;
shader& shader::set_uniform_at_location(int location, texture const& v) {
_impl->bind(location, v);
return *this;
}
bool shader::build()
{
return _impl->build();
}
bool shader::build() { return _impl->build(); }
void shader::use()
{
_impl->use();
}
void shader::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
for (auto& u : c) {
// get name
std::string name = std::get<0>(u);
// get location
GLint loc = std::get<2>(u);
for (auto& u : c) {
// get name
std::string name = std::get<0>(u);
// get location
GLint loc = std::get<2>(u);
// if lower 0 check for location
if (loc < 0) {
loc = _impl->uniform_location(name);
std::get<2>(u) = loc; // cache location
}
// if lower 0 check for location
if (loc < 0) {
loc = _impl->uniform_location(name);
std::get<2>(u) = loc; // cache location
}
auto var = std::get<1>(u);
std::visit([this,loc](auto&& arg) {
auto var = std::get<1>(u);
std::visit([this, loc](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
// TODO query the std::variant of uniform_t
if constexpr ((std::is_same_v<T, vector4f>) ||
(std::is_same_v<T, matrix4x4f>) ||
(std::is_same_v<T, float>) ) {
set_uniform_at_location( loc, std::forward<T>(arg));
} else {
if constexpr ((std::is_same_v<T, vector4f>) ||
(std::is_same_v<T, matrix4x4f>) ||
(std::is_same_v<T, float>)) {
set_uniform_at_location(loc, std::forward<T>(arg));
} else {
debug::e() << "unknown uniform type";
}
}, var);
}
}
}, var);
}
}
uint32_t shader::native_handle() const
{
return _impl->_shader_program;
uint32_t shader::native_handle() const { return _impl->_shader_program; }
int shader::uniform_location(const std::string& name) const {
return _impl->uniform_location(name);
}
int shader::uniform_location(const std::string &name) const
{
return _impl->uniform_location(name);
}
}
} // namespace pw