#include <stdbool.h>
 #include <SDL2/SDL.h>
 #include <GL/glew.h>
+#include "shaderLoader.h"
+#include "err.h"
 
 static SDL_Window *window = NULL;
 static SDL_GLContext *context = NULL;
 static int screen_width = 1280;
 static int screen_height = 720;
 
+static float vertices[] = {
+       -0.5f, -0.5f, 0.0f,
+       0.5f, -0.5f, 0.0f,
+       0.0f, 0.5f, 0.0f
+};
+
+static unsigned int vbo, vao;
+static unsigned int vertShader, fragShader, shaderProgram;
+static GLchar *vertSrc = NULL;
+static GLchar *fragSrc = NULL;
+
+static void initTri()
+{
+       glGenBuffers(1, &vbo);
+       glBindBuffer(GL_ARRAY_BUFFER, vbo);
+       glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+       glGenVertexArrays(1, &vao);
+       glBindVertexArray(vao);
+
+       vertShader = glCreateShader(GL_VERTEX_SHADER);
+       vertSrc = shader_load_src("tri", VERTEX);
+       shader_compile(vertShader, vertSrc, "triangle vertex");
+
+       fragShader = glCreateShader(GL_FRAGMENT_SHADER);
+       fragSrc = shader_load_src("tri", FRAGMENT);
+       shader_compile(fragShader, fragSrc, "triangle fragment");
+
+       shaderProgram = glCreateProgram();
+       glAttachShader(shaderProgram, vertShader);
+       glAttachShader(shaderProgram, fragShader);
+       glLinkProgram(shaderProgram);
+
+       /*
+        * The glVertexAttribPointer call is rather complex, so I will document it
+        * here.
+        * The 1st paramater specifies the vertex attrib to configure. We want to
+        * configure the position attribute, as specified with:
+        * layout (location = 0) in tri.vert.
+        * The 2nd paramater specifies the size of the attribute to configure.
+        * We are using a vec3 value in the shader which is composed of 3 values.
+        * The 3rd specifies the data type of the paramater.
+        * The 4th specifies if the value should be normalised.
+        * The 5th specifies the size of the stride and the 6th is the offset.
+        */
+       glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
+       glEnableVertexAttribArray(0); // param is the location of the attrib to enable.
+
+       // cleaning up
+       glDeleteShader(vertShader);
+       glDeleteShader(fragShader);
+       shader_free_src(vertSrc);
+       shader_free_src(fragSrc);
+}
+
 static bool init()
 {
        if (SDL_Init(
 {
        glClearColor(0.2, 0.3, 0.3, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
+
+       glUseProgram(shaderProgram);
+       glBindVertexArray(vao);
+       glDrawArrays(GL_TRIANGLES, 0, 3);
        SDL_GL_SwapWindow(window);
 }
 
        if(!init())
                return -1;
 
+       initTri();
        itime = SDL_GetTicks();
 
 
 
--- /dev/null
+#include "shaderLoader.h"
+#include "fileRead.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "err.h"
+
+static char *fileEnds[] = {
+       ".vert",
+       ".frag",
+       ".comp",
+       ".tesc",
+       ".tese"
+};
+static char *dirPath = "gl/shaders/";
+
+char *shader_load_src(const char *name, enum ShaderType type)
+{
+       GLchar *src = NULL;
+
+       int nSize = strlen(name);
+       int eSize = strlen(fileEnds[type]);
+       int dSize = strlen(dirPath);
+
+       int tSize = dSize + (2*nSize) + eSize + 2;
+
+       // constructing the final path string
+       char *path = malloc(tSize);
+       printf("sizes: dSize=%d nSize=%d, eSize=%d\n", dSize, nSize, eSize);
+       printf("total allocated %d\n", tSize);
+
+       strcpy(path, dirPath);
+       strcat(path, name);
+       strcat(path, "/");
+       strcat(path, name);
+       strcat(path, fileEnds[type]);
+
+       // debug output
+       printf("path length is %ld\n", strlen(path));
+       printf("loading shader from file '%s'\n\n", path);
+       src = readFile(path);
+       free(path);
+       return src;
+}
+
+void shader_compile(unsigned int shader, const GLchar *shaderSrc, const char *description)
+{
+       int success;
+       char log[512];
+       char out[512];
+
+       strcpy(out, "failed to compile shader: ");
+       strcat(out, description);
+
+       if(shaderSrc){
+               glShaderSource(shader, 1, &shaderSrc, NULL);
+               glCompileShader(shader);
+               glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+
+               if(!success){
+                       glGetShaderInfoLog(shader, 512, NULL, log);
+                       strcat(out, "!\n");
+                       strcat(out, log);
+                       err_output(out);
+               }
+       } else {
+               strcat(out, " source is NULL!\n");
+               err_output(out);
+       }
+}
+
+void shader_free_src(GLchar *src)
+{
+       free(src);
+}