From 9a4ea4db164d8d46808830ae098b6b7fdaf27ffa Mon Sep 17 00:00:00 2001 From: Ben Kyd Date: Wed, 2 Oct 2019 12:32:20 +0100 Subject: [PATCH] Fresnel Reflections --- CMakeLists.txt | 5 ++- src/definitions/materials/material.cpp | 43 ++++------------------ src/definitions/materials/material.hpp | 3 +- src/definitions/materials/specular.cpp | 50 ++++++++++++++++++++++++++ src/definitions/materials/specular.hpp | 4 +++ src/definitions/primatives/plane.cpp | 1 + src/engine/progressiverenderer.hpp | 2 +- src/engine/renderengine.cpp | 35 ++++++++++-------- test/lucy_cornell.cpp | 43 ++++++++++++++++++++++ test/main.cpp | 16 ++++----- test/stanford_dragon_cornell.cpp | 20 ++++------- 11 files changed, 144 insertions(+), 78 deletions(-) create mode 100644 test/lucy_cornell.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fb4a81..4692ab3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,13 +4,12 @@ project(Inferno) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} CMakeModules/) cmake_policy(SET CMP0037 OLD) #set(CMAKE_BUILD_TYPE Debug) -#set(CMAKE_CXX_FLAGS "-g") -set(CMAKE_CXX_FLAGS "-Ofast -mtune=native") +set(CMAKE_CXX_FLAGS "-Ofast") set(executable output) set(SrcDIR ./src) set(TestDIR ./test) -set(CurrentTest stanford_dragon_cornell.cpp) +set(CurrentTest main.cpp) set(IncludeDIR ./include) diff --git a/src/definitions/materials/material.cpp b/src/definitions/materials/material.cpp index 9775d95..322086e 100644 --- a/src/definitions/materials/material.cpp +++ b/src/definitions/materials/material.cpp @@ -8,16 +8,6 @@ Material::Material() { } -Material::Material(glm::vec3 col, float specularity, float emittance) - : Colour(col), - Emittance(emittance) { - Transparent = false; - if (Emittance > 0.0f) { Emissive = true; } - else { Emissive = false; } - - Specularity = specularity; -} - Material::Material(glm::vec3 colour, float emittance, float specularity, float index, float gloss, bool transparent, bool emissive) : Colour(colour), Emittance(emittance), @@ -31,44 +21,25 @@ Material::Material(glm::vec3 colour, float emittance, float specularity, float i else { Emissive = false; } } -glm::vec3 ConeBounce(glm::vec3 reflectDir, float theta) { - if (theta < EPSILON) { - return reflectDir; - } - - float u = rand01(); - float v = rand01(); - - theta = theta * (1 - (2 * acos(u) / PI)); - float m1 = sin(theta); - float m2 = cos(theta); - float a = v * 2 * PI; - glm::vec3 q = randomUnitVector(); - glm::vec3 s = glm::cross(reflectDir, q); - glm::vec3 t = glm::cross(reflectDir, s); - glm::vec3 d = { }; - d = d + (s * (m1 * cos(a))); - d = d + (t * (m1 * sin(a))); - d = d + (reflectDir * m2); - return glm::normalize(d); -} - glm::vec3 Material::Bounce(glm::vec3 in, glm::vec3 normal) { if (Specularity == 0.0f) { return CosineBRDF(normal); } + float r; if (Specularity == 1.0f) { - return Reflect(in, normal); + r = 1.0f; + } else { + r = rand01(); } - float r = rand01(); + float fresnel = FresnelReflect(this, normal, in); - if (r > Specularity) { + if (r > fresnel) { return CosineBRDF(normal); } else { glm::vec3 reflect = Reflect(in, normal); - + if (Gloss == 0.0f) return reflect; diff --git a/src/definitions/materials/material.hpp b/src/definitions/materials/material.hpp index 1abb56c..984a843 100644 --- a/src/definitions/materials/material.hpp +++ b/src/definitions/materials/material.hpp @@ -9,7 +9,6 @@ class Texture; class Material { public: Material(); - Material(glm::vec3 col, float specularity = 0.0f, float emmitance = 0.0f); Material(glm::vec3 colour, float emittance, float Specularity, float index, float gloss, bool transparent, bool emissive); glm::vec3 Bounce(glm::vec3 in, glm::vec3 normal); @@ -30,7 +29,7 @@ public: class GlossyMaterial : public Material { public: - GlossyMaterial(glm::vec3 colour, float shine, float gloss) + GlossyMaterial(glm::vec3 colour, float shine, float gloss, float index = 1.5f) : Material(colour, 0.0f, shine, 1.0f, gloss, false, false) { }; }; diff --git a/src/definitions/materials/specular.cpp b/src/definitions/materials/specular.cpp index d8d8491..a36cf57 100644 --- a/src/definitions/materials/specular.cpp +++ b/src/definitions/materials/specular.cpp @@ -1,5 +1,55 @@ #include "specular.hpp" +#include "random.hpp" +#include "material.hpp" + glm::vec3 Reflect(glm::vec3 I, glm::vec3 N) { return I - 2 * glm::dot(I, N) * N; } + + +glm::vec3 ConeBounce(glm::vec3 reflectDir, float theta) { + if (theta < EPSILON) { + return reflectDir; + } + + float u = rand01(); + float v = rand01(); + + theta = theta * (1 - (2 * acos(u) / PI)); + float m1 = sin(theta); + float m2 = cos(theta); + float a = v * 2 * PI; + glm::vec3 q = randomUnitVector(); + glm::vec3 s = glm::cross(reflectDir, q); + glm::vec3 t = glm::cross(reflectDir, s); + glm::vec3 d = { }; + d = d + (s * (m1 * cos(a))); + d = d + (t * (m1 * sin(a))); + d = d + (reflectDir * m2); + return glm::normalize(d); +} + +float FresnelReflect (Material* mat, glm::vec3 normal, glm::vec3 incident) { + float n1 = 1.0f; + float n2 = mat->Index; + + // Schlick aproximation + float r0 = (n1-n2) / (n1+n2); + r0 *= r0; + float cosX = -glm::dot(normal, incident); + if (n1 > n2) { + float n = n1/n2; + float sinT2 = n*n*(1.0-cosX*cosX); + // Total internal reflection + if (sinT2 > 1.0) + return 1.0; + cosX = sqrt(1.0-sinT2); + } + float x = 1.0-cosX; + float ret = r0+(1.0-r0)*x*x*x*x*x; + + ret = (mat->Specularity + (1.0 - mat->Specularity) * ret); + return ret; +} + diff --git a/src/definitions/materials/specular.hpp b/src/definitions/materials/specular.hpp index eee8f22..e57c555 100644 --- a/src/definitions/materials/specular.hpp +++ b/src/definitions/materials/specular.hpp @@ -3,6 +3,10 @@ #include "../../maths.hpp" +class Material; + glm::vec3 Reflect(glm::vec3 I, glm::vec3 N); +glm::vec3 ConeBounce(glm::vec3 reflectDir, float theta); +float FresnelReflect (Material* mat, glm::vec3 normal, glm::vec3 incident); #endif diff --git a/src/definitions/primatives/plane.cpp b/src/definitions/primatives/plane.cpp index e246c12..1cdd249 100644 --- a/src/definitions/primatives/plane.cpp +++ b/src/definitions/primatives/plane.cpp @@ -7,6 +7,7 @@ bool Plane::Intersect(Ray& ray, float& t) { glm::vec3 v = center - ray.origin; float distance = glm::dot(v, normal) / dNormal; if (distance >= 0.0f) { + if (distance > 20.0f) return false; t = distance; return true; } diff --git a/src/engine/progressiverenderer.hpp b/src/engine/progressiverenderer.hpp index 04bc3c7..3fdb8b8 100644 --- a/src/engine/progressiverenderer.hpp +++ b/src/engine/progressiverenderer.hpp @@ -69,7 +69,7 @@ private: // and are used to set them, must be indexed correctly // according to the enums int m_renderModeSelected = 0; - int m_toneMapModeSelected = 0; + int m_toneMapModeSelected = 1; int m_framesRendererd = 0; diff --git a/src/engine/renderengine.cpp b/src/engine/renderengine.cpp index 04d3164..1704af4 100644 --- a/src/engine/renderengine.cpp +++ b/src/engine/renderengine.cpp @@ -78,9 +78,6 @@ glm::vec3 RenderEngine::GetColour(Ray ray, int& depth) { float t = INFINITY; Primative* hit = nullptr; bool didhit = TraceRayScene(ray, m_scene, t, hit); if (!didhit) { - if (depth > 0) { - return m_scene->SampleSky(ray) * 0.2f; - } return m_scene->SampleSky(ray); } @@ -89,20 +86,28 @@ glm::vec3 RenderEngine::GetColour(Ray ray, int& depth) { if (Mode == MODE_RENDER_NORMALS) { return GetNormalColour(normal); } if (Mode == MODE_RENDER_PATH_LENGTH) { if (t > 255.0f) t = 255.0f; return { (float)t, (float)t, (float)t }; } - glm::vec3 colour = hit->material->Colour; - //if (hit->type == TYPE_PLANE) { - // glm::vec2 uv = hit->TexCoords(hitPoint); - // float angle = fastDegreetoRadian(.0f); - // float s = uv.x * cos(angle) - uv.y * sin(angle); - // float t = uv.y * cos(angle) + uv.x * sin(angle); - // float S = 0.4f; float T = 0.4f; - // float pattern = (modulo(s * S) < 0.5f) ^ (modulo(t * T) < 0.5f); - // colour.r = pattern; colour.g = pattern; colour.b = pattern; - //} + Material* mat = hit->material; + glm::vec3 colour = mat->Colour; - if (hit->material->Emissive) return (colour * hit->material->Emittance); + if (hit->type == TYPE_PLANE) { + glm::vec2 uv = hit->TexCoords(hitPoint); + float angle = fastDegreetoRadian(.0f); + float s = uv.x * cos(angle) - uv.y * sin(angle); + float t = uv.y * cos(angle) + uv.x * sin(angle); + float S = 0.4f; float T = 0.4f; + float pattern = (modulo(s * S) < 0.5f) ^ (modulo(t * T) < 0.5f); + if (pattern == 1) { + mat->Specularity = 0.9f; + mat->Gloss = fastRadianToDegree(0.02f); + } else { + mat->Specularity = 0.9f; + mat->Gloss = fastRadianToDegree(0.0f); + } + } - glm::vec3 direction = hit->material->Bounce(ray.direction, normal); + if (mat->Emissive) return (colour * mat->Emittance); + + glm::vec3 direction = mat->Bounce(ray.direction, normal); Ray newRay{ hitPoint, direction }; diff --git a/test/lucy_cornell.cpp b/test/lucy_cornell.cpp new file mode 100644 index 0000000..18a4768 --- /dev/null +++ b/test/lucy_cornell.cpp @@ -0,0 +1,43 @@ +#include + +#include "../src/inferno.hpp" + +static const int width = 600; +static const int height = 600; + +int main(int argc, char** argv) { + InfernoEngine inferno; + + inferno.SetMode(MODE_OPERATION_PROGRESSIVE_GUI); + + inferno.InitWindow(width, height); + + Scene* scene = new Scene(width, height); + scene->camera = new Camera(width, height); + + Sky* sky = new SolidSky({ 0.0f, 0.0f, 0.0f }, 0.0f); + scene->sky = sky; + + Material* mat = new GlossyMaterial({ 1.0f, 1.0f, 1.0f }, 0.2f, fastDegreetoRadian(30.0f)); + //std::vector tris = LoadTrianglesBasic("E://Projects//Inferno//resources//models//dragon-cornell-size.obj", "E://Projects//Inferno//resources//models", mat); + // std::vector tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/dragon-cornell-size.obj", "/home/ben/programming/inferno/resources/models/", mat); + + //Mesh* mesh = new Mesh(tris); + //mesh->Translate({ 0.01f, -1.0, -3.6f }); + //mesh->Optimise(); + //scene->meshs.push_back(mesh); + + // std::vector tris1 = LoadTrianglesBasic("E://Projects//Inferno//resources//models//cornell-box.obj", "E://Projects//Inferno//resources//models//"); + std::vector tris1 = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/cornell-box.obj", "/home/ben/programming/inferno/resources/models/"); + + Mesh* mesh1 = new Mesh(tris1); + mesh1->Translate({ 0.01f, -1.0, -3.6f }); + scene->meshs.push_back(mesh1); + + inferno.SetScene(scene); + + inferno.Ready(); + inferno.Render(); + + return 0; +} diff --git a/test/main.cpp b/test/main.cpp index f8f9313..c21b139 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -2,8 +2,8 @@ #include "../src/inferno.hpp" -static const int width = 1000; -static const int height = 1000; +static const int width = 700; +static const int height = 700; int main(int argc, char** argv) { InfernoEngine inferno; @@ -18,7 +18,7 @@ int main(int argc, char** argv) { Scene* scene = new Scene(width, height); - Sky* sky = new GradientSky({ 35.0f / 255.0f, 148.0f / 255.0f, 235.0f / 255.0f }, { 1.0f, 1.0f, 1.0f }, 5.0f); + Sky* sky = new GradientSky({ 35.0f / 255.0f, 148.0f / 255.0f, 235.0f / 255.0f }, { 1.0f, 1.0f, 1.0f }, 3.0f); scene->sky = sky; scene->camera = new Camera(width, height); @@ -26,17 +26,17 @@ int main(int argc, char** argv) { //Sphere sphere1({ 1.3f, -0.8f, -5.0f }, 0.2f, new Material({ 0.817f, 0.374, 0.574 })); //scene->objects.push_back(&sphere1); - Sphere sphere({ -2.1f, 0.0f, -8.0f }, 1.0f, new GlossyMaterial({ 0.817f, 0.374, 0.574 }, 0.5f, fastDegreetoRadian(0.0f))); + Sphere sphere({ -2.1f, 0.0f, -8.0f }, 1.0f, new Material({ 0.817f, 0.374, 0.574 }, 0.0f, 0.0f, 0.0f, 0.0f, false, false)); scene->objects.push_back(&sphere); - Sphere sphere1({ 0.0f, 0.0f, -8.0f }, 1.0f, new GlossyMaterial({ 0.817f, 0.374, 0.574 }, 0.5f, fastDegreetoRadian(3.0f))); + Sphere sphere1({ 0.0f, 0.0f, -8.0f }, 1.0f, new GlossyMaterial({ 0.817f, 0.374, 0.574 }, 0.7f, fastDegreetoRadian(30.0f))); scene->objects.push_back(&sphere1); - Sphere sphere2({ 2.1f, 0.0f, -8.0f }, 1.0f, new GlossyMaterial({ 0.817f, 0.374, 0.574 }, 0.5f, fastDegreetoRadian(30.0f))); + Sphere sphere2({ 2.1f, 0.0f, -8.0f }, 1.0f, new GlossyMaterial({ 0.817f, 0.374, 0.574 }, 0.7f, fastDegreetoRadian(60.0f))); scene->objects.push_back(&sphere2); - Sphere light({ 35.0f, 50.0f, 25.0f }, 25.0f, new Material({ 1.0f, 1.0f, 1.0f }, 0.0f, 200.0f)); + Sphere light({ 35.0f, 50.0f, 25.0f }, 25.0f, new Material({ 1.0f, 1.0f, 1.0f }, 100.0f, 0.0f, 1.5f, 0.0f, false, true)); scene->objects.push_back(&light); - Plane plane({ 0.0f, -1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, new Material({ 0.2f, 0.2f, 0.2f })); + Plane plane({ 0.0f, -1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, new Material({ 0.2f, 0.2f, 0.2f }, 0.0f, 0.0f, 1.5f, 0.0f, false, false)); scene->objects.push_back(&plane); inferno.SetScene(scene); diff --git a/test/stanford_dragon_cornell.cpp b/test/stanford_dragon_cornell.cpp index e932c18..3899e31 100644 --- a/test/stanford_dragon_cornell.cpp +++ b/test/stanford_dragon_cornell.cpp @@ -18,26 +18,20 @@ int main(int argc, char** argv) { Sky* sky = new SolidSky({ 0.0f, 0.0f, 0.0f }, 0.0f); scene->sky = sky; - //Sphere* sphere = new Sphere({ -0.302, -0.385999, -3.74202 }, 0.03f, new Material({ 0.345f, 0.133f, 0.050f }, 300.0f, 0.0f, 0.0f, 0.0f, false, true)); - //scene->objects.push_back(sphere); - - Plane* plane = new Plane({ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, new Material({ 1.0f, 1.0f, 1.0f }, 0.0f, 0.0f, 0.0f, 0.0f, false, false)); - scene->objects.push_back(plane); - - Material* mat = new GlossyMaterial({ 1.3f, 1.3f, 1.3f }, 0.2f, fastDegreetoRadian(30.0f)); - //std::vector tris = LoadTrianglesBasic("E://Projects//Inferno//resources//models//dragon-cornell-size.obj", "E://Projects//Inferno//resources//models", mat); - // std::vector tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/dragon-cornell-size.obj", "/home/ben/programming/inferno/resources/models/", mat); - - Sphere* sphere = new Sphere({ 0.0f, -0.6f, -4.0f }, 0.4f, mat); + Sphere* sphere = new Sphere({ -0.302, -0.385999, -3.74202 }, 0.03f, new Material({ 0.345f, 0.133f, 0.050f }, 300.0f, 0.0f, 0.0f, 0.0f, false, true)); scene->objects.push_back(sphere); + Material* mat = new GlossyMaterial({ 1.0f, 1.0f, 1.0f }, 0.2f, fastDegreetoRadian(30.0f)); + //std::vector tris = LoadTrianglesBasic("E://Projects//Inferno//resources//models//dragon-cornell-size.obj", "E://Projects//Inferno//resources//models", mat); + std::vector tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/dragon-cornell-size.obj", "/home/ben/programming/inferno/resources/models/", mat); + //Mesh* mesh = new Mesh(tris); //mesh->Translate({ 0.01f, -1.0, -3.6f }); //mesh->Optimise(); //scene->meshs.push_back(mesh); - std::vector tris1 = LoadTrianglesBasic("E://Projects//Inferno//resources//models//cornell-box.obj", "E://Projects//Inferno//resources//models//"); - //std::vector tris1 = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/cornell-box.obj", "/home/ben/programming/inferno/resources/models/"); + // std::vector tris1 = LoadTrianglesBasic("E://Projects//Inferno//resources//models//cornell-box.obj", "E://Projects//Inferno//resources//models//"); + std::vector tris1 = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/cornell-box.obj", "/home/ben/programming/inferno/resources/models/"); Mesh* mesh1 = new Mesh(tris1); mesh1->Translate({ 0.01f, -1.0, -3.6f });