Skip to content
Permalink
Browse files

Scene reading, Random class and part of Path tracing.

Partial code written during Lecture 12.
  • Loading branch information...
anrieff committed May 22, 2018
1 parent 00dcb90 commit 6c1fb060eb651533eac76d8c24efd1e5da06f3e5
Showing with 1,981 additions and 299 deletions.
  1. +16 −0 src/bitmap.cpp
  2. +2 −0 src/bitmap.h
  3. +2 −1 src/camera.cpp
  4. +30 −3 src/camera.h
  5. +7 −0 src/color.h
  6. +9 −4 src/constants.h
  7. +14 −3 src/environment.h
  8. +46 −5 src/geometry.h
  9. +44 −20 src/lights.cpp
  10. +40 −8 src/lights.h
  11. +140 −24 src/main.cpp
  12. +4 −1 src/matrix.cpp
  13. +13 −13 src/mesh.cpp
  14. +17 −4 src/mesh.h
  15. +303 −0 src/random_generator.cpp
  16. +39 −1 src/random_generator.h
  17. +818 −139 src/scene.cpp
  18. +273 −12 src/scene.h
  19. +68 −36 src/shading.cpp
  20. +96 −21 src/shading.h
  21. +0 −4 src/util.h
@@ -296,3 +296,19 @@ bool Bitmap::saveImage(const char* filename)
return false;
}

void Bitmap::differentiate()
{
Bitmap bumpTex;
bumpTex.generateEmptyImage(this->width, this->height);

for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float dx = getPixel(x, y).intensity() -
getPixel((x + 1) % width, y).intensity();
float dy = getPixel(x, y).intensity() -
getPixel(x, (y + 1) % height).intensity();
bumpTex.setPixel(x, y, Color(dx, dy, 0));
}
}
std::swap(this->data, bumpTex.data);
}
@@ -41,6 +41,8 @@ class Bitmap {
Color getPixel(int x, int y) const; //!< Gets the pixel at coordinates (x, y). Returns black if (x, y) is outside of the image
void setPixel(int x, int y, const Color& col); //!< Sets the pixel at coordinates (x, y).

void differentiate(); //!< compute differential image, for bump mapping

bool loadBMP(const char* filename); //!< Loads an image from a BMP file. Returns false in the case of an error
bool saveBMP(const char* filename); //!< Saves the image to a BMP file (with clamping, etc). Returns false in the case of an error (e.g. read-only media)

@@ -41,7 +41,8 @@ void Camera::beginFrame()
w = frameWidth();
h = frameHeight();

Matrix rotation = rotationAroundZ(roll) * rotationAroundX(pitch) * rotationAroundY(yaw);
Matrix rotation = rotationAroundZ(toRadians(roll)) * rotationAroundX(toRadians(pitch)) *
rotationAroundY(toRadians(yaw));
topLeft *= rotation;
topRight *= rotation;
bottomLeft *= rotation;
@@ -25,14 +25,15 @@

#include "vector.h"
#include "color.h"
#include "scene.h"

enum WhichCamera {
CAMERA_CENTER,
CAMERA_LEFT,
CAMERA_RIGHT,
};

class Camera {
class Camera: public SceneElement {
Vector topLeft, topRight, bottomLeft;
Vector frontDir, upDir, rightDir;
double w, h;
@@ -44,11 +45,37 @@ class Camera {
double fov = 90.0;
double aspectRatio = 1.3333;
double focalPlaneDist = 5.0;
double fNumber;
double fNumber = 2.0;
bool dof = false;
bool autofocus = true;
int numDOFSamples = 32;
double stereoSeparation = 0;
Color leftMask = Color(1, 0, 0), rightMask = Color(0, 1, 1);

void beginFrame();
void fillProperties(ParsedBlock& pb)
{
if (!pb.getVectorProp("position", &pos))
pb.requiredProp("position");
pb.getDoubleProp("aspectRatio", &aspectRatio, 1e-6);
pb.getDoubleProp("fov", &fov, 0.0001, 179);
pb.getDoubleProp("yaw", &yaw);
pb.getDoubleProp("pitch", &pitch, -90, 90);
pb.getDoubleProp("roll", &roll);
pb.getBoolProp("dof", &dof);
pb.getDoubleProp("fNumber", &fNumber, 0);
pb.getIntProp("numSamples", &numDOFSamples, 1);
pb.getDoubleProp("focalPlaneDist", &focalPlaneDist, 0.1);
pb.getBoolProp("autofocus", &autofocus);
pb.getDoubleProp("stereoSeparation", &stereoSeparation, 0.0);
pb.getColorProp("leftMask", &leftMask);
pb.getColorProp("rightMask", &rightMask);

apertureSize = 4.5 / fNumber;
}

void beginFrame() override;

ElementType getElementType() const { return ELEM_CAMERA; }

Ray getScreenRay(double x, double y, WhichCamera whichCamera = CAMERA_CENTER);
Ray getDOFRay(double x, double y);
@@ -98,6 +98,13 @@ struct Color {
g *= multiplier;
b *= multiplier;
}
/// multiplies the color with another color
void operator *= (const Color& rhs)
{
r *= rhs.r;
g *= rhs.g;
b *= rhs.b;
}
/// divides the color
void operator /= (float divider)
{
@@ -24,10 +24,9 @@
#pragma once

#define VFB_MAX_SIZE 3000
//#define RESX 903
//#define RESY 602
#define RESX 1024
#define RESY 768
#define DEFAULT_FRAME_WIDTH 800
#define DEFAULT_FRAME_HEIGHT 600

#define PI 3.141592653589793238
#define INF 1e99

@@ -37,3 +36,9 @@

#define MAX_TRIANGLES_PER_LEAF 20
#define MAX_DEPTH 64

// large `float' number:
#define LARGE_FLOAT 1e17f

// large `double' number:
#define LARGE_DOUBLE 1e120
@@ -25,6 +25,7 @@

#include "color.h"
#include "vector.h"
#include "scene.h"

enum CubeOrder {
NEGX, // 0
@@ -35,11 +36,14 @@ enum CubeOrder {
POSZ, // 5
};

class Environment{
class Environment: public SceneElement {
public:
bool loaded = false;
virtual ~Environment() {}
/// gets a color from the environment at the specified direction
virtual Color getEnvironment(const Vector& dir) = 0;

ElementType getElementType() const { return ELEM_ENVIRONMENT; }
};

class Bitmap;
@@ -48,7 +52,6 @@ class CubemapEnvironment: public Environment {

Color getSide(const Bitmap* bmp, double x, double y);
public:
bool loaded = false;
bool loadMaps(const char* folder);
/// loads a cubemap from 6 separate images, from the specified folder.
/// The images have to be named "posx.bmp", "negx.bmp", "posy.bmp", ...
@@ -62,5 +65,13 @@ class CubemapEnvironment: public Environment {
~CubemapEnvironment();
Color getEnvironment(const Vector& dir);

void fillProperties(ParsedBlock& pb)
{
Environment::fillProperties(pb);
char folder[256];
if (!pb.getFilenameProp("folder", folder)) pb.requiredProp("folder");
if (!loadMaps(folder)) {
fprintf(stderr, "CubemapEnvironment: Could not load maps from `%s'\n", folder);
}
}
};

@@ -26,12 +26,13 @@
#include "vector.h"
#include <functional>
#include "matrix.h"
#include "scene.h"

class Geometry;
struct IntersectionInfo {
double dist;
Vector ip;
Vector norm;
Vector norm, dNdx, dNdy;
double u, v;
Geometry* geom;
};
@@ -44,14 +45,22 @@ class Intersectable {
virtual bool intersect(Ray ray, IntersectionInfo& info) = 0;
};

class Geometry: public Intersectable {
class Geometry: public Intersectable, public SceneElement {
public:
ElementType getElementType() const { return ELEM_GEOMETRY; }
};

class Plane: public Geometry {
public:
double limit;
double height;
Plane(double limit = 128, double height = 0): limit(limit), height(height) {}

void fillProperties(ParsedBlock& pb)
{
pb.getDoubleProp("y", &height);
pb.getDoubleProp("limit", &limit);
}

bool intersect(Ray ray, IntersectionInfo& info) override;
};
@@ -67,6 +76,11 @@ class Sphere: public Geometry {
O = position;
R = radius;
}
void fillProperties(ParsedBlock& pb)
{
pb.getVectorProp("O", &O);
pb.getDoubleProp("R", &R);
}

bool intersect(Ray ray, IntersectionInfo& info) override;
};
@@ -86,6 +100,11 @@ class Cube: public Geometry {
O = position;
this->halfSide = halfSide;
}
void fillProperties(ParsedBlock& pb)
{
pb.getVectorProp("O", &O);
pb.getDoubleProp("halfSide", &halfSide);
}

bool intersect(Ray ray, IntersectionInfo& info) override;

@@ -97,6 +116,14 @@ class CsgOp: public Geometry {
Geometry* right;

virtual bool boolOp(bool inLeft, bool inRight) = 0;

void fillProperties(ParsedBlock& pb)
{
pb.requiredProp("left");
pb.requiredProp("right");
pb.getGeometryProp("left", &left);
pb.getGeometryProp("right", &right);
}

bool intersect(Ray ray, IntersectionInfo& info) override;
};
@@ -126,10 +153,24 @@ class CsgMinus: public CsgOp {
};

struct Shader;
struct Node: public Intersectable {
Geometry* geometry;
Shader* shader;
struct BumpTexture;
struct Node: public Intersectable, public SceneElement {
Geometry* geometry = nullptr;
Shader* shader = nullptr;
Transform T;
Texture* bump = nullptr;

// from Intersectable:
bool intersect(Ray ray, IntersectionInfo& info) override;

// from SceneElement:
ElementType getElementType() const { return ELEM_NODE; }
void fillProperties(ParsedBlock& pb)
{
pb.getGeometryProp("geometry", &geometry);
pb.getShaderProp("shader", &shader);
pb.getTransformProp(T);
pb.getTextureProp("bump", &bump);
}
};

@@ -22,32 +22,28 @@
* @Brief Describes light sources
*/
#include "lights.h"
#include "random_generator.h"

std::vector<Light*> lights;

PointLight::PointLight(Color color, float power, Vector pos)
{
this->color = color;
this->power = power;
this->pos = pos;
}

void PointLight::getNthSample(int sampleIdx, const Vector& shadePos, Vector& samplePos, Color& color)
{
samplePos = this->pos;
color = this->color * this->power;
}


RectLight::RectLight(Color color, float power, Transform T, int xSubd, int ySubd)
void RectLight::beginFrame(void)
{
this->color = color;
this->power = power;
this->T = T;
this->xSubd = xSubd;
this->ySubd = ySubd;
center = T.transformPoint(Vector(0, 0, 0));
Vector a = T.transformPoint(Vector(-0.5, 0.0, -0.5));
Vector b = T.transformPoint(Vector( 0.5, 0.0, -0.5));
Vector c = T.transformPoint(Vector( 0.5, 0.0, 0.5));
float width = (float) (b - a).length();
float height = (float) (b - c).length();
area = width * height; // obtain the area of the light, in world space
}


void RectLight::getNthSample(int sampleIdx, const Vector& shadePos, Vector& samplePos, Color& color)
{
int column = sampleIdx % xSubd;
@@ -59,19 +55,47 @@ void RectLight::getNthSample(int sampleIdx, const Vector& shadePos, Vector& samp
double areaXstart = column * areaXsize;
double areaYstart = row * areaYsize;

double p_x = areaXstart + areaXsize * randomFloat();
double p_y = areaYstart + areaYsize * randomFloat();
Random& rnd = getRandomGen();

double p_x = areaXstart + areaXsize * rnd.randfloat();
double p_y = areaYstart + areaYsize * rnd.randfloat();
Vector pointOnLight(p_x - 0.5, 0, p_y - 0.5); // ([-0.5..0.5], 0, [-0.5..0.5])

// check if shaded point is behind the lamp:
Vector shadedPointInLightSpace = T.untransformPoint(shadePos);
if (shadedPointInLightSpace.y > 0) {
samplePos.makeZero();
color.makeZero();
return;
} else {
float cosWeight = float(dot(Vector(0, -1, 0), shadedPointInLightSpace) / shadedPointInLightSpace.length());
color = this->color * power * area * cosWeight;
}

Vector pointOnLight(p_x - 0.5, 0, p_y - 0.5); // ([-0.5..0.5], 0, [-0.5..0.5])

samplePos = T.transformPoint(pointOnLight);
color = this->color * this->power;
}

bool RectLight::intersect(Ray ray, IntersectionInfo& info)
{
Ray rayLocal;
rayLocal.start = T.untransformPoint(ray.start);
rayLocal.dir = T.untransformDir(ray.dir);

if (rayLocal.start.y >= 0) return false;
if (rayLocal.dir.y <= 0) return false;

double travelByY = fabs(rayLocal.start.y);
double unitTravel = fabs(rayLocal.dir.y);
double scaling = travelByY / unitTravel;

info.ip = rayLocal.start + rayLocal.dir * scaling;

if (fabs(info.ip.x) > 0.5 || fabs(info.ip.z) > 0.5) return false;

info.norm = Vector(0, -1, 0);

info.ip = T.transformPoint(info.ip);
info.norm = T.transformDir(info.norm);
info.dist = distance(ray.start, info.ip);

return true;
}

0 comments on commit 6c1fb06

Please sign in to comment.
You can’t perform that action at this time.