Im just trying to setup my shader function in a class in a way that would make me work with it easier and in a more understandable way.
In Shader.h:
#pragma once
#include"Includes.h"
#include<unordered_map>
namespace GAME
{
enum class Shader_Type
{
NONE = -1,
VERTEX = 0,
FRAGMENT = 1,
GEOMETRY = 2
};
class Shader
{
private:
std::map<Shader_Type, std::string>m_Data;
Shader_Type type;
std::unordered_map<std::string, int> m_UniformLocationCache;
public:
unsigned int Program_id;
private:
unsigned int Compiler(unsigned int type, const std::string& source);
void Check_errors(unsigned int* id, unsigned int type);
void Create_shader();
public:
Shader();
~Shader();
Shader(const Shader& e);
Shader& operator=(const Shader& e);
Shader(Shader&& e)noexcept;
Shader& operator=(Shader&& e)noexcept;
Shader* operator-> () { return this; }
operator Shader* () { return this; }
Shader* Clone() { return new Shader(*this); }
void Bind() const;
void Unbind() const;
void Reset();
void Init(std::string vertexShader = "", std::string fragmentshader = "", std::string Geometryshader = "");
unsigned int GetUniformLocation(const std::string& name);
//uniforms
void Setuniform1f(const std::string& name, float v1);
void Setuniform2f(const std::string& name, float v1, float v2);
void Setuniform3f(const std::string& name, float v1, float v2, float v3);
void Setuniform4f(const std::string& name, float v1, float v2, float v3, float v4);
void Setuniform1i(const std::string& name, int v1);
void Setuniform2i(const std::string& name, int v1, int v2);
void Setuniform3i(const std::string& name, int v1, int v2, int v3);
void Setuniform4i(const std::string& name, int v1, int v2, int v3, int v4);
void Setuniform1d(const std::string& name, double v1);
void Setuniform2d(const std::string& name, double v1, double v2);
void Setuniform3d(const std::string& name, double v1, double v2, double v3);
void Setuniform4d(const std::string& name, double v1, double v2, double v3, double v4);
void Setuniform1fv(const std::string& name, int count, glm::fvec1 v);
void Setuniform2fv(const std::string& name, int count, glm::fvec2 v);
void Setuniform3fv(const std::string& name, int count, glm::fvec3 v);
void Setuniform4fv(const std::string& name, int count, glm::fvec4 v);
void Setuniform1iv(const std::string& name, int count, glm::ivec1 v);
void Setuniform2iv(const std::string& name, int count, glm::ivec2 v);
void Setuniform3iv(const std::string& name, int count, glm::ivec3 v);
void Setuniform4iv(const std::string& name, int count, glm::ivec4 v);
void Setuniform1dv(const std::string& name, int count, glm::dvec1 v);
void Setuniform2dv(const std::string& name, int count, glm::dvec2 v);
void Setuniform3dv(const std::string& name, int count, glm::dvec3 v);
void Setuniform4dv(const std::string& name, int count, glm::dvec4 v);
void SetUniformMat2fv(const std::string& name, int count, GLboolean transpose, glm::mat2 value);
void SetUniformMat3fv(const std::string& name, int count, GLboolean transpose, glm::mat3 value);
void SetUniformMat4fv(const std::string& name, int count, GLboolean transpose, glm::mat4 value);
};
}
#include"Includes.h"
is the header where I kept all includes of gl and other required classes
In Shader.cpp:
#include "Shader.h"
namespace GAME
{
Shader::Shader()
:Program_id(0), type(Shader_Type::NONE)
{
}
Shader::~Shader()
{
}
Shader::Shader(const Shader& e)
{
this->m_Data = e.m_Data;
this->m_UniformLocationCache = e.m_UniformLocationCache;
this->Program_id = e.Program_id;
this->type = Shader_Type(e.type);
}
Shader& Shader::operator=(const Shader& e)
{
this->m_Data = e.m_Data;
this->m_UniformLocationCache = e.m_UniformLocationCache;
this->Program_id = e.Program_id;
this->type = Shader_Type(e.type);
return *this;
}
Shader::Shader(Shader&& e) noexcept
{
this->m_Data = std::move(e.m_Data);
this->m_UniformLocationCache = std::move(e.m_UniformLocationCache);
this->Program_id =std::move( e.Program_id);
this->type = std::move(Shader_Type(e.type));
}
Shader& Shader::operator=(Shader&& e) noexcept
{
this->m_Data = std::move(e.m_Data);
this->m_UniformLocationCache = std::move(e.m_UniformLocationCache);
this->Program_id = std::move(e.Program_id);
this->type = std::move(Shader_Type(e.type));
return *this;
}
void Shader::Bind() const
{
glUseProgram(Program_id);
}
void Shader::Unbind() const
{
glUseProgram(0);
}
void Shader::Reset()
{
this->type = Shader_Type::NONE;
this->Program_id = 0;
this->m_UniformLocationCache.clear();
this->m_Data.clear();
}
void Shader::Init(std::string vertexShader, std::string fragmentshader, std::string Geometryshader)
{
m_Data[Shader_Type::VERTEX] = vertexShader;
m_Data[Shader_Type::FRAGMENT] = fragmentshader;
m_Data[Shader_Type::GEOMETRY] = Geometryshader;
Create_shader();
Unbind();
}
unsigned int Shader::GetUniformLocation(const std::string& name)
{
if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
{
return m_UniformLocationCache[name];
}
int location = glGetUniformLocation(Program_id, name.c_str());
if (location == -1)
{
std::cout << "Warning! Uniform " << name << " is unused or not found or does no exist!" << std::endl;
}
else
m_UniformLocationCache[name] = location;
return location;
}
void Shader::Create_shader()
{
Program_id = glCreateProgram();
if (m_Data[Shader_Type::VERTEX] != "")
{
unsigned int vs = Compiler(GL_VERTEX_SHADER, m_Data[Shader_Type::VERTEX]);
glAttachShader(Program_id, vs);
glDeleteShader(vs);
}
if (m_Data[Shader_Type::FRAGMENT] != "")
{
unsigned int fs = Compiler(GL_FRAGMENT_SHADER, m_Data[Shader_Type::FRAGMENT]);
glAttachShader(Program_id, fs);
glDeleteShader(fs);
}
if (m_Data[Shader_Type::GEOMETRY] != "")
{
unsigned int gs = Compiler(GL_GEOMETRY_SHADER, m_Data[Shader_Type::GEOMETRY]);
glAttachShader(Program_id, gs);
glDeleteShader(gs);
}
glLinkProgram(Program_id);
glValidateProgram(Program_id);
}
unsigned int Shader::Compiler(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
Check_errors(&id, type);
return id;
}
void Shader::Check_errors(unsigned int* id, unsigned int type)
{
int result;
glGetShaderiv(*id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
int length;
glGetShaderiv(*id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(*id, length, &length, message);
std::cout << "Failed to compile ";
switch (type)
{
case GL_VERTEX_SHADER:
std::cout << "vertex";
break;
case GL_FRAGMENT_SHADER:
std::cout << "fragment";
break;
case GL_GEOMETRY_SHADER:
std::cout << "geometry";
break;
default:
std::cout << "unknown";
break;
}
std::cout << " shader!" << std::endl;
std::cout << " Error:" << message << std::endl;
glDeleteShader(*id);
id = 0;
}
}
void Shader::Setuniform1f(const std::string& name, float v1)
{
glUniform1f(GetUniformLocation(name), v1);
}
void Shader::Setuniform2f(const std::string& name, float v1, float v2)
{
glUniform2f(GetUniformLocation(name), v1, v2);
}
void Shader::Setuniform3f(const std::string& name, float v1, float v2, float v3)
{
glUniform3f(GetUniformLocation(name), v1, v2, v3);
}
void Shader::Setuniform4f(const std::string& name, float v1, float v2, float v3, float v4)
{
glUniform4f(GetUniformLocation(name), v1, v2, v3, v4);
}
void Shader::Setuniform1i(const std::string& name, int v1)
{
glUniform1i(GetUniformLocation(name), v1);
}
void Shader::Setuniform2i(const std::string& name, int v1, int v2)
{
glUniform2i(GetUniformLocation(name), v1, v2);
}
void Shader::Setuniform3i(const std::string& name, int v1, int v2, int v3)
{
glUniform3i(GetUniformLocation(name), v1, v2, v3);
}
void Shader::Setuniform4i(const std::string& name, int v1, int v2, int v3, int v4)
{
glUniform4i(GetUniformLocation(name), v1, v2, v3, v4);
}
void Shader::Setuniform1d(const std::string& name, double v1)
{
glUniform1d(GetUniformLocation(name), v1);
}
void Shader::Setuniform2d(const std::string& name, double v1, double v2)
{
glUniform2d(GetUniformLocation(name), v1, v2);
}
void Shader::Setuniform3d(const std::string& name, double v1, double v2, double v3)
{
glUniform3d(GetUniformLocation(name), v1, v2, v3);
}
void Shader::Setuniform4d(const std::string& name, double v1, double v2, double v3, double v4)
{
glUniform4d(GetUniformLocation(name), v1, v2, v3, v4);
}
void Shader::Setuniform1fv(const std::string& name, int count, glm::fvec1 v)
{
glUniform1fv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform2fv(const std::string& name, int count, glm::fvec2 v)
{
glUniform2fv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform3fv(const std::string& name, int count, glm::fvec3 v)
{
glUniform3fv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform4fv(const std::string& name, int count, glm::fvec4 v)
{
glUniform4fv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform1iv(const std::string& name, int count, glm::ivec1 v)
{
glUniform1iv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform2iv(const std::string& name, int count, glm::ivec2 v)
{
glUniform2iv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform3iv(const std::string& name, int count, glm::ivec3 v)
{
glUniform3iv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform4iv(const std::string& name, int count, glm::ivec4 v)
{
glUniform4iv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform1dv(const std::string& name, int count, glm::dvec1 v)
{
glUniform1dv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform2dv(const std::string& name, int count, glm::dvec2 v)
{
glUniform2dv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform3dv(const std::string& name, int count, glm::dvec3 v)
{
glUniform3dv(GetUniformLocation(name), count, &v[0]);
}
void Shader::Setuniform4dv(const std::string& name, int count, glm::dvec4 v)
{
glUniform4dv(GetUniformLocation(name), count, &v[0]);
}
void Shader::SetUniformMat2fv(const std::string& name, int count, GLboolean transpose, glm::mat2 value)
{
glUniformMatrix2fv(GetUniformLocation(name), count, transpose, &value[0][0]);
}
void Shader::SetUniformMat3fv(const std::string& name, int count, GLboolean transpose, glm::mat3 value)
{
glUniformMatrix3fv(GetUniformLocation(name), count, transpose, &value[0][0]);
}
void Shader::SetUniformMat4fv(const std::string& name, int count, GLboolean transpose, glm::mat4 value)
{
glUniformMatrix4fv(GetUniformLocation(name), count, transpose, &value[0][0]);
}
}
Is this enough for using in normal programming or do i need to make some changes to make it more usable and efficient? Any helpful review would be appreciated. Thanks in advance!!