#include "shader.h" #include BEGIN_NAMESPACE void check_compile_error(GLuint shader_id) { GLint isCompiled = 0; glGetShaderiv(shader_id, GL_COMPILE_STATUS, &isCompiled); if (!isCompiled) { GLint maxLength = 0; glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &maxLength); //The maxLength includes the NULL character char errorLog[maxLength]; glGetShaderInfoLog(shader_id, maxLength, &maxLength, &errorLog[0]); LOG(ERROR) << "Shader compile error: " << "(id: " << shader_id << ", code: " << isCompiled << ", bytes: " << maxLength << ") - " << std::string(errorLog, maxLength); //Provide the infolog in whatever manor you deem best. //Exit with failure. glDeleteShader(shader_id); //Don't leak the shader. } else { LOG(INFO) << "Shader " << shader_id << " successfully compiled"; } } void check_link_error(GLuint program_id) { GLint is_linked = 0; glGetShaderiv(program_id, GL_LINK_STATUS, &is_linked); if (!is_linked) { 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: " << "(id: " << program_id << ", code: " << is_linked << ", bytes: " << maxLength << ") - " << std::string(errorLog, maxLength); //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 " << program_id << " successfully linked"; } } shader::shader(const char *vs_content, const char *ps_content) : shader_ids{0, 0}, program_id{0} { shader_ids[0] = glCreateShader(GL_VERTEX_SHADER); glShaderSource(shader_ids[0], 1, &vs_content, NULL); glCompileShader(shader_ids[0]); int success; char infoLog[512]; glGetShaderiv(shader_ids[0], GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shader_ids[0], 512, NULL, infoLog); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; } shader_ids[1] = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(shader_ids[1], 1, &ps_content, NULL); glCompileShader(shader_ids[1]); glGetShaderiv(shader_ids[1], GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shader_ids[1], 512, NULL, infoLog); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; } program_id = glCreateProgram(); glAttachShader(program_id, shader_ids[0]); glAttachShader(program_id, shader_ids[1]); glBindAttribLocation(program_id, 0, "position"); glBindAttribLocation(program_id, 1, "normal"); glBindAttribLocation(program_id, 2, "texCoords"); glLinkProgram(program_id); glGetProgramiv(program_id, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(program_id, 512, NULL, infoLog); std::cout << "ERROR::SHADER::PROGRAM::COMPILATION_FAILED\n" << infoLog << std::endl; } glUseProgram(program_id); // glDeleteShader(shader_ids[0]); // glDeleteShader(shader_ids[1]); // 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); // check_link_error(program_id); // 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) { if (uniform_cache.count(uniformName) == 0) { uniform_cache[uniformName] = glGetUniformLocation(program_id, uniformName); } return uniform_cache[uniformName]; } 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