diff --git a/.gitignore b/.gitignore
index a1c2a23..17505bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,11 @@
+# Mac
+*.DS_Store
+
+
+# IntelliJ Idea folder
+.idea
+
+
 # Compiled class file
 *.class
 
diff --git a/HeliumEngine/HeliumEngine.iml b/HeliumEngine/HeliumEngine.iml
new file mode 100644
index 0000000..0913bd0
--- /dev/null
+++ b/HeliumEngine/HeliumEngine.iml
@@ -0,0 +1,12 @@
+
+
+  
+    
+    
+      
+    
+    
+    
+    
+  
+
\ No newline at end of file
diff --git a/HeliumEngine/src/Test.java b/HeliumEngine/src/Test.java
new file mode 100644
index 0000000..1c153f3
--- /dev/null
+++ b/HeliumEngine/src/Test.java
@@ -0,0 +1,79 @@
+import org.hl.engine.graphics.Mesh;
+import org.hl.engine.graphics.Renderer;
+import org.hl.engine.graphics.Shader;
+import org.hl.engine.graphics.Vertex;
+import org.hl.engine.io.Display;
+import org.hl.engine.io.Input;
+import org.hl.engine.math.Vector3f;
+import org.lwjgl.glfw.GLFW;
+
+
+
+public class Test {
+    public final static int WIDTH = 640, HEIGHT = 480;
+    public final String windowName = "Game!";
+    public Display display;
+    public Input i;
+    public Renderer renderer;
+    public Shader shader;
+
+    public Mesh mesh = new Mesh(new Vertex[] {
+            new Vertex(new Vector3f(-0.5F, 0.5F, 0.0F), new Vector3f(0, 0, 1.0F)),
+            new Vertex(new Vector3f(-0.5F, -0.5F, 0.0F), new Vector3f(0, 0, 1.0F)),
+            new Vertex(new Vector3f(0.5F, -0.5F, 0.0F), new Vector3f(1.0F, 0, 1.0F)),
+            new Vertex(new Vector3f(0.5F, 0.5F, 0.0F), new Vector3f(1.0F, 0, 1.0F) ),
+
+    }, new int[] {
+            0, 1, 2,
+            0, 2, 3
+
+    });
+
+    public void run() {
+        init();
+        i = new Input(display);
+        while (!(display.shouldClose()) && !i.isKeyDown(GLFW.GLFW_KEY_ESCAPE)) {
+            update();
+            render();
+        }
+
+        close();
+
+    }
+    public void init() {
+        // System.out.println("Initializing Game ");
+        display = new Display(WIDTH, HEIGHT, windowName);
+        shader = new Shader("/resources/shaders/mainVertex.glsl", "/resources/shaders/mainFragment.glsl");
+        renderer = new Renderer(shader);
+        display.setBackgroundColor(1F, 0, 0);
+        display.create();
+        mesh.create();
+        shader.create();
+
+    }
+    private void update() {
+        // System.out.println("Updating ");
+        int frames = display.update();
+        display.setWindowName(display.getWindowName().substring(0, 4) + " (Frames : " + frames + ")");
+
+        i.reset();
+
+    }
+
+    private void render() {
+        // System.out.println("Rendering ");
+        renderer.renderMesh(mesh);
+        display.swapBuffers();
+
+    }
+
+    private void close() {
+        display.destroy();
+        mesh.destroy();
+        shader.destroy();
+    }
+
+    public static void main(String[] args) {
+        new Test().run();
+    }
+}
diff --git a/HeliumEngine/src/org/hl/engine/graphics/Mesh.java b/HeliumEngine/src/org/hl/engine/graphics/Mesh.java
new file mode 100644
index 0000000..b6d6194
--- /dev/null
+++ b/HeliumEngine/src/org/hl/engine/graphics/Mesh.java
@@ -0,0 +1,111 @@
+package org.hl.engine.graphics;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL15;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+import org.lwjgl.system.MemoryUtil;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+public class Mesh {
+    private Vertex[] vertices;
+    private int[] indices;
+    private int vertexArrayObject, positionBufferObject, indicesBufferObject, colorBufferObject;
+
+    // A group of vertices combined based on the indexes
+    public Mesh(Vertex[] vertices, int[] indices) {
+        this.vertices = vertices;
+        this.indices = indices;
+    }
+
+    // Destroy the mesh
+    public void destroy () {
+        GL15.glDeleteBuffers(positionBufferObject);
+        GL15.glDeleteBuffers(indicesBufferObject);
+        GL15.glDeleteBuffers(colorBufferObject);
+
+        GL30.glDeleteVertexArrays(vertexArrayObject);
+    }
+
+    // getters for the mesh
+
+    public Vertex[] getVertices() {
+        return vertices;
+    }
+
+    public int[] getIndices() {
+        return indices;
+    }
+
+    public int getVertexArrayObject() {
+        return vertexArrayObject;
+    }
+
+    public int getPositionBufferObject() {
+        return positionBufferObject;
+    }
+
+    public int getIndicesBufferObject() {
+        return indicesBufferObject;
+    }
+
+    public int getColorBufferObject() {
+        return colorBufferObject;
+    }
+
+    public void create() {
+
+        // Creates the mesh by formatting the vertices and indices and inputting them to OpenGL
+        vertexArrayObject = GL30.glGenVertexArrays();
+        GL30.glBindVertexArray(vertexArrayObject);
+
+
+        // Putting the position of the vertex into the buffer so the renderer can read it
+
+        FloatBuffer positionBuffer = MemoryUtil.memAllocFloat(vertices.length * 3);
+        float[] positionData = new float[vertices.length * 3];
+        for (int i = 0; i < vertices.length; i ++ ) {
+            positionData[i * 3] = vertices[i].getPosition().getX();
+            positionData[i * 3 + 1] = vertices[i].getPosition().getY();
+            positionData[i * 3 + 2] = vertices[i].getPosition().getZ();
+        }
+        positionBuffer.put(positionData).flip();
+
+        positionBufferObject = storeData(positionBuffer, 0, 3);
+
+        // Putting the color into the buffer so renderer and shader can read it
+
+        FloatBuffer colorBuffer = MemoryUtil.memAllocFloat(vertices.length * 3);
+        float[] colorData = new float[vertices.length * 3];
+        for (int i = 0; i < vertices.length; i ++ ) {
+            colorData[i * 3] = vertices[i].getColor().getX();
+            colorData[i * 3 + 1] = vertices[i].getColor().getY();
+            colorData[i * 3 + 2] = vertices[i].getColor().getZ();
+        }
+        colorBuffer.put(colorData).flip();
+
+        colorBufferObject = storeData(colorBuffer, 1, 3);
+
+        IntBuffer indicesBuffer = MemoryUtil.memAllocInt(indices.length);
+        indicesBuffer.put(indices).flip();
+
+        indicesBufferObject = GL15.glGenBuffers();
+        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBufferObject);
+        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STATIC_DRAW);
+        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
+    }
+
+    // Storing data to the buffer at position index (helps with storing color / position)
+
+    private int storeData(FloatBuffer buffer, int index, int size) {
+        int bufferID = GL15.glGenBuffers();
+        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferID);
+        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
+        GL20.glVertexAttribPointer(index, size, GL11.GL_FLOAT, false, 0, 0);
+        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
+
+        return bufferID;
+    }
+}
diff --git a/HeliumEngine/src/org/hl/engine/graphics/Renderer.java b/HeliumEngine/src/org/hl/engine/graphics/Renderer.java
new file mode 100644
index 0000000..17f7c53
--- /dev/null
+++ b/HeliumEngine/src/org/hl/engine/graphics/Renderer.java
@@ -0,0 +1,34 @@
+package org.hl.engine.graphics;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL15;
+import org.lwjgl.opengl.GL30;
+
+public class Renderer {
+
+    private Shader shader;
+
+    public Renderer(Shader shader) {
+        this.shader = shader;
+    }
+
+
+    public void renderMesh(Mesh mesh) {
+
+        // Renders the mesh by drawing it using triangles (least complicated)
+        GL30.glBindVertexArray(mesh.getVertexArrayObject());
+        GL30.glEnableVertexAttribArray(0);
+        GL30.glEnableVertexAttribArray(1);
+        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, mesh.getIndicesBufferObject());
+
+        shader.bind();
+
+        GL11.glDrawElements(GL11.GL_TRIANGLES, mesh.getIndices().length, GL11.GL_UNSIGNED_INT, 0);
+
+        shader.unbind();
+        GL30.glDisableVertexAttribArray(0);
+        GL30.glDisableVertexAttribArray(1);
+        GL30.glBindVertexArray(0);
+
+    }
+}
diff --git a/HeliumEngine/src/org/hl/engine/graphics/Shader.java b/HeliumEngine/src/org/hl/engine/graphics/Shader.java
new file mode 100644
index 0000000..5a62d04
--- /dev/null
+++ b/HeliumEngine/src/org/hl/engine/graphics/Shader.java
@@ -0,0 +1,88 @@
+package org.hl.engine.graphics;
+
+import org.hl.engine.utils.FileUtils;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL20;
+
+public class Shader {
+    private String vertexFile;
+    private String fragmentFile;
+
+    private int vertexID, fragmentID, programID;
+
+    public Shader(String vertexPath, String fragmentPath) {
+        vertexFile = FileUtils.loadAsString(vertexPath);
+        fragmentFile = FileUtils.loadAsString(fragmentPath);
+
+    }
+
+    public void create() {
+
+        // Creates the program
+        programID = GL20.glCreateProgram();
+
+
+        // loads the vertex shader
+        vertexID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
+
+        GL20.glShaderSource(vertexID, vertexFile);
+        GL20.glCompileShader(vertexID);
+
+        if (GL20.glGetShaderi(vertexID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
+            System.err.println("Vertex Shader: " + GL20.glGetShaderInfoLog(vertexID));
+            System.exit(1);
+
+        }
+
+        // loads the fragment shader
+        fragmentID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
+
+        GL20.glShaderSource(fragmentID, fragmentFile);
+        GL20.glCompileShader(fragmentID);
+
+        if (GL20.glGetShaderi(fragmentID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
+            System.err.println("Fragment Shader: " + GL20.glGetShaderInfoLog(fragmentID));
+            System.exit(1);
+
+        }
+
+        // Attach shaders to program
+        GL20.glAttachShader(programID, vertexID);
+        GL20.glAttachShader(programID, fragmentID);
+
+        // Link the program
+        GL20.glLinkProgram(programID);
+        if (GL20.glGetProgrami(programID, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) {
+            System.err.println("Program Linking: " + GL20.glGetProgramInfoLog(programID));
+            System.exit(1);
+            return;
+        }
+
+        // Validate the program
+        GL20.glValidateProgram(programID);
+        if (GL20.glGetProgrami(programID, GL20.GL_VALIDATE_STATUS) == GL11.GL_FALSE) {
+            System.err.println("Program Validation: " + GL20.glGetProgramInfoLog(programID));
+            System.exit(1);
+            return;
+        }
+
+        GL20.glDeleteShader(vertexID);
+        GL20.glDeleteShader(fragmentID);
+
+    }
+
+    // Bind so we can use the shader
+    public void bind() {
+        GL20.glUseProgram(programID);
+    }
+
+    // Unbind the shader after use
+    public void unbind() {
+        GL20.glUseProgram(0);
+    }
+
+    // Destroy the program
+    public void destroy() {
+        GL20.glDeleteProgram(programID);
+    }
+}
diff --git a/HeliumEngine/src/org/hl/engine/graphics/Vertex.java b/HeliumEngine/src/org/hl/engine/graphics/Vertex.java
new file mode 100644
index 0000000..5e2df5b
--- /dev/null
+++ b/HeliumEngine/src/org/hl/engine/graphics/Vertex.java
@@ -0,0 +1,24 @@
+package org.hl.engine.graphics;
+
+import org.hl.engine.math.Vector3f;
+
+public class Vertex {
+
+    // Just a vertex
+
+    private Vector3f position;
+    private Vector3f color;
+
+    public Vertex (Vector3f position, Vector3f color) {
+        this.position = position;
+        this.color = color;
+    }
+
+    public Vector3f getPosition() {
+        return position;
+    }
+
+    public Vector3f getColor() {
+        return color;
+    }
+}
diff --git a/HeliumEngine/src/org/hl/engine/io/Display.java b/HeliumEngine/src/org/hl/engine/io/Display.java
new file mode 100644
index 0000000..0c0c5ec
--- /dev/null
+++ b/HeliumEngine/src/org/hl/engine/io/Display.java
@@ -0,0 +1,212 @@
+package org.hl.engine.io;
+import org.hl.engine.math.Vector3f;
+import org.lwjgl.glfw.GLFWVidMode;
+import org.lwjgl.glfw.GLFWWindowSizeCallback;
+import org.lwjgl.opengl.GL;
+import org.lwjgl.opengl.GL11;
+
+import static org.lwjgl.glfw.GLFW.*;
+
+public class Display {
+    private int width, height;
+    private String windowName;
+    private long window;
+    public int frames;
+    public int previousFrames = frames;
+    public long time;
+    public Input input;
+    private Vector3f background = new Vector3f(0, 0, 0);
+    private GLFWWindowSizeCallback resizeCallback;
+    private boolean isResized;
+    private boolean isFullscreen;
+    private int[] windowXPos = new int[1];
+    private int[] windowYPos = new int[1];
+    private GLFWVidMode videoMode;
+    private int savedPosX;
+    private int savedPosY;
+    private int savedWidth;
+    private int savedHeight;
+
+
+
+
+    // Constructor to create the display
+    public Display (int width, int height, String windowName) {
+        this.width = width;
+        this.height = height;
+        this.windowName = windowName;
+    }
+
+    // Change the window name
+    public void setWindowName(String windowName) {
+        this.windowName = windowName;
+        glfwSetWindowTitle(window, windowName);
+    }
+
+    // Getters for size, name, window, time, and fullScreen
+    public int getWidth() {
+        return width;
+    }
+    public int getHeight() {
+        return height;
+    }
+    public String getWindowName() {
+        return windowName;
+    }
+    public long getWindow() {
+        return window;
+    }
+    public long getTime() {
+        return time;
+    }
+
+    public boolean isFullscreen() {
+        return isFullscreen;
+    }
+
+    // Makes the screen fullscreen or not based on the argument
+    public void setFullscreen(boolean fullscreen) {
+        isFullscreen = fullscreen;
+        isResized = true;
+        GL11.glViewport(0, 0, width, height);
+        if (isFullscreen) {
+
+            int[] xpos = {0};
+            int[] ypos = {0};
+            glfwGetWindowPos(this.window, xpos, ypos);
+            savedPosX = xpos[0];
+            savedPosY = ypos[0];
+
+            savedWidth = width;
+            savedHeight = height;
+            glfwGetWindowPos(window, windowXPos, windowYPos);
+            glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, videoMode.width(), videoMode.height(), 0);
+        } else {
+            glfwSetWindowMonitor(window, 0, savedPosX, savedPosY, savedWidth, savedHeight, 0);
+        }
+    }
+
+    // resized getter
+
+    public boolean isResized() {
+        return isResized;
+    }
+
+
+    // Creates the window (should go in the init() function of your Main program)
+    public void create() {
+
+        // initializing glfw
+        if (!glfwInit()) {
+            System.err.println("Failed to initialize GLFW! ");
+            System.exit(1);
+        }
+
+        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL11.GL_TRUE);
+        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+
+        //Creating window
+        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
+        window = glfwCreateWindow(this.width, this.height, this.windowName, isFullscreen ? glfwGetPrimaryMonitor():0, 0);
+        if (window == 0) {
+            System.err.println("Failed to create window! ");
+            System.exit(1);
+        }
+
+        // Setting size of window
+
+        videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
+        windowXPos[0] = (videoMode.width() - this.width) / 2;
+        windowYPos[0] = (videoMode.height() - this.height ) / 2;
+        glfwSetWindowPos(window, windowXPos[0], windowYPos[0]);
+
+
+        // Graphics
+        glfwMakeContextCurrent(window);
+        GL.createCapabilities();
+
+        GL11.glEnable(GL11.GL_DEPTH_TEST);
+
+        callBacks();
+        glfwShowWindow(window);
+        glfwSwapInterval(1);
+
+        // setting time
+
+        time = System.currentTimeMillis();
+
+    }
+
+
+    // Creating the resize callback (all other callbacks were removed and are now in Input class)
+    private void callBacks() {
+
+        resizeCallback = new GLFWWindowSizeCallback() {
+
+            @Override
+            public void invoke(long window, int w, int h) {
+                width = w;
+                height = h;
+                isResized = true;
+            }
+        };
+
+
+        glfwSetWindowSizeCallback(window, resizeCallback);
+    }
+
+    // Refreshes the screen, resets frame count
+    public int update() {
+        if (isResized) {
+            GL11.glViewport(0, 0, width, height);
+            isResized = false;
+        }
+        GL11.glClearColor(background.getX(), background.getY(), background.getZ(), 1.0F);
+        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT |  GL11.GL_DEPTH_BUFFER_BIT);
+        glfwPollEvents();
+        frames++;
+        if (System.currentTimeMillis() > time + 1000) {
+            previousFrames = frames;
+            time = System.currentTimeMillis();
+            frames = 0;
+            return frames;
+        } else {
+            return previousFrames;
+
+        }
+    }
+
+    // Terminates the program (making WindowShouldClose)
+
+    public void terminate() {
+        glfwSetWindowShouldClose(window, true);
+    }
+
+
+    // Completely DESTROYS the window
+    public void destroy() {
+        resizeCallback.free();
+        glfwDestroyWindow(window);
+        glfwTerminate();
+    }
+
+    // switches the buffers (for rendering)
+
+    public void swapBuffers() {
+        glfwSwapBuffers(window);
+    }
+
+
+    // get whether the window should close
+    public boolean shouldClose() {
+        return glfwWindowShouldClose(window);
+    }
+
+    // changes the background color
+
+    public void setBackgroundColor(float r, float g, float b) {
+        background.setVector(r, g, b);
+    }
+}
\ No newline at end of file
diff --git a/HeliumEngine/src/org/hl/engine/io/Input.java b/HeliumEngine/src/org/hl/engine/io/Input.java
new file mode 100644
index 0000000..7b7f258
--- /dev/null
+++ b/HeliumEngine/src/org/hl/engine/io/Input.java
@@ -0,0 +1,121 @@
+package org.hl.engine.io;
+
+import org.lwjgl.glfw.GLFW;
+
+import java.util.Arrays;
+
+import static org.lwjgl.glfw.GLFW.*;
+
+public class Input {
+    private boolean[] keys = new boolean[GLFW.GLFW_KEY_LAST];
+    private boolean[] buttons = new boolean[GLFW.GLFW_MOUSE_BUTTON_LAST];
+
+    private int[] keyState = new int[GLFW.GLFW_KEY_LAST];
+    private int[] buttonState = new int[GLFW.GLFW_MOUSE_BUTTON_LAST];
+
+    private long window;
+    private Display display;
+
+    private boolean inWindow;
+
+    private double mouseX, mouseY;
+    private double scrollX, scrollY;
+
+    // Sets up the callbacks based on the window
+    public Input(Display d) {
+        this.display = d;
+        this.window = this.display.getWindow();
+
+        glfwSetKeyCallback(this.window, (window, key, scancode, action, mods) -> {
+            keys[key] = action != GLFW.GLFW_RELEASE;
+            keyState[key] = action;
+        });
+
+        glfwSetMouseButtonCallback(this.window, (window, button, action, mods) -> {
+            buttons[button] = action != GLFW.GLFW_RELEASE;
+            buttonState[button] = action;
+        });
+
+        glfwSetCursorPosCallback(this.window, (window, xpos, ypos) -> {
+            mouseX = xpos;
+            mouseY = ypos;
+        });
+
+        glfwSetCursorEnterCallback(this.window, (window, entered) -> {
+            inWindow = entered;
+        });
+
+        glfwSetScrollCallback(this.window, (window, xoffset, yoffset) -> {
+            scrollX += xoffset;
+            scrollY += yoffset;
+        });
+
+        resetKeyboard();
+        resetButtons();
+    }
+
+    // All states (isDown will return whether it has been held down but Press only returns a press)
+
+    public boolean isKeyDown(int key) {
+        return keys[key];
+    }
+
+    public boolean keyPress(int key) {
+        return keyState[key] == GLFW.GLFW_PRESS;
+    }
+
+    public boolean keyReleased(int key) {
+        return keyState[key] == GLFW.GLFW_RELEASE;
+    }
+
+    public boolean isButtonDown(int button) {
+        return buttons[button];
+    }
+
+    public boolean buttonPress(int button) {
+        return buttonState[button] == GLFW.GLFW_PRESS;
+    }
+
+    public boolean buttonReleased(int button) {
+        return buttonState[button] == GLFW.GLFW_RELEASE;
+    }
+
+    // Resets keyboard and buttons so the presses will only be registered once
+    private void resetKeyboard() {
+        Arrays.fill(keyState, -1);
+    }
+
+    private void resetButtons() {
+        Arrays.fill(buttonState, -1);
+    }
+
+
+    // This function should only be called after all input has been taken inside the loop. It must be called if keyPress and buttonPress should work.
+
+    public void reset() {
+        resetKeyboard();
+        resetButtons();
+    }
+
+    // Scroll, mouse, and window getters
+
+    public double getMouseX() {
+        return mouseX;
+    }
+
+    public double getMouseY() {
+        return mouseY;
+    }
+
+    public boolean inWindow() {
+        return inWindow;
+    }
+
+    public double getScrollX() {
+        return scrollX;
+    }
+
+    public double getScrollY() {
+        return scrollY;
+    }
+}
diff --git a/HeliumEngine/src/org/hl/engine/math/Vector3f.java b/HeliumEngine/src/org/hl/engine/math/Vector3f.java
new file mode 100644
index 0000000..fa1da5e
--- /dev/null
+++ b/HeliumEngine/src/org/hl/engine/math/Vector3f.java
@@ -0,0 +1,44 @@
+package org.hl.engine.math;
+
+public class Vector3f {
+    private float x;
+    private float y;
+    private float z;
+
+    // Just a vector if you know what I mean
+    public Vector3f (float x, float y, float z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    public void setVector(float x, float y, float z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    public float getX() {
+        return x;
+    }
+
+    public void setX(float x) {
+        this.x = x;
+    }
+
+    public float getY() {
+        return y;
+    }
+
+    public void setY(float y) {
+        this.y = y;
+    }
+
+    public float getZ() {
+        return z;
+    }
+
+    public void setZ(float z) {
+        this.z = z;
+    }
+}
diff --git a/HeliumEngine/src/org/hl/engine/utils/FileUtils.java b/HeliumEngine/src/org/hl/engine/utils/FileUtils.java
new file mode 100644
index 0000000..f1a1390
--- /dev/null
+++ b/HeliumEngine/src/org/hl/engine/utils/FileUtils.java
@@ -0,0 +1,28 @@
+package org.hl.engine.utils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class FileUtils {
+
+    // Reads a filepath and returns that as a String
+    public static String loadAsString(String filepath) {
+        StringBuilder result = new StringBuilder();
+        try (BufferedReader reader = new BufferedReader(new
+                InputStreamReader(FileUtils.class.getResourceAsStream(filepath)))) {
+            String line = "";
+            while ((line = reader.readLine()) != null) {
+                result.append(line) .append("\n");
+            }
+        } catch (Exception e) {
+            System.err.println("Couldn't get the file at " + filepath);
+            System.exit(1);
+
+        }
+
+
+        return result.toString();
+    }
+}
diff --git a/HeliumEngine/src/resources/shaders/mainFragment.glsl b/HeliumEngine/src/resources/shaders/mainFragment.glsl
new file mode 100644
index 0000000..85d4098
--- /dev/null
+++ b/HeliumEngine/src/resources/shaders/mainFragment.glsl
@@ -0,0 +1,9 @@
+#version 330 core
+
+in vec3 passColor;
+
+out vec4 outColor;
+
+void main() {
+    outColor = vec4(passColor, 1.0);
+}
diff --git a/HeliumEngine/src/resources/shaders/mainVertex.glsl b/HeliumEngine/src/resources/shaders/mainVertex.glsl
new file mode 100644
index 0000000..9ae1698
--- /dev/null
+++ b/HeliumEngine/src/resources/shaders/mainVertex.glsl
@@ -0,0 +1,11 @@
+#version 330 core
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec3 color;
+
+out vec3 passColor;
+
+void main() {
+    gl_Position = vec4(position, 1.0);
+    passColor = color;
+}
\ No newline at end of file