#include "glew.h" #include "shader.h" #include #include Shader::Shader(const std::string &vertexSource, const std::string &fragmentSource) { program = glCreateProgram(); GLuint vertexShaderId = createShader(vertexSource, GL_VERTEX_SHADER); GLuint fragmentShaderId = createShader(fragmentSource, GL_FRAGMENT_SHADER); glAttachShader(program, vertexShaderId); glAttachShader(program, fragmentShaderId); glBindAttribLocation(program, 0, "inPosition"); glBindAttribLocation(program, 1, "inNormal"); glBindAttribLocation(program, 2, "inTexCoord"); glBindAttribLocation(program, 3, "inTangent"); glBindAttribLocation(program, 4, "inBinormal"); glLinkProgram(program); // check errors GLint linked; glGetProgramiv(program, GL_LINK_STATUS, &linked); if (!linked) { std::cerr << "Program not linked" << std::endl; printProgramInfoLog(program); program = 0; } glDetachShader(program, vertexShaderId); glDetachShader(program, fragmentShaderId); glDeleteShader(vertexShaderId); glDeleteShader(fragmentShaderId); } Shader::Shader(const std::string &vertexSource, const std::string &geometrySource, const std::string &fragmentSource) { program = glCreateProgram(); GLuint vertexShaderId = createShader(vertexSource, GL_VERTEX_SHADER); GLuint geometryShaderId = createShader(geometrySource, GL_GEOMETRY_SHADER); GLuint fragmentShaderId = createShader(fragmentSource, GL_FRAGMENT_SHADER); glAttachShader(program, vertexShaderId); glAttachShader(program, geometryShaderId); glAttachShader(program, fragmentShaderId); glBindAttribLocation(program, 0, "inPosition"); glBindAttribLocation(program, 1, "inNormal"); glBindAttribLocation(program, 2, "inTexCoord"); glLinkProgram(program); // check errors GLint linked; glGetProgramiv(program, GL_LINK_STATUS, &linked); if (!linked) { std::cerr << "Program not linked" << std::endl; printProgramInfoLog(program); program = 0; } glDetachShader(program, vertexShaderId); glDetachShader(program, geometryShaderId); glDetachShader(program, fragmentShaderId); glDeleteShader(vertexShaderId); glDeleteShader(geometryShaderId); glDeleteShader(fragmentShaderId); } Shader::~Shader() { bool ok; ok = glIsProgram(program); if(ok) glDeleteProgram(program); } GLuint Shader::createShader(const std::string &source, GLenum shaderType) { GLuint shaderId = glCreateShader(shaderType); const GLchar *data = (const GLchar *)source.c_str(); glShaderSource(shaderId, 1, &data, NULL); glCompileShader(shaderId); // check errors GLint compiled; glGetShaderiv(shaderId, GL_COMPILE_STATUS, &compiled); if (!compiled) { std::string type_str; switch(shaderType) { case GL_VERTEX_SHADER: type_str = "Vertex"; break; case GL_GEOMETRY_SHADER: type_str = "Geometry"; break; case GL_FRAGMENT_SHADER: type_str = "Fragment"; break; } std::cerr << type_str << " shader not compiled : " << std::endl; std::cout << "Shader source :" << std::endl << source << std::endl; printShaderInfoLog(shaderId); return 0; } else return shaderId; } void Shader::printShaderInfoLog(GLuint shaderId) { int infoLogLen = 0; int charsWritten = 0; GLchar *infoLog; glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLogLen); if (infoLogLen > 0) { infoLog = new GLchar[infoLogLen]; glGetShaderInfoLog(shaderId, infoLogLen, &charsWritten, infoLog); std::cerr << "InfoLog:" << std::endl << infoLog << std::endl; delete [] infoLog; } } void Shader::printProgramInfoLog(GLuint programId) { int infoLogLen = 0; int charsWritten = 0; GLchar *infoLog; glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLen); if (infoLogLen > 0) { infoLog = new GLchar[infoLogLen]; glGetProgramInfoLog(programId, infoLogLen, &charsWritten, infoLog); std::cerr << "InfoLog:" << std::endl << infoLog << std::endl; delete [] infoLog; } } GLuint Shader::getLocation(std::string attribName) { GLuint loc = glGetUniformLocation(program, attribName.c_str()); return loc; } void Shader::bind() { glUseProgram(program); } void Shader::unbind() { glUseProgram(0); } void Shader::bindFloat(GLuint location, float val) { glUniform1f(location, val); } void Shader::bindMat3(GLuint location, glm::mat3 mat) { glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(mat)); } void Shader::bindMat4(GLuint location, glm::mat4 mat) { glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(mat)); } void Shader::bindVec2(GLuint location, glm::vec2 vec) { glUniform2fv(location, 1, glm::value_ptr(vec)); } void Shader::bindVec3(GLuint location, glm::vec3 vec) { glUniform3fv(location, 1, glm::value_ptr(vec)); } void Shader::bindVec4(GLuint location, glm::vec4 vec) { glUniform4fv(location, 1, glm::value_ptr(vec)); } void Shader::bindVec3Array(GLuint location, glm::vec3* vec, int nb_elements) { glUniform3fv(location, nb_elements, (GLfloat*)vec); } void Shader::bindUnsignedInteger(GLuint location, GLuint unsigned_integer) { glUniform1ui(location, unsigned_integer); } void Shader::bindInteger(GLuint location, GLint integer) { glUniform1i(location, integer); }