diff --git a/CMakeLists.txt b/CMakeLists.txt index 639e78c7e5bfbf69ae738b71c879f6171ea55331..e71a1f8bae46f638c3a5ef88318d5d6f6acfd7be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,13 @@ find_package(OpenGL REQUIRED) link_directories(${GTKMM_LIBRARY_DIRS}) include_directories(${GTKMM_INCLUDE_DIRS}) +find_package(OpenMP) +if (OPENMP_FOUND) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") +endif() + add_executable(Skeleton framework.h framework.cpp diff --git a/Skeleton.cpp b/Skeleton.cpp index 63829ab53814234644cafb5c68b086db1623c35b..8b6014218c03039ef021fe594800c7010de96b02 100644 --- a/Skeleton.cpp +++ b/Skeleton.cpp @@ -42,10 +42,34 @@ int objIndex[12][5]{ {5, 6, 19, 10, 14} }; +enum MaterialType { ROUGH, REFLECTIVE }; + struct Material { vec3 ka, kd, ks; float shininess; - Material(vec3 _kd, vec3 _ks, float _shininess) : ka(_kd * M_PI), kd(_kd), ks(_ks) { shininess = _shininess; } + vec3 F0; + MaterialType type; + Material(MaterialType t): type(t) {} +}; + +struct RoughMaterial: Material { + RoughMaterial(vec3 _kd, vec3 _ks, float _shininess): Material(ROUGH) { + ka = _kd * M_PI; + kd = _kd; + ks = _ks; + shininess = _shininess; + } +}; + +vec3 operator/(const vec3& num, const vec3& denom) { + return vec3(num.x / denom.x, num.y / denom.y, num.z / denom.z); +} + +struct ReflectiveMaterial: Material { + ReflectiveMaterial(vec3 n, vec3 kappa): Material(REFLECTIVE) { + vec3 one(1, 1, 1); + F0 = ((n - one)*(n - one) + kappa*kappa) / ((n + one)*(n + one) + kappa*kappa); + } }; struct Hit { @@ -192,13 +216,15 @@ public: La = vec3(0.4f, 0.4f, 0.4f); vec3 lightPosition(.5, .5, 0), Le(2, 2, 2); lights.push_back(new Light(lightPosition, Le)); - - vec3 kd(0.3f, 0.2f, 0.1f), ks(2, 2, 2); - Material * material = new Material(kd, ks, 50); - objects.push_back(new Sphere(vec3(0, 0, 0), .25f, material)); - //objects.push_back(new Pentagon(vec3(0.03, -.01, 0), vec3(0, .37, 0), vec3(-.47, .49, 0), vec3(-.73, .08, 0), vec3(-.414, -0.288, 0), material)); + vec3 n(.17, .35, 1.5); + vec3 kappa(3.1, 2.7, 1.9); + Material* gold = new ReflectiveMaterial(n, kappa); + objects.push_back(new Sphere(vec3(0, 0, 0), .25f, gold)); + //objects.push_back(new Pentagon(vec3(0.03, -.01, 0), vec3(0, .37, 0), vec3(-.47, .49, 0), vec3(-.73, .08, 0), vec3(-.414, -0.288, 0), dodekaMat)); + vec3 kd(0.3f, 0.3f, .3f), ks(2, 2, 2); + Material* dodekaMat = new RoughMaterial(kd, ks, 50); for (int i = 0; i < 12; i++) { auto indexRow = objIndex[i]; auto p1 = objPoints[indexRow[0]]; @@ -207,13 +233,13 @@ public: auto p4 = objPoints[indexRow[3]]; auto p5 = objPoints[indexRow[4]]; - objects.push_back(new Pentagon(p1, p2, p3, p4, p5, material)); + objects.push_back(new Pentagon(p1, p2, p3, p4, p5, dodekaMat)); } } void render(std::vector<vec4>& image) { +#pragma omp parallel for collapse(2) for (int Y = 0; Y < windowHeight; Y++) { -#pragma omp parallel for for (int X = 0; X < windowWidth; X++) { vec3 color = trace(camera.getRay(X, Y)); image[Y * windowWidth + X] = vec4(color.x, color.y, color.z, 1); @@ -242,19 +268,39 @@ public: } vec3 trace(Ray ray, int depth = 0) { + if (depth > 5) { + return La; + } + Hit hit = firstIntersect(ray); if (hit.t < 0) return La; - vec3 outRadiance = hit.material->ka * La; - for (Light * light : lights) { - Ray shadowRay(hit.position + hit.normal * epsilon, light->position); - float cosTheta = dot(hit.normal, light->position); - if (cosTheta > 0 && !shadowIntersect(shadowRay)) { // shadow computation - outRadiance = outRadiance + light->Le * hit.material->kd * cosTheta; - vec3 halfway = normalize(-ray.dir + light->position); - float cosDelta = dot(hit.normal, halfway); - if (cosDelta > 0) outRadiance = outRadiance + light->Le * hit.material->ks * powf(cosDelta, hit.material->shininess); - } - } + + vec3 outRadiance(0, 0, 0); + if (hit.material->type == ROUGH) { + outRadiance = hit.material->ka * La; + for (Light *light : lights) { + Ray shadowRay(hit.position + hit.normal * epsilon, light->position); + float cosTheta = dot(hit.normal, light->position); + if (cosTheta > 0 && !shadowIntersect(shadowRay)) { // shadow computation + outRadiance = outRadiance + light->Le * hit.material->kd * cosTheta; + vec3 halfway = normalize(-ray.dir + light->position); + float cosDelta = dot(hit.normal, halfway); + if (cosDelta > 0) outRadiance = outRadiance + light->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; + } + return outRadiance; }