diff --git a/RayTracer/shape/Sphere.cpp b/RayTracer/shape/Sphere.cpp
index 08420e50ca55bfbc321d64ac6395ff69045bc9b3..d9c90e3e5078998c1037a98bf28580494f44291e 100644
--- a/RayTracer/shape/Sphere.cpp
+++ b/RayTracer/shape/Sphere.cpp
@@ -25,16 +25,18 @@ std::optional<cam::Hit> Sphere::intersect(const cam::Ray& r) const {
 			util::Vec3 t1HitPoint = r(t1);
 			float theta = acos(t1HitPoint.y() / radius);
 			float phi = M_PI + atan2(t1HitPoint.x(), t1HitPoint.z());
-			return std::optional<cam::Hit>(
-			    {t1HitPoint, t1HitPoint, t1, material});
+			return std::optional<cam::Hit>({t1HitPoint, t1HitPoint,
+			                                texture_coordinates(t1HitPoint), t1,
+			                                material});
 		} else {
 			float t2 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a);
 			if (r.in_range(t2)) {
 				util::Vec3 t2HitPoint = r(t2);
 				float theta = acos(t2HitPoint.y() / radius);
 				float phi = M_PI + atan2(t2HitPoint.x(), t2HitPoint.z());
-				return std::optional<cam::Hit>(
-				    {t2HitPoint, t2HitPoint, t2, material});
+				return std::optional<cam::Hit>({t2HitPoint, t2HitPoint,
+				                                texture_coordinates(t2HitPoint),
+				                                t2, material});
 			} else {
 				return std::nullopt;
 			}
@@ -43,6 +45,12 @@ std::optional<cam::Hit> Sphere::intersect(const cam::Ray& r) const {
 		return std::nullopt;
 	}
 }
+std::pair<float, float> Sphere::texture_coordinates(
+    const util::Vec3& pos) const {
+	float theta = std::acos(pos.y() / radius);
+	float phi = M_PI + std::atan2(pos.x(), pos.z());
+	return std::pair<float, float>({phi / (2 * M_PI), theta / M_PI});
+}
 util::AxisAlignedBoundingBox Sphere::bounds() const {
 	return util::AxisAlignedBoundingBox(util::Vec3(-radius),
 	                                    util::Vec3(radius));
@@ -56,7 +64,8 @@ util::SurfacePoint Sphere::sampleLight() const {
 	util::Vec3 point(radius * std::cos(theta) * std::sin(phi),
 	                 radius * std::sin(theta) * std::sin(phi),
 	                 radius * std::cos(phi));
-	return util::SurfacePoint(point, point.normalize(), material);
+	return util::SurfacePoint(point, point.normalize(),
+	                          texture_coordinates(point), material);
 }
 util::Vec3 Sphere::calculateLightEmission(const util::SurfacePoint& p,
                                           const util::Vec3& d) const {
diff --git a/RayTracer/shape/Sphere.h b/RayTracer/shape/Sphere.h
index 73edcc2a9d12a20799d69102b9c21f63c7bff657..6216575f94b380c4dac2a82ab4fab27ab188a90f 100644
--- a/RayTracer/shape/Sphere.h
+++ b/RayTracer/shape/Sphere.h
@@ -8,6 +8,8 @@ class Sphere : public Light, public Shape {
    public:
 	Sphere(float radius, const std::shared_ptr<material::Material>& material);
 	std::optional<cam::Hit> intersect(const cam::Ray& r) const override;
+	std::pair<float, float> texture_coordinates(
+	    const util::Vec3& pos) const override;
 	util::AxisAlignedBoundingBox bounds() const override;
 	util::SurfacePoint sampleLight() const override;
 	util::Vec3 calculateLightEmission(const util::SurfacePoint& p,