mirror of
https://github.com/kuhyx/engineer-thesis-WUT.git
synced 2026-07-04 16:03:14 +02:00
158 lines
5.6 KiB
C++
158 lines
5.6 KiB
C++
#ifndef SHADER_CPP
|
|
#define SHADER_CPP
|
|
#include "shader.hpp"
|
|
#include "misc.hpp"
|
|
#include <glad/glad.h> // include glad to get all the required OpenGL headers
|
|
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
|
|
Shader::Shader(const std::string vertexPath, const std::string fragmentPath)
|
|
{
|
|
const char* vertexSource = this->readFile(vertexPath);
|
|
const char* shaderSource = this->readFile(fragmentPath);
|
|
const std::pair<unsigned int, unsigned int> shaders = this->compileShaders(vertexSource, shaderSource);
|
|
|
|
this->ID = this->linkShaderObjectsShaderProgram(shaders.first, shaders.second);
|
|
}
|
|
// use/activate the shader
|
|
void Shader::use()
|
|
{
|
|
glUseProgram(ID);
|
|
}
|
|
// utility uniform functions
|
|
void Shader::setBool(const std::string &name, bool value) const
|
|
{
|
|
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
|
|
}
|
|
void Shader::setInt(const std::string &name, int value) const
|
|
{
|
|
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
|
|
}
|
|
void Shader::setFloat(const std::string &name, float value) const
|
|
{
|
|
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
|
|
}
|
|
|
|
void Shader::shaderFailedMessage(const unsigned int shader, const bool compilation) const
|
|
{
|
|
char infoLog[512];
|
|
const size_t sizeOfInfoLog = sizeof(infoLog) / sizeof(infoLog[0]);
|
|
compilation ? glGetShaderInfoLog(shader, sizeOfInfoLog, NULL, infoLog)
|
|
: glGetProgramInfoLog(shader, sizeOfInfoLog, NULL, infoLog);
|
|
std::cout << "ERROR vertex shader compilation failed \n"
|
|
<< infoLog << std::endl;
|
|
}
|
|
|
|
int Shader::shaderSuccessful(const unsigned int shader, const bool compilation) const
|
|
{
|
|
// check if compilation was successful
|
|
// int because glGetShaderiv requires int
|
|
int success;
|
|
// here we store info about compilation
|
|
// check if compilation was successful
|
|
compilation ? glGetShaderiv(shader, GL_COMPILE_STATUS, &success)
|
|
: glGetProgramiv(shader, GL_LINK_STATUS, &success);
|
|
// if not display compilation log
|
|
if (!success)
|
|
{
|
|
shaderFailedMessage(shader, compilation);
|
|
}
|
|
return success;
|
|
}
|
|
|
|
unsigned int Shader::compileShader(const GLenum shaderType, const char *shaderSource) const
|
|
{
|
|
// we create vertex shader and assign its id to shader variable
|
|
const unsigned int shaderID = glCreateShader(shaderType);
|
|
|
|
// attach shader source code to shader object
|
|
// from left: shader object to compile, how many strings as source code, actual source code (we leave the 4th as NULL)
|
|
glShaderSource(shaderID, 1, &shaderSource, NULL);
|
|
// compile shader
|
|
glCompileShader(shaderID);
|
|
if (!shaderSuccessful(shaderID, true))
|
|
return 0;
|
|
return shaderID;
|
|
}
|
|
|
|
const char* Shader::readFile(const std::string fileName) const
|
|
{
|
|
// 1. retrieve the vertex/fragment source code from filePath
|
|
std::string shaderCode;
|
|
std::ifstream shaderFile;
|
|
// ensure ifstream objects can throw exceptions:
|
|
shaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
|
|
try
|
|
{
|
|
// open file
|
|
shaderFile.open(fileName);
|
|
std::stringstream shaderStream;
|
|
// read file buffer contents into streams
|
|
shaderStream << shaderFile.rdbuf();
|
|
// close file handlers
|
|
shaderFile.close();
|
|
// convert stream into string
|
|
shaderCode = shaderStream.str();
|
|
}
|
|
catch(std::ifstream::failure const& e)
|
|
{
|
|
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
|
|
}
|
|
const char* vShaderCode = shaderCode.c_str();
|
|
return vShaderCode;
|
|
}
|
|
|
|
unsigned int Shader::linkShaderObjectsShaderProgram(const unsigned int vertexShaders, const unsigned int fragmentShader) const
|
|
{
|
|
// link shader objects into shader program
|
|
// will store shader program id
|
|
// creates program
|
|
const unsigned int programID = glCreateProgram();
|
|
|
|
// attachShaders
|
|
glAttachShader(programID, vertexShaders);
|
|
glAttachShader(programID, fragmentShader);
|
|
|
|
// link shaders
|
|
glLinkProgram(programID);
|
|
if (!shaderSuccessful(programID, false))
|
|
return 0;
|
|
|
|
// activate program
|
|
// after that every shader and rendering call will use this program object
|
|
glUseProgram(programID);
|
|
|
|
// delete shaders (they are linked into shaderProgram and we do not need them anymore)
|
|
glDeleteShader(vertexShaders);
|
|
glDeleteShader(fragmentShader);
|
|
if (programID == 0)
|
|
print("Shader Program Linking Failed");
|
|
|
|
return programID;
|
|
}
|
|
|
|
std::pair<unsigned int, unsigned int> Shader::compileShaders(const char* vertexShaderSource, const char* fragmentShaderSource) const
|
|
{
|
|
const unsigned int vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
|
|
if (vertexShader == 0)
|
|
{
|
|
print("Vertex Shader Compilation Failed");
|
|
return std::make_pair(0, 0);
|
|
}
|
|
|
|
const unsigned int fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
|
|
if (fragmentShader == 0)
|
|
{
|
|
print("Fragment Shader Compilation Failed");
|
|
return std::make_pair(0, 0);
|
|
}
|
|
return std::make_pair(vertexShader, fragmentShader);
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif |