diff --git a/Skeleton.cpp b/Skeleton.cpp
index 16b7627cd67b86f6e10009c344e01d600774d4a2..dd0e3a598165f6361e31589339262f6031e716f8 100644
--- a/Skeleton.cpp
+++ b/Skeleton.cpp
@@ -48,15 +48,14 @@ struct Light;
 class Scene;
 
 struct Material {
-	vec3 ka, kd, ks;
-	float  shininess;
-	vec3 F0;
 	Material() {}
     
     virtual void trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) = 0;
 };
 
 struct RoughMaterial: Material {
+    vec3 ka, kd, ks;
+    float  shininess;
     RoughMaterial(vec3 _kd, vec3 _ks, float _shininess) {
         ka = _kd * M_PI;
         kd = _kd;
@@ -72,6 +71,7 @@ vec3 operator/(const vec3& num, const vec3& denom) {
 }
 
 struct ReflectiveMaterial: Material {
+    vec3 F0;
     ReflectiveMaterial(vec3 n, vec3 kappa) {
         vec3 one(1, 1, 1);
         F0 = ((n - one)*(n - one) + kappa*kappa) / ((n + one)*(n + one) + kappa*kappa);
@@ -80,13 +80,10 @@ struct ReflectiveMaterial: Material {
     void trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) override;
 };
 
-struct PortalMaterial: ReflectiveMaterial {
-    PortalMaterial(): ReflectiveMaterial(0, 0){
-        F0 = 1;
-    }
-    void trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) override {
-        ReflectiveMaterial::trace(scene, hit, ray, lights, depth, outRadiance);
+struct PortalMaterial: Material {
+    PortalMaterial() {
     }
+    void trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) override;
 };
 
 struct Hit {
@@ -329,17 +326,17 @@ public:
 };
 
 void RoughMaterial::trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) {
-    outRadiance = hit.material->ka * scene.getLa();
+    outRadiance = ka * scene.getLa();
     for (Light *light : lights) {
         auto cosTheta = dot(hit.normal, light->getDirection(hit.position));
         Ray shadowRay(hit.position + hit.normal * epsilon, light->getDirection(hit.position));
         if (cosTheta > 0 && !scene.shadowIntersect(shadowRay, light)) {    // shadow computation
             vec3 le = light->Le / powf(light->getDistance(hit.position), 2);
-            outRadiance = outRadiance + le * hit.material->kd * cosTheta;
+            outRadiance = outRadiance + le * kd * cosTheta;
             vec3 halfway = normalize(-ray.dir + light->getDirection(hit.position));
             float cosDelta = dot(hit.normal, halfway);
             if (cosDelta > 0)
-                outRadiance = outRadiance + le * hit.material->ks * powf(cosDelta, hit.material->shininess);
+                outRadiance = outRadiance + le * ks * powf(cosDelta, shininess);
         }
     }
 }
@@ -349,11 +346,16 @@ void ReflectiveMaterial::trace(const Scene& scene, const Hit& hit, const Ray& ra
     
     float cosa = -dot(ray.dir, hit.normal);
     vec3 one(1, 1, 1);
-    vec3 F = hit.material->F0 + (one - hit.material->F0) * pow(1 - cosa, 5);
+    vec3 F = F0 + (one - F0) * pow(1 - cosa, 5);
     
     outRadiance = outRadiance + scene.trace(Ray(hit.position + hit.normal * epsilon, reflectedDir), depth + 1) * F;
 }
 
+void PortalMaterial::trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) {
+    vec3 reflectedDir = ray.dir - hit.normal * dot(hit.normal, ray.dir) * 2.0f;
+    outRadiance = outRadiance + scene.trace(Ray(hit.position + hit.normal * epsilon, reflectedDir), depth + 1);
+}
+
 GPUProgram gpuProgram; // vertex and fragment shaders
 Scene scene;