diff --git a/src/shaders/textured.c b/src/shaders/textured.c
new file mode 100644
index 00000000..86395d4f
--- /dev/null
+++ b/src/shaders/textured.c
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2021 Dominic Masters
+ * 
+ * This software is released under the MIT License.
+ * https://opensource.org/licenses/MIT
+ */
+
+#include "textured.h"
+
+void shaderInit(shader_t *shader) {
+  shader->programCount = 0;
+  shader->varCount = 0;
+
+  shaderSetInt32(shader, SHADER_KEY_WIDTH, 32);
+  shaderSetInt32(shader, SHADER_KEY_HEIGHT, 32);
+
+  renderListInit(
+    &shader->renderList,
+    shaderGetInt32(shader, SHADER_KEY_WIDTH),
+    shaderGetInt32(shader, SHADER_KEY_HEIGHT)
+  );
+}
+
+// Setters
+int32_t shaderSet(shader_t *shader, char *key, uint8_t type) {
+  int32_t i = dictionaryGetOrAdd(
+    shader->varNames, key, &shader->varCount,
+    SHADER_VARIABLE_NAME, shader->varNameBuffer
+  );
+  shader->varTypes[i] = type;
+  return i;
+}
+
+int32_t shaderSetColor(shader_t *shader, char *key, pixel_t color) {
+  int32_t i = shaderSet(shader, key, 0x00);
+  shader->varData[i].color = color;
+  return i;
+}
+
+void shaderSetInt32(shader_t *shader, char *key, int32_t v) {
+  int32_t i = shaderSet(shader, key, SHADER_VAR_TYPE_I32);
+  shader->varData[i].i32 = v;
+  return i;
+}
+
+// Getters
+int32_t shaderGet(shader_t *shader, char *key) {
+  return dictionaryGetIndex(shader->varNames, key, shader->varCount);
+}
+
+int32_t shaderGetInt32(shader_t *shader, char *key) {
+  int32_t i = shaderGet(shader, key);
+  if(i == -1) return 0;
+  return shader->varData[i].i32;
+}
\ No newline at end of file
diff --git a/src/shaders/textured.h b/src/shaders/textured.h
new file mode 100644
index 00000000..e67e4c32
--- /dev/null
+++ b/src/shaders/textured.h
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2021 Dominic Masters
+ * 
+ * This software is released under the MIT License.
+ * https://opensource.org/licenses/MIT
+ */
+
+#pragma once
+#include "../libs.h"
+#include "../display/renderlist.h"
+#include "../util/dictionary.h"
+
+#define SHADER_VARIABLE_COUNT 128
+#define SHADER_VARIABLE_NAME 32
+#define SHADER_PROGRAM_COUNT 8
+
+#define SHADER_KEY_WIDTH "width"
+#define SHADER_KEY_HEIGHT "height"
+
+#define SHADER_VAR_TYPE_I32 0x00
+
+/** Representation of a shader uniform */
+typedef GLuint shaderuniform_t;
+
+typedef union {
+  pixel_t color;
+  matrix_t matrix;
+  int32_t i32;
+} shadervariabledata_t;
+
+typedef struct {
+  /** Pointer to an uploaded vertex shader program */
+  GLuint shaderVertex;
+
+  /** Pointer to an uploaded fragment shader program */
+  GLuint shaderFrag;
+
+  /** Pointer to an uploaded shader program linked */
+  GLuint shaderProgram;
+
+  /** Buffer of chars where we store the uniform names */
+  char uniformBuffer[SHADER_UNIFORM_NAME_MAX * SHADER_UNIFORM_COUNT];
+
+  /** Array of strings (pointers to the above buffer) of the uniform names */
+  char *uniformNames[SHADER_UNIFORM_COUNT];
+  int32_t uniformCount;
+
+  /** Type of each uniform */
+  GLenum types[SHADER_UNIFORM_COUNT];
+
+  /** Texture Slots (which texture slot for GL to use for each uniform) */
+  uint8_t textureSlots[SHADER_UNIFORM_COUNT];
+} shaderprogram_t;
+
+typedef struct {
+  renderlist_t renderList;
+  scene_t *scene;
+  void *user;
+
+  shaderprogram_t programs[SHADER_PROGRAM_COUNT];
+  int32_t programCount;
+  
+  char varNameBuffer[SHADER_VARIABLE_COUNT * SHADER_VARIABLE_NAME]
+  shadervariabledata_t varData[SHADER_VARIABLE_COUNT];
+  uint8_t varTypes[SHADER_VARIABLE_COUNT];
+  char *varNames[SHADER_VARIABLE_COUNT];
+  int32_t varCount;
+} shader_t;
\ No newline at end of file
diff --git a/src/util/dictionary.c b/src/util/dictionary.c
new file mode 100644
index 00000000..2e1c9b22
--- /dev/null
+++ b/src/util/dictionary.c
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2021 Dominic Masters
+ * 
+ * This software is released under the MIT License.
+ * https://opensource.org/licenses/MIT
+ */
+
+#include "dictionary.h"
+
+int32_t dictionaryGetIndex(char **keys, char *name, int32_t count) {
+  int32_t i;
+  for(i = 0; i < count; i++) {
+    if(keys[i] == NULL) continue;
+    if(strcmp(keys[i], name) == 0) return i;
+  }
+  return -1;
+}
+
+int32_t dictionaryGetOrAdd(
+  char **keys, char *name, int32_t *count, int32_t stride, char *buffer
+) {
+  int32_t i;
+  int32_t firstFree = -1;
+
+  for(i = 0; i < *count; i++) {
+    if(keys[i] == NULL) {
+      if(firstFree == -1) firstFree = i;
+      continue;
+    }
+    if(strcmp(keys[i], name) == 0) return i;
+  }
+
+  if(firstFree == -1) {
+    firstFree = *count;
+    *count = *count + 1;
+  }
+  
+  keys[i] = buffer + (sizeof(char) * i * stride);
+  memcpy(keys[i], name, strlen(name) + 1);
+  return *count;
+}
+
+void dictionaryRemoveByIndex(char **keys, int32_t i) {
+  keys[i] = NULL;
+}
+
+void dictionaryRemove(char **keys, char *name, int32_t count) {
+  int32_t i = dictionaryGetIndex(keys, name, count);
+  if(i == -1) return;
+  keys[i] = NULL;
+}
\ No newline at end of file
diff --git a/src/util/dictionary.h b/src/util/dictionary.h
new file mode 100644
index 00000000..2e4e6635
--- /dev/null
+++ b/src/util/dictionary.h
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2021 Dominic Masters
+ * 
+ * This software is released under the MIT License.
+ * https://opensource.org/licenses/MIT
+ */
+
+#pragma once
+#include "../libs.h"
+
+/**
+ * Retrieve the index of a given key from a dictionary.
+ * 
+ * @param keys Array of strings.
+ * @param name Key to search for.
+ * @param count How long the array is.
+ * @return The index of the key within the dictionary (or -1 if not found).
+ */
+int32_t dictionaryGetIndex(char **keys, char *name, int32_t *count);
+
+/**
+ * Retrieves or adds a key to the dictionary. Note that we take in the count as
+ * a pointer to an integer because this will automatically be incremented if the
+ * dictionary does not contain the string.
+ * 
+ * @param keys Array of strings.
+ * @param name Key to add/get.
+ * @param count Pointer to an int32 that contains the count of items.
+ * @param stride How many elements between each key within the char buffer.
+ * @param buffer Char buffer where the key will be copied.
+ * @return The index where the item was added.
+ */
+int32_t dictionaryGetOrAdd(
+  char **keys, char *name, int32_t *count, int32_t stride, char *buffer
+);
+
+/**
+ * Removes a key from the dictionary.
+ * 
+ * @param keys Array of strings.
+ * @param i Index to remove.
+ */
+void dictionaryRemoveByIndex(char **keys, int32_t i);
+
+/**
+ * Remove an item from the dictionary by its key.
+ * 
+ * @param keys Array of strings.
+ * @param name Key to remove.
+ * @param count Count of items within the dictionary.
+ */
+void dictionaryRemove(char **keys, char *name, int32_t count);
\ No newline at end of file