From 1d2054d8503bc7c4dab16f7df22b8fef108c2897 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mikl=C3=B3s=20T=C3=B3th?= <tothmiklostibor@gmail.com>
Date: Thu, 15 Apr 2021 20:45:28 +0200
Subject: [PATCH] OOP

---
 Skeleton.cpp | 74 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 46 insertions(+), 28 deletions(-)

diff --git a/Skeleton.cpp b/Skeleton.cpp
index 0535868..fb4e53d 100644
--- a/Skeleton.cpp
+++ b/Skeleton.cpp
@@ -44,12 +44,19 @@ int objIndex[12][5]{
 
 enum MaterialType { ROUGH, REFLECTIVE };
 
+struct Hit;
+struct Ray;
+struct Light;
+class Scene;
+
 struct Material {
 	vec3 ka, kd, ks;
 	float  shininess;
 	vec3 F0;
 	MaterialType type;
 	Material(MaterialType t): type(t) {}
+    
+    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 {
@@ -59,6 +66,8 @@ struct RoughMaterial: Material {
         ks = _ks;
         shininess = _shininess;
     }
+    
+    void trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) override;
 };
 
 vec3 operator/(const vec3& num, const vec3& denom) {
@@ -70,6 +79,8 @@ struct ReflectiveMaterial: Material {
         vec3 one(1, 1, 1);
         F0 = ((n - one)*(n - one) + kappa*kappa) / ((n + one)*(n + one) + kappa*kappa);
     }
+    
+    void trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) override;
 };
 
 struct Hit {
@@ -217,6 +228,10 @@ class Scene {
 	Camera camera;
 	vec3 La;
 public:
+    const vec3& getLa() const {
+        return La;
+    }
+    
 	void build() {
 		vec3 eye = vec3( .9, 0, .9), vup = vec3(0, 1, 0), lookat = vec3(0, 0, 0);
 		float fov = 45 * M_PI / 180;
@@ -256,7 +271,7 @@ public:
 		}
 	}
 
-	Hit firstIntersect(Ray ray) {
+	Hit firstIntersect(Ray ray) const {
 		Hit bestHit;
 		for (Intersectable * object : objects) {
 			Hit hit = object->intersect(ray); //  hit.t < 0 if no intersection
@@ -266,7 +281,7 @@ public:
 		return bestHit;
 	}
 
-	bool shadowIntersect(Ray ray, Light* light) {	// for directional lights
+	bool shadowIntersect(Ray ray, Light* light) const {	// for directional lights
 		for (Intersectable * object : objects) {
             Hit hit = object->intersect(ray);
             if (hit.t > 0)
@@ -276,7 +291,7 @@ public:
 		return false;
 	}
 
-	vec3 trace(Ray ray, int depth = 0) {
+	vec3 trace(Ray ray, int depth = 0) const {
         if (depth > 5) {
             return La;
         }
@@ -285,31 +300,8 @@ public:
 		if (hit.t < 0) return La;
 		
 		vec3 outRadiance(0, 0, 0);
-		if (hit.material->type == ROUGH) {
-            outRadiance = hit.material->ka * La;
-            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 && !shadowIntersect(shadowRay, light)) {    // shadow computation
-                    vec3 le = light->Le / powf(light->getDistance(hit.position), 2);
-                    outRadiance = outRadiance + le * hit.material->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);
-                }
-            }
-        }
-        
-        if (hit.material->type == REFLECTIVE) {
-            vec3 reflectedDir = ray.dir - hit.normal * dot(hit.normal, ray.dir) * 2.0f;
-            
-            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);
-            
-            outRadiance = outRadiance + trace(Ray(hit.position + hit.normal * epsilon, reflectedDir), depth + 1) * F;
-        }
+		
+		hit.material->trace(*this, hit, ray, lights, depth, outRadiance);
 		
 		return outRadiance;
 	}
@@ -319,6 +311,32 @@ 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();
+    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;
+            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);
+        }
+    }
+}
+
+void ReflectiveMaterial::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;
+    
+    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);
+    
+    outRadiance = outRadiance + scene.trace(Ray(hit.position + hit.normal * epsilon, reflectedDir), depth + 1) * F;
+}
+
 GPUProgram gpuProgram; // vertex and fragment shaders
 Scene scene;
 
-- 
GitLab