diff --git a/src/dawn/component/ui/UICanvas.cpp b/src/dawn/component/ui/UICanvas.cpp
index dbc4b18f..917b7564 100644
--- a/src/dawn/component/ui/UICanvas.cpp
+++ b/src/dawn/component/ui/UICanvas.cpp
@@ -5,9 +5,8 @@
 
 #include "UICanvas.hpp"
 #include "display/pass/RenderPass.hpp"
-#include "display/shader/UIShader.hpp"
-
 #include "display/mesh/QuadMesh.hpp"
+#include "ui/UIComponent.hpp"
 
 using namespace Dawn;
 
@@ -35,32 +34,70 @@ void UICanvas::onDispose() {
 }
 
 std::vector<std::shared_ptr<IRenderPass>> UICanvas::getPasses(
-  struct RenderPassContext &ctx
+struct RenderPassContext &ctx
 ) {
-  std::vector<std::shared_ptr<IRenderPass>> passes;
-  std::unordered_map<shadertexturebinding_t, std::shared_ptr<Texture>> textures;
-  UIShaderData data = {
-    .projection = ctx.camera->getProjection(),
-    .view = ctx.camera->getItem()->getWorldTransform(),
-    .model = this->getItem()->getWorldTransform()
-  };
-  
-  size_t quadCount = 0;
+  if(this->components.empty()) return {};
+
+  data.projection = ctx.camera->getProjection();
+  data.view = ctx.camera->getItem()->getWorldTransform();
+  data.model = this->getItem()->getWorldTransform();
+
+  this->passes.clear();
+  this->textureBindings.clear();
+  this->textures.clear();
+  quadCount = 0;
+  nextBinding = 0;
+
   auto itComponents = components.begin();
+  auto self = std::ref(*this);
   while(itComponents != components.end()) {
     auto component = *itComponents;
-
-    // Get this components' quads.
-    auto quads = component->getQuads({ 0, 0 });
-    for(auto quad : quads) {
-      data.quads[quadCount++] = quad;
-      assertTrue(quadCount <= UI_SHADER_QUAD_COUNT, "Too many UI quads!");
-    }
+    component->getQuads({ 0, 0 }, self);
     ++itComponents;
   }
+  flushPass();
 
-  // No render passes if no quads.
-  if(quadCount == 0) return passes;
+  return passes;
+}
+
+void UICanvas::addQuad(
+  const glm::vec4 quad,
+  const glm::vec4 uvs,
+  const struct Color color,
+  const std::shared_ptr<Texture> text
+) {
+  float_t fTexture = -1;
+  if(text == nullptr) {
+    fTexture = -1;
+  } else {
+    shadertexturebinding_t texture;
+    auto bindingIt = textureBindings.find(text);
+    if(bindingIt == textureBindings.end()) {
+      if(nextBinding >= UI_SHADER_TEXTURE_COUNT) {
+        flushPass();
+      }
+      textureBindings[text] = nextBinding;
+      textures[nextBinding] = text;
+      data.textures[nextBinding] = nextBinding;
+      texture = nextBinding++;
+    } else {
+      texture = bindingIt->second;
+    }
+    fTexture = (float_t)texture;
+  }
+
+  data.quads[quadCount] = {
+    quad,
+    uvs,
+    color,
+    fTexture
+  };
+  quadCount++;
+  if(quadCount == UI_SHADER_QUAD_COUNT) flushPass();
+}
+
+void UICanvas::flushPass() {
+  if(quadCount == 0) return;
 
   auto pass = createRenderPass<UIShader, UIShaderData>(
     std::ref(*this),
@@ -73,6 +110,8 @@ std::vector<std::shared_ptr<IRenderPass>> UICanvas::getPasses(
   );
   passes.push_back(pass);
 
-
-  return passes;
+  quadCount = 0;
+  nextBinding = 0;
+  textures.clear();
+  textureBindings.clear();
 }
\ No newline at end of file
diff --git a/src/dawn/component/ui/UICanvas.hpp b/src/dawn/component/ui/UICanvas.hpp
index 4c121715..124610cd 100644
--- a/src/dawn/component/ui/UICanvas.hpp
+++ b/src/dawn/component/ui/UICanvas.hpp
@@ -6,25 +6,47 @@
 #pragma once
 #include "scene/SceneItem.hpp"
 #include "component/display/IRenderableComponent.hpp"
-#include "ui/UIComponent.hpp"
+#include "display/shader/UIShader.hpp"
 
 namespace Dawn {
+  class UIComponent;
+
   class UICanvas :
     public SceneComponent,
     public IRenderableComponent
   {
-    protected:
+    private:
       std::shared_ptr<Mesh> mesh;
+      UIShaderData data;
 
+      size_t quadCount = 0;
+      shadertexturebinding_t nextBinding = 0;
+      std::unordered_map<
+        shadertexturebinding_t, std::shared_ptr<Texture>
+      > textures;
+      std::map<
+        std::shared_ptr<Texture>, shadertexturebinding_t
+      > textureBindings;
+      
+      std::vector<std::shared_ptr<IRenderPass>> passes;
+      
+    protected:
       virtual void onInit() override;
       virtual void onDispose() override;
+      void flushPass();
 
     public:
       std::vector<std::shared_ptr<UIComponent>> components;
 
-
       std::vector<std::shared_ptr<IRenderPass>> getPasses(
         struct RenderPassContext &ctx
       ) override;
+
+      void addQuad(
+        const glm::vec4 quad,
+        const glm::vec4 uvs,
+        const struct Color color,
+        const std::shared_ptr<Texture> texture
+      );
   };
 }
\ No newline at end of file
diff --git a/src/dawn/ui/UIComponent.cpp b/src/dawn/ui/UIComponent.cpp
index c7e377ee..276462e2 100644
--- a/src/dawn/ui/UIComponent.cpp
+++ b/src/dawn/ui/UIComponent.cpp
@@ -11,15 +11,12 @@ std::vector<std::shared_ptr<UIComponent>> UIComponent::getChildren() {
   return {};
 }
 
-std::vector<struct UIShaderQuad> UIComponent::getQuads(const glm::vec2 parent) {
+void UIComponent::getQuads(const glm::vec2 parent, UICanvas &ctx) {
   glm::vec2 transform = parent + position;
-  std::vector<struct UIShaderQuad> quads = this->getSelfQuads(transform);
+  this->getSelfQuads(transform, ctx);
 
   auto children = getChildren();
   for(auto &c : children) {
-    auto childQuads = c->getQuads(transform);
-    quads.insert(quads.end(), childQuads.begin(), childQuads.end());
+    c->getQuads(transform, ctx);
   }
-
-  return quads;
 }
\ No newline at end of file
diff --git a/src/dawn/ui/UIComponent.hpp b/src/dawn/ui/UIComponent.hpp
index b8ec683d..90158cb2 100644
--- a/src/dawn/ui/UIComponent.hpp
+++ b/src/dawn/ui/UIComponent.hpp
@@ -6,19 +6,14 @@
 #pragma once
 #include "ui/UIAlign.hpp"
 #include "display/shader/UIShader.hpp"
+#include "component/ui/UICanvas.hpp"
 
 namespace Dawn {
-  class UICanvas;
-
   class UIComponent {
     protected:
-      virtual std::vector<struct UIShaderQuad> getSelfQuads(
-        const glm::vec2 t
-      ) = 0;
-
+      virtual void getSelfQuads(const glm::vec2 t, UICanvas &ctx) = 0;
       virtual std::vector<std::shared_ptr<UIComponent>> getChildren();
-
-      std::vector<struct UIShaderQuad> getQuads(const glm::vec2 parent);
+      void getQuads(const glm::vec2 parent, UICanvas &ctx);
 
     public:
       glm::vec2 position;
diff --git a/src/dawn/ui/UILabel.cpp b/src/dawn/ui/UILabel.cpp
index ac44532a..dc079ca7 100644
--- a/src/dawn/ui/UILabel.cpp
+++ b/src/dawn/ui/UILabel.cpp
@@ -7,30 +7,29 @@
 
 using namespace Dawn;
 
-std::vector<struct UIShaderQuad> UILabel::getSelfQuads(const glm::vec2 t) {
+void UILabel::getSelfQuads(const glm::vec2 t, UICanvas &ctx) {
   std::vector<struct UIShaderQuad> quads;
-  if(this->texture == nullptr) return quads;
+  if(this->texture == nullptr) return;
 
-  const std::wstring text = L"Hello World!";
+  const std::wstring text = L"He";
   glm::vec2 position = t;
   glm::vec4 quad;
 
   for(wchar_t c : text) {
     auto info = texture->getCharacterData(c);
-    quads.push_back({
-      .quad = {
+    ctx.addQuad(
+      {
         position.x,
         position.y,
         position.x + info.size.x,
         position.y + info.size.y
       },
-      .uv = info.quad,
-      .color = COLOR_WHITE
-    });
+      info.quad,
+      COLOR_WHITE,
+      texture->texture
+    );
     position += info.advance;
   }
-
-  return quads;
 }
 
 void UILabel::setFont(std::shared_ptr<TrueTypeTexture> texture) {
diff --git a/src/dawn/ui/UILabel.hpp b/src/dawn/ui/UILabel.hpp
index 4faac414..6533a82c 100644
--- a/src/dawn/ui/UILabel.hpp
+++ b/src/dawn/ui/UILabel.hpp
@@ -13,7 +13,7 @@ namespace Dawn {
       std::shared_ptr<TrueTypeTexture> texture = nullptr;
 
     protected:
-      std::vector<struct UIShaderQuad> getSelfQuads(const glm::vec2 t) override;
+      void getSelfQuads(const glm::vec2 t, UICanvas &ctx) override;
 
     public:
       void setFont(std::shared_ptr<TrueTypeTexture> texture);
diff --git a/src/dawn/ui/UIRectangle.cpp b/src/dawn/ui/UIRectangle.cpp
index c27399fa..7cadac8a 100644
--- a/src/dawn/ui/UIRectangle.cpp
+++ b/src/dawn/ui/UIRectangle.cpp
@@ -7,12 +7,12 @@
 
 using namespace Dawn;
 
-std::vector<struct UIShaderQuad> UIRectangle::getSelfQuads(const glm::vec2 t) {
+void UIRectangle::getSelfQuads(const glm::vec2 t, UICanvas &ctx) {
   std::vector<struct UIShaderQuad> quads;
-  quads.push_back({
+  ctx.addQuad(
     glm::vec4(t, t + size),
     uv,
-    color
-  });
-  return quads;
+    color,
+    nullptr
+  );
 }
\ No newline at end of file
diff --git a/src/dawn/ui/UIRectangle.hpp b/src/dawn/ui/UIRectangle.hpp
index f98ccf2d..4f9d592d 100644
--- a/src/dawn/ui/UIRectangle.hpp
+++ b/src/dawn/ui/UIRectangle.hpp
@@ -9,7 +9,7 @@
 namespace Dawn {
   class UIRectangle final : public UIComponent {
     protected:
-      std::vector<struct UIShaderQuad> getSelfQuads(const glm::vec2 t) override;
+      void getSelfQuads(const glm::vec2 t, UICanvas &ctx) override;
 
     public:
       struct Color color = COLOR_WHITE;
diff --git a/src/dawnhelloworld/scene/HelloWorldScene.cpp b/src/dawnhelloworld/scene/HelloWorldScene.cpp
index e3b65a84..255f6758 100644
--- a/src/dawnhelloworld/scene/HelloWorldScene.cpp
+++ b/src/dawnhelloworld/scene/HelloWorldScene.cpp
@@ -52,10 +52,10 @@ void Dawn::helloWorldScene(Scene &s) {
   auto uiCanvasItem = s.createSceneItem();
   auto uiCanvas = uiCanvasItem->addComponent<UICanvas>();
 
-  auto rect = std::make_shared<UIRectangle>();
-  rect->position = { -32, -32 };
-  rect->color = COLOR_MAGENTA;
-  uiCanvas->components.push_back(rect);
+  // auto rect = std::make_shared<UIRectangle>();
+  // rect->position = { -32, -32 };
+  // rect->color = COLOR_MAGENTA;
+  // uiCanvas->components.push_back(rect);
 
   auto label = std::make_shared<UILabel>();
   label->setFont(texture);
diff --git a/src/dawnopengl/display/shader/ShaderStage.cpp b/src/dawnopengl/display/shader/ShaderStage.cpp
index 8ea49c15..e48c5a16 100644
--- a/src/dawnopengl/display/shader/ShaderStage.cpp
+++ b/src/dawnopengl/display/shader/ShaderStage.cpp
@@ -57,7 +57,7 @@ ShaderStage::ShaderStage(
     GLchar *log = new GLchar[logLength];
     glGetShaderInfoLog(this->id, logLength, NULL, log);
     assertNoGLError();
-    assertUnreachable("Failed to compile shader stage:\n%s", log);
+    assertUnreachable("Failed to compile shader stage %i:\n%s", type, log);
   }
 }
 
diff --git a/src/dawnopengl/display/shader/UIShader.cpp b/src/dawnopengl/display/shader/UIShader.cpp
index ba8f9052..600a3c06 100644
--- a/src/dawnopengl/display/shader/UIShader.cpp
+++ b/src/dawnopengl/display/shader/UIShader.cpp
@@ -33,19 +33,21 @@ void UIShader::getStages(
           "vec4 quad;\n"
           "vec4 uv;\n"
           "vec4 color;\n"
+          "float texture;\n"
         "};\n"
         "layout (std140) uniform ub_Quad {\n"
           "UIShaderQuad quads[" MACRO_STRINGIFY(UI_SHADER_QUAD_COUNT) "];\n"
         "};\n"
-        "out vec2 o_TextCoord;\n"
+        "out vec2 v_TextCoord;\n"
         "out vec4 v_Color;\n"
+        "out float v_TextureIndex;\n"
         "void main() {\n"
           "vec4 pos;\n"
           "vec2 coord;\n"
           "int index = int(aPos.z);\n"
           "int quadIndex = index / 4;\n"
           "int vertexIndex = index % 4;\n"
-          "struct UIShaderQuad quad = quads[quadIndex];\n"
+          "UIShaderQuad quad = quads[quadIndex];\n"
           "if(vertexIndex == 0) {\n"
             "pos.x = quad.quad.x;\n"
             "pos.y = quad.quad.y;\n"
@@ -70,19 +72,44 @@ void UIShader::getStages(
           "pos.z = 0;\n"
           "pos.w = 1;\n"
           "gl_Position = u_Projection * u_View * u_Model * pos;\n"
-          "o_TextCoord = coord;\n"
+          "v_TextCoord = coord;\n"
           "v_Color = quad.color;\n"
+          "v_TextureIndex = quad.texture;\n"
         "}"
       );
       
       fragment = std::make_shared<ShaderStage>(
         ShaderStageType::FRAGMENT,
         "#version 330 core\n"
-        "in vec2 o_TextCoord;\n"
+        "in vec2 v_TextCoord;\n"
         "in vec4 v_Color;\n"
-        "out vec4 o_Color;\n"
+        "in float v_TextureIndex;\n"
+        "uniform sampler2D u_Texture[" MACRO_STRINGIFY(UI_SHADER_TEXTURE_COUNT) "];\n"
+        "out vec4 o_Color;\n" 
         "void main() {\n"
-          "o_Color = v_Color;\n"
+          "vec4 texColor = vec4(1, 1, 1, 1);\n"
+          // "switch(int(v_TextureIndex)) {\n"
+          //   "case 0:\n"
+          //     "texColor = texture(u_Texture[0], v_TextCoord);\n"
+          //     "break;\n"
+          //   "case 1:\n"
+          //     "texColor = texture(u_Texture[1], v_TextCoord);\n"
+          //     "break;\n"
+          //   "case 2:\n"
+          //     "texColor = texture(u_Texture[2], v_TextCoord);\n"
+          //     "break;\n"
+          //   "case 3:\n"
+          //     "texColor = texture(u_Texture[3], v_TextCoord);\n"
+          //     "break;\n"
+          //   "case 4:\n"
+          //     "texColor = texture(u_Texture[4], v_TextCoord);\n"
+          //     "break;\n"
+          //   "case 5:\n"
+          //     "texColor = texture(u_Texture[5], v_TextCoord);\n"
+          //     "break;\n"
+          // "}\n"
+          "texColor = texture(u_Texture[0], v_TextCoord);\n"
+          "o_Color = texColor * v_Color;\n"
         "}\n"
       );
       break;
@@ -113,6 +140,13 @@ void UIShader::getStages(
     &rel->model,
     ShaderParameterType::MAT4
   ));
+
+  parameters.push_back(ShaderParameter(
+    "u_Texture",
+    &rel->textures,
+    ShaderParameterType::TEXTURE,
+    UI_SHADER_TEXTURE_COUNT
+  ));
   
   structures.push_back(ShaderStructure<struct UIShaderQuad>(
     "ub_Quad",
@@ -136,6 +170,12 @@ void UIShader::getStages(
         &rel.color,
         ShaderParameterType::COLOR
       ));
+
+      parameters.push_back(ShaderParameter(
+        "u_Texture",
+        &rel.texture,
+        ShaderParameterType::TEXTURE
+      ));
     },
     UI_SHADER_QUAD_COUNT
   ));
diff --git a/src/dawnopengl/display/shader/UIShader.hpp b/src/dawnopengl/display/shader/UIShader.hpp
index 0fdf7aa8..f5013748 100644
--- a/src/dawnopengl/display/shader/UIShader.hpp
+++ b/src/dawnopengl/display/shader/UIShader.hpp
@@ -8,17 +8,20 @@
 
 namespace Dawn {
   #define UI_SHADER_QUAD_COUNT 32
+  #define UI_SHADER_TEXTURE_COUNT 6
 
   struct UIShaderQuad {
     glm::vec4 quad;
     glm::vec4 uv;
     struct Color color;
+    float_t texture;
   };
   
   struct UIShaderData {
     glm::mat4 projection;
     glm::mat4 view;
     glm::mat4 model;
+    shadertexturebinding_t textures[UI_SHADER_TEXTURE_COUNT];
     struct UIShaderQuad quads[UI_SHADER_QUAD_COUNT];
   };