diff --git a/src/rendering/rasterize.c b/src/rendering/rasterize.c
new file mode 100644
index 0000000000000000000000000000000000000000..ecf1f4845ed805a6ae418b06670f7dd523f27e07
--- /dev/null
+++ b/src/rendering/rasterize.c
@@ -0,0 +1,274 @@
+#include "rasterize.h"
+
+inline float removeSign(float f){
+    if(f<0)
+        return 0;
+    return f;
+}
+
+_2x1Matrix transpose_map(_3x3Matrix m1, _3x1Matrix m2){
+    _2x1Matrix ma = {
+            (m1.a11 * m2.a11) + (m1.a12 * m2.a21) + (m1.a13 * m2.a31),
+            (m1.a21 * m2.a11) + (m1.a22 * m2.a21) + (m1.a23 * m2.a31),
+    };
+
+    return ma;
+}
+
+rectangle getXYBound2d(tri2d t){
+    uint16_t xHigh = (uint16_t)fmax(fmax(t.p0.a11,t.p1.a11),t.p2.a11);
+    uint16_t xLow = (uint16_t)fmin(fmin(t.p0.a11,t.p1.a11),t.p2.a11);
+    uint16_t yHigh = (uint16_t)fmax(fmax(t.p0.a21,t.p1.a21),t.p2.a21);
+    uint16_t yLow = (uint16_t)fmin(fmin(t.p0.a21,t.p1.a21),t.p2.a21);
+
+    rectangle r = {xLow, xHigh+1, yLow, yHigh+1};
+    return r;
+}
+
+rectangle getXYBound2dRect(rect2d t){
+    uint16_t xLow = (uint16_t)fmin(fmin(fmin(removeSign(t.p0.a11),removeSign(t.p1.a11)),
+                                        removeSign(t.p2.a11)),removeSign(t.p3.a11));
+    uint16_t xHigh = (uint16_t)fmax(fmax(fmax(removeSign(t.p0.a11),removeSign(t.p1.a11)),
+                                         removeSign(t.p2.a11)),removeSign(t.p3.a11));
+    uint16_t yLow = (uint16_t)fmin(fmin(fmin(removeSign(t.p0.a21),removeSign(t.p1.a21)),
+                                        removeSign(t.p2.a21)),removeSign(t.p3.a21));
+    uint16_t yHigh = (uint16_t)fmax(fmax(fmax(removeSign(t.p0.a21),removeSign(t.p1.a21)),
+                                         removeSign(t.p2.a21)),removeSign(t.p3.a21));
+
+    rectangle r = {xLow, xHigh+1, yLow, yHigh+1};
+    return r;
+}
+
+rectangle getXYBound3d(tri3d t){
+    uint16_t xHigh = (uint16_t)fmax(fmax(removeSign(t.p0.a11),removeSign(t.p1.a11)),removeSign(t.p2.a11));
+    uint16_t xLow = (uint16_t)fmin(fmin(removeSign(t.p0.a11),removeSign(t.p1.a11)),removeSign(t.p2.a11));
+    uint16_t yHigh = (uint16_t)fmax(fmax(removeSign(t.p0.a21),removeSign(t.p1.a21)),removeSign(t.p2.a21));
+    uint16_t yLow = (uint16_t)fmin(fmin(removeSign(t.p0.a21),removeSign(t.p1.a21)),removeSign(t.p2.a21));
+
+    rectangle r = {xLow, xHigh+1, yLow, yHigh+1};
+    return r;
+}
+
+void affineRasterize(_2x2Matrix m, PGM_P imgdata, rectangle imgRegion, int16_t dispX, int16_t dispY){ //Rectangle affine without Composites
+    rect2d t = {{imgRegion.left, imgRegion.top}, {imgRegion.right, imgRegion.top},
+                {imgRegion.right, imgRegion.bottom}, {imgRegion.left, imgRegion.bottom}};
+    _2x2Matrix invM = inverse_2x2(m);
+    rect2d tP = transpose2dRect(t, m);
+
+    rectangle r = getXYBound2dRect(tP);
+    r.bottom = removeSign((((int16_t) r.bottom) + dispY));
+    r.right = removeSign((((int16_t) r.right) + dispX));
+
+    uint16_t imgwidth = imgRegion.right-imgRegion.left;
+    uint16_t imgheight = imgRegion.bottom-imgRegion.top;
+    rectangleInRegion(&r);
+    int16_t width = r.right - r.left;
+    int16_t height = r.bottom - r.top;
+
+    char* targetptr = imgdata;
+    setupDraw(r);
+    uint16_t pixVal;
+
+    for(int16_t y=-dispY; y<=height-dispY; y++)
+        for(int16_t x=-dispX; x<=width-dispX; x++){
+            _2x1Matrix p = {x,y};
+            _2x1Matrix pT = transpose_2x2(invM, p);
+            if(pT.a11 >= 0 && pT.a11 <= imgwidth
+            && pT.a21 >= 0 && pT.a21 <= imgheight){
+                uint16_t xComp = (uint16_t) (removeSign(pT.a11));
+                uint16_t yComp = (uint16_t) (removeSign(pT.a21));
+                targetptr = imgdata + (2*(xComp+(yComp*(imgwidth+1))));
+                pixVal = pgm_read_word(targetptr);
+            } else {
+                pixVal = 0;
+            }
+            write_data16(pixVal);
+        }
+}
+
+void perspectiveRasterize(tri3d t, tri2d tuv, PGM_P imgdata, rectangle imgRegion) {
+    _3x3Matrix triangleMat = combine(t.p0, t.p1, t.p2);
+    _3x3Matrix uvMat = combine2d(tuv.p0, tuv.p1, tuv.p2);
+    _3x3Matrix invMTM = inverse_3x3(triangleMat);
+    _3x3Matrix mapping = multiply_3x3(uvMat, invMTM);
+    plane3d pl = getPlane(t);
+
+    rectangle r = getXYBound3d(t);
+    uint16_t imgwidth = imgRegion.right-imgRegion.left;
+    uint16_t imgheight = imgRegion.bottom-imgRegion.top;
+    rectangleInRegion(&r);
+    uint16_t width = r.right - r.left;
+    uint16_t height = r.bottom - r.top;
+
+    tri2d t2d = {{t.p0.a11,t.p0.a21},
+                 {t.p1.a11,t.p1.a21},
+                 {t.p2.a11,t.p2.a21}};
+
+    char* targetptr = imgdata;
+    setupDraw(r);
+    uint16_t pixVal;
+
+    for (uint16_t y = r.top; y <= r.bottom; y++) {
+        for (uint16_t x = r.left; x <= r.right; x++) {
+            _2x1Matrix point = {x, y};
+            _2x1Matrix tPoint = transpose_2x3(mapping, point);
+            if(inTriangle(tPoint.a11, tPoint.a21, tuv)){
+                uint16_t xComp = (uint16_t) (removeSign(tPoint.a11));
+                uint16_t yComp = (uint16_t) (removeSign(tPoint.a21));
+                targetptr = imgdata + (2*(xComp+(yComp*(imgwidth+1))));
+                pixVal = pgm_read_word(targetptr);
+            } else {
+                pixVal = 12;
+            }
+            write_data16(pixVal);
+        }
+    }
+}
+
+void perspectiveRasterizeComposite(tri3d t, tri2d tuv, PGM_P imgdata, rectangle imgRegion, float composite){
+    _3x3Matrix triangleMat = combine(t.p0, t.p1, t.p2);
+    _3x3Matrix uvMat = combine2d(tuv.p0, tuv.p1, tuv.p2);
+    _3x3Matrix invMTM = inverse_3x3(triangleMat);
+    _3x3Matrix mapping = multiply_3x3(uvMat, invMTM);
+    plane3d pl = getPlane(t);
+
+    rectangle r = getXYBound3d(t);
+    uint16_t imgwidth = imgRegion.right-imgRegion.left;
+    uint16_t imgheight = imgRegion.bottom-imgRegion.top;
+    rectangleInRegion(&r);
+    uint16_t width = r.right - r.left;
+    uint16_t height = r.bottom - r.top;
+
+    tri2d t2d = {{t.p0.a11,t.p0.a21},
+                 {t.p1.a11,t.p1.a21},
+                 {t.p2.a11,t.p2.a21}};
+
+    char* targetptr = imgdata;
+    uint16_t pixVal;
+
+    if(composite <= 0 || composite > 1.0f)
+        return;
+
+    for (uint16_t y = 0; y <= r.bottom-r.top; y++) {
+        uint16_t yVal = y + r.top;
+        rectangle rReg;
+        uint16_t topR = y + r.top;
+
+        write_cmd(COLUMN_ADDRESS_SET);
+        write_data16(r.left);
+        write_data16(r.right);
+        write_cmd(PAGE_ADDRESS_SET);
+        write_data16(topR);
+        write_data16(topR);
+        write_cmd(MEMORY_READ);
+
+        uint16_t colorValues[width + 1];
+        read_data(); //Throw away a byte
+        for (uint16_t x = 0; x <= r.right-r.left; x++) {
+            unsigned char r = read_data() >> 2;
+            unsigned char g = read_data() >> 2;
+            unsigned char b = read_data() >> 2;
+            uint16_t value = (((uint16_t)b)>>1) + (((uint16_t)g) << 5) + ((((uint16_t)r)>>1) << 11);
+            colorValues[x] = value; //It'd be quick to not convert but requires bigger cache, makes this less memory heavy
+        }
+
+        write_cmd(MEMORY_WRITE);
+        for (uint16_t x = 0; x <= r.right-r.left; x++) {
+            uint16_t xVal = x + r.left;
+            _2x1Matrix point = {xVal, yVal};
+            _2x1Matrix tPoint = transpose_2x3(mapping, point);
+            if(inTriangle(tPoint.a11, tPoint.a21, tuv)){
+                uint16_t xComp = (uint16_t) (removeSign(tPoint.a11));
+                uint16_t yComp = (uint16_t) (removeSign(tPoint.a21));
+                targetptr = imgdata + (2*(xComp+(yComp*(imgwidth+1))));
+                pixVal = pgm_read_word(targetptr);
+                if(pixVal == TRANSPARENTCOLOR){
+                    pixVal = colorValues[x];
+                } else if(composite != 1.0f){
+                    unsigned char r = ((unsigned char) ((((colorValues[x]>>11) & 31) * (1.0 - composite)) + (((pixVal>>11) & 31) * (composite)))) & 31;
+                    unsigned char g = ((unsigned char) ((((colorValues[x]>>5) & 63) * (1.0 - composite)) + (((pixVal>>5) & 63) * (composite)))) & 63;
+                    unsigned char b = ((unsigned char) (((colorValues[x] & 31) * (1.0 - composite)) + ((pixVal & 31) * (composite)))) & 31;
+                    pixVal = ((uint16_t)b) + (((uint16_t)g) << 5) + ((((uint16_t)r)) << 11);
+                }
+
+            } else {
+                pixVal = colorValues[x];
+            }
+            write_data16(pixVal);
+        }
+    }
+}
+
+//Credit:Kornel Kisielewicz, https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle
+
+float triSign (_2x1Matrix p0, _2x1Matrix p1, _2x1Matrix p2){
+    return ((p0.a11 - p2.a11) * (p1.a21 - p2.a21)) -  ((p1.a11 - p2.a11) * (p0.a21 - p2.a21));
+}
+
+plane3d getPlane(tri3d t){
+    _3x1Matrix Vp2p0 = minus_3x1(t.p2, t.p0);
+    _3x1Matrix Vp1p0 = minus_3x1(t.p1, t.p0);
+    _3x1Matrix crossVectors = crossProduct(Vp1p0,Vp2p0);
+    plane3d p = {crossVectors, t.p0};
+
+    return p;
+}
+
+float getZ(float x, float y, plane3d p){
+    float z = p.anchor.a31 + ((-(p.gr.a11*(x-p.anchor.a11))-(p.gr.a21*(y-p.anchor.a21)))/p.gr.a31);
+    return z;
+}
+
+unsigned char inTriangle(float x, float y, tri2d t){
+    _2x1Matrix px = {x, y};
+    float d1 = triSign(px, t.p0, t.p1);
+    float d2 = triSign(px, t.p1, t.p2);
+    float d3 = triSign(px, t.p2, t.p0);
+
+    unsigned char hasNegative = (d1 < 0) || (d2 < 0) || (d3 < 0);
+    unsigned char hasPositive = (d1 > 0) || (d2 > 0) || (d3 > 0);
+
+    return !(hasNegative && hasPositive);
+}
+
+
+rect2d transpose2dRect(rect2d t, _2x2Matrix m){
+    rect2d tP;
+    tP.p0 = transpose_2x2(m, t.p0);
+    tP.p1 = transpose_2x2(m, t.p1);
+    tP.p2 = transpose_2x2(m, t.p2);
+    tP.p3 = transpose_2x2(m, t.p3);
+
+    return tP;
+}
+
+tri3d seperate(_3x3Matrix m){
+    _3x1Matrix p0 = {m.a11, m.a21, m.a31};
+    _3x1Matrix p1 = {m.a12, m.a22, m.a32};
+    _3x1Matrix p2 = {m.a13, m.a23, m.a33};
+
+    tri3d t = {p0, p1, p2};
+    return t;
+}
+
+tri3d transpose3dTri(tri3d t, _3x3Matrix m) {
+    _3x3Matrix m1 = combine(t.p0, t.p1, t.p2);
+    _3x3Matrix tP = multiply_3x3(m, m1);
+    return seperate(tP);
+}
+
+_3x3Matrix combine2d(_2x1Matrix m1, _2x1Matrix m2, _2x1Matrix m3){
+    _3x3Matrix m = {m1.a11, m2.a11, m3.a11,
+                    m1.a21, m2.a21, m3.a21,
+                    0, 0, 0};
+    return m;
+}
+
+_2x1Matrix transpose_2x3(_3x3Matrix m1, _2x1Matrix m2){
+    _2x1Matrix ma = {
+            (m1.a11 * m2.a11) + (m1.a12 * m2.a21) + m1.a13,
+            (m1.a21 * m2.a11) + (m1.a22 * m2.a21) + m1.a23,
+
+    };
+    return ma;
+}
\ No newline at end of file