Skip to content

Commit

Permalink
Sample multiple lights.
Browse files Browse the repository at this point in the history
  • Loading branch information
kugimasa committed Aug 26, 2023
1 parent aed7de4 commit 819d7ac
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 33 deletions.
46 changes: 23 additions & 23 deletions resources/shader/compute-sample.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -163,24 +163,27 @@ fn sample_direction(hit: HitInfo) -> vec3f {
}

fn sample_from_light(hit: HitInfo) -> vec3f {
// FIXME: 境界が目立つ
// ヒット位置とライト位置を比較
var dist = distance(hit.pos, sphere_lights.l1.center);
var sphere = sphere_lights.l1;
// FIXME: ライトの個数分追加が必要
var l1_dist = distance(hit.pos, sphere_lights.l1.center);
let l2_dist = distance(hit.pos, sphere_lights.l2.center);
let l3_dist = distance(hit.pos, sphere_lights.l3.center);
let l4_dist = distance(hit.pos, sphere_lights.l4.center);
if (l2_dist < dist) {
dist = l2_dist;
sphere = sphere_lights.l2;
let l1_w = 1.0 / (l1_dist * l1_dist);
let l2_w = 1.0 / (l2_dist * l2_dist);
let l3_w = 1.0 / (l3_dist * l3_dist);
let l4_w = 1.0 / (l4_dist * l4_dist);
let sum = l1_w + l2_w + l3_w + l4_w;
let rand = rand();
var sphere = sphere_lights.l1;
if (l1_w / sum < rand && rand <= (l1_w + l2_w) / sum) {
sphere = sphere_lights.l2;
}
if (l3_dist < dist) {
dist = l3_dist;
sphere = sphere_lights.l3;
if ((l1_w + l2_w) / sum < rand && rand <= (l1_w + l2_w + l3_w) / sum) {
sphere = sphere_lights.l3;
}
if (l4_dist < dist) {
dist = l4_dist;
sphere = sphere_lights.l4;
if ((l1_w + l2_w + l3_w) / sum < rand && rand <= 1.0) {
sphere = sphere_lights.l4;
}
return sample_from_sphere(sphere, hit.pos);
}
Expand Down Expand Up @@ -214,21 +217,21 @@ fn sample_from_cosine(hit: HitInfo) -> vec3f {
}

fn mixture_pdf(hit: HitInfo, dir: vec3f) -> f32 {
/// FIXME: 暗くなってしまう
let l1_dist = distance(hit.pos, sphere_lights.l1.center);
// FIXME: ライトの個数分追加が必要
var l1_dist = distance(hit.pos, sphere_lights.l1.center);
let l2_dist = distance(hit.pos, sphere_lights.l2.center);
let l3_dist = distance(hit.pos, sphere_lights.l3.center);
let l4_dist = distance(hit.pos, sphere_lights.l4.center);
let dist_sum = l1_dist + l2_dist + l3_dist + l4_dist;
let l1_w = (l2_dist + l3_dist + l4_dist) / dist_sum;
let l2_w = (l1_dist + l3_dist + l4_dist) / dist_sum;
let l3_w = (l1_dist + l2_dist + l4_dist) / dist_sum;
let l4_w = (l1_dist + l2_dist + l3_dist) / dist_sum;
let l1_w = 1.0 / (l1_dist * l1_dist);
let l2_w = 1.0 / (l2_dist * l2_dist);
let l3_w = 1.0 / (l3_dist * l3_dist);
let l4_w = 1.0 / (l4_dist * l4_dist);
let sum = l1_w + l2_w + l3_w + l4_w;
let light_pdf = l1_w * sphere_pdf(hit, sphere_lights.l1, dir) +
l2_w * sphere_pdf(hit, sphere_lights.l2, dir) +
l3_w * sphere_pdf(hit, sphere_lights.l3, dir) +
l4_w * sphere_pdf(hit, sphere_lights.l4, dir);
return 0.5 * cosine_pdf(hit, dir) + 0.5 * light_pdf;
return 0.5 * cosine_pdf(hit, dir) + 0.5 * light_pdf / sum;
}

fn sphere_pdf(hit: HitInfo, sphere: Sphere, dir: vec3f) -> f32 {
Expand Down Expand Up @@ -284,7 +287,6 @@ fn raytrace(path: Path, depth: i32) -> Path {
if (depth == 0) {
var light_col = hit.col / length(hit.col);
let dist = distance(camera.start.xyz, hit.pos.xyz);
light_col = hit.col / max(dist * dist, 1.0);
return Path(r, light_col, true);
}
// 照明計算
Expand All @@ -296,8 +298,6 @@ fn raytrace(path: Path, depth: i32) -> Path {
// 反射
let scatter_dir = sample_direction(hit);
let pdf_val = mixture_pdf(hit, scatter_dir);
// let scatter_dir = sample_from_cosine(hit);
// let pdf_val = cosine_pdf(hit, scatter_dir);
// パスを更新
let scattered_ray = Ray(hit.pos, scatter_dir);
let scattered_col = path.col * hit.col * scattering_pdf(hit, scatter_dir) / pdf_val;
Expand Down
9 changes: 6 additions & 3 deletions src/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,14 @@ void Camera::InitBindGroup(Device &device) {
}

void Camera::Update(Queue &queue, float t, float aspect) {
t = EaseInOutExpo(t);
float move_dist = Lerp(0.0, 40.0, t);
float fovy = t < 0.5 ? Lerp(40, 90, t / 0.5f) : Lerp(90, 40, (t - 0.5f) / 0.5f);
// カメラ: [前半]InQuart, [後半]等速
float move_dist = t < 0.2f ? 8.0f * EaseInQuart(t / 0.2f) : 8.0f * EaseInQuart((t - 0.2f) / 0.8f + 1.0f);
Point3 origin = Vec3(0, 0, 0.01f - move_dist);
Point3 target = Vec3(0, 0, 15 + move_dist);
// fovy変化: 増加は 0.0 ~ 0.15, 減少は 0.95 ~ 1.0
float fovy_add_t = t / 0.15f;
float fovy_dec_t = (t - 0.95f) / 0.05f;
float fovy = t < 0.15f ? Lerp(40, 65, fovy_add_t) : t < 0.95f ? 65 : Lerp(65, 40, EaseOutCubic(fovy_dec_t));
float time = 0.0f;
CameraParam param(origin, target, aspect, fovy, time, RandSeed());
queue.writeBuffer(uniform_buffer_, 0, &param, sizeof(CameraParam));
Expand Down
10 changes: 9 additions & 1 deletion src/include/utils/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ inline double Deg2Rad(double degrees) {
return degrees * M_PI * 0.00555555555;
}

inline double Clamp(double x, double min, double max) {
inline float Clamp(float x, float min, float max) {
if (x < min) return min;
if (x > max) return max;
return x;
Expand Down Expand Up @@ -67,9 +67,17 @@ inline float EaseInQuart(float t) {
return t * t * t * t;
}

inline float EaseOutCubic(float t) {
return 1.0f - (1.0f - t) * (1.0f - t) * (1.0f - t);
}

inline float EaseInOutExpo(float t) {
if (t == 0 || t == 1) {
return t;
}
return t < 0.5 ? pow(2.0f, 20.0f * t - 10.0f) / 2.0f : (2.0f - pow(2.0f, -20.0f * t + 10.0f)) / 2.0f;
}

inline float Sigmoid(float t) {
return 3.0f * t * t - 2.0f * t * t * t;
}
19 changes: 13 additions & 6 deletions src/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,21 @@
*/
Scene::Scene(Device &device) {
/// Quadの追加
auto pos = Point3(0, 0, -9);
auto scale = Vec3(8, 5, 100);
auto pos = Point3(0, 0, 0);
auto scale = Vec3(8, 5, 500);
auto cb = CornellBox(pos, scale);
/// CornellBoxの追加
cb.PushToQuads(quads_);

/// Sphereの追加
spheres_.emplace_back(Point3(-1.0, 0, -9), 0.3, Color3(0.8, 0.8, 0.8));
// TODO: 光源に変更
// 最終位置
float end_pos = 128;
spheres_.emplace_back(Point3(0.0, 2.0, -(30 + end_pos)), 0.3, Color3(0.8, 0.8, 0.8));
spheres_.emplace_back(Point3(0.0, 2.0, -(60 + end_pos)), 0.3, Color3(0.8, 0.8, 0.8));
spheres_.emplace_back(Point3(0.0, 2.0, -(90 + end_pos)), 0.3, Color3(0.8, 0.8, 0.8));
spheres_.emplace_back(Point3(0.0, 2.0, -(120 + end_pos)), 0.3, Color3(0.8, 0.8, 0.8));
/// バッファのバインド
InitBindGroupLayout(device);
InitBuffers(device);
Expand Down Expand Up @@ -328,10 +335,10 @@ void Scene::InitBindGroup(Device &device) {
* SphereLightの更新
*/
void Scene::UpdateSphereLights(Queue &queue, float t) {
Sphere l1(Point3(0, 0, -50), 0.5, Color3(2000, 2000, 2000), true);
Sphere l2(Point3(1.0, 2.0, -10), 0.3, Color3(20, 1500, 20), true);
Sphere l3(Point3(0.0, 2.0, -20), 0.3, Color3(1500, 20, 20), true);
Sphere l4(Point3(-1.0, 2.0, -30), 0.3, Color3(20, 20, 1500), true);
Sphere l1(Point3(0.0, 2.0, -120), 0.3, Color3(500, 500, 500), true);
Sphere l2(Point3(0.0, 2.0, -30), 0.3, Color3(2, 150, 2), true);
Sphere l3(Point3(0.0, 2.0, -60), 0.3, Color3(150, 2, 2), true);
Sphere l4(Point3(0.0, 2.0, -90), 0.3, Color3(2, 2, 150), true);
SphereLights lights(l1, l2, l3, l4);
queue.writeBuffer(sphere_light_buffer_, 0, &lights, sizeof(SphereLights));
}

0 comments on commit 819d7ac

Please sign in to comment.