Skip to content

Commit

Permalink
Merge pull request #79 from NJUCG/thin_lens
Browse files Browse the repository at this point in the history
Complete the thin-lens camera.
  • Loading branch information
ChenxiZhou0619 authored Oct 24, 2023
2 parents 30f8001 + ed1c4dc commit 558021d
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 131 deletions.
100 changes: 78 additions & 22 deletions scenes/green-bathroom/scene.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
{
"renderer": {
"spp": 4096,
"spp": 4,
"output_file": "green_bathroom"
},

"mediums": [],

"materials": [
{
"name": "bamboo",
Expand All @@ -26,14 +24,22 @@
{
"name": "ceramics",
"type": "plastic",
"albedo": [0.9, 0.9, 0.9],
"albedo": [
0.9,
0.9,
0.9
],
"roughness": 0.015,
"ior": 1.45
},
{
"name": "czarne",
"type": "plastic",
"albedo": [0.1, 0.1, 0.1],
"albedo": [
0.1,
0.1,
0.1
],
"roughness": 0.01,
"ior": 1.7
},
Expand All @@ -42,24 +48,40 @@
"type": "conductor",
"distribution": "ggx",
"material": "Al",
"albedo": [0.8, 0.8, 0.8],
"albedo": [
0.8,
0.8,
0.8
],
"roughness": 0.3
},
{
"name": "Material.005",
"type": "lambert",
"albedo": [0.8, 0.8, 0.8]
"albedo": [
0.8,
0.8,
0.8
]
},
{
"name": "czerwony",
"type": "conductor",
"albedo": [1, 0.042, 0],
"albedo": [
1,
0.042,
0
],
"roughness": 0.02
},
{
"name": "Material.004",
"type": "lambert",
"albedo": [0.8, 0.779, 0.687]
"albedo": [
0.8,
0.779,
0.687
]
},
{
"name": "Material.009",
Expand All @@ -74,7 +96,11 @@
{
"name": "Material.013",
"type": "lambert",
"albedo": [1, 1, 1]
"albedo": [
1,
1,
1
]
},
{
"name": "szare plytki",
Expand All @@ -86,19 +112,31 @@
{
"name": "biale sciany",
"type": "lambert",
"albedo": [1, 1, 1]
"albedo": [
1,
1,
1
]
},
{
"name": "zielony",
"type": "plastic",
"albedo": [0.364, 0.8, 0.110],
"albedo": [
0.364,
0.8,
0.110
],
"roughness": 0.02,
"ior": 1.5
},
{
"name": "bialy.001",
"type": "plastic",
"albedo": [0.8, 0.8, 0.8],
"albedo": [
0.8,
0.8,
0.8
],
"roughness": 0.01,
"ior": 1.3
},
Expand Down Expand Up @@ -129,7 +167,11 @@
{
"name": "Material.008",
"type": "lambert",
"albedo": [0.8, 0.8, 0.8]
"albedo": [
0.8,
0.8,
0.8
]
},
{
"name": "Material.017",
Expand All @@ -154,8 +196,16 @@
"distribution": "ggx",
"roughness": 0.001,
"ior": 1.45,
"albedo_reflection": [1, 0.717, 0.194],
"albedo_transmission": [1, 0.717, 0.194]
"albedo_reflection": [
1,
0.717,
0.194
],
"albedo_transmission": [
1,
0.717,
0.194
]
},
{
"name": "n5",
Expand All @@ -165,13 +215,16 @@
{
"name": "White-pot",
"type": "disney",
"albedo": [0.8, 0.8, 0.8],
"albedo": [
0.8,
0.8,
0.8
],
"metallic": 0,
"specular": 0.5,
"roughness": 0.5
}
],

"entities": [
{
"type": "mesh",
Expand Down Expand Up @@ -439,7 +492,9 @@
"material": "Material.014",
"transform": {
"rotation": [
0, 0, 0
0,
0,
0
]
}
},
Expand Down Expand Up @@ -538,10 +593,11 @@
"emission": "textures/envmap.hdr"
}
],

"camera": {
"type": "pinhole",
"type": "thinlens",
"fov": 50,
"aperture_radius": 0.1,
"focus_distance": 10,
"resolution": [
1400,
900
Expand All @@ -564,4 +620,4 @@
]
}
}
}
}
22 changes: 22 additions & 0 deletions src/CoreLayer/Math/Warp.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,25 @@ inline float SquareToBeckmannPdf(const Vec3d &m, double alpha) {
float longitudinal = exp(-tan2Theta/(alpha*alpha)) / (alpha*alpha*pow(cosTheta,3));
return azimuthal * longitudinal;
}

// Modified implementation from Mitsuba
inline Point2d SquareToUniformDiskConcentric(const Point2d &sample) {
double r1 = 2.0 * sample.x - 1.0;
double r2 = 2.0 * sample.y - 1.0;

double phi, r;
if (r1 == 0 && r2 == 0) {
r = phi = 0;
} else if (r1 * r1 > r2 * r2) {
r = r1;
phi = (M_PI / 4.0) * (r2 / r1);
} else {
r = r2;
phi = (M_PI / 2.0) - (r1 / r2) * (M_PI / 4.0);
}

double cosPhi = fm::cos(phi);
double sinPhi = fm::sin(phi);

return { r * cosPhi, r * sinPhi };
}
7 changes: 4 additions & 3 deletions src/FunctionLayer/Camera/CameraFactory.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "CameraFactory.h"
#include "Camera.h"
#include "Pinhole.h"
#include "Thinlens.h"
#include "DifferentialPinhole.h"

namespace CameraFactory {
Expand All @@ -12,10 +13,10 @@ std::shared_ptr<T> cameraCreatorHelper(const Json &json) {

static std::unordered_map<std::string, std::function<std::shared_ptr<Camera>(const Json &)>> cameraMap{
{"pinhole", cameraCreatorHelper<PinholeCamera>},
{"differential_pinhole", cameraCreatorHelper<DifferentialPinholeCamera>}
};
{"thinlens", cameraCreatorHelper<ThinlensCamera>},
{"differential_pinhole", cameraCreatorHelper<DifferentialPinholeCamera>}};

std::shared_ptr<Camera> LoadCameraFromJson(const Json &json) {
return cameraMap[json["type"]](json);
return cameraMap[json.at("type")](json);
}
}// namespace CameraFactory
39 changes: 19 additions & 20 deletions src/FunctionLayer/Camera/Thinlens.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
#include <cmath>
#include "Thinlens.h"
#include "CoreLayer/Math/Common.h"
#include "FastMath.h"
#include "CoreLayer/Math/Warp.h"

#define _USE_MATH_DEFINES
ThinlensCamera::ThinlensCamera(const Json &json) : PerspectiveCamera(json) {

apertureRadius = getOptional(json, "aperture_radius", 0.1);
focusDistance = getOptional(json, "focus_distance", 10);
}

Ray ThinlensCamera::generateRay(const Point2i &filmResolution, const Point2i &pixelPosition, const CameraSample &sample) const {
double x = (double) (pixelPosition.x + sample.xy.x) / filmResolution.x,
y = (double) (pixelPosition.y + sample.xy.y) / filmResolution.y;

Point3d pointOnFilm = sampleToFilm * Point3d (x, y, 0),
pointOnFocalPlane = pointOnFilm * (focalDistance / pointOnFilm.z);
// TODO warp the sample transform
float r = fm::sqrt(sample.lens[0]),
theta = sample.lens[1] * 2 * M_PI;
Point3d pointOnApeture =
apertureRadius * Point3d(r * fm::cos(theta), r * fm::sin(theta), 0);
Vec3d dir = normalize(pointOnFocalPlane - pointOnApeture);
return Ray(
cameraToWorld * pointOnApeture,
cameraToWorld * dir
);
}
double x = (double)(pixelPosition.x + sample.xy.x) / filmResolution.x;
double y = (double)(pixelPosition.y + sample.xy.y) / filmResolution.y;

Point3d pointOnFilm = sampleToFilm * Point3d(x, y, 0);
Point3d pointOnFocalPlane = pointOnFilm * (focusDistance / pointOnFilm.z);

Point2d pointOnDisk = apertureRadius * SquareToUniformDiskConcentric(sample.lens);
Point3d pointOnAperture = {pointOnDisk.x, pointOnDisk.y, 0};

Vec3d dir = normalize(pointOnFocalPlane - pointOnAperture);

return {cameraToWorld * pointOnAperture, cameraToWorld * dir};
}
45 changes: 9 additions & 36 deletions src/FunctionLayer/Camera/Thinlens.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,16 @@
* @ingroup Camera
*/
class ThinlensCamera : public PerspectiveCamera {
protected:
double apertureRadius, focalLen, focalDistance;
public:
ThinlensCamera() = default;
ThinlensCamera(
const Point3d &lookFrom,
const Point3d &lookAt,
const Vec3d &up,
double xFov,
double aspectRatio,
double _focaDistance,
double _apertureRadius = 0.1,
double _focalLen = 0.05
):apertureRadius(_apertureRadius), focalLen(_focalLen), focalDistance(_focaDistance) {
double distToFilm =
(_focalLen * _focaDistance) / (_focaDistance - _focalLen);

cameraToWorld =
Matrix4x4::lookAt(lookFrom, lookAt - lookFrom, up).inverse();
// ! near is the distToFilm and far set to MAX_FLOAT
// ! if far set to MAX_DOUBLE, it will crash when computing the matrix
Matrix4x4 filmToSample = Matrix4x4::perspective(
Angle(xFov, Angle::EAngleType::ANGLE_DEG),
aspectRatio,
distToFilm,
std::numeric_limits<float>::max()
);
sampleToFilm =
Matrix4x4::scale(0.5, -0.5, 1.0)
* Matrix4x4::translate(1, -1, 0)
* filmToSample;
sampleToFilm = sampleToFilm.inverse();

}
explicit ThinlensCamera(const Json &json);

[[nodiscard]]
Ray generateRay(const Point2i &filmResolution, const Point2i &pixelPosition, const CameraSample &sample) const override;

protected:

double apertureRadius;
double focusDistance;

virtual Ray generateRay(const Point2i &filmResolution ,
const Point2i &pixelPosition,
const CameraSample &sample) const override;
};
};
Loading

0 comments on commit 558021d

Please sign in to comment.