our_dick/include/gfx/ogl/shader_program.hpp
2022-02-10 16:56:01 -08:00

300 lines
8.7 KiB
C++

/**
This file is a part of our_dick
Copyright (C) 2020-2022 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OUR_DICK_GRAPHICS_OGL_SHADER_PROGRAM_HPP
#define OUR_DICK_GRAPHICS_OGL_SHADER_PROGRAM_HPP
#include "gl_include.hpp"
#include "shader.hpp"
#include "texture.hpp"
#include "ubo.hpp"
#include <utility> //forward
#include <string>
#include "math/math.hpp"
namespace gfx::ogl{
using namespace math;
class uniform
{
private:
GLuint m_shader_id;
GLint m_location;
public:
uniform(GLuint owner, const char* name);
uniform(GLuint owner, GLint location);
uniform(const uniform&) = default;
uniform(uniform&&) = default;
~uniform(void) = default;
uniform& operator=(const uniform&) = default;
uniform& operator=(uniform&&) = default;
GLenum get_type(void)const;
GLfloat get_float(void)const;
math::vec2<GLfloat> get_vec2(void)const;
math::vec3<GLfloat> get_vec3(void)const;
math::vec4<GLfloat> get_vec4(void)const;
GLdouble get_double(void)const;
math::vec2<GLdouble> get_dvec2(void)const;
math::vec3<GLdouble> get_dvec3(void)const;
math::vec4<GLdouble> get_dvec4(void)const;
GLint get_int(void)const;
math::vec2<GLint> get_ivec2(void)const;
math::vec3<GLint> get_ivec3(void)const;
math::vec4<GLint> get_ivec4(void)const;
GLuint get_uint(void)const;
math::vec2<GLuint> get_uvec2(void)const;
math::vec3<GLuint> get_uvec3(void)const;
math::vec4<GLuint> get_uvec4(void)const;
GLboolean get_bool(void)const;
math::vec2<GLboolean> get_bvec2(void)const;
math::vec3<GLboolean> get_bvec3(void)const;
math::vec4<GLboolean> get_bvec4(void)const;
math::mat2<GLfloat> get_mat2(void)const;
math::mat3<GLfloat> get_mat3(void)const;
math::mat4<GLfloat> get_mat4(void)const;
math::matrix<GLfloat,2,3> get_mat2x3(void)const;
math::matrix<GLfloat,2,4> get_mat2x4(void)const;
math::matrix<GLfloat,3,2> get_mat3x2(void)const;
math::matrix<GLfloat,3,4> get_mat3x4(void)const;
math::matrix<GLfloat,4,2> get_mat4x2(void)const;
math::matrix<GLfloat,4,3> get_mat4x3(void)const;
math::mat2<GLdouble> get_dmat2(void)const;
math::mat3<GLdouble> get_dmat3(void)const;
math::mat4<GLdouble> get_dmat4(void)const;
math::matrix<GLdouble,2,3> get_dmat2x3(void)const;
math::matrix<GLdouble,2,4> get_dmat2x4(void)const;
math::matrix<GLdouble,3,2> get_dmat3x2(void)const;
math::matrix<GLdouble,3,4> get_dmat3x4(void)const;
math::matrix<GLdouble,4,2> get_dmat4x2(void)const;
math::matrix<GLdouble,4,3> get_dmat4x3(void)const;
//float
void set(GLfloat);
void set(GLfloat, GLfloat);
void set(GLfloat, GLfloat, GLfloat);
void set(GLfloat, GLfloat, GLfloat, GLfloat);
//int
void set(GLint);
void set(GLint, GLint);
void set(GLint, GLint, GLint);
void set(GLint, GLint, GLint, GLint);
//unsigned int
void set(GLuint);
void set(GLuint, GLuint);
void set(GLuint, GLuint, GLuint);
void set(GLuint, GLuint, GLuint, GLuint);
//Texture
void set(const texture&, GLuint tex_unit = 0);
void set(const texture_array& t, GLuint tex_unit = 0);
void set(const weak_texture&, GLuint tex_unit = 0);
//Float vectors
void set(const vec2<GLfloat>&);
void set(const vec3<GLfloat>&);
void set(const vec4<GLfloat>&);
//Float vector array
void set(GLsizei count, const vec2<GLfloat>*);
void set(GLsizei count, const vec3<GLfloat>*);
void set(GLsizei count, const vec4<GLfloat>*);
//Explicit float vectors
void set_1(GLsizei count, const GLfloat*);
void set_2(GLsizei count, const GLfloat*);
void set_3(GLsizei count, const GLfloat*);
void set_4(GLsizei count, const GLfloat*);
//Int vectors
void set(const vec2<GLint>&);
void set(const vec3<GLint>&);
void set(const vec4<GLint>&);
//Int vector array
void set(GLsizei count, const vec2<GLint>*);
void set(GLsizei count, const vec3<GLint>*);
void set(GLsizei count, const vec4<GLint>*);
//Explicit int vectors
void set_1(GLsizei count, const GLint*);
void set_2(GLsizei count, const GLint*);
void set_3(GLsizei count, const GLint*);
void set_4(GLsizei count, const GLint*);
//Unsigned int vectors
void set(const vec2<GLuint>&);
void set(const vec3<GLuint>&);
void set(const vec4<GLuint>&);
//Unsigned int vector array
void set(GLsizei count, const vec2<GLuint>*);
void set(GLsizei count, const vec3<GLuint>*);
void set(GLsizei count, const vec4<GLuint>*);
//Explicit unsigned int vectors
void set_1(GLsizei count, const GLuint*);
void set_2(GLsizei count, const GLuint*);
void set_3(GLsizei count, const GLuint*);
void set_4(GLsizei count, const GLuint*);
//Matrices
void set(const mat2<GLfloat>&);
void set(const mat3<GLfloat>&);
void set(const mat4<GLfloat>&);
//Matrix array
void set(GLsizei count, const mat2<GLfloat>*);
void set(GLsizei count, const mat3<GLfloat>*);
void set(GLsizei count, const mat4<GLfloat>*);
//Explicit matrices
void set_mat2(GLsizei count, const GLfloat*);
void set_mat3(GLsizei count, const GLfloat*);
void set_mat4(GLsizei count, const GLfloat*);
void set_mat2x3(GLsizei count, const GLfloat*);
void set_mat3x2(GLsizei count, const GLfloat*);
void set_mat2x4(GLsizei count, const GLfloat*);
void set_mat4x2(GLsizei count, const GLfloat*);
void set_mat3x4(GLsizei count, const GLfloat*);
void set_mat4x3(GLsizei count, const GLfloat*);
private:
GLint get_location_from_name_(const char* name);
};
class uniform_block
{
private:
GLuint m_shader_id;
GLuint m_index;
public:
uniform_block(GLuint owner, GLuint index);
uniform_block(GLuint owner, const char* name);
uniform_block(const uniform_block&) = default;
uniform_block(uniform_block&&) = default;
~uniform_block(void) = default;
uniform_block& operator=(const uniform_block&) = default;
uniform_block& operator=(uniform_block&&) = default;
void set_binding(size_t binding);
template<class... Types>
void set_binding(size_t binding, const ubo<Types...>& u);
private:
GLuint get_index_from_name_(const char* name);
};
//represents an opengl program (NOT a shader object)
class shader_program
{
private:
GLuint m_shader_id = 0; //handle to opengl program
public:
//create the program with no shaders attached
shader_program(void);
//create the program and attach 'args'... as shaders
template<class... Args>
shader_program(Args&&... args);
shader_program(const shader_program&) = delete;
shader_program(shader_program&&);
~shader_program(void);
shader_program& operator=(const shader_program&) = delete;
shader_program& operator=(shader_program&&);
//release ownership of the program handle. unsafe
GLuint release(void);
//attach a single shader to this program
void attach_shader(const shader& s);
//attach many shaders to this program
template<class... Args>
void attach_shaders(const shader& s, Args&&... args);
//attempt to link the program with the currently attached shaders. returns true on success
bool link(void);
//set this program as the currently active one in the gl context
void use(void);
//search for a uniform by name in this program
GLint get_uniform_loc(const char* u)const;
GLuint get_uniform_block_loc(const char* u)const;
//raw access to the program handle
GLuint raw(void)const;
//check if an error exists after a link attempt
bool has_link_error(void)const;
//get the most recently generated error from this program's infolog
std::string get_error(void)const;
uniform get_uniform(const char* name);
uniform get_uniform(int uloc);
GLenum get_uniform_type(const char* name)const;
GLenum get_uniform_type(int uloc)const;
uniform_block get_uniform_block(const char* name);
uniform_block get_uniform_block(unsigned int uloc);
};
template<class... Args>
shader_program::shader_program(Args&&... args):
shader_program()
{
attach_shaders(std::forward<Args>(args)...);
link();
}
template<class... Args>
void shader_program::attach_shaders(const shader& s, Args&&... args){
attach_shader(s);
if constexpr(sizeof...(args) > 0){
attach_shaders(std::forward<Args>(args)...);
}
}
template<class... Types>
void uniform_block::set_binding(size_t binding, const ubo<Types...>& u){
u.bind(binding);
set_binding(binding);
}
}
#endif