Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Final evaluation for Implementing Oren-Nayar BRDF and Creating New Scene #2

Open
wants to merge 4 commits into
base: week-7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Add OrenNayer brdf with new scene
  • Loading branch information
sps1112 committed Jun 9, 2021
commit 1d4c60641317669724a5788799c346d96d52af97
76 changes: 67 additions & 9 deletions src/brdfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace path
// NOTE: in is w.r.t. rays from the camera
struct BaseBRDF
{
virtual Ray sample(const Ray& in, const HitResult& hit)
virtual Ray sample(const Ray &in, const HitResult &hit)
{
// Samples a hemisphere uniformly by default
double u1 = dist(gen);
Expand All @@ -21,16 +21,15 @@ namespace path
double phi = 2 * PBR_PI * u2;

Vec w = hit.normal;
Vec u = normalize(cross(w, Vec { 0, 1, 0 }));
Vec u = normalize(cross(w, Vec{0, 1, 0}));
Vec v = normalize(cross(u, w));

return {
hit.point,
normalize(u * A * std::cos(phi) + v * A * std::sin(phi) + w * u1)
};
normalize(u * A * std::cos(phi) + v * A * std::sin(phi) + w * u1)};
}

virtual Colorf eval(const Ray& in, const HitResult& hit, const Ray& out)
virtual Colorf eval(const Ray &in, const HitResult &hit, const Ray &out)
{
// Returns hit.material.color by default
return hit.material->color;
Expand All @@ -50,7 +49,7 @@ namespace path
/** Lambertian Diffuse BRDF */
struct DiffuseBRDF : public BaseBRDF
{
virtual Colorf eval(const Ray& in, const HitResult& hit, const Ray& out) override
virtual Colorf eval(const Ray &in, const HitResult &hit, const Ray &out) override
{
// return normalize(out.direction);
auto diff = cosv(out.direction, hit.normal);
Expand All @@ -60,21 +59,80 @@ namespace path

struct SpecularBRDF : public BaseBRDF
{
virtual Ray sample(const Ray& in, const HitResult& hit) override
virtual Ray sample(const Ray &in, const HitResult &hit) override
{
Ray refl;
refl.direction = reflect(in.direction, hit.normal);
refl.origin = hit.point;
return refl;
}

virtual Colorf eval(const Ray& in, const HitResult& hit, const Ray& out) override
virtual Colorf eval(const Ray &in, const HitResult &hit, const Ray &out) override
{
return PBR_COLOR_WHITE;
}
};
}

/** Oren Nayer BRDF */
struct OrenNayarBRDF : public BaseBRDF
{
virtual Colorf eval(const Ray &in, const HitResult &hit, const Ray &out) override
{
// in ==> camera to point
// out ==> point to light

// Roughness calculations
double sigma = 0.75;
double A = 1.0 - (0.5 * ((sigma * sigma) / ((sigma * sigma) + 0.33)));
double B = 0.45 * ((sigma * sigma) / ((sigma * sigma) + 0.09));

// Angle Calculations
/*
double thetaI = pbr_angle(out.direction, hit.normal);
double thetaO = pbr_angle(in.direction, hit.normal);
double alpha = pbr_max(thetaI, thetaO);
double beta = pbr_min(thetaI, thetaO);
Vec cos_values;
cos_values.x = clamp(dot(hit.normal, out.direction));
cos_values.y = clamp(dot(hit.normal, in.direction));
Vec out_plane = normalize(out.direction - hit.normal * cos_values.x);
Vec in_plane = normalize(in.direction - hit.normal * cos_values.y);
float cos_val = clamp(dot(out_plane, in_plane));
auto diff = cosv(out.direction, hit.normal) * (A + (B * cos_val * sin(alpha) * tan(beta)));
*/

// Simplified Implementation
Vec N = hit.normal;
double L = clamp(dot(out.direction, N));
double V = clamp(dot(in.direction, N));
double D = sqrt(1 - (L * L)) * sqrt(1 - (V * V)) / pbr_max(L, V);
Vec out_plane = normalize(out.direction - N * L);
Vec in_plane = normalize(in.direction - N * V);
double C = clamp(dot(out_plane, in_plane));
auto diff = cosv(out.direction, hit.normal) * (A + (B * C * D));

return hit.material->color * diff * 2; // 2pi for monte carlo, 1/pi for Lambertian BRDF
}
};

struct PhongBRDF : public BaseBRDF
{
virtual Colorf eval(const Ray &in, const HitResult &hit, const Ray &out) override
{
const double kD = 0.95;
const double kS = 1 - kD;
const double shininess = 32;

auto diff = clamp(cosv(out.direction, hit.normal));
auto spec = std::pow(
clamp(dot(
normalize(reflect(out.direction * -1, hit.normal)),
normalize(in.direction * -1))),
shininess);
return hit.material->color * (kD * diff + kS * spec) * 2; // 2pi for monte carlo, 1/pi for Lambertian BRDF
}
};
}

#if 0

Expand Down
8 changes: 4 additions & 4 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@

#define PBR_MAX_RECURSION_DEPTH 4

#define PBR_SAMPLES_PER_PIXEL 32
#define PBR_SAMPLES_PER_PIXEL 1024

///////////////////////////////////////////////////////////////////////////////
// Scene and camera

#define PBR_ACTIVE_SCENE PBR_SCENE_RTWEEKEND
#define PBR_ACTIVE_SCENE PBR_SCENE_FINAL_ON

#define PBR_CAMERA_LOOKAT \
Vec { 0, 1, 0 }
#define PBR_CAMERA_POSITION \
Vec { 0, 2, 5 }
Vec { 0, 2.5, 6 }
#define PBR_CAMERA_FOV_DEG 45

///////////////////////////////////////////////////////////////////////////////
Expand All @@ -36,7 +36,7 @@
#define PBR_COLOR_BLUE \
Colorf { 0.0, 0.0, 1.0 }

#define PBR_BACKGROUND_COLOR PBR_COLOR_BLACK
#define PBR_BACKGROUND_COLOR PBR_COLOR_SKYBLUE

///////////////////////////////////////////////////////////////////////////////
// Output
Expand Down
46 changes: 30 additions & 16 deletions src/math_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ struct Vec
{
double x, y, z;


Vec(double x_, double y_, double z_) : x(x_), y(y_), z(z_) {}
Vec(double scalar = 0.0) : Vec(scalar, scalar, scalar) {}

Expand All @@ -49,64 +48,62 @@ struct Vec

inline Vec operator*(double s) const
{
return { x * s, y * s, z * s };
return {x * s, y * s, z * s};
}

inline Vec operator*(const Vec& v) const
inline Vec operator*(const Vec &v) const
{
return { x * v.x, y * v.y, z * v.z };
return {x * v.x, y * v.y, z * v.z};
}

inline Vec operator/(double s) const
{
return *this * (1. / s);
}

inline Vec operator+(const Vec& b) const
inline Vec operator+(const Vec &b) const
{
return {x + b.x, y + b.y, z + b.z};
}

inline Vec operator-(const Vec& b) const
inline Vec operator-(const Vec &b) const
{
return *this + b * (-1.);
}

};

/** Normalize the vector, return a unit vector in the same direction as the parameter. */
inline Vec normalize(const Vec& v)
inline Vec normalize(const Vec &v)
{
return v / v.len();
}

/** Calculate the dot product between vectors a and b. */
inline double dot(const Vec& a, const Vec& b)
inline double dot(const Vec &a, const Vec &b)
{
return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
}

/** Calculate the cos of the angle between vectors a and b. */
inline double cosv(const Vec& a, const Vec& b)
inline double cosv(const Vec &a, const Vec &b)
{
return dot(normalize(a), normalize(b));
}

/** Calculate the cross product between a and b. */
inline Vec cross(const Vec& a, const Vec& b)
inline Vec cross(const Vec &a, const Vec &b)
{
return {
return {
(a.y * b.z) - (a.z * b.y),
(a.z * b.x) - (a.x * b.z),
(a.x * b.y) - (a.y * b.x)
};
(a.x * b.y) - (a.y * b.x)};
}

// ^^^
///////////////////////////////////////////////////////////////////////////////

/** Reflect the incident vector v about a normal n. */
inline Vec reflect(const Vec& v, const Vec& n)
inline Vec reflect(const Vec &v, const Vec &n)
{
return v - n * 2 * cosv(v, n) * v.len();
}
Expand All @@ -121,5 +118,22 @@ struct Ray
/** Clamp a value x between min and max. */
inline double clamp(double x, double min = 0, double max = 1)
{
return (x < min) ? min : (x > max) ? max : x;
return (x < min) ? min : (x > max) ? max
: x;
}

inline double pbr_max(double x, double y)
{
return (x > y) ? x : y;
}

inline double pbr_min(double x, double y)
{
return (x > y) ? y : x;
}

inline double pbr_angle(const Vec &a, const Vec &b)
{
double cosvalue = dot(a, b) / (a.len() * b.len());
return acos(cosvalue);
}
77 changes: 77 additions & 0 deletions src/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,80 @@ Scene PBR_SCENE_RTWEEKEND = {
Vec{0.0, -1e5, 0.0}, // Position
1e5 // Radius
}}};

Scene PBR_SCENE_FINAL_ON = {
// Red ball
Actor{
std::make_shared<Material>(
Colorf{1.0, 0.1, 0.1}, // Color
Colorf{0.0, 0.0, 0.0}, // Emission
new path::OrenNayarBRDF),
SphereGeometry{
Vec{3.0, 1.0, 0.0}, // Position
1.0 // Radius
}},
// Blue ball
Actor{
std::make_shared<Material>(
Colorf{0.1, 0.1, 1.0}, // Color
Colorf{0.0, 0.0, 0.0}, // Emission
new path::OrenNayarBRDF),
SphereGeometry{
Vec{-3.0, 1.0, 0.0}, // Position
1.0 // Radius
}},

// Yellow ball
Actor{
std::make_shared<Material>(
Colorf{1.0, 1.0, 0.1}, // Color
Colorf{0.0, 0.0, 0.0}, // Emission
new path::PhongBRDF),
SphereGeometry{
Vec{0.0, 4.0, -2.5}, // Position
1.0 // Radius
}},

// Light 1
Actor{
std::make_shared<Material>(
Colorf{1.0, 1.0, 1.0}, // Color
Colorf{6.0, 6.0, 6.0}, // Emission
new path::DiffuseBRDF),
SphereGeometry{
Vec{6.0, 4.5, -4.0}, // Position
3.0 // Radius
}},

// Light 2
Actor{
std::make_shared<Material>(
Colorf{1.0, 1.0, 1.0}, // Color
Colorf{6.0, 6.0, 6.0}, // Emission
new path::DiffuseBRDF),
SphereGeometry{
Vec{-6.0, 4.5, -4.0}, // Position
3.0 // Radius
}},

// Mirror
Actor{
std::make_shared<Material>(
Colorf{1.0, 1.0, 1.0}, // Color
Colorf{0.0, 0.0, 0.0}, // Emission
new path::SpecularBRDF),
SphereGeometry{
Vec{0.0, 1.0, 0.0}, // Position
1.0 // Radius
}},

// Floor
Actor{
std::make_shared<Material>(
Colorf{0.1, 1.0, 0.1}, // Color
Colorf{0.0, 0.0, 0.0}, // Emission
new path::DiffuseBRDF),
SphereGeometry{
Vec{0.0, -1e5, 0.0}, // Position
1e5 // Radius
}}};
11 changes: 7 additions & 4 deletions src/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct SphereGeometry
Vec center;
float radius;

bool intersect(const Ray& ray, Vec& point) const
bool intersect(const Ray &ray, Vec &point) const
{
// For intersection, solve
// |(o + t*dir) - position| = radius
Expand All @@ -23,8 +23,10 @@ struct SphereGeometry
double C = op.sqlen() - radius * radius;

double D = B * B - 4 * A * C;
if (D < 0) return false; // no solution
else D = std::sqrt(D);
if (D < 0)
return false; // no solution
else
D = std::sqrt(D);

double t1 = (-1 * B + D) / (2 * A);
double t2 = (-1 * B - D) / (2 * A);
Expand Down Expand Up @@ -69,7 +71,7 @@ struct Actor
* @param hit Output hit data
* @return bool Indicates if the ray intersects with this actor
*/
bool intersect(const Ray& ray, HitResult& hit) const
bool intersect(const Ray &ray, HitResult &hit) const
{
Vec point;
if (geometry.intersect(ray, point))
Expand All @@ -94,4 +96,5 @@ using Scene = std::vector<Actor>;
//// So I don't want this to be defined in each translation unit separately.

extern Scene PBR_SCENE_RTWEEKEND;
extern Scene PBR_SCENE_FINAL_ON;
// extern Scene PBR_SCENE_CORNELL;