diff --git a/src/base/geometry.cpp b/src/base/geometry.cpp index 22ae715c..a7b505ae 100644 --- a/src/base/geometry.cpp +++ b/src/base/geometry.cpp @@ -162,6 +162,39 @@ void Geometry::_process_shape( } } +void Geometry::_alpha_skip(SurfaceCandidate &c) const noexcept { + $outline { + auto hit = c.hit(); + auto ray = c.ray(); + auto bary = make_float3(1.f - hit.bary.x - hit.bary.y, hit.bary); + auto it = interaction(hit.inst, hit.prim, bary, -ray->direction()); + $if(it->shape().maybe_non_opaque() & it->shape().has_surface()) { + auto u = xxhash32(make_uint4(hit.inst, hit.prim, compute::as(hit.bary))) * 0x1p-32f; + $switch(it->shape().surface_tag()) { + for (auto i = 0u; i < _pipeline.surfaces().size(); i++) { + if (auto surface = _pipeline.surfaces().impl(i); + surface->maybe_non_opaque()) { + $case(i) { + // TODO: pass the correct swl and time + if (auto opacity = surface->evaluate_opacity(*it, _pipeline.spectrum()->sample(.5f), 0.f)) { + $if (u < *opacity) { + c.commit(); + }; + } else { + c.commit(); + } + }; + } + } + $default { compute::unreachable(); }; + }; + } + $else { + c.commit(); + }; + }; +} + bool Geometry::update(CommandBuffer &command_buffer, float time) noexcept { auto updated = false; if (!_dynamic_transforms.empty()) { @@ -195,35 +228,7 @@ Var Geometry::trace_closest(const Var &ray) const noexcept { auto rq_hit = _accel->traverse(ray, {}) .on_surface_candidate([&](compute::SurfaceCandidate &c) noexcept { - auto hit = c.hit(); - auto bary = make_float3(1.f - hit.bary.x - hit.bary.y, hit.bary); - auto it = interaction(hit.inst, hit.prim, bary, -ray->direction()); - $if(it->shape().maybe_non_opaque() & it->shape().has_surface()) { - PolymorphicCall call; - _pipeline.surfaces().dispatch(it->shape().surface_tag(), [&](auto surface) noexcept { - if (surface->maybe_non_opaque()) { - // TODO: pass the correct time - surface->closure(call, *it, _pipeline.spectrum()->sample(.5f), -ray->direction(), 1.f, 0.f); - } else { - compute::unreachable(); - } - }); - auto u = xxhash32(make_uint4(hit.inst, hit.prim, compute::as(hit.bary))) * 0x1p-32f; - call.execute([&](const Surface::Closure *closure) noexcept { - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u >= opacity; - } - $if(!alpha_skip) { - c.commit(); - }; - }); - } - $else { - c.commit(); - }; + this->_alpha_skip(c); }) .trace(); return Var{rq_hit.inst, rq_hit.prim, rq_hit.bary}; @@ -237,35 +242,7 @@ Var Geometry::trace_any(const Var &ray) const noexcept { auto rq_hit = _accel->traverse_any(ray, {}) .on_surface_candidate([&](compute::SurfaceCandidate &c) noexcept { - auto hit = c.hit(); - auto bary = make_float3(1.f - hit.bary.x - hit.bary.y, hit.bary); - auto it = interaction(hit.inst, hit.prim, bary, -ray->direction()); - $if(it->shape().maybe_non_opaque() & it->shape().has_surface()) { - PolymorphicCall call; - _pipeline.surfaces().dispatch(it->shape().surface_tag(), [&](auto surface) noexcept { - if (surface->maybe_non_opaque()) { - // TODO: pass the correct time - surface->closure(call, *it, _pipeline.spectrum()->sample(.5f), -ray->direction(), 1.f, 0.f); - } else { - compute::unreachable(); - } - }); - auto u = xxhash32(make_uint4(hit.inst, hit.prim, compute::as(hit.bary))) * 0x1p-32f; - call.execute([&](const Surface::Closure *closure) noexcept { - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u >= opacity; - } - $if(!alpha_skip) { - c.commit(); - }; - }); - } - $else { - c.commit(); - }; + this->_alpha_skip(c); }) .trace(); return !rq_hit->miss(); diff --git a/src/base/geometry.h b/src/base/geometry.h index ea434928..eb8181d0 100644 --- a/src/base/geometry.h +++ b/src/base/geometry.h @@ -57,6 +57,8 @@ class Geometry { static_assert(sizeof(MeshData) == 16u); + using SurfaceCandidate = compute::SurfaceCandidate; + private: Pipeline &_pipeline; Accel _accel; @@ -69,7 +71,7 @@ class Geometry { Buffer _instance_buffer; float3 _world_min; float3 _world_max; - uint _triangle_count;// for debug + uint _triangle_count{};// for debug bool _any_non_opaque{false}; private: @@ -80,6 +82,8 @@ class Geometry { const Medium *overridden_medium = nullptr, bool overridden_visible = true) noexcept; + void _alpha_skip(SurfaceCandidate &c) const noexcept; + public: explicit Geometry(Pipeline &pipeline) noexcept : _pipeline{pipeline} {}; void build(CommandBuffer &command_buffer, diff --git a/src/base/surface.h b/src/base/surface.h index 7922fa71..b4e6ead5 100644 --- a/src/base/surface.h +++ b/src/base/surface.h @@ -94,7 +94,6 @@ class Surface : public SceneNode { TransportMode mode = TransportMode::RADIANCE) const noexcept; // surface properties - [[nodiscard]] virtual luisa::optional opacity() const noexcept { return nullopt; } // nullopt if never possible to be non-opaque [[nodiscard]] virtual luisa::optional eta() const noexcept { return nullopt; } // nullopt if never possible to be transmissive [[nodiscard]] virtual luisa::optional is_dispersive() const noexcept { return nullopt; }// nullopt if never possible to be dispersive [[nodiscard]] virtual const Interaction &it() const noexcept = 0; @@ -129,6 +128,10 @@ class Surface : public SceneNode { [[nodiscard]] auto &pipeline() const noexcept { return _pipeline; } [[nodiscard]] virtual bool maybe_non_opaque() const noexcept { return false; } + [[nodiscard]] virtual luisa::optional evaluate_opacity( + const Interaction &it, + const SampledWavelengths &swl, + Expr time) const noexcept { return luisa::nullopt; } void closure(PolymorphicCall &call, const Interaction &it, const SampledWavelengths &swl, @@ -162,62 +165,6 @@ class OpacitySurfaceWrapper : public BaseSurface { std::derived_from); public: - class Closure final : public Surface::Closure { - - private: - luisa::unique_ptr _base; - - public: - struct Context { - Float opacity; - }; - - public: - Closure(const Pipeline &pipeline, - const SampledWavelengths &swl, - Expr time, - luisa::unique_ptr base) noexcept - : Surface::Closure{pipeline, swl, time}, - _base{std::move(base)} {} - [[nodiscard]] auto base() const noexcept { return _base.get(); } - - public: - [[nodiscard]] SampledSpectrum albedo() const noexcept override { - return _base->albedo(); - } - [[nodiscard]] Float2 roughness() const noexcept override { - return _base->roughness(); - } - [[nodiscard]] const Interaction &it() const noexcept override { - return _base->it(); - } - [[nodiscard]] luisa::optional opacity() const noexcept override { - return context().opacity; - } - [[nodiscard]] optional eta() const noexcept override { - return _base->eta(); - } - [[nodiscard]] optional is_dispersive() const noexcept override { - return _base->is_dispersive(); - } - - public: - void pre_eval() noexcept override { _base->pre_eval(); } - void post_eval() noexcept override { _base->post_eval(); } - - private: - [[nodiscard]] Surface::Evaluation _evaluate(Expr wo, - Expr wi, - TransportMode mode) const noexcept override { - return _base->_evaluate(wo, wi, mode); - } - [[nodiscard]] Surface::Sample _sample(Expr wo, - Expr u_lobe, Expr u, - TransportMode mode) const noexcept override { - return _base->_sample(wo, u_lobe, u, mode); - } - }; - class Instance : public BaseInstance { private: @@ -227,39 +174,19 @@ class OpacitySurfaceWrapper : public BaseSurface { Instance(BaseInstance &&base, const Texture::Instance *opacity) noexcept : BaseInstance{std::move(base)}, _opacity{opacity} {} - public: - [[nodiscard]] luisa::string closure_identifier() const noexcept override { - auto base_identifier = BaseInstance::closure_identifier(); - if (_opacity == nullptr) { return base_identifier; } - return luisa::format("opacity<{}>", base_identifier); - } - [[nodiscard]] luisa::unique_ptr create_closure( - const SampledWavelengths &swl, Expr time) const noexcept override { - auto base = BaseInstance::create_closure(swl, time); - if (_opacity == nullptr) { return base; } - Closure cls{this->pipeline(), swl, time, std::move(base)}; - return luisa::make_unique(std::move(cls)); - } - void populate_closure(Surface::Closure *closure_in, const Interaction &it, - Expr wo, Expr eta_i) const noexcept override { - if (_opacity == nullptr) { - BaseInstance::populate_closure(closure_in, it, wo, eta_i); - return; - } - auto closure = static_cast(closure_in); - auto &swl = closure->swl(); - auto time = closure->time(); - BaseInstance::populate_closure(closure->base(), it, wo, eta_i); - auto o = _opacity->evaluate(it, swl, time).x; - typename Closure::Context ctx{.opacity = o}; - closure->bind(std::move(ctx)); - } - [[nodiscard]] bool maybe_non_opaque() const noexcept override { if (BaseInstance::maybe_non_opaque()) { return true; } return _opacity != nullptr && _opacity->node()->evaluate_static().value_or(make_float4(0.f)).x < 1.f; } + + [[nodiscard]] luisa::optional evaluate_opacity(const Interaction &it, + const SampledWavelengths &swl, + Expr time) const noexcept override { + if (!maybe_non_opaque()) { return luisa::nullopt; } + auto base_alpha = BaseInstance::evaluate_opacity(it, swl, time).value_or(1.f); + return base_alpha * _opacity->evaluate(it, swl, time).x; + } }; private: diff --git a/src/integrators/aov.cpp b/src/integrators/aov.cpp index e75aed6a..ac98abe0 100644 --- a/src/integrators/aov.cpp +++ b/src/integrators/aov.cpp @@ -329,49 +329,33 @@ void AuxiliaryBufferPathTracingInstance::_render_one_camera( if (auto dispersive = closure->is_dispersive()) { $if(*dispersive) { swl.terminate_secondary(); }; } - - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); - } - - $if(alpha_skip) { - ray = it->spawn_ray(ray->direction()); - pdf_bsdf = 1e16f; - } - $else { - - // direct lighting - $if(light_sample.eval.pdf > 0.0f & !occluded) { - auto wi = light_sample.shadow_ray->direction(); - auto eval = closure->evaluate(wo, wi); - auto w = balance_heuristic(light_sample.eval.pdf, eval.pdf) / - light_sample.eval.pdf; - Li += w * beta * eval.f * light_sample.eval.L; - $if(!specular_bounce) { - Li_diffuse += w * beta_diffuse * eval.f * light_sample.eval.L; - }; - }; - - // sample material - auto sample = closure->sample(wo, u_lobe, u_bsdf); - ray = it->spawn_ray(sample.wi); - pdf_bsdf = sample.eval.pdf; - auto w = ite(sample.eval.pdf > 0.f, 1.f / sample.eval.pdf, 0.f); - beta *= w * sample.eval.f; + // direct lighting + $if(light_sample.eval.pdf > 0.0f & !occluded) { + auto wi = light_sample.shadow_ray->direction(); + auto eval = closure->evaluate(wo, wi); + auto w = balance_heuristic(light_sample.eval.pdf, eval.pdf) / + light_sample.eval.pdf; + Li += w * beta * eval.f * light_sample.eval.L; $if(!specular_bounce) { - beta_diffuse *= w * sample.eval.f; + Li_diffuse += w * beta_diffuse * eval.f * light_sample.eval.L; }; + }; - // apply eta scale - auto eta = closure->eta().value_or(1.f); - $switch(sample.event) { - $case(Surface::event_enter) { eta_scale = sqr(eta); }; - $case(Surface::event_exit) { eta_scale = sqr(1.f / eta); }; - }; + // sample material + auto sample = closure->sample(wo, u_lobe, u_bsdf); + ray = it->spawn_ray(sample.wi); + pdf_bsdf = sample.eval.pdf; + auto w = ite(sample.eval.pdf > 0.f, 1.f / sample.eval.pdf, 0.f); + beta *= w * sample.eval.f; + $if(!specular_bounce) { + beta_diffuse *= w * sample.eval.f; + }; + + // apply eta scale + auto eta = closure->eta().value_or(1.f); + $switch(sample.event) { + $case(Surface::event_enter) { eta_scale = sqr(eta); }; + $case(Surface::event_exit) { eta_scale = sqr(1.f / eta); }; }; specular_bounce = all(closure->roughness() < .05f); }); diff --git a/src/integrators/direct.cpp b/src/integrators/direct.cpp index fdc9a83c..cb5fa6f4 100644 --- a/src/integrators/direct.cpp +++ b/src/integrators/direct.cpp @@ -135,41 +135,28 @@ class DirectLightingInstance final : public ProgressiveIntegrator::Instance { surface->closure(call, *it, swl, wo, 1.f, time); }); call.execute([&](auto closure) noexcept { - // apply opacity map - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); + // some preparations + if (auto dispersive = closure->is_dispersive()) { + $if(*dispersive) { swl.terminate_secondary(); }; } - - $if(alpha_skip) { - ray = it->spawn_ray(ray->direction()); - } - $else { - // some preparations - if (auto dispersive = closure->is_dispersive()) { - $if(*dispersive) { swl.terminate_secondary(); }; - } - // direct lighting - if (samples_lights) { - $if(light_sample.eval.pdf > 0.0f & !occluded) { - auto wi = light_sample.shadow_ray->direction(); - auto eval = closure->evaluate(wo, wi); - $if(eval.pdf > 0.f) { - auto w = def(1.f); - // MIS if sampling surfaces as well - if (samples_surfaces) { w = balance_heuristic(light_sample.eval.pdf, eval.pdf); } - Li += w * cs.weight * eval.f * light_sample.eval.L / light_sample.eval.pdf; - }; + // direct lighting + if (samples_lights) { + $if(light_sample.eval.pdf > 0.0f & !occluded) { + auto wi = light_sample.shadow_ray->direction(); + auto eval = closure->evaluate(wo, wi); + $if(eval.pdf > 0.f) { + auto w = def(1.f); + // MIS if sampling surfaces as well + if (samples_surfaces) { w = balance_heuristic(light_sample.eval.pdf, eval.pdf); } + Li += w * cs.weight * eval.f * light_sample.eval.L / light_sample.eval.pdf; }; - } - - // sample material - if (samples_surfaces) { - surface_sample = closure->sample(wo, u_lobe, u_bsdf); - ray = it->spawn_ray(surface_sample.wi); - } - }; + }; + } + // sample material + if (samples_surfaces) { + surface_sample = closure->sample(wo, u_lobe, u_bsdf); + ray = it->spawn_ray(surface_sample.wi); + } }); $if(!alpha_skip) { diff --git a/src/integrators/mega_vpt.cpp b/src/integrators/mega_vpt.cpp index 1ff91903..eca385f1 100644 --- a/src/integrators/mega_vpt.cpp +++ b/src/integrators/mega_vpt.cpp @@ -47,7 +47,7 @@ class MegakernelVolumePathTracingInstance final : public ProgressiveIntegrator:: "No lights in scene. Rendering aborted."); return; } -// pipeline().printer().set_log_dispatch_id(make_uint2(330, 770)); + // pipeline().printer().set_log_dispatch_id(make_uint2(330, 770)); Instance::_render_one_camera(command_buffer, camera); } @@ -474,15 +474,8 @@ class MegakernelVolumePathTracingInstance final : public ProgressiveIntegrator:: }); call.execute([&](auto closure) noexcept { // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); - } - UInt surface_event; - $if(alpha_skip | (medium_tag != medium_tracker.current().medium_tag)) { + $if(medium_tag != medium_tracker.current().medium_tag) { surface_event = surface_event_skip; ray = it->spawn_ray(ray->direction()); pdf_bsdf = 1e16f; diff --git a/src/integrators/mega_vpt_naive.cpp b/src/integrators/mega_vpt_naive.cpp index eefcab9a..77feb73f 100644 --- a/src/integrators/mega_vpt_naive.cpp +++ b/src/integrators/mega_vpt_naive.cpp @@ -60,8 +60,8 @@ class MegakernelVolumePathTracingNaiveInstance final : public ProgressiveIntegra "No lights in scene. Rendering aborted."); return; } -// pipeline().printer().set_level_warning(); -// pipeline().printer().set_log_dispatch_id(make_uint2(430, 350)); + // pipeline().printer().set_level_warning(); + // pipeline().printer().set_log_dispatch_id(make_uint2(430, 350)); Instance::_render_one_camera(command_buffer, camera); } @@ -151,19 +151,9 @@ class MegakernelVolumePathTracingNaiveInstance final : public ProgressiveIntegra surface->closure(call, *it, swl, wo, 1.f, time); }); call.execute([&](auto closure) noexcept { - // alpha skip - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - auto completely_opaque = opacity == 1.f; - transmittance.f = ite(completely_opaque, 0.f, transmittance.f); - transmittance.pdf = ite(completely_opaque, 1e16f, transmittance.pdf + 1.f / (1.f - opacity)); - } - // surface transmit - else { - auto surface_evaluation = closure->evaluate(wo, wi); - transmittance.f *= surface_evaluation.f; - transmittance.pdf += surface_evaluation.pdf; - } + auto surface_evaluation = closure->evaluate(wo, wi); + transmittance.f *= surface_evaluation.f; + transmittance.pdf += surface_evaluation.pdf; }); }; @@ -393,16 +383,8 @@ class MegakernelVolumePathTracingNaiveInstance final : public ProgressiveIntegra surface->closure(call, *it, swl, wo, eta, time); }); call.execute([&](auto closure) noexcept { - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); - } - UInt surface_event; - $if(alpha_skip | !medium_tracker.true_hit(medium_info.medium_tag)) { + $if(!medium_tracker.true_hit(medium_info.medium_tag)) { surface_event = surface_event_skip; ray = it->spawn_ray(ray->direction()); pdf_bsdf = 1e16f; diff --git a/src/integrators/megapm.cpp b/src/integrators/megapm.cpp index dda20b37..08821129 100644 --- a/src/integrators/megapm.cpp +++ b/src/integrators/megapm.cpp @@ -644,89 +644,75 @@ class MegakernelPhotonMappingInstance final : public ProgressiveIntegrator::Inst surface->closure(call, *it, swl, wo, 1.f, time); }); call.execute([&](auto closure) noexcept { - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); + if (auto dispersive = closure->is_dispersive()) { + $if(*dispersive) { swl.terminate_secondary(); }; } - - $if(alpha_skip) { - ray = it->spawn_ray(ray->direction()); - pdf_bsdf = 1e16f; + // direct lighting + if (node()->separate_direct()) { + $if(light_sample.eval.pdf > 0.0f & !occluded) { + auto wi = light_sample.shadow_ray->direction(); + auto eval = closure->evaluate(wo, wi); + auto w = balance_heuristic(light_sample.eval.pdf, eval.pdf) / + light_sample.eval.pdf; + Li += w * beta * eval.f * light_sample.eval.L; + }; } - $else { - if (auto dispersive = closure->is_dispersive()) { - $if(*dispersive) { swl.terminate_secondary(); }; - } - // direct lighting - if (node()->separate_direct()) { - $if(light_sample.eval.pdf > 0.0f & !occluded) { - auto wi = light_sample.shadow_ray->direction(); - auto eval = closure->evaluate(wo, wi); - auto w = balance_heuristic(light_sample.eval.pdf, eval.pdf) / - light_sample.eval.pdf; - Li += w * beta * eval.f * light_sample.eval.L; - }; - } - //TODO: get this done - auto roughness = closure->roughness(); - Bool stop_check; - if (node()->separate_direct()) { - stop_check = (roughness.x * roughness.y > 0.16f) | stop_direct; - } else { - stop_check = true;//always stop at first intersection - } - $if(stop_check) { - stop_direct = true; - auto grid = photons.point_to_grid(it->p()); - $for(x, grid.x - 1, grid.x + 2) { - $for(y, grid.y - 1, grid.y + 2) { - $for(z, grid.z - 1, grid.z + 2) { - Int3 check_grid{x, y, z}; - auto photon_index = photons.grid_head(photons.grid_to_index(check_grid)); - $while(photon_index != ~0u) { - auto position = photons.position(photon_index); - auto dis = distance(position, it->p()); - //pipeline().printer().info("check_grid:{},{},{};test_grid:{},{},{}; limit:{}", x, y, z, test_grid[0], test_grid[1], test_grid[2], indirect.radius(pixel_id)); - $if(dis <= indirect.radius(pixel_id)) { - auto photon_wi = photons.wi(photon_index); - auto photon_beta = photons.beta(photon_index); - auto test_grid = photons.point_to_grid(position); - auto eval_photon = closure->evaluate(wo, photon_wi); - auto wi_local = it->shading().world_to_local(photon_wi); - Float3 Phi; - if (!spectrum->node()->is_fixed()) { - auto photon_swl = photons.swl(photon_index); - Phi = spectrum->wavelength_mul(swl, beta * (eval_photon.f / abs_cos_theta(wi_local)), photon_swl, photon_beta); - } else { - Phi = spectrum->srgb(swl, beta * photon_beta * eval_photon.f / abs_cos_theta(wi_local)); - } - //testbeta += Phi; - indirect.add_phi(pixel_id, Phi); - indirect.add_cur_n(pixel_id, 1u); - //pipeline().printer().info("render:{}", indirect.cur_n(pixel_id)); - }; - - photon_index = photons.nxt(photon_index); + //TODO: get this done + auto roughness = closure->roughness(); + Bool stop_check; + if (node()->separate_direct()) { + stop_check = (roughness.x * roughness.y > 0.16f) | stop_direct; + } else { + stop_check = true;//always stop at first intersection + } + $if(stop_check) { + stop_direct = true; + auto grid = photons.point_to_grid(it->p()); + $for(x, grid.x - 1, grid.x + 2) { + $for(y, grid.y - 1, grid.y + 2) { + $for(z, grid.z - 1, grid.z + 2) { + Int3 check_grid{x, y, z}; + auto photon_index = photons.grid_head(photons.grid_to_index(check_grid)); + $while(photon_index != ~0u) { + auto position = photons.position(photon_index); + auto dis = distance(position, it->p()); + //pipeline().printer().info("check_grid:{},{},{};test_grid:{},{},{}; limit:{}", x, y, z, test_grid[0], test_grid[1], test_grid[2], indirect.radius(pixel_id)); + $if(dis <= indirect.radius(pixel_id)) { + auto photon_wi = photons.wi(photon_index); + auto photon_beta = photons.beta(photon_index); + auto test_grid = photons.point_to_grid(position); + auto eval_photon = closure->evaluate(wo, photon_wi); + auto wi_local = it->shading().world_to_local(photon_wi); + Float3 Phi; + if (!spectrum->node()->is_fixed()) { + auto photon_swl = photons.swl(photon_index); + Phi = spectrum->wavelength_mul(swl, beta * (eval_photon.f / abs_cos_theta(wi_local)), photon_swl, photon_beta); + } else { + Phi = spectrum->srgb(swl, beta * photon_beta * eval_photon.f / abs_cos_theta(wi_local)); + } + //testbeta += Phi; + indirect.add_phi(pixel_id, Phi); + indirect.add_cur_n(pixel_id, 1u); + //pipeline().printer().info("render:{}", indirect.cur_n(pixel_id)); }; + + photon_index = photons.nxt(photon_index); }; }; }; }; - // sample material - auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); - ray = it->spawn_ray(surface_sample.wi); - pdf_bsdf = surface_sample.eval.pdf; - auto w = ite(surface_sample.eval.pdf > 0.f, 1.f / surface_sample.eval.pdf, 0.f); - beta *= w * surface_sample.eval.f; - // apply eta scale - auto eta = closure->eta().value_or(1.f); - $switch(surface_sample.event) { - $case(Surface::event_enter) { eta_scale = sqr(eta); }; - $case(Surface::event_exit) { eta_scale = sqr(1.f / eta); }; - }; + }; + // sample material + auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); + ray = it->spawn_ray(surface_sample.wi); + pdf_bsdf = surface_sample.eval.pdf; + auto w = ite(surface_sample.eval.pdf > 0.f, 1.f / surface_sample.eval.pdf, 0.f); + beta *= w * surface_sample.eval.f; + // apply eta scale + auto eta = closure->eta().value_or(1.f); + $switch(surface_sample.event) { + $case(Surface::event_enter) { eta_scale = sqr(eta); }; + $case(Surface::event_exit) { eta_scale = sqr(1.f / eta); }; }; }); beta = zero_if_any_nan(beta); @@ -818,38 +804,24 @@ class MegakernelPhotonMappingInstance final : public ProgressiveIntegrator::Inst surface->closure(call, *it, swl, wi, 1.f, time); }); call.execute([&](auto closure) noexcept { - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); + if (auto dispersive = closure->is_dispersive()) { + $if(*dispersive) { swl.terminate_secondary(); }; } - $if(alpha_skip) { - ray = it->spawn_ray(ray->direction()); - pdf_bsdf = 1e16f; - } - $else { - if (auto dispersive = closure->is_dispersive()) { - $if(*dispersive) { swl.terminate_secondary(); }; - } - - // sample material - auto surface_sample = closure->sample(wi, u_lobe, u_bsdf, TransportMode::IMPORTANCE); - ray = it->spawn_ray(surface_sample.wi); - pdf_bsdf = surface_sample.eval.pdf; - auto w = ite(surface_sample.eval.pdf > 0.f, 1.f / surface_sample.eval.pdf, 0.f); - auto bnew = beta * w * surface_sample.eval.f; - // apply eta scale - auto eta = closure->eta().value_or(1.f); - $switch(surface_sample.event) { - $case(Surface::event_enter) { eta_scale = sqr(eta); }; - $case(Surface::event_exit) { eta_scale = sqr(1.f / eta); }; - }; - eta_scale *= ite(beta.max() < bnew.max(), 1.f, bnew.max() / beta.max()); - beta = bnew; + // sample material + auto surface_sample = closure->sample(wi, u_lobe, u_bsdf, TransportMode::IMPORTANCE); + ray = it->spawn_ray(surface_sample.wi); + pdf_bsdf = surface_sample.eval.pdf; + auto w = ite(surface_sample.eval.pdf > 0.f, 1.f / surface_sample.eval.pdf, 0.f); + auto bnew = beta * w * surface_sample.eval.f; + // apply eta scale + auto eta = closure->eta().value_or(1.f); + $switch(surface_sample.event) { + $case(Surface::event_enter) { eta_scale = sqr(eta); }; + $case(Surface::event_exit) { eta_scale = sqr(1.f / eta); }; }; + eta_scale *= ite(beta.max() < bnew.max(), 1.f, bnew.max() / beta.max()); + beta = bnew; }); beta = zero_if_any_nan(beta); $if(beta.all([](auto b) noexcept { return b <= 0.f; })) { $break; }; diff --git a/src/integrators/megawave.cpp b/src/integrators/megawave.cpp index 2711ca7b..1dd1acef 100644 --- a/src/integrators/megawave.cpp +++ b/src/integrators/megawave.cpp @@ -657,55 +657,41 @@ void MegakernelWaveFrontInstance::_render_one_camera( surface->closure(call, *it, swl, wo, 1.f, time); }); call.execute([&](const Surface::Closure *closure) noexcept { - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); - } - - $if(alpha_skip) { - ray = it->spawn_ray(ray->direction()); - path_state[path_id].pdf_bsdf = 1e16f; - } - $else { - if (auto dispersive = closure->is_dispersive()) { - $if(*dispersive) { - swl.terminate_secondary(); - if (!spectrum->node()->is_fixed()) { - path_state[path_id].wl_sample = -u_wl; - } - }; - } - // direct lighting - auto light_wi_and_pdf = path_state[path_id].wi_and_pdf; - auto pdf_light = light_wi_and_pdf.w; - $if(light_wi_and_pdf.w > 0.f) { - auto eval = closure->evaluate(wo, light_wi_and_pdf.xyz()); - auto mis_weight = balance_heuristic(pdf_light, eval.pdf); - // update Li - SampledSpectrum Ld{dim}; - for (auto i = 0u; i < dim; ++i) { - Ld[i] = path_state_dim[path_id * dim + i].emission; + if (auto dispersive = closure->is_dispersive()) { + $if(*dispersive) { + swl.terminate_secondary(); + if (!spectrum->node()->is_fixed()) { + path_state[path_id].wl_sample = -u_wl; } - auto Li = mis_weight / pdf_light * beta * eval.f * Ld; - auto pixel_id = path_state[path_id].pixel_index; - auto pixel_coord = make_uint2(pixel_id % resolution.x, pixel_id / resolution.x); - camera->film()->accumulate(pixel_coord, spectrum->srgb(swl, Li), 0.f); - }; - // sample material - auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); - path_state[path_id].pdf_bsdf = surface_sample.eval.pdf; - ray = it->spawn_ray(surface_sample.wi); - auto w = ite(surface_sample.eval.pdf > 0.0f, 1.f / surface_sample.eval.pdf, 0.f); - beta *= w * surface_sample.eval.f; - // eta scale - auto eta = closure->eta().value_or(1.f); - $switch(surface_sample.event) { - $case(Surface::event_enter) { eta_scale = sqr(eta); }; - $case(Surface::event_exit) { eta_scale = 1.f / sqr(eta); }; }; + } + // direct lighting + auto light_wi_and_pdf = path_state[path_id].wi_and_pdf; + auto pdf_light = light_wi_and_pdf.w; + $if(light_wi_and_pdf.w > 0.f) { + auto eval = closure->evaluate(wo, light_wi_and_pdf.xyz()); + auto mis_weight = balance_heuristic(pdf_light, eval.pdf); + // update Li + SampledSpectrum Ld{dim}; + for (auto i = 0u; i < dim; ++i) { + Ld[i] = path_state_dim[path_id * dim + i].emission; + } + auto Li = mis_weight / pdf_light * beta * eval.f * Ld; + auto pixel_id = path_state[path_id].pixel_index; + auto pixel_coord = make_uint2(pixel_id % resolution.x, pixel_id / resolution.x); + camera->film()->accumulate(pixel_coord, spectrum->srgb(swl, Li), 0.f); + }; + // sample material + auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); + path_state[path_id].pdf_bsdf = surface_sample.eval.pdf; + ray = it->spawn_ray(surface_sample.wi); + auto w = ite(surface_sample.eval.pdf > 0.0f, 1.f / surface_sample.eval.pdf, 0.f); + beta *= w * surface_sample.eval.f; + // eta scale + auto eta = closure->eta().value_or(1.f); + $switch(surface_sample.event) { + $case(Surface::event_enter) { eta_scale = sqr(eta); }; + $case(Surface::event_exit) { eta_scale = 1.f / sqr(eta); }; }; }); diff --git a/src/integrators/pssmlt.cpp b/src/integrators/pssmlt.cpp index 2bcc2247..4f87666a 100644 --- a/src/integrators/pssmlt.cpp +++ b/src/integrators/pssmlt.cpp @@ -398,42 +398,28 @@ class PSSMLTInstance final : public ProgressiveIntegrator::Instance { surface->closure(call, *it, swl, wo, 1.f, time); }); call.execute([&](auto closure) noexcept { - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); + if (auto dispersive = closure->is_dispersive()) { + $if(*dispersive) { swl.terminate_secondary(); }; } - - $if(alpha_skip) { - ray = it->spawn_ray(ray->direction()); - pdf_bsdf = 1e16f; - } - $else { - if (auto dispersive = closure->is_dispersive()) { - $if(*dispersive) { swl.terminate_secondary(); }; - } - // direct lighting - $if(light_sample.eval.pdf > 0.0f & !occluded) { - auto wi = light_sample.shadow_ray->direction(); - auto eval = closure->evaluate(wo, wi); - auto w = balance_heuristic(light_sample.eval.pdf, eval.pdf) / - light_sample.eval.pdf; - Li += w * beta * eval.f * light_sample.eval.L; - }; - // sample material - auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); - ray = it->spawn_ray(surface_sample.wi); - pdf_bsdf = surface_sample.eval.pdf; - auto w = ite(surface_sample.eval.pdf > 0.f, 1.f / surface_sample.eval.pdf, 0.f); - beta *= w * surface_sample.eval.f; - // apply eta scale - auto eta = closure->eta().value_or(1.f); - $switch(surface_sample.event) { - $case(Surface::event_enter) { eta_scale = sqr(eta); }; - $case(Surface::event_exit) { eta_scale = sqr(1.f / eta); }; - }; + // direct lighting + $if(light_sample.eval.pdf > 0.0f & !occluded) { + auto wi = light_sample.shadow_ray->direction(); + auto eval = closure->evaluate(wo, wi); + auto w = balance_heuristic(light_sample.eval.pdf, eval.pdf) / + light_sample.eval.pdf; + Li += w * beta * eval.f * light_sample.eval.L; + }; + // sample material + auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); + ray = it->spawn_ray(surface_sample.wi); + pdf_bsdf = surface_sample.eval.pdf; + auto w = ite(surface_sample.eval.pdf > 0.f, 1.f / surface_sample.eval.pdf, 0.f); + beta *= w * surface_sample.eval.f; + // apply eta scale + auto eta = closure->eta().value_or(1.f); + $switch(surface_sample.event) { + $case(Surface::event_enter) { eta_scale = sqr(eta); }; + $case(Surface::event_exit) { eta_scale = sqr(1.f / eta); }; }; }); beta = zero_if_any_nan(beta); diff --git a/src/integrators/wave_path_readback.cpp b/src/integrators/wave_path_readback.cpp index a0d118fe..04ff4362 100644 --- a/src/integrators/wave_path_readback.cpp +++ b/src/integrators/wave_path_readback.cpp @@ -409,49 +409,35 @@ void WavefrontPathTracingInstance::_render_one_camera( }); call.execute([&](const Surface::Closure *closure) noexcept { - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); - } - - $if(alpha_skip) { - ray = it->spawn_ray(ray->direction()); - path_states.write_pdf_bsdf(path_id, 1e16f); - } - $else { - if (auto dispersive = closure->is_dispersive()) { - $if(*dispersive) { - swl.terminate_secondary(); - path_states.terminate_secondary_wavelengths(path_id, u_wl); - }; - } - // direct lighting - auto light_wi_and_pdf = light_samples.read_wi_and_pdf(queue_id); - auto pdf_light = light_wi_and_pdf.w; - $if(light_wi_and_pdf.w > 0.f) { - auto eval = closure->evaluate(wo, light_wi_and_pdf.xyz()); - auto mis_weight = balance_heuristic(pdf_light, eval.pdf); - // update Li - auto Ld = light_samples.read_emission(queue_id); - auto Li = path_states.read_radiance(path_id); - Li += mis_weight / pdf_light * beta * eval.f * Ld; - path_states.write_radiance(path_id, Li); - }; - // sample material - auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); - path_states.write_pdf_bsdf(path_id, surface_sample.eval.pdf); - ray = it->spawn_ray(surface_sample.wi); - auto w = ite(surface_sample.eval.pdf > 0.0f, 1.f / surface_sample.eval.pdf, 0.f); - beta *= w * surface_sample.eval.f; - // eta scale - auto eta = closure->eta().value_or(1.f); - $switch(surface_sample.event) { - $case(Surface::event_enter) { eta_scale = sqr(eta); }; - $case(Surface::event_exit) { eta_scale = 1.f / sqr(eta); }; + if (auto dispersive = closure->is_dispersive()) { + $if(*dispersive) { + swl.terminate_secondary(); + path_states.terminate_secondary_wavelengths(path_id, u_wl); }; + } + // direct lighting + auto light_wi_and_pdf = light_samples.read_wi_and_pdf(queue_id); + auto pdf_light = light_wi_and_pdf.w; + $if(light_wi_and_pdf.w > 0.f) { + auto eval = closure->evaluate(wo, light_wi_and_pdf.xyz()); + auto mis_weight = balance_heuristic(pdf_light, eval.pdf); + // update Li + auto Ld = light_samples.read_emission(queue_id); + auto Li = path_states.read_radiance(path_id); + Li += mis_weight / pdf_light * beta * eval.f * Ld; + path_states.write_radiance(path_id, Li); + }; + // sample material + auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); + path_states.write_pdf_bsdf(path_id, surface_sample.eval.pdf); + ray = it->spawn_ray(surface_sample.wi); + auto w = ite(surface_sample.eval.pdf > 0.0f, 1.f / surface_sample.eval.pdf, 0.f); + beta *= w * surface_sample.eval.f; + // eta scale + auto eta = closure->eta().value_or(1.f); + $switch(surface_sample.event) { + $case(Surface::event_enter) { eta_scale = sqr(eta); }; + $case(Surface::event_exit) { eta_scale = 1.f / sqr(eta); }; }; }); diff --git a/src/integrators/wave_path_v2.cpp b/src/integrators/wave_path_v2.cpp index 01652fd7..9bea640a 100644 --- a/src/integrators/wave_path_v2.cpp +++ b/src/integrators/wave_path_v2.cpp @@ -762,54 +762,37 @@ void WavefrontPathTracingv2Instance::_render_one_camera( }); call.execute([&](const Surface::Closure *closure) noexcept { - - // apply opacity map - auto alpha_skip = def(false); - if (auto o = closure->opacity()) { - auto opacity = saturate(*o); - alpha_skip = u_lobe >= opacity; - u_lobe = ite(alpha_skip, (u_lobe - opacity) / (1.f - opacity), u_lobe / opacity); - } - - $if(alpha_skip) { - ray = it->spawn_ray(ray->direction()); - path_states.write_pdf_bsdf(path_id, 1e16f); - } - $else { - if (auto dispersive = closure->is_dispersive()) { - $if(*dispersive) { - swl.terminate_secondary(); - path_states.terminate_secondary_wavelengths(path_id, u_wl); - }; - } - // direct lighting - auto light_wi_and_pdf = light_samples.read_wi_and_pdf(path_id); - auto pdf_light = light_wi_and_pdf.w; - $if(light_wi_and_pdf.w > 0.f) { - auto eval = closure->evaluate(wo, light_wi_and_pdf.xyz()); - auto mis_weight = balance_heuristic(pdf_light, eval.pdf); - // update Li - auto Ld = light_samples.read_emission(path_id); - auto Li = mis_weight / pdf_light * beta * eval.f * Ld; - auto pixel_id = path_states.read_pixel_index(path_id); - auto pixel_coord = make_uint2(pixel_id % resolution.x, pixel_id / resolution.x); - camera->film()->accumulate(pixel_coord, spectrum->srgb(swl, Li), 0.f); - }; - // sample material - auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); - path_states.write_pdf_bsdf(path_id, surface_sample.eval.pdf); - ray = it->spawn_ray(surface_sample.wi); - auto w = ite(surface_sample.eval.pdf > 0.0f, 1.f / surface_sample.eval.pdf, 0.f); - beta *= w * surface_sample.eval.f; - // eta scale - auto eta = closure->eta().value_or(1.f); - $switch(surface_sample.event) { - $case(Surface::event_enter) { eta_scale = sqr(eta); }; - $case(Surface::event_exit) { eta_scale = 1.f / sqr(eta); }; + if (auto dispersive = closure->is_dispersive()) { + $if(*dispersive) { + swl.terminate_secondary(); + path_states.terminate_secondary_wavelengths(path_id, u_wl); }; + } + // direct lighting + auto light_wi_and_pdf = light_samples.read_wi_and_pdf(path_id); + auto pdf_light = light_wi_and_pdf.w; + $if(light_wi_and_pdf.w > 0.f) { + auto eval = closure->evaluate(wo, light_wi_and_pdf.xyz()); + auto mis_weight = balance_heuristic(pdf_light, eval.pdf); + // update Li + auto Ld = light_samples.read_emission(path_id); + auto Li = mis_weight / pdf_light * beta * eval.f * Ld; + auto pixel_id = path_states.read_pixel_index(path_id); + auto pixel_coord = make_uint2(pixel_id % resolution.x, pixel_id / resolution.x); + camera->film()->accumulate(pixel_coord, spectrum->srgb(swl, Li), 0.f); + }; + // sample material + auto surface_sample = closure->sample(wo, u_lobe, u_bsdf); + path_states.write_pdf_bsdf(path_id, surface_sample.eval.pdf); + ray = it->spawn_ray(surface_sample.wi); + auto w = ite(surface_sample.eval.pdf > 0.0f, 1.f / surface_sample.eval.pdf, 0.f); + beta *= w * surface_sample.eval.f; + // eta scale + auto eta = closure->eta().value_or(1.f); + $switch(surface_sample.event) { + $case(Surface::event_enter) { eta_scale = sqr(eta); }; + $case(Surface::event_exit) { eta_scale = 1.f / sqr(eta); }; }; - - }); // prepare for next bounce @@ -880,7 +863,7 @@ void WavefrontPathTracingv2Instance::_render_one_camera( auto slot = queue_size.atomic(0u).fetch_add(1u); queue.write(slot, path_id); };*/ - + auto slot = def(0u); { Shared index{1u}; @@ -1054,7 +1037,7 @@ void WavefrontPathTracingv2Instance::_render_one_camera( if (gathering) path_states.write_kernel_index(path_id, ite(condition, nxt1, nxt2)); /* $if(condition) { - + auto queue_id = queue_out1_size.atomic(0u).fetch_add(1u); //queue_out1.write(queue_id, path_id); } @@ -1222,7 +1205,7 @@ void WavefrontPathTracingv2Instance::_render_one_camera( command_buffer << gather_shader.get()(aqueue.index_buffer(INVALID), aqueue.counter_buffer(INVALID), INVALID, state_count) .dispatch(luisa::align(state_count, gather_shader.get().block_size().x)); } - + aqueue.clear_counter_buffer(command_buffer,INVALID); if (compact) { empty_queue.clear_counter_buffer(command_buffer); diff --git a/src/surfaces/layered.cpp b/src/surfaces/layered.cpp index 177b2212..f86f98d7 100644 --- a/src/surfaces/layered.cpp +++ b/src/surfaces/layered.cpp @@ -250,12 +250,6 @@ class LayeredSurfaceClosure : public Surface::Closure { return *top_dispersive | *bottom_dispersive; } [[nodiscard]] luisa::optional eta() const noexcept override { return _bottom->eta(); } - [[nodiscard]] luisa::optional opacity() const noexcept override { - auto top_opacity = _top->opacity(); - auto bottom_opacity = _bottom->opacity(); - return 1.f - ((1.f - top_opacity.value_or(1.f)) * - (1.f - bottom_opacity.value_or(1.f))); - } private: [[nodiscard]] Surface::Evaluation _evaluate(Expr wo, Expr wi, diff --git a/src/surfaces/mix.cpp b/src/surfaces/mix.cpp index 88566e9e..e5b37105 100644 --- a/src/surfaces/mix.cpp +++ b/src/surfaces/mix.cpp @@ -59,6 +59,15 @@ class MixSurfaceInstance : public Surface::Instance { [[nodiscard]] bool maybe_non_opaque() const noexcept override { return _a->maybe_non_opaque() || _b->maybe_non_opaque(); } + + [[nodiscard]] luisa::optional evaluate_opacity(const Interaction &it, + const SampledWavelengths &swl, + Expr time) const noexcept override { + if (!maybe_non_opaque()) { return luisa::nullopt; } + auto opacity_a = _a->evaluate_opacity(it, swl, time).value_or(1.f); + auto opacity_b = _b->evaluate_opacity(it, swl, time).value_or(1.f); + return opacity_a * opacity_b; + } }; luisa::unique_ptr MixSurface::_build( @@ -129,14 +138,6 @@ class MixSurfaceClosure : public Surface::Closure { } [[nodiscard]] const Interaction &it() const noexcept override { return context().it; } - [[nodiscard]] luisa::optional opacity() const noexcept override { - auto &&ctx = context(); - - auto opacity_a = a()->opacity(); - auto opacity_b = b()->opacity(); - if (!opacity_a && !opacity_b) { return luisa::nullopt; } - return lerp(opacity_b.value_or(1.f), opacity_a.value_or(1.f), ctx.ratio); - } [[nodiscard]] luisa::optional eta() const noexcept override { auto &&ctx = context();