BlockGame/gl/Shader.cpp
2022-02-05 21:44:31 +01:00

137 lines
4.1 KiB
C++

//
// Created by lukas on 03.02.22.
//
#include "Shader.h"
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glcorearb.h>
#include <string>
#include <fstream>
#include <vector>
#include <sstream>
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<char> 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) {
// Compile Vertex Shader
printf("Compiling vertex shader\n");
uint VertexShaderID = compileShader(vertex_src.c_str(), GL_VERTEX_SHADER);
if (VertexShaderID == 0) {
printf("Error Compiling shader\n");
return 0;
}
printf("Compiling geometry shader\n");
uint GeometryShaderID = compileShader(geometry_src.c_str(), GL_GEOMETRY_SHADER);
if (GeometryShaderID == 0) {
printf("Error Compiling shader\n");
return 0;
}
printf("Compiling fragment shader\n");
uint 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();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, GeometryShaderID);
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<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
// cleanup shaders
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
mProgHandle = ProgramID;
return ProgramID;
}