BLT-With-Graphics-Template/include/blt/gfx/shader.h

228 lines
8.1 KiB
C
Raw Normal View History

2023-12-17 20:39:01 -05:00
/*
* <Short Description>
* Copyright (C) 2023 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef BLT_WITH_GRAPHICS_SHADER_H
#define BLT_WITH_GRAPHICS_SHADER_H
#include <blt/gfx/gl_includes.h>
#include <unordered_map>
#include <string>
#include <blt/math/math.h>
#include <blt/parse/templating.h>
#include <optional>
#include <memory>
2023-12-17 20:39:01 -05:00
namespace blt::gfx
{
2023-12-26 15:14:24 -05:00
class uniform_buffer
{
private:
GLuint uboID = 0;
2023-12-26 15:14:24 -05:00
size_t size_;
GLuint location_;
2023-12-26 15:14:24 -05:00
public:
2023-12-27 01:10:53 -05:00
explicit uniform_buffer(size_t size, GLuint location = 0);
uniform_buffer(void* data, size_t size, GLuint location = 0);
2023-12-26 15:14:24 -05:00
/**
* Resizes the internal UBO
* @param newSize new size for the UBO
*/
uniform_buffer& resize(size_t newSize);
2023-12-26 15:14:24 -05:00
/**
* Uploads data to the UBO. This can be an arbitrary locations and does not need to be the whole UBO.
*/
uniform_buffer& upload(void* data, size_t size, size_t offset = 0);
uniform_buffer& bind();
inline uniform_buffer& unbind()
{
glBindBuffer(GL_UNIFORM_BUFFER, 0);
return *this;
}
2023-12-26 15:14:24 -05:00
~uniform_buffer();
[[nodiscard]] inline size_t size() const
{ return size_; }
[[nodiscard]] inline GLuint location() const
{ return location_; }
2023-12-26 15:14:24 -05:00
};
2023-12-28 16:14:12 -05:00
class shader_base_t
2023-12-26 15:14:24 -05:00
{
friend uniform_buffer;
2023-12-17 20:39:01 -05:00
protected:
2023-12-26 15:14:24 -05:00
struct IntDefaultedToMinusOne
{
2023-12-17 20:39:01 -05:00
GLint i = -1;
inline explicit operator bool() const
{ return i != -1; }
2023-12-17 20:39:01 -05:00
};
2023-12-17 20:39:01 -05:00
std::unordered_map<std::string, IntDefaultedToMinusOne> uniformVars;
GLuint programID = 0;
IntDefaultedToMinusOne getUniformLocation(const std::string& name);
2023-12-17 20:39:01 -05:00
public:
2024-05-03 16:25:02 -04:00
const shader_base_t& bind() const
{
glUseProgram(programID);
return *this;
}
2024-05-03 16:25:02 -04:00
shader_base_t& bind()
2023-12-26 15:14:24 -05:00
{
2023-12-17 20:39:01 -05:00
glUseProgram(programID);
return *this;
}
2024-05-03 16:25:02 -04:00
shader_base_t& unbind()
{
glUseProgram(0);
return *this;
2023-12-17 20:39:01 -05:00
}
shader_base_t& setBool(const std::string& name, bool value);
shader_base_t& setInt(const std::string& name, int value);
shader_base_t& setFloat(const std::string& name, float value);
shader_base_t& setMatrix(const std::string& name, blt::mat4x4& matrix);
2024-01-11 14:36:48 -05:00
// poor solution: TODO
shader_base_t& setMatrix(const std::string& name, blt::mat4x4&& matrix);
shader_base_t& setVec2(const std::string& name, const blt::vec2& vec);
shader_base_t& setVec3(const std::string& name, const blt::vec3& vec);
shader_base_t& setVec4(const std::string& name, const blt::vec4& vec);
2024-05-05 17:03:50 -04:00
shader_base_t& setVec4i(const std::string& name, const blt::vec4i& vec);
shader_base_t& setVec2(const std::string& name, float x, float y);
shader_base_t& setVec3(const std::string& name, float x, float y, float z);
shader_base_t& setVec4(const std::string& name, float x, float y, float z, float w);
2023-12-17 20:39:01 -05:00
};
2023-12-17 20:39:01 -05:00
/**
* a basic computer shader class, contains the functions and resources required to use compute shaders!
*/
2023-12-28 16:14:12 -05:00
class compute_shader_t : public shader_base_t
2023-12-26 15:14:24 -05:00
{
2023-12-17 20:39:01 -05:00
private:
GLuint shaderID = 0;
2023-12-17 20:39:01 -05:00
public:
2023-12-28 16:14:12 -05:00
explicit compute_shader_t(const std::string& shader_source, bool loadAsString = true);
2024-05-03 16:25:02 -04:00
void execute(const int x, const int y, const int z) const
2023-12-26 15:14:24 -05:00
{
2023-12-17 20:39:01 -05:00
bind();
glDispatchCompute(x, y, z);
}
2023-12-28 16:14:12 -05:00
~compute_shader_t();
2023-12-17 20:39:01 -05:00
};
2023-12-28 16:14:12 -05:00
class shader_t : public shader_base_t
2023-12-26 15:14:24 -05:00
{
2023-12-17 20:39:01 -05:00
private:
GLuint vertexShaderID = 0;
GLuint fragmentShaderID = 0;
2023-12-17 20:39:01 -05:00
static unsigned int createShader(const std::string& source, int type);
2024-04-11 00:12:02 -04:00
static std::string loadShader(std::string_view file);
shader_t(std::string_view vertex, std::string_view fragment);
static std::pair<std::string, std::string> process_templates(template_engine_t& engine, std::string_view vertex,
std::string_view fragment);
2023-12-17 20:39:01 -05:00
public:
/**
* Creates a shader from source file
* @param vertex vertex shader source
* @param fragment fragment shader source
2023-12-17 20:39:01 -05:00
*/
static shader_t* make(std::optional<std::reference_wrapper<template_engine_t>> engine, std::string_view vertex,
std::string_view fragment);
static shader_t* make(std::string_view vertex, std::string_view fragment)
{
return make({}, vertex, fragment);
}
static std::unique_ptr<shader_t> make_unique(std::optional<std::reference_wrapper<template_engine_t>> engine,
std::string_view vertex, std::string_view fragment);
static std::unique_ptr<shader_t> make_unique(std::string_view vertex, std::string_view fragment)
{
return make_unique({}, vertex, fragment);
}
/**
* Creates a shader by loading lines of source from the file.
* @param vertex vertex shader file path
* @param fragment fragment shader file path
*/
static shader_t* load(std::optional<std::reference_wrapper<template_engine_t>> engine, std::string_view vertex,
std::string_view fragment);
static shader_t* load(std::string_view vertex, std::string_view fragment)
{
return load({}, vertex, fragment);
}
static std::unique_ptr<shader_t> load_unique(std::optional<std::reference_wrapper<template_engine_t>> engine,
std::string_view vertex, std::string_view fragment);
static std::unique_ptr<shader_t> load_unique(std::string_view vertex, std::string_view fragment)
{
return load_unique({}, vertex, fragment);
}
2023-12-28 16:14:12 -05:00
shader_t(shader_t&& move) noexcept;
shader_t(const shader_t& copy) = delete;
2023-12-17 20:39:01 -05:00
// used to set the location of VAOs to the in variables in opengl shaders.
2023-12-26 15:14:24 -05:00
void bindAttribute(int attribute, const std::string& name) const;
2023-12-17 20:39:01 -05:00
// used to set location of shared UBOs like the perspective and view matrix
2023-12-26 15:14:24 -05:00
void setUniformBlockLocation(const std::string& name, int location) const;
2023-12-28 16:14:12 -05:00
~shader_t();
2023-12-17 20:39:01 -05:00
};
}
#endif //BLT_WITH_GRAPHICS_SHADER_H