diff --git a/projects/saf_r/shaders/raytracing.comp b/projects/saf_r/shaders/raytracing.comp index d7f791899be922b23ec277b3820b8d99e913b52f..a7c6b92a646e5c2f753946f74fe7ab78aea44fe6 100644 --- a/projects/saf_r/shaders/raytracing.comp +++ b/projects/saf_r/shaders/raytracing.comp @@ -10,8 +10,9 @@ layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; //structs of materials, lights, spheres and intersection for use in compute shader struct Material { vec3 albedo; - vec3 diffuse_color; - float specular_exponent; + vec3 diffuseColor; + float specularExponent; + float refractiveIndex; }; struct Light{ @@ -53,6 +54,40 @@ layout( push_constant ) uniform constants{ int sphereCount; }; +/* +* safrReflect computes the new reflected or refracted ray depending on the material +* @param vec3: raydirection vector +* @param vec3: normalvector on which should be reflected or refracted +* @param float: degree of refraction. In case of simple reflection it is 1.0 +* @return vec3: new ray that is the result of the reflection or refraction +*/ +vec3 safrReflect(vec3 V, vec3 N, float refractIndex){ + if(refractIndex != 1.0){ + // Snell's law + float cosi = - max(-1.f, min(1.f, dot(V,N))); + float etai = 1; + float etat = refractIndex; + vec3 n = N; + float swap; + if(cosi < 0){ + cosi = -cosi; + n = -N; + swap = etai; + etai = etat; + etat = swap; + } + float eta = etai / etat; + float k = 1 - eta * eta * (1 - cosi * cosi); + if(k < 0){ + return vec3(0,0,0); + } else { + return V * eta + n * (eta * cosi - sqrt(k)); + } + }else{ + return reflect(V, N); + } +} + /* * the rayIntersect function checks, if a ray from the raytracer passes through the sphere, hits the sphere or passes by the the sphere * @param vec3: origin of ray @@ -167,11 +202,11 @@ vec3 computeHitLighting(Intersection intersection, vec3 V, out float outReflecti } lightIntensityDiffuse += inLights[i].intensity * max(0.f, dot(L, intersection.N)); - lightIntensitySpecular += pow(max(0.f, dot(reflect(V, intersection.N), L)), intersection.material.specular_exponent) * inLights[i].intensity; + lightIntensitySpecular += pow(max(0.f, dot(safrReflect(V, intersection.N, intersection.material.refractiveIndex), L)), intersection.material.specularExponent) * inLights[i].intensity; } outReflectionThroughput = intersection.material.albedo[2]; - return intersection.material.diffuse_color * lightIntensityDiffuse * intersection.material.albedo[0] + lightIntensitySpecular * intersection.material.albedo[1]; + return intersection.material.diffuseColor * lightIntensityDiffuse * intersection.material.albedo[0] + lightIntensitySpecular * intersection.material.albedo[1]; } /* @@ -214,7 +249,7 @@ vec3 castRay(const vec3 initialOrigin, const vec3 initialDirection, int max_dept } //compute new direction and origin of the reflected ray - rayDirection = normalize(reflect(rayDirection, intersection.N)); + rayDirection = normalize(safrReflect(rayDirection, intersection.N, intersection.material.refractiveIndex)); rayOrigin = biasHitPosition(intersection.pos, rayDirection, intersection.N); } diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp index 18b691b16f80f84da62c70c97bfc09c4958b8757..3fef073a00f8263cc08ce17f033170d0f4031dc4 100644 --- a/projects/saf_r/src/main.cpp +++ b/projects/saf_r/src/main.cpp @@ -97,9 +97,11 @@ int main(int argc, const char** argv) { //materials for the spheres std::vector<safrScene::Material> materials; - safrScene::Material ivory(glm::vec3(0.6, 0.3, 0.1), glm::vec3(0.4, 0.4, 0.3), 50.); - safrScene::Material red_rubber(glm::vec3(0.9, 0.1, 0.0), glm::vec3(0.3, 0.1, 0.1), 10.); - safrScene::Material mirror(glm::vec3(0.0, 10.0, 0.8), glm::vec3(1.0, 1.0, 1.0), 1425.); + safrScene::Material ivory(glm::vec4(0.6, 0.3, 0.1, 0.0), glm::vec3(0.4, 0.4, 0.3), 50., 1.0); + safrScene::Material red_rubber(glm::vec4(0.9, 0.1, 0.0, 0.0), glm::vec3(0.3, 0.1, 0.1), 10., 1.0); + safrScene::Material mirror( glm::vec4(0.0, 10.0, 0.8, 0.0), glm::vec3(1.0, 1.0, 1.0), 1425., 1.0); + safrScene::Material glass( glm::vec4(0.0, 10.0, 0.8, 0.0), glm::vec3(1.0, 1.0, 1.0), 1425., 1.5); + materials.push_back(ivory); materials.push_back(red_rubber); materials.push_back(mirror); @@ -108,7 +110,7 @@ int main(int argc, const char** argv) { std::vector<safrScene::Sphere> spheres; spheres.push_back(safrScene::Sphere(glm::vec3(-3, 0, -16), 2, ivory)); // spheres.push_back(safrScene::Sphere(glm::vec3(-1.0, -1.5, 12), 2, mirror)); - spheres.push_back(safrScene::Sphere(glm::vec3(-1.0, -1.5, -12), 2, mirror)); + spheres.push_back(safrScene::Sphere(glm::vec3(-1.0, -1.5, -12), 2, glass)); spheres.push_back(safrScene::Sphere(glm::vec3( 1.5, -0.5, -18), 3, red_rubber)); spheres.push_back(safrScene::Sphere(glm::vec3( 7, 5, -18), 4, mirror)); diff --git a/projects/saf_r/src/safrScene.hpp b/projects/saf_r/src/safrScene.hpp index a8141efd5859bb2f30f064e2b83aac0e610972bc..33a298f82121971021d1912e6c1205e9c48a49f0 100644 --- a/projects/saf_r/src/safrScene.hpp +++ b/projects/saf_r/src/safrScene.hpp @@ -27,11 +27,12 @@ public: * Material struct with defuse color, albedo and specular component */ struct Material { - Material(const glm::vec3& a, const glm::vec3& color, const float& spec) : albedo(a), diffuse_color(color), specular_exponent(spec) {} - Material() : albedo(1, 0, 0), diffuse_color(), specular_exponent() {} - glm::vec3 albedo; - alignas(16) glm::vec3 diffuse_color; - float specular_exponent; + Material(const glm::vec4& a, const glm::vec3& color, const float& spec, const float& r) : albedo(a), diffuse_color(color), specular_exponent(spec), refractive_index(r) {} + Material() : refractive_index(1), albedo(1, 0, 0, 0), diffuse_color(), specular_exponent() {} + glm::vec4 albedo; + alignas(16) glm::vec3 diffuse_color; + float specular_exponent; + float refractive_index; }; /*