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