Add ShaderManager class
This commit is contained in:
@@ -89,8 +89,9 @@ namespace Inferno {
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
m_shaderSimple = std::make_shared<Shader>("assets/glsl/simple.vert", "assets/glsl/simple.frag");
|
ShaderManager shaderManager;
|
||||||
m_shaderTexture = std::make_shared<Shader>("assets/glsl/texture.vert", "assets/glsl/texture.frag");
|
m_shaderSimple = shaderManager.load("assets/glsl/simple");
|
||||||
|
m_shaderTexture = shaderManager.load("assets/glsl/texture");
|
||||||
m_shaderTexture->setInt("u_texture", m_texture->id());
|
m_shaderTexture->setInt("u_texture", m_texture->id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,12 @@
|
|||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
Shader::Shader(const std::string& vertexSource, const std::string& fragmentSource) :
|
Shader::Shader(const std::string& name)
|
||||||
m_program(0)
|
: m_id(0)
|
||||||
{
|
{
|
||||||
// Get file contents
|
// Get file contents
|
||||||
std::string vertexSrc = File::read(vertexSource);
|
std::string vertexSrc = File::read(name + ".vert");
|
||||||
std::string fragmentSrc = File::read(fragmentSource);
|
std::string fragmentSrc = File::read(name + ".frag");
|
||||||
|
|
||||||
// Compile shaders
|
// Compile shaders
|
||||||
uint32_t vertexID = compileShader(GL_VERTEX_SHADER, vertexSrc.c_str());
|
uint32_t vertexID = compileShader(GL_VERTEX_SHADER, vertexSrc.c_str());
|
||||||
@@ -24,7 +24,7 @@ namespace Inferno {
|
|||||||
|
|
||||||
// Link shaders
|
// Link shaders
|
||||||
if (vertexID > 0 && fragmentID > 0) {
|
if (vertexID > 0 && fragmentID > 0) {
|
||||||
m_program = linkShader(vertexID, fragmentID);
|
m_id = linkShader(vertexID, fragmentID);
|
||||||
}
|
}
|
||||||
// Clear resources
|
// Clear resources
|
||||||
else if (vertexID > 0) glDeleteShader(vertexID);
|
else if (vertexID > 0) glDeleteShader(vertexID);
|
||||||
@@ -33,75 +33,70 @@ namespace Inferno {
|
|||||||
|
|
||||||
Shader::~Shader()
|
Shader::~Shader()
|
||||||
{
|
{
|
||||||
if (m_program > 0) {
|
if (m_id > 0) {
|
||||||
glDeleteProgram(m_program);
|
glDeleteProgram(m_id);
|
||||||
m_program = 0;
|
m_id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
int32_t Shader::findUniform(const std::string& name) const
|
||||||
|
{
|
||||||
|
int32_t location = glGetUniformLocation(m_id, name.c_str());
|
||||||
|
ASSERT(location != -1, "Shader could not find uniform '{}'", name.c_str());
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
void Shader::setInt(const std::string &name, int value)
|
void Shader::setInt(const std::string &name, int value)
|
||||||
{
|
{
|
||||||
// Set unifrom int
|
// Set unifrom int
|
||||||
GLint location = glGetUniformLocation(m_program, name.c_str());
|
glUniform1i(findUniform(name), value);
|
||||||
glUniform1i(location, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const std::string &name, float value) const
|
void Shader::setFloat(const std::string &name, float value) const
|
||||||
{
|
{
|
||||||
// Set uniform float
|
// Set uniform float
|
||||||
GLint location = glGetUniformLocation(m_program, name.c_str());
|
glUniform1f(findUniform(name), value);
|
||||||
glUniform1f(location, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const std::string &name, float v1, float v2, float v3, float v4) const
|
void Shader::setFloat(const std::string &name, float v1, float v2, float v3, float v4) const
|
||||||
{
|
{
|
||||||
// Set uniform vec4 data
|
// Set uniform vec4 data
|
||||||
GLint location = glGetUniformLocation(m_program, name.c_str());
|
glUniform4f(findUniform(name), v1, v2, v3, v4);
|
||||||
glUniform4f(location, v1, v2, v3, v4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const std::string &name, glm::vec2 value) const
|
void Shader::setFloat(const std::string &name, glm::vec2 value) const
|
||||||
{
|
{
|
||||||
// Set uniform vec2 data
|
// Set uniform vec2 data
|
||||||
GLint location = glGetUniformLocation(m_program, name.c_str());
|
glUniform2f(findUniform(name), value.x, value.y);
|
||||||
glUniform2f(location, value.x, value.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const std::string &name, glm::vec3 value) const
|
void Shader::setFloat(const std::string &name, glm::vec3 value) const
|
||||||
{
|
{
|
||||||
// Set uniform vec3 data
|
// Set uniform vec3 data
|
||||||
GLint location = glGetUniformLocation(m_program, name.c_str());
|
glUniform3f(findUniform(name), value.x, value.y, value.z);
|
||||||
glUniform3f(location, value.x, value.y, value.z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const std::string &name, glm::vec4 value) const
|
void Shader::setFloat(const std::string &name, glm::vec4 value) const
|
||||||
{
|
{
|
||||||
// Set uniform vec4 data
|
// Set uniform vec4 data
|
||||||
GLint location = glGetUniformLocation(m_program, name.c_str());
|
glUniform4f(findUniform(name), value.x, value.y, value.z, value.w);
|
||||||
glUniform4f(location, value.x, value.y, value.z, value.w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const std::string &name, glm::mat3 matrix) const
|
void Shader::setFloat(const std::string &name, glm::mat3 matrix) const
|
||||||
{
|
{
|
||||||
// Set uniform mat3 data
|
// Set uniform mat3 data
|
||||||
GLint location = glGetUniformLocation(m_program, name.c_str());
|
glUniformMatrix3fv(findUniform(name), 1, GL_FALSE, glm::value_ptr(matrix));
|
||||||
glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const std::string &name, glm::mat4 matrix) const
|
void Shader::setFloat(const std::string &name, glm::mat4 matrix) const
|
||||||
{
|
{
|
||||||
// Set uniform mat4 data
|
// Set uniform mat4 data
|
||||||
GLint location = glGetUniformLocation(m_program, name.c_str());
|
glUniformMatrix4fv(findUniform(name), 1, GL_FALSE, glm::value_ptr(matrix));
|
||||||
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
void Shader::bind() const
|
void Shader::bind() const
|
||||||
{
|
{
|
||||||
glUseProgram(m_program);
|
glUseProgram(m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::unbind() const
|
void Shader::unbind() const
|
||||||
@@ -109,8 +104,6 @@ namespace Inferno {
|
|||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
uint32_t Shader::compileShader(int32_t type, const char* source) const
|
uint32_t Shader::compileShader(int32_t type, const char* source) const
|
||||||
{
|
{
|
||||||
// Create new shader
|
// Create new shader
|
||||||
@@ -190,4 +183,71 @@ namespace Inferno {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void ShaderManager::add(const std::string& name, const std::shared_ptr<Shader>& shader)
|
||||||
|
{
|
||||||
|
// Construct (key, value) pair and insert it into the unordered_map
|
||||||
|
m_shaderList.emplace(name, shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Shader> ShaderManager::load(const std::string& name)
|
||||||
|
{
|
||||||
|
if (exists(name)) {
|
||||||
|
return get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Shader> shader = std::make_shared<Shader>(name);
|
||||||
|
add(name, shader);
|
||||||
|
return get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Shader> ShaderManager::load(const std::string& vertexSource,
|
||||||
|
const std::string& fragmentSource)
|
||||||
|
{
|
||||||
|
std::string name = computeName(vertexSource, fragmentSource);
|
||||||
|
return load(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Shader> ShaderManager::get(const std::string& name)
|
||||||
|
{
|
||||||
|
return exists(name) ? m_shaderList.at(name) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShaderManager::exists(const std::string& name)
|
||||||
|
{
|
||||||
|
return m_shaderList.find(name) != m_shaderList.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderManager::remove(const std::string& name)
|
||||||
|
{
|
||||||
|
if (exists(name)) {
|
||||||
|
m_shaderList.erase(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderManager::remove(const std::shared_ptr<Shader>& shader)
|
||||||
|
{
|
||||||
|
if (exists(shader->name())) {
|
||||||
|
m_shaderList.erase(shader->name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ShaderManager::computeName(const std::string& vertexSource,
|
||||||
|
const std::string& fragmentSource)
|
||||||
|
{
|
||||||
|
auto vertexPos = vertexSource.find_last_of('.');
|
||||||
|
auto fragmentPos = fragmentSource.find_last_of('.');
|
||||||
|
|
||||||
|
ASSERT(vertexPos != std::string::npos, "Shader did not have file extension: '{}'", vertexSource);
|
||||||
|
ASSERT(fragmentPos != std::string::npos, "Shader did not have file extension: '{}'", fragmentSource);
|
||||||
|
|
||||||
|
auto vertexName = vertexSource.substr(0, vertexPos);
|
||||||
|
auto fragmentName = vertexSource.substr(0, fragmentPos);
|
||||||
|
|
||||||
|
ASSERT(vertexName == fragmentName, "Shader names did not match: {} {}", vertexSource, fragmentSource);
|
||||||
|
|
||||||
|
return vertexName;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,21 @@
|
|||||||
#define SHADER_H
|
#define SHADER_H
|
||||||
|
|
||||||
#include <cstdint> // std::int32_t, std::uint32_t
|
#include <cstdint> // std::int32_t, std::uint32_t
|
||||||
|
#include <memory>
|
||||||
#include <string> // std::string
|
#include <string> // std::string
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
class Shader {
|
class Shader {
|
||||||
public:
|
public:
|
||||||
Shader(const std::string &vertexSource, const std::string &fragmentSource);
|
Shader(const std::string& name);
|
||||||
~Shader();
|
~Shader();
|
||||||
|
|
||||||
// -----------------------------------------
|
int32_t findUniform(const std::string& name) const;
|
||||||
|
|
||||||
// Set uniform data
|
|
||||||
void setInt(const std::string& name, int value);
|
void setInt(const std::string& name, int value);
|
||||||
void setFloat(const std::string& name, float value) const;
|
void setFloat(const std::string& name, float value) const;
|
||||||
void setFloat(const std::string& name, float v1, float v2, float v3, float v4) const;
|
void setFloat(const std::string& name, float v1, float v2, float v3, float v4) const;
|
||||||
@@ -25,16 +26,11 @@ namespace Inferno {
|
|||||||
void setFloat(const std::string& name, glm::mat3 matrix) const;
|
void setFloat(const std::string& name, glm::mat3 matrix) const;
|
||||||
void setFloat(const std::string& name, glm::mat4 matrix) const;
|
void setFloat(const std::string& name, glm::mat4 matrix) const;
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
void bind() const;
|
void bind() const;
|
||||||
void unbind() const;
|
void unbind() const;
|
||||||
|
|
||||||
// -----------------------------------------
|
inline std::string name() const { return m_name; }
|
||||||
|
inline uint32_t program() const { return m_id; }
|
||||||
inline uint32_t getProgram() const { return m_program; }
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t compileShader(int32_t type, const char* shaderSource) const;
|
uint32_t compileShader(int32_t type, const char* shaderSource) const;
|
||||||
@@ -42,7 +38,30 @@ namespace Inferno {
|
|||||||
int32_t checkStatus(uint32_t check, bool isProgram = false) const;
|
int32_t checkStatus(uint32_t check, bool isProgram = false) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_program;
|
std::string m_name;
|
||||||
|
uint32_t m_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class ShaderManager {
|
||||||
|
public:
|
||||||
|
void add(const std::string& name, const std::shared_ptr<Shader>& shader);
|
||||||
|
std::shared_ptr<Shader> load(const std::string& name);
|
||||||
|
std::shared_ptr<Shader> load(const std::string& vertexSource,
|
||||||
|
const std::string& fragmentSource);
|
||||||
|
std::shared_ptr<Shader> get(const std::string& name);
|
||||||
|
bool exists(const std::string& name);
|
||||||
|
|
||||||
|
void remove(const std::string& name);
|
||||||
|
void remove(const std::shared_ptr<Shader>& shader);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string computeName(const std::string& vertexSource,
|
||||||
|
const std::string& fragmentSource);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Shader>> m_shaderList;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user