Files
panopainter/src/shader.cpp

218 lines
5.6 KiB
C++

#include "pch.h"
#include "log.h"
#include "shader.h"
std::map<kShader, Shader> ShaderManager::m_shaders;
Shader* ShaderManager::m_current;
bool Shader::create(const char* vertex, const char* fragment)
{
GLint status;
static char infolog[4096];
int infolen;
const GLchar* source;
auto vs = glCreateShader(GL_VERTEX_SHADER);
if (!vs)
{
return false;
}
source = vertex;
glShaderSource(vs, 1, &source, nullptr);
glCompileShader(vs);
glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
LOG("VERTEX SHADER:\n%s", infolog);
if (status == 0)
{
glDeleteShader(vs);
return false;
}
auto fs = glCreateShader(GL_FRAGMENT_SHADER);
if (!fs)
{
glDeleteShader(vs);
return false;
}
source = fragment;
glShaderSource(fs, 1, &source, nullptr);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
LOG("FRAGMENT SHADER:\n%s", infolog);
if (status == 0)
{
glDeleteShader(vs);
glDeleteShader(fs);
return false;
}
auto ps = glCreateProgram();
if (!ps)
{
glDeleteShader(vs);
glDeleteShader(fs);
return false;
}
glAttachShader(ps, vs);
glAttachShader(ps, fs);
glDeleteShader(vs);
glDeleteShader(fs);
glLinkProgram(ps);
if (glGetAttribLocation(ps, "pos") != -1)
glBindAttribLocation(ps, 0, "pos");
if (glGetAttribLocation(ps, "uvs") != -1)
glBindAttribLocation(ps, 1, "uvs");
if (glGetAttribLocation(ps, "uvs2") != -1)
glBindAttribLocation(ps, 2, "uvs2");
if (glGetAttribLocation(ps, "col") != -1)
glBindAttribLocation(ps, 3, "col");
if (glGetAttribLocation(ps, "nor") != -1)
glBindAttribLocation(ps, 3, "nor");
glLinkProgram(ps);
glGetProgramiv(ps, GL_LINK_STATUS, &status);
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
LOG("LINK SHADER:\n%s", infolog);
if (status == 0)
{
glDeleteProgram(ps);
return false;
}
// Parse shader uniforms
{
GLint count;
GLint size; // size of the variable
GLenum type; // type of the variable (float, vec3 or mat4, etc)
const GLsizei bufSize = 16; // maximum name length
GLchar name[bufSize]; // variable name in GLSL
GLsizei length; // name length
glGetProgramiv(ps, GL_ACTIVE_UNIFORMS, &count);
for (int i = 0; i < count; i++)
{
glGetActiveUniform(ps, (GLuint)i, bufSize, &length, &size, &type, name);
m_umap[(kShaderUniform)const_hash(name)] = glGetUniformLocation(ps, name);
//printf("Uniform #%d Type: %u Name: %s Loc: %d\n", i, type, name, glGetUniformLocation(ps, name));
}
}
prog = ps;
return true;
}
void Shader::use()
{
glUseProgram(prog);
}
void Shader::u_vec4(kShaderUniform id, const glm::vec4& v)
{
if (m_umap.count(id) == 0)
LOG("UNIFORM vec4 %d NOT FOUND in shader %d", (int)id, (int)name)
else glUniform4fv(m_umap[id], 1, glm::value_ptr(v));
}
void Shader::u_vec3(kShaderUniform id, const glm::vec3& v)
{
if (m_umap.count(id) == 0)
LOG("UNIFORM vec3 %d NOT FOUND in shader %d", (int)id, (int)name)
else glUniform3fv(m_umap[id], 1, glm::value_ptr(v));
}
void Shader::u_vec2(kShaderUniform id, const glm::vec2& v)
{
if (m_umap.count(id) == 0)
LOG("UNIFORM vec2 %d NOT FOUND in shader %d", (int)id, (int)name)
else glUniform2fv(m_umap[id], 1, glm::value_ptr(v));
}
void Shader::u_mat4(kShaderUniform id, const glm::mat4& m)
{
if (m_umap.count(id) == 0)
LOG("UNIFORM mat4 %d NOT FOUND in shader %d", (int)id, (int)name)
else glUniformMatrix4fv(m_umap[id], 1, GL_FALSE, glm::value_ptr(m));
}
void Shader::u_int(kShaderUniform id, int i)
{
if (m_umap.count(id) == 0)
LOG("UNIFORM int %d NOT FOUND in shader %d", (int)id, (int)name)
else
glUniform1i(m_umap[id], i);
}
void Shader::u_float(kShaderUniform id, float f)
{
if (m_umap.count(id) == 0)
LOG("UNIFORM float %d NOT FOUND in shader %d", (int)id, (int)name)
else glUniform1f(m_umap[id], f);
}
GLint Shader::GetAttribLocation(const char* name)
{
return glGetAttribLocation(prog, name);
}
bool ShaderManager::create(kShader id, const char* vertex, const char* fragment)
{
m_shaders[id].name = id;
return m_shaders[id].create(vertex, fragment);
}
void ShaderManager::use(kShader id)
{
m_current = &m_shaders[id];
m_current->use();
}
void ShaderManager::use(const char* name)
{
m_current = &m_shaders[(kShader)const_hash(name)];
m_current->use();
}
void ShaderManager::u_vec4(kShaderUniform id, const glm::vec4& v)
{
m_current->u_vec4(id, v);
}
void ShaderManager::u_vec3(kShaderUniform id, const glm::vec3& v)
{
m_current->u_vec3(id, v);
}
void ShaderManager::u_vec2(kShaderUniform id, const glm::vec2& v)
{
m_current->u_vec2(id, v);
}
void ShaderManager::u_mat4(kShaderUniform id, const glm::mat4& m)
{
m_current->u_mat4(id, m);
}
void ShaderManager::u_int(kShaderUniform id, int i)
{
m_current->u_int(id, i);
}
Shader* ShaderManager::get(kShader id)
{
auto it = m_shaders.find(id);
return (it == m_shaders.end()) ? nullptr : &it->second;
}
void ShaderManager::u_float(kShaderUniform id, float f)
{
m_current->u_float(id, f);
}
void ShaderManager::invalidate()
{
m_shaders.clear();
}