Fresnel Reflections

This commit is contained in:
Ben Kyd
2019-10-02 12:32:20 +01:00
parent 5959687f93
commit 9a4ea4db16
11 changed files with 144 additions and 78 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -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) { };
};

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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 };

43
test/lucy_cornell.cpp Normal file
View File

@@ -0,0 +1,43 @@
#include <iostream>
#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<Triangle*> tris = LoadTrianglesBasic("E://Projects//Inferno//resources//models//dragon-cornell-size.obj", "E://Projects//Inferno//resources//models", mat);
// std::vector<Triangle*> 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<Triangle*> tris1 = LoadTrianglesBasic("E://Projects//Inferno//resources//models//cornell-box.obj", "E://Projects//Inferno//resources//models//");
std::vector<Triangle*> 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;
}

View File

@@ -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);

View File

@@ -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<Triangle*> tris = LoadTrianglesBasic("E://Projects//Inferno//resources//models//dragon-cornell-size.obj", "E://Projects//Inferno//resources//models", mat);
// std::vector<Triangle*> 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<Triangle*> tris = LoadTrianglesBasic("E://Projects//Inferno//resources//models//dragon-cornell-size.obj", "E://Projects//Inferno//resources//models", mat);
std::vector<Triangle*> 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<Triangle*> tris1 = LoadTrianglesBasic("E://Projects//Inferno//resources//models//cornell-box.obj", "E://Projects//Inferno//resources//models//");
//std::vector<Triangle*> tris1 = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/cornell-box.obj", "/home/ben/programming/inferno/resources/models/");
// std::vector<Triangle*> tris1 = LoadTrianglesBasic("E://Projects//Inferno//resources//models//cornell-box.obj", "E://Projects//Inferno//resources//models//");
std::vector<Triangle*> 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 });