2022-02-05 20:44:31 +00:00
|
|
|
//
|
|
|
|
// 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>
|
2022-02-10 17:24:56 +00:00
|
|
|
#include <iostream>
|
2022-02-05 20:44:31 +00:00
|
|
|
|
|
|
|
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) {
|
2022-02-06 21:53:29 +00:00
|
|
|
if (uniformhandles.find(name) != uniformhandles.end()) {
|
2022-02-05 20:44:31 +00:00
|
|
|
return uniformhandles[name];
|
2022-02-06 21:53:29 +00:00
|
|
|
} else {
|
2022-02-05 20:44:31 +00:00
|
|
|
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) {
|
2022-02-06 21:53:29 +00:00
|
|
|
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;
|
|
|
|
}
|
2022-02-05 20:44:31 +00:00
|
|
|
}
|
|
|
|
|
2022-02-06 21:53:29 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2022-02-05 20:44:31 +00:00
|
|
|
}
|
|
|
|
|
2022-02-06 21:53:29 +00:00
|
|
|
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;
|
|
|
|
}
|
2022-02-05 20:44:31 +00:00
|
|
|
}
|
|
|
|
|
2022-02-06 21:53:29 +00:00
|
|
|
|
2022-02-05 20:44:31 +00:00
|
|
|
// Link the program
|
|
|
|
GLint Result = GL_FALSE;
|
|
|
|
int InfoLogLength;
|
|
|
|
|
|
|
|
printf("Linking shader program\n");
|
|
|
|
GLuint ProgramID = glCreateProgram();
|
2022-02-06 21:53:29 +00:00
|
|
|
if (!vertex_src.empty()) {
|
|
|
|
glAttachShader(ProgramID, VertexShaderID);
|
|
|
|
}
|
|
|
|
if (!geometry_src.empty()) {
|
|
|
|
glAttachShader(ProgramID, GeometryShaderID);
|
|
|
|
}
|
|
|
|
if (!fragment_src.empty()) {
|
|
|
|
glAttachShader(ProgramID, FragmentShaderID);
|
|
|
|
}
|
|
|
|
|
2022-02-05 20:44:31 +00:00
|
|
|
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
|
2022-02-06 21:53:29 +00:00
|
|
|
if (!vertex_src.empty()){
|
|
|
|
glDetachShader(ProgramID, VertexShaderID);
|
|
|
|
glDeleteShader(VertexShaderID);
|
|
|
|
}
|
2022-02-05 20:44:31 +00:00
|
|
|
|
2022-02-06 21:53:29 +00:00
|
|
|
if (!geometry_src.empty()){
|
|
|
|
glDetachShader(ProgramID, GeometryShaderID);
|
|
|
|
glDeleteShader(GeometryShaderID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fragment_src.empty()){
|
|
|
|
glDetachShader(ProgramID, FragmentShaderID);
|
|
|
|
glDeleteShader(FragmentShaderID);
|
|
|
|
}
|
2022-02-05 20:44:31 +00:00
|
|
|
|
|
|
|
mProgHandle = ProgramID;
|
|
|
|
return ProgramID;
|
|
|
|
}
|