psemek/libs/gfx/include/psemek/gfx/program.hpp
2020-10-23 17:14:54 +03:00

178 lines
4.6 KiB
C++

#pragma once
#include <psemek/gfx/gl.hpp>
#include <psemek/geom/vector.hpp>
#include <psemek/geom/point.hpp>
#include <psemek/geom/matrix.hpp>
#include <psemek/geom/interval.hpp>
#include <unordered_map>
#include <string_view>
namespace psemek::gfx
{
struct program
{
program(std::string_view vertex_source, std::string_view fragment_source);
program(std::string_view vertex_source, std::string_view geometry_source, std::string_view fragment_source);
~program();
GLuint id() const;
void bind() const;
GLint location(char const * name) const;
struct uniform_proxy
{
uniform_proxy(GLint location)
: location_(location)
{}
GLint location() const { return location_; }
void operator = (bool b);
void operator = (int i);
void operator = (unsigned int i);
void operator = (float f);
void operator = (geom::vector<int, 1> const & v);
void operator = (geom::vector<int, 2> const & v);
void operator = (geom::vector<int, 3> const & v);
void operator = (geom::vector<int, 4> const & v);
void operator = (geom::vector<unsigned int, 1> const & v);
void operator = (geom::vector<unsigned int, 2> const & v);
void operator = (geom::vector<unsigned int, 3> const & v);
void operator = (geom::vector<unsigned int, 4> const & v);
void operator = (geom::vector<float, 1> const & v);
void operator = (geom::vector<float, 2> const & v);
void operator = (geom::vector<float, 3> const & v);
void operator = (geom::vector<float, 4> const & v);
template <typename T, std::size_t D>
void operator = (geom::vector<T, D> const & v);
void operator = (geom::point<int, 1> const & v);
void operator = (geom::point<int, 2> const & v);
void operator = (geom::point<int, 3> const & v);
void operator = (geom::point<int, 4> const & v);
void operator = (geom::point<unsigned int, 1> const & v);
void operator = (geom::point<unsigned int, 2> const & v);
void operator = (geom::point<unsigned int, 3> const & v);
void operator = (geom::point<unsigned int, 4> const & v);
void operator = (geom::point<float, 1> const & v);
void operator = (geom::point<float, 2> const & v);
void operator = (geom::point<float, 3> const & v);
void operator = (geom::point<float, 4> const & v);
template <typename T, std::size_t D>
void operator = (geom::point<T, D> const & v);
void operator = (geom::matrix<float, 2, 2> const & m);
void operator = (geom::matrix<float, 2, 3> const & m);
void operator = (geom::matrix<float, 2, 4> const & m);
void operator = (geom::matrix<float, 3, 2> const & m);
void operator = (geom::matrix<float, 3, 3> const & m);
void operator = (geom::matrix<float, 3, 4> const & m);
void operator = (geom::matrix<float, 4, 2> const & m);
void operator = (geom::matrix<float, 4, 3> const & m);
void operator = (geom::matrix<float, 4, 4> const & m);
void operator = (geom::interval<int> const & i);
void operator = (geom::interval<unsigned int> const & i);
void operator = (geom::interval<float> const & i);
template <typename T>
void operator = (geom::interval<T> const & i);
private:
GLint location_;
};
uniform_proxy operator[] (char const * name) const;
private:
GLuint program_;
mutable std::unordered_map<std::string, GLint> uniforms_;
};
template <typename T, std::size_t D>
void program::uniform_proxy::operator = (geom::vector<T, D> const & v)
{
if constexpr (std::is_floating_point_v<T>)
{
(*this) = geom::cast<float>(v);
}
else if (std::is_integral_v<T>)
{
if constexpr (std::is_unsigned_v<T>)
{
(*this) = geom::cast<unsigned int>(v);
}
else
{
(*this) = geom::cast<int>(v);
}
}
else
{
static_assert("Unknown uniform data type");
}
}
template <typename T, std::size_t D>
void program::uniform_proxy::operator = (geom::point<T, D> const & p)
{
if constexpr (std::is_floating_point_v<T>)
{
(*this) = geom::cast<float>(p);
}
else if (std::is_integral_v<T>)
{
if constexpr (std::is_unsigned_v<T>)
{
(*this) = geom::cast<unsigned int>(p);
}
else
{
(*this) = geom::cast<int>(p);
}
}
else
{
static_assert("Unknown uniform data type");
}
}
template <typename T>
void program::uniform_proxy::operator = (geom::interval<T> const & i)
{
if constexpr (std::is_floating_point_v<T>)
{
(*this) = geom::cast<float>(i);
}
else if (std::is_integral_v<T>)
{
if constexpr (std::is_unsigned_v<T>)
{
(*this) = geom::cast<unsigned int>(i);
}
else
{
(*this) = geom::cast<int>(i);
}
}
else
{
static_assert("Unknown uniform data type");
}
}
}