BlockGame/gl/Shader.cpp
lukas 360a1cc79d add crosshair
blockgen with sin
2022-02-10 18:24:56 +01:00

166 lines
4.8 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>
#include <iostream>
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) {
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<char> 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;
}