2022-04-23 16:41:33 +03:00
|
|
|
#include "shader.h"
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
BEGIN_NAMESPACE
|
|
|
|
|
|
|
|
|
|
void check_compile_error(GLuint shaderId) {
|
|
|
|
|
GLint isCompiled = 0;
|
|
|
|
|
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &isCompiled);
|
|
|
|
|
if (isCompiled == GL_FALSE) {
|
|
|
|
|
GLint maxLength = 0;
|
|
|
|
|
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &maxLength);
|
|
|
|
|
|
|
|
|
|
//The maxLength includes the NULL character
|
|
|
|
|
char errorLog[maxLength];
|
|
|
|
|
glGetShaderInfoLog(shaderId, maxLength, &maxLength, &errorLog[0]);
|
|
|
|
|
|
2022-04-24 07:15:30 +03:00
|
|
|
LOG(ERROR) << "Shader compile error: (" << isCompiled << ") - " << std::string(errorLog);
|
2022-04-23 16:41:33 +03:00
|
|
|
|
|
|
|
|
//Provide the infolog in whatever manor you deem best.
|
|
|
|
|
//Exit with failure.
|
|
|
|
|
glDeleteShader(shaderId); //Don't leak the shader.
|
2022-04-24 07:15:30 +03:00
|
|
|
} else {
|
|
|
|
|
LOG(INFO) << "Shader successfully compiled";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void check_link_error(GLuint program_id) {
|
|
|
|
|
GLint is_linked = 0;
|
|
|
|
|
glGetShaderiv(program_id, GL_LINK_STATUS, &is_linked);
|
|
|
|
|
if (is_linked == GL_FALSE) {
|
|
|
|
|
GLint maxLength = 0;
|
|
|
|
|
glGetShaderiv(program_id, GL_INFO_LOG_LENGTH, &maxLength);
|
|
|
|
|
|
|
|
|
|
//The maxLength includes the NULL character
|
|
|
|
|
char errorLog[maxLength];
|
|
|
|
|
glGetShaderInfoLog(program_id, maxLength, &maxLength, &errorLog[0]);
|
|
|
|
|
|
|
|
|
|
LOG(ERROR) << "Shader program link error: " << "(" << is_linked << ") - " << std::string(errorLog);
|
|
|
|
|
|
|
|
|
|
//Provide the info log in whatever manner you deem best.
|
|
|
|
|
//Exit with failure.
|
|
|
|
|
glDeleteShader(program_id); //Don't leak the program shader.
|
|
|
|
|
} else {
|
|
|
|
|
LOG(INFO) << "Shader program successfully linked";
|
2022-04-23 16:41:33 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shader::shader(const char *vs_content, const char *ps_content) {
|
|
|
|
|
shader_ids[0] = glCreateShader(GL_VERTEX_SHADER);
|
|
|
|
|
glShaderSource(shader_ids[0], 1, &vs_content, nullptr);
|
|
|
|
|
glCompileShader(shader_ids[0]);
|
|
|
|
|
check_compile_error(shader_ids[0]);
|
|
|
|
|
|
|
|
|
|
shader_ids[1] = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
|
glShaderSource(shader_ids[1], 1, &ps_content, nullptr);
|
|
|
|
|
glCompileShader(shader_ids[1]);
|
|
|
|
|
check_compile_error(shader_ids[1]);
|
|
|
|
|
|
|
|
|
|
program_id = glCreateProgram();
|
|
|
|
|
glAttachShader(program_id, shader_ids[0]);
|
|
|
|
|
glAttachShader(program_id, shader_ids[1]);
|
|
|
|
|
|
|
|
|
|
// TODO Adrian: these should come from an external enumeration
|
|
|
|
|
glBindAttribLocation(program_id, 0, "position");
|
|
|
|
|
glBindAttribLocation(program_id, 1, "normal");
|
|
|
|
|
glBindAttribLocation(program_id, 2, "texCoords");
|
|
|
|
|
|
|
|
|
|
glLinkProgram(program_id);
|
2022-04-24 07:15:30 +03:00
|
|
|
check_link_error(program_id);
|
|
|
|
|
|
2022-04-23 16:41:33 +03:00
|
|
|
glUseProgram(program_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shader::~shader() {
|
|
|
|
|
glDetachShader(program_id, shader_ids[0]);
|
|
|
|
|
glDetachShader(program_id, shader_ids[1]);
|
|
|
|
|
|
|
|
|
|
glDeleteShader(shader_ids[0]);
|
|
|
|
|
glDeleteShader(shader_ids[1]);
|
|
|
|
|
|
|
|
|
|
glDeleteProgram(program_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void shader::use() const {
|
|
|
|
|
glUseProgram(program_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void shader::unuse() const {
|
|
|
|
|
glUseProgram(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int shader::getUniform(const char *uniformName) {
|
2022-04-23 16:52:26 +03:00
|
|
|
if (uniform_cache.count(uniformName) == 0) {
|
|
|
|
|
uniform_cache[uniformName] = glGetUniformLocation(program_id, uniformName);
|
2022-04-23 16:41:33 +03:00
|
|
|
}
|
2022-04-23 16:52:26 +03:00
|
|
|
return uniform_cache[uniformName];
|
2022-04-23 16:41:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void shader::setMatrix3Uniform(float *matrix, const char *uniformName) {
|
|
|
|
|
GLint location = getUniform(uniformName);
|
|
|
|
|
if (location != -1)
|
|
|
|
|
glUniformMatrix3fv(location, 1, false, matrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void shader::setMatrix4Uniform(float *matrix, const char *uniformName) {
|
|
|
|
|
GLint location = getUniform(uniformName);
|
|
|
|
|
if (location != -1)
|
|
|
|
|
glUniformMatrix4fv(location, 1, false, matrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void shader::setVec3Uniform(float *value, const char *uniformName) {
|
|
|
|
|
GLint location = getUniform(uniformName);
|
|
|
|
|
if (location != -1)
|
|
|
|
|
glUniform3fv(location, 1, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void shader::setVec4Uniform(float *value, const char *uniformName) {
|
|
|
|
|
GLint location = getUniform(uniformName);
|
|
|
|
|
if (location != -1)
|
|
|
|
|
glUniform4fv(location, 1, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void shader::setIntUniform(int value, const char *uniformName) {
|
|
|
|
|
GLint location = getUniform(uniformName);
|
|
|
|
|
if (location != -1)
|
|
|
|
|
glUniform1i(location, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void shader::setFloatUniform(float value, const char *uniformName) {
|
|
|
|
|
GLint location = getUniform(uniformName);
|
|
|
|
|
if (location != -1)
|
|
|
|
|
glUniform1f(location, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
END_NAMESPACE
|