Proper specular gloss using cone bounces

This commit is contained in:
Ben Kyd
2019-09-18 17:09:24 +01:00
parent 1d9407a046
commit 3c89c800c6
4 changed files with 69 additions and 12 deletions

View File

@@ -18,6 +18,40 @@ Material::Material(glm::vec3 col, float specularity, float emittance)
Specularity = specularity;
}
Material::Material(glm::vec3 colour, float emittance, float specularity, float index, float gloss, bool transparent, bool emissive)
: Colour(colour),
Emittance(emittance),
Specularity(specularity),
Index(index),
Gloss(gloss),
Transparent(transparent),
Emissive(emissive) {
if (Emittance > 0.0f) { Emissive = true; }
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) {
@@ -33,7 +67,11 @@ glm::vec3 Material::Bounce(glm::vec3 in, glm::vec3 normal) {
if (r > Specularity) {
return CosineBRDF(normal);
} else {
return Reflect(in, normal);
}
glm::vec3 reflect = Reflect(in, normal);
if (Gloss == 0.0f)
return reflect;
return ConeBounce(reflect, Gloss);
}
}

View File

@@ -10,6 +10,7 @@ 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);
@@ -19,12 +20,18 @@ public:
Texture* GlossTexture = nullptr;
float Emittance;
float Specularity; // 1.0f = perfect reflective
// float Index; // refractive index
// float Gloss; // reflection cone angle in radians
float Index; // refractive index
float Gloss; // reflection cone angle in radians
// float Tint; // specular and refractive tinting
// float Reflectivity; // metallic reflection
bool Transparent;
bool Emissive;
};
class GlossyMaterial : public Material {
public:
GlossyMaterial(glm::vec3 colour, float shine, float gloss)
: Material(colour, 0.0f, shine, 1.0f, gloss, false, false) { };
};
#endif

View File

@@ -6,6 +6,7 @@
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <random>
#include <algorithm>
#include <vector>
#include <math.h>
@@ -30,6 +31,17 @@ inline float fastRadianToDegree(const float Radian) { return (Radian * RAD2DEG);
inline float getFovAdjustment(const float fov) { return tanf(fov * PI / 360.0f); }
inline float getAspectRatio(const float w, const float h) { return (float)w / (float)h; }
inline glm::vec3 randomUnitVector() {
std::default_random_engine generator;
std::uniform_real_distribution<float> distribution(-1, 1);
float x = distribution(generator);
float y = distribution(generator);
float z = distribution(generator);
return glm::normalize(glm::vec3({x,y,z}));
}
// (-b += sqrt(b^2-4ac)) / 2a
inline bool quadratic(float a, float b, float c, float& x0, float& x1) {
float discr = b * b - 4.0f * a * c;

View File

@@ -2,8 +2,8 @@
#include "../src/inferno.hpp"
static const int width = 1080;
static const int height = 720;
static const int width = 700;
static const int height = 700;
int main(int argc, char** argv) {
InfernoEngine inferno;
@@ -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({ 0.0f, 0.0f, -5.0f }, 1.0f, new Material({ 0.817f, 0.374, 0.574 }));
// sphere.material->NormalTexture = new Texture("E:/Projects/Inferno/resources/textures/dirt-normal.jpg");
sphere.material->NormalTexture = new Texture("/home/ben/programming/inferno/resources/textures/dirt-normal.jpg");
Sphere sphere({ -2.1f, 0.0f, -8.0f }, 1.0f, new GlossyMaterial({ 0.817f, 0.374, 0.574 }, 0.5f, fastDegreetoRadian(0.0f)));
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)));
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)));
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));
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.material->NormalTexture = new Texture("E:/Projects/Inferno/resources/textures/normals.png");
plane.material->NormalTexture = new Texture("/home/ben/programming/inferno/resources/textures/normals.png");
Plane plane({ 0.0f, -1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, new Material({ 0.2f, 0.2f, 0.2f }));
scene->objects.push_back(&plane);
inferno.SetScene(scene);