Initial commit: Final state of the master project
This commit is contained in:
175
Research/shaders/ShaderLoader.cpp
Normal file
175
Research/shaders/ShaderLoader.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
#include "ShaderLoader.h"
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include "../inc/gl/glew.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../PropertyLoader.h"
|
||||
|
||||
|
||||
ShaderLoader* ShaderLoader::mInstance = NULL;
|
||||
|
||||
void ShaderLoader::Create() {
|
||||
if (mInstance == NULL)
|
||||
mInstance = new ShaderLoader();
|
||||
}
|
||||
|
||||
void ShaderLoader::Destroy() {
|
||||
if (mInstance != NULL)
|
||||
delete mInstance;
|
||||
mInstance = NULL;
|
||||
}
|
||||
|
||||
ShaderLoader* ShaderLoader::Instance() {
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
void ShaderLoader::SetShaderPath(std::string shaderPath)
|
||||
{
|
||||
mShaderPath = shaderPath;
|
||||
}
|
||||
|
||||
std::string ShaderLoader::GetShaderPath() {
|
||||
return mShaderPath;
|
||||
}
|
||||
|
||||
// Load shader
|
||||
unsigned ShaderLoader::LoadShader(const char* vertexFileName, const char* fragmentFileName, std::map<std::string, std::string> additionalProperties) {
|
||||
|
||||
// Create the shaders
|
||||
unsigned vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
||||
unsigned fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
std::string vertexPath = mShaderPath;
|
||||
std::string fragmentPath = mShaderPath;
|
||||
vertexPath.append(vertexFileName);
|
||||
fragmentPath.append(fragmentFileName);
|
||||
|
||||
// Read the vertex shader code from the file
|
||||
std::string vertexShaderCode;
|
||||
std::ifstream vertexShaderStream(vertexPath, std::ios::in);
|
||||
if (vertexShaderStream.is_open()) {
|
||||
std::string line;
|
||||
while (getline(vertexShaderStream, line)) {
|
||||
ParseProperties(line, '$', additionalProperties);
|
||||
ParseProperties(line, '%', additionalProperties);
|
||||
vertexShaderCode += "\n" + line;
|
||||
}
|
||||
vertexShaderStream.close();
|
||||
}
|
||||
|
||||
// Read the fragment shader code from the file
|
||||
std::string fragmentShaderCode;
|
||||
std::ifstream fragmentShaderStream(fragmentPath, std::ios::in);
|
||||
if (fragmentShaderStream.is_open()) {
|
||||
std::string line = "";
|
||||
while (getline(fragmentShaderStream, line)) {
|
||||
ParseProperties(line, '$', additionalProperties);
|
||||
ParseProperties(line, '%', additionalProperties);
|
||||
fragmentShaderCode += "\n" + line;
|
||||
}
|
||||
fragmentShaderStream.close();
|
||||
}
|
||||
|
||||
int result = GL_FALSE;
|
||||
int infoLogLength;
|
||||
|
||||
// Compile vertex shader
|
||||
if (verbose) printf("Compiling shader : %s\n", vertexFileName);
|
||||
char const* vertexSourcePointer = vertexShaderCode.c_str();
|
||||
glShaderSource(vertexShaderID, 1, &vertexSourcePointer, NULL);
|
||||
glCompileShader(vertexShaderID);
|
||||
|
||||
// Check vertex shader
|
||||
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &result);
|
||||
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
if (infoLogLength > 0)
|
||||
{
|
||||
std::vector<char> vertexShaderErrorMessage(infoLogLength);
|
||||
glGetShaderInfoLog(vertexShaderID, infoLogLength, NULL, &vertexShaderErrorMessage[0]);
|
||||
fprintf(stdout, "%s\n", &vertexShaderErrorMessage[0]);
|
||||
}
|
||||
|
||||
// Compile fragment shader
|
||||
if (verbose) printf("Compiling shader : %s\n", fragmentFileName);
|
||||
char const * fragmentSourcePointer = fragmentShaderCode.c_str();
|
||||
glShaderSource(fragmentShaderID, 1, &fragmentSourcePointer, NULL);
|
||||
glCompileShader(fragmentShaderID);
|
||||
|
||||
// Check fragment shader
|
||||
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &result);
|
||||
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
if (infoLogLength > 0)
|
||||
{
|
||||
std::vector<char> fragmentShaderErrorMessage(infoLogLength);
|
||||
glGetShaderInfoLog(fragmentShaderID, infoLogLength, NULL, &fragmentShaderErrorMessage[0]);
|
||||
if (fragmentShaderErrorMessage.size() > 1)
|
||||
fprintf(stdout, "%s\n", &fragmentShaderErrorMessage[0]);
|
||||
}
|
||||
|
||||
// Link the program
|
||||
if (verbose) fprintf(stdout, "Linking program\n");
|
||||
unsigned programID = glCreateProgram();
|
||||
glAttachShader(programID, vertexShaderID);
|
||||
glAttachShader(programID, fragmentShaderID);
|
||||
glLinkProgram(programID);
|
||||
|
||||
// Check the program
|
||||
glGetProgramiv(programID, GL_LINK_STATUS, &result);
|
||||
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
std::vector<char> programErrorMessage(glm::max(infoLogLength, int(1)));
|
||||
glGetProgramInfoLog(programID, infoLogLength, NULL, &programErrorMessage[0]);
|
||||
if (programErrorMessage.size() > 1)
|
||||
fprintf(stdout, "%s\n", &programErrorMessage[0]);
|
||||
|
||||
glDeleteShader(vertexShaderID);
|
||||
glDeleteShader(fragmentShaderID);
|
||||
|
||||
return programID;
|
||||
}
|
||||
|
||||
ShaderLoader::ShaderLoader() {
|
||||
PropertyLoader::Create();
|
||||
mShaderPath = "../Research/shaders/";
|
||||
}
|
||||
|
||||
ShaderLoader::~ShaderLoader() {
|
||||
|
||||
}
|
||||
|
||||
//************************************
|
||||
// Parse shader properties, i.e. text between delimiters
|
||||
//************************************
|
||||
void ShaderLoader::ParseProperties(std::string &line, char delimiter, std::map<std::string, std::string> additionalProperties) {
|
||||
size_t open = 0, close = 0;
|
||||
bool inProperty = false;
|
||||
size_t i = 0;
|
||||
while(i < line.size()) {
|
||||
// Whenever a delimiter is found, toggle between in and out of property
|
||||
if (line[i] == delimiter)
|
||||
{
|
||||
if (inProperty)
|
||||
{
|
||||
// If we were in a property, this delimiter marks the end of it.
|
||||
// Replace all text between open and close by an additional property
|
||||
close = i;
|
||||
std::string identifier = line.substr(open + 1, close - open - 1);
|
||||
auto addProp = additionalProperties.find(identifier);
|
||||
std::string value;
|
||||
if (addProp != additionalProperties.end())
|
||||
value = addProp->second;
|
||||
else
|
||||
value = PropertyLoader::Instance()->GetProperty("shader_" + identifier);
|
||||
if (value.empty()) return;
|
||||
line.replace(open, close - open + 1, value);
|
||||
i = open + value.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we were NOT in a property, this is the start of one
|
||||
open = i;
|
||||
}
|
||||
inProperty = !inProperty;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user