diff --git a/index.html b/index.html
index d2a125a6c4a6830a12284dd3fbc28d067f07a5a9..d31a42c2c9dbfaaefa8b5155e0b44d722c8c6f39 100644
--- a/index.html
+++ b/index.html
@@ -15,6 +15,6 @@
     <script type="module" src="/src/cg/perspectiveDivide.ts"></script>
     <script type="module" src="/src/cg/walkToVec.ts"></script>
     <script type="module" src="/src/cg/basis.ts"></script-->
-    <script type="module" src="/src/cg/raytracing2.ts"></script>
+    <script type="module" src="/src/cg/raytracing2animation.ts"></script>
   </body>
 </html>
diff --git a/src/cg/raytracing2.ts b/src/cg/raytracing2.ts
index 4fec61b39b6946645072af844d217227607852df..475ec1c8f23a11facf34e692ec7810090b7364d8 100644
--- a/src/cg/raytracing2.ts
+++ b/src/cg/raytracing2.ts
@@ -4,7 +4,7 @@ import { ISphere, Vec3, raySphereIntersect } from "./utils";
 const width = 200
 const height = 200
 const framebuffer = new Framebuffer(width, height);
-const imagePlaneDist = -1
+const imagePlaneDist = -0.5
 
 const tNear = 1;
 const tFar = 1000;
@@ -12,14 +12,19 @@ const tFar = 1000;
 const spheres = [
     {
         position: [0, 0, -3],// <--- 
-        radius: 2,// <--- 
+        radius: 1,// <--- 
         color: [255,0,0]// <--- 
     },
     {
         position: [3,2,-3],// <--- 
-        radius: 2,// <--- 
+        radius: 0.5,// <--- 
         color: [0,255,0]// <--- 
     },
+    {
+        position: [-2, -2, -4],
+        radius: 1,
+        color: [0,0,255]
+    }
     //... add more spheres if you like
 ]
 
diff --git a/src/cg/raytracing2animation frames/render.spheres.1.png b/src/cg/raytracing2animation frames/render.spheres.1.png
new file mode 100644
index 0000000000000000000000000000000000000000..99e5178a669525e38d730702d80ef979db95cc9e
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.1.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.10.png b/src/cg/raytracing2animation frames/render.spheres.10.png
new file mode 100644
index 0000000000000000000000000000000000000000..807475fa31af0b4aff8d2277adfa2a7c897cda2d
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.10.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.11.png b/src/cg/raytracing2animation frames/render.spheres.11.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a4030e4ffe0d9f33175953a37cb76839f4ae8bc
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.11.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.2.png b/src/cg/raytracing2animation frames/render.spheres.2.png
new file mode 100644
index 0000000000000000000000000000000000000000..390880d5272c8f53faec88857ec4400a4a5d1770
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.2.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.3.png b/src/cg/raytracing2animation frames/render.spheres.3.png
new file mode 100644
index 0000000000000000000000000000000000000000..5255f85565a517ea56130c79492961616fe59b02
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.3.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.5.png b/src/cg/raytracing2animation frames/render.spheres.5.png
new file mode 100644
index 0000000000000000000000000000000000000000..ef64d1405296089a52e0367d33386a6b79247a4d
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.5.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.6.png b/src/cg/raytracing2animation frames/render.spheres.6.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e56bda15c4d3d502e4031b0687c054df4bea10f
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.6.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.7.png b/src/cg/raytracing2animation frames/render.spheres.7.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b972a8d57ea6ce17a05a800fcfe4f94aa7bbb71
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.7.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.8.png b/src/cg/raytracing2animation frames/render.spheres.8.png
new file mode 100644
index 0000000000000000000000000000000000000000..a003471af1daeb790582b9fd5342bf55a1830a59
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.8.png differ
diff --git a/src/cg/raytracing2animation frames/render.spheres.9.png b/src/cg/raytracing2animation frames/render.spheres.9.png
new file mode 100644
index 0000000000000000000000000000000000000000..5bbe0f02f1eda97774dfc131d3c85226645960ad
Binary files /dev/null and b/src/cg/raytracing2animation frames/render.spheres.9.png differ
diff --git a/src/cg/raytracing2animation.ts b/src/cg/raytracing2animation.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d1b060067710ab9e278b2461bad5c7ede969f8ac
--- /dev/null
+++ b/src/cg/raytracing2animation.ts
@@ -0,0 +1,97 @@
+import Framebuffer from "./framebuffer";
+import { Vec3, Matrix4, Matrix3, matrix3ToMatrix4, matrix4Product, raySphereIntersect, ISphere, rotX, rotY, multVec3Matrix4 } from "./utils";
+
+const width = 600
+const height = 600
+const framebuffer = new Framebuffer(width, height);
+const imagePlaneDist = -0.5
+
+const tNear = 1;
+const tFar = 1000;
+
+const spheres = [
+    {
+        "position": [-2.5, 0, 0],
+        "radius": 1,
+        "color": [128, 0, 0]
+    },
+    {
+        "position": [0, 0, 0],
+        "radius": 1,
+        "color": [0, 128, 0]
+    },
+    {
+        "position": [2.5, 0, 0],
+        "radius": 1,
+        "color": [0, 0, 128]
+    },
+]
+
+const o: Vec3 = [0, 0, 0]
+
+
+const camT: Matrix4 = [
+    1, 0, 0, 0,
+    0, 1, 0, 0,
+    0, 0, 1, 0,
+    0, 0, 3, 1  // <--- 4x4 matrix that moves the camera in Z
+]
+
+const camRx = matrix3ToMatrix4(rotX(-30))// <--- rotation matrix around X. Convert it to 4x4. 
+
+const camInitialTransform = matrix4Product(camT, camRx)// <--- combine camT and camRX into a new matrix
+
+let currentFrame = 0
+
+for (let i = 0; i <= 1; i += .1) {
+    framebuffer.clear()
+
+    
+    const camRot = rotY(360*i)// <--- rotation matrix around Y using 360 * i in each frame 
+
+    
+    const combinedCameraTransform = matrix4Product(camInitialTransform, matrix3ToMatrix4(camRot)) // <--- Combine transformations: 
+                                    // initial transform then rotate
+
+
+    // Loop over framebuffer pixels
+    for (let x = 0; x <= width; x++) {
+        for (let y = 0; y <= height; y++) {
+
+            // Convert to screen space
+            const v = framebuffer.rasterToScreen(x, y, width, height, imagePlaneDist)// <--- convert raster to screen space 
+            const vTransformed = multVec3Matrix4(v, combinedCameraTransform)// <--- apply camera transform
+            const oTransformed = multVec3Matrix4(o, combinedCameraTransform)// <--- apply camera transform
+
+            // ...
+            // ... same as in previous task but using transformed camera vectors
+            let closestSphere = null;
+            let closestIntersection = 9999;
+
+            for (let i = 0; i < spheres.length; i++) {
+
+                const [t1, t2] = raySphereIntersect(vTransformed, oTransformed, spheres[i] as ISphere)// <--- Calculate intersections
+    
+                if (t1 < closestIntersection && tNear < t1 && t1 < tFar) {
+                    closestIntersection = t1;
+                    closestSphere = spheres[i]
+                }
+    
+                if (t2 < closestIntersection && tNear < t2 && t2 < tFar) {
+                    closestIntersection = t2;
+                    closestSphere = spheres[i];
+                }
+            }
+            if (!closestSphere) {
+                framebuffer.draw(x,y,[0,0,50]) // <--- Draw a background color
+            } else {
+                framebuffer.draw(x,y,closestSphere.color) // <--- Draw color of closest sphere
+            }
+
+        }
+
+    }
+    framebuffer.update();
+    framebuffer.save("spheres." + ++currentFrame);
+
+}
\ No newline at end of file
diff --git a/src/cg/utils.ts b/src/cg/utils.ts
index 1a4beb8a8ab71bc9f2674b95c9b9f9c0b9f372f6..7e334667721bf82501a41fd854fd7b9521c841bb 100644
--- a/src/cg/utils.ts
+++ b/src/cg/utils.ts
@@ -124,7 +124,7 @@ export function multVecMatrix(v: Array<number>, m: Array<number>){
     ]
 }
 
-export function rotX(degrees: number){
+export function rotX(degrees: number): Matrix3{
     const radian = degrees * Math.PI / 180
     return [
         1, 0, 0,
@@ -133,7 +133,7 @@ export function rotX(degrees: number){
     ]
 }
 
-export function rotY(degrees: number){
+export function rotY(degrees: number): Matrix3{
     const radian = degrees * Math.PI / 180
     return [
         Math.cos(radian), 0, -1*Math.sin(radian),
@@ -142,7 +142,7 @@ export function rotY(degrees: number){
     ]
 }
 
-export function rotZ(degrees: number){
+export function rotZ(degrees: number): Matrix3{
     const radian = degrees * Math.PI / 180
     return [
         Math.cos(radian), Math.sin(radian), 0,