// // Created by lukas on 03.02.22. // #include "Shader.h" #define GL_GLEXT_PROTOTYPES #include #include #include #include #include #include unsigned int Shader::compileShader(const char *source, unsigned int type) const { unsigned int shaderid = glCreateShader(type); // Compile Shader glShaderSource(shaderid, 1, &source, NULL); glCompileShader(shaderid); // Check Shader int Result = GL_FALSE; int InfoLogLength; glGetShaderiv(shaderid, GL_COMPILE_STATUS, &Result); glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &InfoLogLength); if (InfoLogLength > 0) { std::vector VertexShaderErrorMessage(InfoLogLength + 1); glGetShaderInfoLog(shaderid, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); printf("%s\n", &VertexShaderErrorMessage[0]); return 0; } return shaderid; } void Shader::Bind() const { glUseProgram(mProgHandle); } unsigned Shader::getHandle() const { return mProgHandle; } unsigned Shader::getUniformHandle(std::string name) { if (uniformhandles.find(name) != uniformhandles.end()) { return uniformhandles[name]; } else { const unsigned id = glGetUniformLocation(mProgHandle, name.c_str()); uniformhandles[name] = id; return id; } } std::string Shader::readFile(std::string path) { // Read the Vertex Shader code from the file std::string VertexShaderCode; std::ifstream VertexShaderStream(path, std::ios::in); if (VertexShaderStream.is_open()) { std::stringstream sstr; sstr << VertexShaderStream.rdbuf(); VertexShaderCode = sstr.str(); VertexShaderStream.close(); } else { printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", path.c_str()); getchar(); return ""; } return VertexShaderCode; } unsigned int Shader::loadShaderFromFile(const std::string vertex_file_path, const std::string geometry_file_path, const std::string fragment_file_path) { // Read the Vertex Shader code from the file std::string VertexShaderCode = readFile(vertex_file_path); std::string FragmentShaderCode = readFile(fragment_file_path); std::string GeometryShaderCode = readFile("../geometry.shader"); return loadShader(VertexShaderCode, GeometryShaderCode, FragmentShaderCode); } unsigned int Shader::loadShader(const std::string vertex_src, const std::string geometry_src, const std::string fragment_src) { uint VertexShaderID; uint GeometryShaderID; uint FragmentShaderID; if (!vertex_src.empty()) { // Compile Vertex Shader printf("Compiling vertex shader\n"); VertexShaderID = compileShader(vertex_src.c_str(), GL_VERTEX_SHADER); if (VertexShaderID == 0) { printf("Error Compiling vertex shader\n"); return 0; } } if (!geometry_src.empty()) { printf("Compiling geometry shader\n"); GeometryShaderID = compileShader(geometry_src.c_str(), GL_GEOMETRY_SHADER); if (GeometryShaderID == 0) { printf("Error Compiling shader\n"); return 0; } } if (!fragment_src.empty()) { printf("Compiling fragment shader\n"); FragmentShaderID = compileShader(fragment_src.c_str(), GL_FRAGMENT_SHADER); if (FragmentShaderID == 0) { printf("Error Compiling shader\n"); return 0; } } // Link the program GLint Result = GL_FALSE; int InfoLogLength; printf("Linking shader program\n"); GLuint ProgramID = glCreateProgram(); if (!vertex_src.empty()) { glAttachShader(ProgramID, VertexShaderID); } if (!geometry_src.empty()) { glAttachShader(ProgramID, GeometryShaderID); } if (!fragment_src.empty()) { glAttachShader(ProgramID, FragmentShaderID); } glLinkProgram(ProgramID); // Check the program glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); if (InfoLogLength > 0) { std::vector ProgramErrorMessage(InfoLogLength + 1); glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); printf("%s\n", &ProgramErrorMessage[0]); } // cleanup shaders if (!vertex_src.empty()){ glDetachShader(ProgramID, VertexShaderID); glDeleteShader(VertexShaderID); } if (!geometry_src.empty()){ glDetachShader(ProgramID, GeometryShaderID); glDeleteShader(GeometryShaderID); } if (!fragment_src.empty()){ glDetachShader(ProgramID, FragmentShaderID); glDeleteShader(FragmentShaderID); } mProgHandle = ProgramID; return ProgramID; }