Browse Source

Add ShaderManager class

master
Riyyi 4 years ago
parent
commit
e076c80a21
  1. 5
      inferno/src/inferno/application.cpp
  2. 120
      inferno/src/inferno/render/shader.cpp
  3. 41
      inferno/src/inferno/render/shader.h

5
inferno/src/inferno/application.cpp

@ -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());
} }

120
inferno/src/inferno/render/shader.cpp

@ -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;
}
} }

41
inferno/src/inferno/render/shader.h

@ -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;
}; };
} }

Loading…
Cancel
Save