clean up some headers
This commit is contained in:
parent
c70c18e41c
commit
a5d42995b2
5 changed files with 251 additions and 358 deletions
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue