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

189 lines
6.3 KiB
C++

/*
* <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 <vector>
#include <unordered_map>
#include <string>
#include <blt/math/math.h>
namespace blt::gfx
{
class uniform_buffer
{
private:
GLuint uboID;
size_t size_;
GLuint location_;
public:
uniform_buffer(size_t size, GLuint location = 0);
uniform_buffer(void* data, size_t size, GLuint location = 0);
/**
* Resizes the internal UBO
* @param newSize new size for the UBO
*/
uniform_buffer& resize(size_t newSize);
/**
* 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);
/**
* Binds the UBO to a binding location
*/
uniform_buffer& bind(GLuint location);
~uniform_buffer();
[[nodiscard]] inline size_t size() const
{
return size_;
}
[[nodiscard]] inline GLuint location() const
{
return location_;
}
};
class shader_base
{
friend uniform_buffer;
protected:
struct IntDefaultedToMinusOne
{
GLint i = -1;
};
std::unordered_map<std::string, IntDefaultedToMinusOne> uniformVars;
GLuint programID = 0;
inline GLint getUniformLocation(const std::string& name)
{
if (uniformVars[name].i != -1)
return uniformVars[name].i;
int loc = glGetUniformLocation(programID, name.c_str());
uniformVars[name].i = loc;
return loc;
}
public:
inline void bind() const
{
glUseProgram(programID);
}
inline void setBool(const std::string& name, bool value)
{
glUniform1i(getUniformLocation(name), (int) value);
}
inline void setInt(const std::string& name, int value)
{
glUniform1i(getUniformLocation(name), value);
}
inline void setFloat(const std::string& name, float value)
{
glUniform1f(getUniformLocation(name), value);
}
inline void setMatrix(const std::string& name, blt::mat4x4& matrix)
{
glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, matrix.ptr());
}
inline void setVec3(const std::string& name, const blt::vec3& vec)
{
glUniform3f(getUniformLocation(name), vec.x(), vec.y(), vec.z());
}
inline void setVec4(const std::string& name, const blt::vec4& vec)
{
glUniform4f(getUniformLocation(name), vec.x(), vec.y(), vec.z(), vec.w());
}
inline void setVec2(const std::string& name, float x, float y)
{
glUniform2f(getUniformLocation(name), x, y);
}
inline void setVec3(const std::string& name, float x, float y, float z)
{
glUniform3f(getUniformLocation(name), x, y, z);
}
inline void setVec4(const std::string& name, float x, float y, float z, float w)
{
glUniform4f(getUniformLocation(name), x, y, z, w);
}
};
/**
* a basic computer shader class, contains the functions and resources required to use compute shaders!
*/
class compute_shader : public shader_base
{
private:
GLuint shaderID = 0;
public:
explicit compute_shader(const std::string& shader_source, bool loadAsString = true);
inline void execute(int x, int y, int z) const
{
bind();
glDispatchCompute(x, y, z);
}
~compute_shader();
};
class shader : public shader_base
{
private:
GLuint vertexShaderID = 0;
GLuint fragmentShaderID = 0;
static unsigned int createShader(const std::string& source, int type);
public:
/**
* Creates a shader
* @param vertex vertex shader source or file
* @param fragment fragment shader source or file
* @param geometry geometry shader source or file (optional)
* @param load_as_string load the shader as a string (true) or use the string to load the shader as a file (false)
*/
shader(const std::string& vertex, const std::string& fragment, bool load_as_string = true);
shader(shader&& move) noexcept;
// used to set the location of VAOs to the in variables in opengl shaders.
void bindAttribute(int attribute, const std::string& name) const;
// used to set location of shared UBOs like the perspective and view matrix
void setUniformBlockLocation(const std::string& name, int location) const;
~shader();
};
}
#endif //BLT_WITH_GRAPHICS_SHADER_H