diff --git a/resources/shader/compute-sample.wgsl b/resources/shader/compute-sample.wgsl index 872e5c7..c700677 100644 --- a/resources/shader/compute-sample.wgsl +++ b/resources/shader/compute-sample.wgsl @@ -72,6 +72,11 @@ struct SphereLights { l2 : Sphere, l3 : Sphere, l4 : Sphere, + l5 : Sphere, + l6 : Sphere, + l7 : Sphere, + l8 : Sphere, + l9 : Sphere, } fn fabs(x: f32) -> f32 { @@ -165,26 +170,60 @@ fn sample_direction(hit: HitInfo) -> vec3f { fn sample_from_light(hit: HitInfo) -> vec3f { // ヒット位置とライト位置を比較 // FIXME: ライトの個数分追加が必要 - var l1_dist = distance(hit.pos, sphere_lights.l1.center); + let 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 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; + var l5_dist = distance(hit.pos, sphere_lights.l5.center); + let l6_dist = distance(hit.pos, sphere_lights.l6.center); + let l7_dist = distance(hit.pos, sphere_lights.l7.center); + let l8_dist = distance(hit.pos, sphere_lights.l8.center); + let l9_dist = distance(hit.pos, sphere_lights.l9.center); + let l1_w = select(0.0, 1.0 / (l1_dist * l1_dist), sphere_lights.l1.emissive > 0.0f); + let l2_w = select(0.0, 1.0 / (l2_dist * l2_dist), sphere_lights.l2.emissive > 0.0f); + let l3_w = select(0.0, 1.0 / (l3_dist * l3_dist), sphere_lights.l3.emissive > 0.0f); + let l4_w = select(0.0, 1.0 / (l4_dist * l4_dist), sphere_lights.l4.emissive > 0.0f); + let l5_w = select(0.0, 1.0 / (l5_dist * l5_dist), sphere_lights.l5.emissive > 0.0f); + let l6_w = select(0.0, 1.0 / (l6_dist * l6_dist), sphere_lights.l6.emissive > 0.0f); + let l7_w = select(0.0, 1.0 / (l7_dist * l7_dist), sphere_lights.l7.emissive > 0.0f); + let l8_w = select(0.0, 1.0 / (l8_dist * l8_dist), sphere_lights.l8.emissive > 0.0f); + let l9_w = select(0.0, 1.0 / (l9_dist * l9_dist), sphere_lights.l9.emissive > 0.0f); + let sum = l1_w + l2_w + l3_w + l4_w + l5_w + l6_w + l7_w + l8_w + l9_w; + let l1_t = l1_w / sum; + let l2_t = l1_t + l2_w / sum; + let l3_t = l2_t + l3_w / sum; + let l4_t = l3_t + l4_w / sum; + let l5_t = l4_t + l5_w / sum; + let l6_t = l5_t + l6_w / sum; + let l7_t = l6_t + l7_w / sum; + let l8_t = l7_t + l8_w / sum; + let l9_t = l8_t + l9_w / sum; let rand = rand(); var sphere = sphere_lights.l1; - if (l1_w / sum < rand && rand <= (l1_w + l2_w) / sum) { + if (l1_t < rand && rand <= l2_t) { sphere = sphere_lights.l2; } - if ((l1_w + l2_w) / sum < rand && rand <= (l1_w + l2_w + l3_w) / sum) { + if (l2_t < rand && rand <= l3_t) { sphere = sphere_lights.l3; } - if ((l1_w + l2_w + l3_w) / sum < rand && rand <= 1.0) { + if (l3_t < rand && rand <= l4_t) { sphere = sphere_lights.l4; } + if (l4_t < rand && rand <= l5_t) { + sphere = sphere_lights.l5; + } + if (l5_t < rand && rand <= l6_t) { + sphere = sphere_lights.l6; + } + if (l6_t < rand && rand <= l7_t) { + sphere = sphere_lights.l7; + } + if (l7_t < rand && rand <= l8_t) { + sphere = sphere_lights.l8; + } + if (l8_t < rand && rand <= l9_t) { + sphere = sphere_lights.l9; + } return sample_from_sphere(sphere, hit.pos); } @@ -218,19 +257,34 @@ fn sample_from_cosine(hit: HitInfo) -> vec3f { fn mixture_pdf(hit: HitInfo, dir: vec3f) -> f32 { // FIXME: ライトの個数分追加が必要 - var l1_dist = distance(hit.pos, sphere_lights.l1.center); + let 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 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; + var l5_dist = distance(hit.pos, sphere_lights.l5.center); + let l6_dist = distance(hit.pos, sphere_lights.l6.center); + let l7_dist = distance(hit.pos, sphere_lights.l7.center); + let l8_dist = distance(hit.pos, sphere_lights.l8.center); + let l9_dist = distance(hit.pos, sphere_lights.l9.center); + let l1_w = select(0.0, 1.0 / (l1_dist * l1_dist), sphere_lights.l1.emissive > 0.0f); + let l2_w = select(0.0, 1.0 / (l2_dist * l2_dist), sphere_lights.l2.emissive > 0.0f); + let l3_w = select(0.0, 1.0 / (l3_dist * l3_dist), sphere_lights.l3.emissive > 0.0f); + let l4_w = select(0.0, 1.0 / (l4_dist * l4_dist), sphere_lights.l4.emissive > 0.0f); + let l5_w = select(0.0, 1.0 / (l5_dist * l5_dist), sphere_lights.l5.emissive > 0.0f); + let l6_w = select(0.0, 1.0 / (l6_dist * l6_dist), sphere_lights.l6.emissive > 0.0f); + let l7_w = select(0.0, 1.0 / (l7_dist * l7_dist), sphere_lights.l7.emissive > 0.0f); + let l8_w = select(0.0, 1.0 / (l8_dist * l8_dist), sphere_lights.l8.emissive > 0.0f); + let l9_w = select(0.0, 1.0 / (l9_dist * l9_dist), sphere_lights.l9.emissive > 0.0f); + let sum = l1_w + l2_w + l3_w + l4_w + l5_w + l6_w + l7_w + l8_w + l9_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); + l4_w * sphere_pdf(hit, sphere_lights.l4, dir) + + l5_w * sphere_pdf(hit, sphere_lights.l5, dir) + + l6_w * sphere_pdf(hit, sphere_lights.l6, dir) + + l7_w * sphere_pdf(hit, sphere_lights.l7, dir) + + l8_w * sphere_pdf(hit, sphere_lights.l8, dir) + + l9_w * sphere_pdf(hit, sphere_lights.l9, dir); return 0.5 * cosine_pdf(hit, dir) + 0.5 * light_pdf / sum; } @@ -285,8 +339,9 @@ fn raytrace(path: Path, depth: i32) -> Path { // 光源の場合、トレースを終了 if (emissive) { if (depth == 0) { - var light_col = hit.col / length(hit.col); + var light_col = hit.col; let dist = distance(camera.start.xyz, hit.pos.xyz); + light_col = light_col / dist; return Path(r, light_col, true); } // 照明計算 @@ -323,6 +378,11 @@ fn sample_hit(r: Ray) -> HitInfo { hit = intersect_sphere(r, sphere_lights.l2, hit); hit = intersect_sphere(r, sphere_lights.l3, hit); hit = intersect_sphere(r, sphere_lights.l4, hit); + hit = intersect_sphere(r, sphere_lights.l5, hit); + hit = intersect_sphere(r, sphere_lights.l6, hit); + hit = intersect_sphere(r, sphere_lights.l7, hit); + hit = intersect_sphere(r, sphere_lights.l8, hit); + hit = intersect_sphere(r, sphere_lights.l9, hit); return hit; } diff --git a/src/camera.cpp b/src/camera.cpp index 08982f5..608e207 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -61,7 +61,8 @@ void Camera::InitBindGroup(Device &device) { void Camera::Update(Queue &queue, float t, float aspect) { // カメラ: [前半]InQuart, [後半]等速 - float move_dist = t < 0.2f ? 8.0f * EaseInQuart(t / 0.2f) : 8.0f * EaseInQuart((t - 0.2f) / 0.8f + 1.0f); + float end_dist = 8.0f * EaseInQuart((0.95f - 0.2f) / 0.8f + 1.0f); + float move_dist = t < 0.2f ? 8.0f * EaseInQuart(t / 0.2f) : t < 0.95f ? 8.0f * EaseInQuart((t - 0.2f) / 0.8f + 1.0f) : end_dist; 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 diff --git a/src/include/scene.h b/src/include/scene.h index 412987e..28dc682 100644 --- a/src/include/scene.h +++ b/src/include/scene.h @@ -23,8 +23,14 @@ class Scene { Sphere l2_; Sphere l3_; Sphere l4_; - - SphereLights(Sphere l1, Sphere l2, Sphere l3, Sphere l4) : l1_(l1), l2_(l2), l3_(l3), l4_(l4) {}; + Sphere l5_; + Sphere l6_; + Sphere l7_; + Sphere l8_; + Sphere l9_; + + SphereLights(Sphere l1, Sphere l2, Sphere l3, Sphere l4, Sphere l5, Sphere l6, Sphere l7, Sphere l8, Sphere l9) + : l1_(l1), l2_(l2), l3_(l3), l4_(l4), l5_(l5), l6_(l6), l7_(l7), l8_(l8), l9_(l9) {}; }; void Release(); diff --git a/src/scene.cpp b/src/scene.cpp index c63ba9f..23f77de 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -19,7 +19,6 @@ Scene::Scene(Device &device) { /// 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)); @@ -335,10 +334,44 @@ void Scene::InitBindGroup(Device &device) { * SphereLightの更新 */ void Scene::UpdateSphereLights(Queue &queue, float t) { - 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); + float cam_pos = t < 0.2f ? 8.0f * EaseInQuart(t / 0.2f) : 8.0f * EaseInQuart((t - 0.2f) / 0.8f + 1.0f); + float dist_from_cam = 5.0f; + float move_dist = cam_pos + dist_from_cam; + bool is_on = t < 0.95f; + bool l1_on = is_on && move_dist > 15 - dist_from_cam; + bool l2_on = is_on && move_dist > 30 - dist_from_cam; + bool l3_on = is_on && move_dist > 45 - dist_from_cam; + bool l4_on = is_on && move_dist > 60 - dist_from_cam; + bool l5_on = is_on && move_dist > 75 - dist_from_cam; + bool l6_on = is_on && move_dist > 90 - dist_from_cam; + bool l7_on = is_on && move_dist > 105 - dist_from_cam; + bool l8_on = is_on && move_dist > 120 - dist_from_cam; + Color3 light_col = Color3(1000, 1000, 1000); + Color3 light_off_col = Color3(0.2, 0.2, 0.2); + Color3 move_light_col = Color3(2000, 2000, 2000); + Color3 col1 = l1_on ? light_col + Color3(250, 0, 0) : light_off_col; + Color3 col2 = l2_on ? light_col + Color3(0, 250, 0) : light_off_col; + Color3 col3 = l3_on ? light_col + Color3(0, 0, 250) : light_off_col; + Color3 col4 = l4_on ? light_col + Color3(250, 250, 0) : light_off_col; + Color3 col5 = l5_on ? light_col + Color3(0, 250, 250) : light_off_col; + Color3 col6 = l6_on ? light_col + Color3(250, 0, 250) : light_off_col; + Color3 col7 = l7_on ? light_col + Color3(500, 0, 250) : light_off_col; + Color3 col8 = l8_on ? light_col + Color3(250, 0, 500) : light_off_col; + Sphere l1(Point3(0.0, 2.0, -15), 0.3, col1, l1_on); + Sphere l2(Point3(0.0, 2.0, -30), 0.3, col2, l2_on); + Sphere l3(Point3(0.0, 2.0, -45), 0.3, col3, l3_on); + Sphere l4(Point3(0.0, 2.0, -60), 0.3, col4, l4_on); + Sphere l5(Point3(0.0, 2.0, -75), 0.3, col5, l5_on); + Sphere l6(Point3(0.0, 2.0, -90), 0.3, col6, l6_on); + Sphere l7(Point3(0.0, 2.0, -105), 0.3, col7, l7_on); + Sphere l8(Point3(0.0, 2.0, -120), 0.3, col8, l8_on); +// float end_pos = 8.0f * EaseInQuart((0.95f - 0.2f) / 0.8f + 1.0f); +// float theta = (is_on ? cam_pos / 12.0f : Lerp(end_pos / 12.0f, 360.0f, (t - 0.95f) / 0.05f)) * (float) (M_PI * 2.0f); + float theta = cam_pos / 12.0f * (float) (M_PI * 2.0f); + float x = cos(theta); + float y = sin(theta); + Point3 origin = Vec3(x, y, 0.01f - move_dist); + Sphere move_l(origin, 0.1, move_light_col, true); + SphereLights lights(l1, l2, l3, l4, l5, l6, l7, l8, move_l); queue.writeBuffer(sphere_light_buffer_, 0, &lights, sizeof(SphereLights)); }