From d102e798a8abf9dffac3e8e1d6ec56c1c0a1ad0b Mon Sep 17 00:00:00 2001
From: Geert Custers <geert.aj.custers@gmail.com>
Date: Fri, 25 Aug 2017 18:17:35 +0300
Subject: [PATCH] Create res directory

Also includes Environment and Path
---
 Makefile                                      |  39 +----------
 .../DejaVuSerif-Bold.ttf                      | Bin
 DejaVuSerif.ttf => res/DejaVuSerif.ttf        | Bin
 anime.pnm => res/anime.pnm                    | Bin
 .../opengl => res}/shaders/FontShader.frag    |   0
 .../opengl => res}/shaders/FontShader.vert    |   0
 .../opengl => res}/shaders/TextureShader.frag |   0
 .../opengl => res}/shaders/TextureShader.vert |   0
 src/environment/Environment.cpp               |  35 ++++++++++
 src/environment/Environment.h                 |  16 +++++
 src/environment/Path.cpp                      |  21 ++++++
 src/environment/Path.h                        |  13 ++++
 src/graphics/components/DocumentComponent.cpp |  10 ++-
 src/graphics/components/InputComponent.cpp    |  10 ++-
 src/graphics/components/MultiComponent.cpp    |  10 ++-
 src/graphics/opengl/Shader.h                  |   8 +--
 src/graphics/opengl/ShaderLoader.cpp          |  64 +++++++++++-------
 src/graphics/opengl/ShaderLoader.h            |  10 +--
 src/graphics/opengl/Window.cpp                |  10 ++-
 src/graphics/text/TextRasterizer.cpp          |   6 +-
 src/main.cpp                                  |   3 +
 src/pnm.cpp                                   |   5 +-
 22 files changed, 164 insertions(+), 96 deletions(-)
 rename DejaVuSerif-Bold.ttf => res/DejaVuSerif-Bold.ttf (100%)
 rename DejaVuSerif.ttf => res/DejaVuSerif.ttf (100%)
 rename anime.pnm => res/anime.pnm (100%)
 rename {src/graphics/opengl => res}/shaders/FontShader.frag (100%)
 rename {src/graphics/opengl => res}/shaders/FontShader.vert (100%)
 rename {src/graphics/opengl => res}/shaders/TextureShader.frag (100%)
 rename {src/graphics/opengl => res}/shaders/TextureShader.vert (100%)
 create mode 100644 src/environment/Environment.cpp
 create mode 100644 src/environment/Environment.h
 create mode 100644 src/environment/Path.cpp
 create mode 100644 src/environment/Path.h

diff --git a/Makefile b/Makefile
index 41f4cc30..416a8f9e 100644
--- a/Makefile
+++ b/Makefile
@@ -38,42 +38,7 @@ all: $(SOURCES) netrunner
 netrunner: $(OBJECTS)
 	$(LINK) $(LDFLAGS) -o $@ $^ $(LIBS)
 
-# make make 3.81 happy (since it can't parse any echo parameters)
-ifeq ($(UNAME), Darwin)
-shaders:
-ifneq ($(shell cat src/graphics/opengl/shaders/FontShader.vert src/graphics/opengl/shaders/FontShader.frag src/graphics/opengl/shaders/TextureShader.vert src/graphics/opengl/shaders/TextureShader.frag | $(MD5SUM)), $(shell cat src/graphics/opengl/shaders/gen/hashsum))
-	@mkdir -p "src/graphics/opengl/shaders/gen"
-	@echo "#ifndef FONTSHADER_H\n#define FONTSHADER_H\n\nconst char *fontVertexShaderSource =\n" > src/graphics/opengl/shaders/gen/FontShader.h;
-	@cat src/graphics/opengl/shaders/FontShader.vert | awk '{if ($$0!="}") {print "\t\""$$0"\\n\""} else {print "\t\""$$0"\";\n"}}' >> src/graphics/opengl/shaders/gen/FontShader.h;
-	@echo "const char *fontFragmentShaderSource =\n" >> src/graphics/opengl/shaders/gen/FontShader.h;
-	@cat src/graphics/opengl/shaders/FontShader.frag | awk '{if ($$0!="}") {print "\t\""$$0"\\n\""} else {print "\t\""$$0"\";\n"}}' >> src/graphics/opengl/shaders/gen/FontShader.h;
-	@echo "#endif\n" >> src/graphics/opengl/shaders/gen/FontShader.h;
-	@echo "#ifndef TEXTURESHADER_H\n#define TEXTURESHADER_H\n\nconst char *textureVertexShaderSource =\n" > src/graphics/opengl/shaders/gen/TextureShader.h;
-	@cat src/graphics/opengl/shaders/TextureShader.vert | awk '{if ($$0!="}") {print "\t\""$$0"\\n\""} else {print "\t\""$$0"\";\n"}}' >> src/graphics/opengl/shaders/gen/TextureShader.h;
-	@echo "const char *textureFragmentShaderSource =\n" >> src/graphics/opengl/shaders/gen/TextureShader.h;
-	@cat src/graphics/opengl/shaders/TextureShader.frag | awk '{if ($$0!="}") {print "\t\""$$0"\\n\""} else {print "\t\""$$0"\";\n"}}' >> src/graphics/opengl/shaders/gen/TextureShader.h;
-	@echo "#endif\n" >> src/graphics/opengl/shaders/gen/TextureShader.h;
-	@cat src/graphics/opengl/shaders/FontShader.vert src/graphics/opengl/shaders/FontShader.frag src/graphics/opengl/shaders/TextureShader.vert src/graphics/opengl/shaders/TextureShader.frag | $(MD5SUM) > src/graphics/opengl/shaders/gen/hashsum;
-endif
-else
-shaders:
-ifneq ($(shell cat src/graphics/opengl/shaders/FontShader.vert src/graphics/opengl/shaders/FontShader.frag src/graphics/opengl/shaders/TextureShader.vert src/graphics/opengl/shaders/TextureShader.frag | $(MD5SUM)), $(shell cat src/graphics/opengl/shaders/gen/hashsum))
-	@mkdir -p "src/graphics/opengl/shaders/gen"
-	@cat src/graphics/opengl/shaders/FontShader.vert src/graphics/opengl/shaders/FontShader.frag src/graphics/opengl/shaders/TextureShader.vert src/graphics/opengl/shaders/TextureShader.frag | $(MD5SUM) > src/graphics/opengl/shaders/gen/hashsum;
-	@/bin/echo -ne "#ifndef FONTSHADER_H\n#define FONTSHADER_H\n\nconst char *fontVertexShaderSource =\n" > src/graphics/opengl/shaders/gen/FontShader.h;
-	@cat src/graphics/opengl/shaders/FontShader.vert | awk '{if ($$0!="}") {print "\t\""$$0"\\n\""} else {print "\t\""$$0"\";\n"}}' >> src/graphics/opengl/shaders/gen/FontShader.h;
-	@/bin/echo -ne "const char *fontFragmentShaderSource =\n" >> src/graphics/opengl/shaders/gen/FontShader.h;
-	@cat src/graphics/opengl/shaders/FontShader.frag | awk '{if ($$0!="}") {print "\t\""$$0"\\n\""} else {print "\t\""$$0"\";\n"}}' >> src/graphics/opengl/shaders/gen/FontShader.h;
-	@/bin/echo -ne "#endif\n" >> src/graphics/opengl/shaders/gen/FontShader.h;
-	@/bin/echo -ne "#ifndef TEXTURESHADER_H\n#define TEXTURESHADER_H\n\nconst char *textureVertexShaderSource =\n" > src/graphics/opengl/shaders/gen/TextureShader.h;
-	@cat src/graphics/opengl/shaders/TextureShader.vert | awk '{if ($$0!="}") {print "\t\""$$0"\\n\""} else {print "\t\""$$0"\";\n"}}' >> src/graphics/opengl/shaders/gen/TextureShader.h;
-	@/bin/echo -ne "const char *textureFragmentShaderSource =\n" >> src/graphics/opengl/shaders/gen/TextureShader.h;
-	@cat src/graphics/opengl/shaders/TextureShader.frag | awk '{if ($$0!="}") {print "\t\""$$0"\\n\""} else {print "\t\""$$0"\";\n"}}' >> src/graphics/opengl/shaders/gen/TextureShader.h;
-	@/bin/echo -ne "#endif\n" >> src/graphics/opengl/shaders/gen/TextureShader.h;
-endif
-endif
-
-$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | shaders
+$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
 	@mkdir -p $(@D)
 	@mkdir -p $(subst gen,d,$(@D))
 	$(CXX) -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td $(CXXFLAGS) $(INCPATH) $(WARNINGS) -c -o $@ $<
@@ -89,6 +54,6 @@ ntr-run-tests: test-url.o $(OBJDIR)/URL.o $(OBJDIR)/StringUtils.o
 	$(LINK) $(LDFLAGS) -o $@ test-url.o $(OBJDIR)/URL.o $(OBJDIR)/StringUtils.o $(LIBS)
 
 clean:
-	-@rm -rf src/graphics/opengl/shaders/gen $(OBJDIR) $(EXECUTABLE) 2>/dev/null || true
+	-@rm -rf $(OBJDIR) $(EXECUTABLE) 2>/dev/null || true
 
 include $(addsuffix .d,$(subst $(SRCDIR),$(DEPDIR),$(basename $(SOURCES))))
diff --git a/DejaVuSerif-Bold.ttf b/res/DejaVuSerif-Bold.ttf
similarity index 100%
rename from DejaVuSerif-Bold.ttf
rename to res/DejaVuSerif-Bold.ttf
diff --git a/DejaVuSerif.ttf b/res/DejaVuSerif.ttf
similarity index 100%
rename from DejaVuSerif.ttf
rename to res/DejaVuSerif.ttf
diff --git a/anime.pnm b/res/anime.pnm
similarity index 100%
rename from anime.pnm
rename to res/anime.pnm
diff --git a/src/graphics/opengl/shaders/FontShader.frag b/res/shaders/FontShader.frag
similarity index 100%
rename from src/graphics/opengl/shaders/FontShader.frag
rename to res/shaders/FontShader.frag
diff --git a/src/graphics/opengl/shaders/FontShader.vert b/res/shaders/FontShader.vert
similarity index 100%
rename from src/graphics/opengl/shaders/FontShader.vert
rename to res/shaders/FontShader.vert
diff --git a/src/graphics/opengl/shaders/TextureShader.frag b/res/shaders/TextureShader.frag
similarity index 100%
rename from src/graphics/opengl/shaders/TextureShader.frag
rename to res/shaders/TextureShader.frag
diff --git a/src/graphics/opengl/shaders/TextureShader.vert b/res/shaders/TextureShader.vert
similarity index 100%
rename from src/graphics/opengl/shaders/TextureShader.vert
rename to res/shaders/TextureShader.vert
diff --git a/src/environment/Environment.cpp b/src/environment/Environment.cpp
new file mode 100644
index 00000000..7126b5bd
--- /dev/null
+++ b/src/environment/Environment.cpp
@@ -0,0 +1,35 @@
+#include "Environment.h"
+
+#include <vector>
+
+#include "Path.h"
+#include "../Log.h"
+
+std::string Environment::resourceDir = "";
+
+void Environment::init() {
+	if (!resourceDir.empty())
+		return; // already initialized O_o
+
+	std::vector<std::string> paths = {
+		"res"
+	};
+#ifndef _WIN32
+	// linux or osx
+	paths.push_back("/usr/share/netrunner/resources");
+#else
+	paths.push_back(""); //TODO: place it somewhere for windows
+#endif
+
+	for (std::string &path : paths) {
+		if (Path::directoryExists(path)) {
+			resourceDir = path;
+			logInfo() << "Found resource dir at " << path << "!" << std::endl;
+			break;
+		}
+	}
+}
+
+std::string Environment::getResourceDir() {
+	return resourceDir;
+}
diff --git a/src/environment/Environment.h b/src/environment/Environment.h
new file mode 100644
index 00000000..3a871282
--- /dev/null
+++ b/src/environment/Environment.h
@@ -0,0 +1,16 @@
+#ifndef ENVIRONMENT_H
+#define ENVIRONMENT_H
+
+#include <string>
+
+class Environment {
+public:
+	static void init();
+
+	static std::string getResourceDir();
+
+	static void setResourceDir();
+private:
+	static std::string resourceDir;
+};
+#endif
diff --git a/src/environment/Path.cpp b/src/environment/Path.cpp
new file mode 100644
index 00000000..6809e6e4
--- /dev/null
+++ b/src/environment/Path.cpp
@@ -0,0 +1,21 @@
+#include "Path.h"
+
+#include <sys/stat.h>
+
+bool Path::directoryExists(const std::string &path) {
+	struct stat sb;
+
+	if (stat(path.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
+		return true;
+	}
+	return false;
+}
+
+std::string Path::fromUnixPath(const std::string &path) {
+	std::string returnPath(path);
+#ifdef _WIN32
+	for (int i = 0; i < path.size(); i++)
+		if (path.at(i) == '/') path.at(i) = '\\';
+#endif
+	return returnPath;
+}
diff --git a/src/environment/Path.h b/src/environment/Path.h
new file mode 100644
index 00000000..37171247
--- /dev/null
+++ b/src/environment/Path.h
@@ -0,0 +1,13 @@
+#ifndef PATH_H
+#define PATH_H
+
+#include <string>
+
+class Path {
+public:
+	static bool directoryExists(const std::string &path);
+
+	static std::string fromUnixPath(const std::string &path);
+};
+
+#endif
diff --git a/src/graphics/components/DocumentComponent.cpp b/src/graphics/components/DocumentComponent.cpp
index 9eb21960..e47068bb 100644
--- a/src/graphics/components/DocumentComponent.cpp
+++ b/src/graphics/components/DocumentComponent.cpp
@@ -7,8 +7,6 @@
 
 #include "../opengl/Shader.h"
 #include "../opengl/ShaderLoader.h"
-#include "../opengl/shaders/gen/TextureShader.h"
-#include "../opengl/shaders/gen/FontShader.h"
 
 void deleteComponent(std::shared_ptr<Component> &component);
 void deleteNode(std::shared_ptr<Node> node);
@@ -279,14 +277,14 @@ void DocumentComponent::render() {
     //if (transformMatrixDirty) {
         //const std::clock_t begin = clock();
 		
-		Shader *fontShader = ShaderLoader::getShader(VertexShader(fontVertexShaderSource),
-				FragmentShader(fontFragmentShaderSource));
+		Shader *fontShader = ShaderLoader::getShader(VertexShader("FontShader.vert"),
+				FragmentShader("FontShader.frag"));
 		GLint transformLocation = fontShader->uniform("transform");
         glUniformMatrix4fv(transformLocation, 1, GL_FALSE, transformMatrix);
         //const std::clock_t end = clock();
         //std::cout << "Updated font matrix in: " << std::fixed << ((static_cast<double>(end - begin)) / CLOCKS_PER_SEC) << std::scientific << " seconds" << std::endl;
-		Shader *textureShader = ShaderLoader::getShader(VertexShader(textureVertexShaderSource),
-				FragmentShader(textureFragmentShaderSource));
+		Shader *textureShader = ShaderLoader::getShader(VertexShader("TextureShader.vert"),
+				FragmentShader("TextureShader.frag"));
         GLint transformLocation2 = textureShader->uniform("transform");
         glUniformMatrix4fv(transformLocation2, 1, GL_FALSE, transformMatrix);
 
diff --git a/src/graphics/components/InputComponent.cpp b/src/graphics/components/InputComponent.cpp
index 7a9e48ce..6eff6537 100644
--- a/src/graphics/components/InputComponent.cpp
+++ b/src/graphics/components/InputComponent.cpp
@@ -5,8 +5,6 @@
 
 #include "../opengl/Shader.h"
 #include "../opengl/ShaderLoader.h"
-#include "../opengl/shaders/gen/TextureShader.h"
-#include "../opengl/shaders/gen/FontShader.h"
 
 extern TextRasterizerCache *rasterizerCache;
 extern std::unique_ptr<Scheduler> scheduler;
@@ -164,8 +162,8 @@ void InputComponent::render() {
     // can actuall delete vertices here
     if (userInputText) {
         // make sure we're using win's transformMatrix
-		Shader *fontShader = ShaderLoader::getShader(VertexShader(fontVertexShaderSource),
-				FragmentShader(fontFragmentShaderSource));
+		Shader *fontShader = ShaderLoader::getShader(VertexShader("FontShader.vert"),
+				FragmentShader("FontShader.frag"));
 		fontShader->bind();
         if (!boundToPage) {
             GLint transformLocation = fontShader->uniform("transform");
@@ -182,8 +180,8 @@ void InputComponent::render() {
         }
         //std::cout << "rendering some text" << std::endl;
         userInputText->render();
-		Shader *textureShader = ShaderLoader::getShader(VertexShader(textureVertexShaderSource),
-				FragmentShader(textureFragmentShaderSource));
+		Shader *textureShader = ShaderLoader::getShader(VertexShader("TextureShader.vert"),
+				FragmentShader("TextureShader.frag"));
 		textureShader->bind();
     }
     if (focused) {
diff --git a/src/graphics/components/MultiComponent.cpp b/src/graphics/components/MultiComponent.cpp
index b2a0efe4..46f66e21 100644
--- a/src/graphics/components/MultiComponent.cpp
+++ b/src/graphics/components/MultiComponent.cpp
@@ -8,8 +8,6 @@
 
 #include "../opengl/Shader.h"
 #include "../opengl/ShaderLoader.h"
-#include "../opengl/shaders/gen/TextureShader.h"
-#include "../opengl/shaders/gen/FontShader.h"
 
 MultiComponent::MultiComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight) {
     
@@ -220,14 +218,14 @@ void MultiComponent::resize(const int passedWindowWidth, const int passedWindowH
 
 void MultiComponent::render() {
     //std::cout << "MultiComponent::render" << std::endl;
-	Shader *fontShader = ShaderLoader::getShader(VertexShader(fontVertexShaderSource),
-			FragmentShader(fontFragmentShaderSource));
+	Shader *fontShader = ShaderLoader::getShader(VertexShader("FontShader.vert"),
+			FragmentShader("FontShader.frag"));
 	fontShader->bind();
     renderDocumentComponents(rootComponent);
 	fontShader->release();
 
-	Shader *textureShader = ShaderLoader::getShader(VertexShader(textureVertexShaderSource),
-			FragmentShader(textureFragmentShaderSource));
+	Shader *textureShader = ShaderLoader::getShader(VertexShader("TextureShader.vert"),
+			FragmentShader("TextureShader.frag"));
 	textureShader->bind();
     renderBoxComponents(rootComponent);
 	textureShader->release();
diff --git a/src/graphics/opengl/Shader.h b/src/graphics/opengl/Shader.h
index 2a875b22..d5bf2fac 100644
--- a/src/graphics/opengl/Shader.h
+++ b/src/graphics/opengl/Shader.h
@@ -6,13 +6,13 @@
 #include <map>
 
 struct VertexShader {
-	VertexShader(std::string s) : source(s) { }
-	std::string source;
+	VertexShader(std::string n) : name(n) { }
+	std::string name;
 };
 
 struct FragmentShader {
-	FragmentShader(std::string s) : source(s) { }
-	std::string source;
+	FragmentShader(std::string n) : name(n) { }
+	std::string name;
 };
 
 class Shader {
diff --git a/src/graphics/opengl/ShaderLoader.cpp b/src/graphics/opengl/ShaderLoader.cpp
index 7228d9e2..bd2aad9c 100644
--- a/src/graphics/opengl/ShaderLoader.cpp
+++ b/src/graphics/opengl/ShaderLoader.cpp
@@ -1,37 +1,53 @@
 #include "ShaderLoader.h"
 
+#include <stdlib.h>
 #include <fstream>
 #include <iostream>
-#include <memory>
 
 #include "Shader.h"
 #include "../../Log.h"
+#include "../../environment/Environment.h"
+#include "../../environment/Path.h"
 
 static constexpr GLint maxLogSize = 1024 * 1024 * 2; //2 MiB
 
 ShaderLoader::ShaderCache ShaderLoader::shaderCache;
 
-GLuint ShaderLoader::loadShader(const std::string &shaderSource, Shader::Type type) {
+GLuint ShaderLoader::loadShader(const std::string &shaderName, Shader::Type type) {
 	GLenum glType = getGlShaderType(type);
 	if (!glType) {
 		logError() << "Unknown shader type: " << type << std::endl;
 		return 0;
 	}
 	GLuint shader = glCreateShader(glType);
-	const char *source = shaderSource.c_str();
-	glShaderSource(shader, 1, &source, NULL);
+
+	std::string path = Path::fromUnixPath(Environment::getResourceDir() + "/shaders/" + shaderName);
+	std::ifstream file(path, std::ifstream::ate);
+	if (!file.is_open()) {
+		logError() << "Could not open shader " << shaderName << std::endl;
+		return 0;
+	}
+
+	int fileSize = file.tellg();
+	file.seekg(std::ifstream::beg);
+	char *buffer = (char*) malloc(fileSize + 1);
+	file.read(buffer, fileSize);
+	buffer[fileSize] = 0;
+	glShaderSource(shader, 1, &buffer, NULL);
 	glCompileShader(shader);
 
-	if(checkShader(shader, shaderSource, type))
+	free(buffer);
+
+	if(checkShader(shader, shaderName, type))
 		return 0;
 
 	return shader;
 }
 
-GLuint ShaderLoader::createProgram(const std::string &shader1Source, Shader::Type shader1Type,
-	   	const std::string &shader2Source, Shader::Type shader2Type) {
-	GLuint shader1 = loadShader(shader1Source, shader1Type);
-	GLuint shader2 = loadShader(shader2Source, shader2Type);
+GLuint ShaderLoader::createProgram(const std::string &shader1Name, Shader::Type shader1Type,
+	   	const std::string &shader2Name, Shader::Type shader2Type) {
+	GLuint shader1 = loadShader(shader1Name, shader1Type);
+	GLuint shader2 = loadShader(shader2Name, shader2Type);
 
 	if (!shader1 || !shader2)
 		return 0;
@@ -41,18 +57,18 @@ GLuint ShaderLoader::createProgram(const std::string &shader1Source, Shader::Typ
 	glAttachShader(program, shader2);
 
 	glLinkProgram(program);
-	if (checkProgram(program, GL_LINK_STATUS, shader1Source))
-		return 0;
-	glValidateProgram(program);
-	if (checkProgram(program, GL_VALIDATE_STATUS, shader1Source))
+	if (checkProgram(program, GL_LINK_STATUS, shader1Name))
 		return 0;
+	/* glValidateProgram(program);
+	if (checkProgram(program, GL_VALIDATE_STATUS, shader1Name))
+		return 0; */
 
 	return program;
 }
 
 Shader *ShaderLoader::getShader(VertexShader vertexShader, FragmentShader fragmentShader) {
 	// concatenate strings to create unique key for the shader
-	std::string key = vertexShader.source + fragmentShader.source;
+	std::string key = vertexShader.name + fragmentShader.name;
 
 	// has the shader been cached?
 	auto it = shaderCache.find(key);
@@ -60,8 +76,8 @@ Shader *ShaderLoader::getShader(VertexShader vertexShader, FragmentShader fragme
 		return it->second;
 
 	// Ok. It isn't. Let's create the shader Q.Q
-	GLuint program = createProgram(vertexShader.source, Shader::Type::Vertex,
-		   	fragmentShader.source, Shader::Type::Fragment);
+	GLuint program = createProgram(vertexShader.name, Shader::Type::Vertex,
+		   	fragmentShader.name, Shader::Type::Fragment);
 	if (!program) //reee it failed
 		return NULL;
 
@@ -70,23 +86,23 @@ Shader *ShaderLoader::getShader(VertexShader vertexShader, FragmentShader fragme
 	return shader;
 }
 
-int ShaderLoader::checkShader(GLuint shader, const std::string &source, Shader::Type type) {
+int ShaderLoader::checkShader(GLuint shader, const std::string &shaderName, Shader::Type type) {
 	GLint success = 0;
 	glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
 
 	if (success == GL_TRUE) {
-		logDebug() << "Shader " << source << " compiled successfully!" << std::endl;
+		logDebug() << "Shader " << shaderName << " compiled successfully!" << std::endl;
 	} else {
 		GLint logSize = 0;
 		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize);
 		if (logSize > maxLogSize) {
-			logError() << "Shader " << source << " failed to compile but \
+			logError() << "Shader " << shaderName << " failed to compile but \
 				the log is too long to show." << std::endl;
 			return 1;
 		}
 		char log[logSize];
 		glGetShaderInfoLog(shader, logSize, &logSize, &log[0]);
-		logError() << "Shader " << source << " failed to compile. GL log output: "
+		logError() << "Shader " << shaderName << " failed to compile. GL log output: "
 			<< log << std::endl;
 		glDeleteShader(shader);
 		return 1;
@@ -94,23 +110,23 @@ int ShaderLoader::checkShader(GLuint shader, const std::string &source, Shader::
 	return 0;
 }
 
-int ShaderLoader::checkProgram(GLuint program, GLenum pname, const std::string &source) {
+int ShaderLoader::checkProgram(GLuint program, GLenum pname, const std::string &shaderName) {
 	GLint success = 0;
 	glGetProgramiv(program, pname, &success);
 	if (success == GL_TRUE) {
-		logDebug() << "Program with shader1 " << source << " " << getProgramStatusString(pname)
+		logDebug() << "Program with shader1 " << shaderName << " " << getProgramStatusString(pname)
 			<< std::endl;
 	} else {
 		GLint logSize = 0;
 		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize);
 		if (logSize > maxLogSize) {
-			logError() << "Program with shader1 " << source << " failed to be "
+			logError() << "Program with shader1 " << shaderName << " failed to be "
 				<< getProgramStatusString(pname) << " but the log is too long to show" << std::endl;
 			return 1;
 		}
 		char log[logSize];
 		glGetProgramInfoLog(program, logSize, &logSize, &log[0]);
-		logError() << "Program with shader1 " << source << " failed to be "
+		logError() << "Program with shader1 " << shaderName << " failed to be "
 			<< getProgramStatusString(pname) << ". GL log output: " << log << std::endl;
 		glDeleteProgram(program);
 		return 1;
diff --git a/src/graphics/opengl/ShaderLoader.h b/src/graphics/opengl/ShaderLoader.h
index 98e37b97..98c28daa 100644
--- a/src/graphics/opengl/ShaderLoader.h
+++ b/src/graphics/opengl/ShaderLoader.h
@@ -15,17 +15,17 @@ public:
 	static Shader *getShader(VertexShader vertexShader, FragmentShader fragmentShader);
 
 	// Load a shader from disk and return the its handle
-	static GLuint loadShader(const std::string &source, Shader::Type shaderType);
+	static GLuint loadShader(const std::string &shader, Shader::Type shaderType);
 
-	static GLuint createProgram(const std::string &shader1Source, Shader::Type shader1Type,
-			const std::string &shader2Source, Shader::Type shader2Type);
+	static GLuint createProgram(const std::string &shader1Name, Shader::Type shader1Type,
+			const std::string &shader2Name, Shader::Type shader2Type);
 private:
 	static ShaderCache shaderCache;
 
 	static int checkProgram(GLuint program, GLenum programName,
-			const std::string &source);
+			const std::string &shaderName);
 
-	static int checkShader(GLuint shader, const std::string &source, Shader::Type shaderType);
+	static int checkShader(GLuint shader, const std::string &shaderName, Shader::Type shaderType);
 
 	static constexpr GLenum getGlShaderType(const Shader::Type type);
 
diff --git a/src/graphics/opengl/Window.cpp b/src/graphics/opengl/Window.cpp
index eaf0430c..eea8b7c3 100644
--- a/src/graphics/opengl/Window.cpp
+++ b/src/graphics/opengl/Window.cpp
@@ -17,8 +17,6 @@
 #include "../components/InputComponent.h"
 #include "../opengl/Shader.h"
 #include "../opengl/ShaderLoader.h"
-#include "../opengl/shaders/gen/TextureShader.h"
-#include "../opengl/shaders/gen/FontShader.h"
 
 #include <cmath>
 #include <ctime>
@@ -702,8 +700,8 @@ void Window::render() {
             std::cout << "window::render - box render start - not ok: " << glErr << std::endl;
         }
 
-		Shader *textureShader = ShaderLoader::getShader(VertexShader(textureVertexShaderSource),
-				FragmentShader(textureFragmentShaderSource));
+		Shader *textureShader = ShaderLoader::getShader(VertexShader("TextureShader.vert"),
+				FragmentShader("TextureShader.frag"));
 		textureShader->bind();
         glErr=glGetError();
         if(glErr != GL_NO_ERROR) {
@@ -724,8 +722,8 @@ void Window::render() {
         renderComponentType("input", rootComponent);
 
         // it's quick but done on scroll
-		Shader *fontShader = ShaderLoader::getShader(VertexShader(fontVertexShaderSource),
-				FragmentShader(fontFragmentShaderSource));
+		Shader *fontShader = ShaderLoader::getShader(VertexShader("FontShader.vert"),
+				FragmentShader("FontShader.frag"));
 		fontShader->bind();
         // reset both, since components can change this
         // god we may have to reset this after each component render...
diff --git a/src/graphics/text/TextRasterizer.cpp b/src/graphics/text/TextRasterizer.cpp
index 735a46b6..7ee3a27c 100644
--- a/src/graphics/text/TextRasterizer.cpp
+++ b/src/graphics/text/TextRasterizer.cpp
@@ -1,14 +1,18 @@
 #include "TextRasterizer.h"
+#include <string>
 #include <cmath>
 #include <limits>
 #include <iostream>
 
+#include "../../environment/Environment.h"
+
 TextRasterizer::TextRasterizer(const std::string &fontPath, const int size, const unsigned int resolution, const bool bold) {
     fontSize = size;
     FT_Init_FreeType(&lib);
 
     face = std::make_unique<FT_Face>();
-    if (FT_New_Face(lib, bold ? (fontPath.substr(0, fontPath.length() - 4) + "-Bold.ttf").c_str() : fontPath.c_str(), 0, face.get())) {
+	std::string path = Environment::getResourceDir() + "/" + fontPath;
+    if (FT_New_Face(lib, bold ? (path.substr(0, fontPath.length() - 4) + "-Bold.ttf").c_str() : path.c_str(), 0, face.get())) {
         std::cout << "Could not open font" << std::endl;
         return;
     }
diff --git a/src/main.cpp b/src/main.cpp
index 28046842..30971c56 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,5 +1,6 @@
 #include "CommandLineParams.h"
 #include "graphics/opengl/Window.h"
+#include "environment/Environment.h"
 #include "html/HTMLParser.h"
 #include "Log.h"
 #include "URL.h"
@@ -82,6 +83,7 @@ int main(int argc, char *argv[]) {
     */
     std::cout << "/g/ntr - NetRunner build " << __DATE__ << std::endl;
 
+	Environment::init();
     // we need to set up OGL before we can setDOM (because component can't be constructed (currently) without OGL)
     // but should be after CommandLineParams incase we need to change some type of window config
     window->windowWidth = 1024;
@@ -90,6 +92,7 @@ int main(int argc, char *argv[]) {
     if (!window->window) {
         return 1;
     }
+
     //std::cout << "argc " << argc << std::endl;
     if (argc > 1) {
         initCLParams(argc, argv);
diff --git a/src/pnm.cpp b/src/pnm.cpp
index dfd629c0..c7cefe54 100644
--- a/src/pnm.cpp
+++ b/src/pnm.cpp
@@ -1,8 +1,11 @@
 #include "pnm.h"
+#include <string>
 #include <iostream>
 #include <stdio.h>
 #include <string.h>
 
+#include "environment/Environment.h"
+
 // pnm
 // The PNM format is just an abstraction of the PBM, PGM, and PPM formats. I.e. the name "PNM" refers collectively to PBM, PGM, and PPM.
 // pam has the advanced header
@@ -10,7 +13,7 @@
 RGBAPNMObject * readPPM(const char* fileName) {
     RGBAPNMObject *data=new RGBAPNMObject;
     // open the file to read just the header reading
-    FILE* fr = fopen(fileName, "r");
+    FILE* fr = fopen(std::string(Environment::getResourceDir() + "/" + fileName).c_str(), "r");
     if (!fr) {
         std::cout << "Can't open " << fileName << std::endl;
         return nullptr;
-- 
GitLab