Skip to content

Commit ae501ac

Browse files
committed
fix: half vector incorrect termination
1 parent 0d12543 commit ae501ac

1 file changed

Lines changed: 65 additions & 9 deletions

File tree

src/integrators/gpt.cpp

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,15 @@ class ImageBuffer {
241241
return v;
242242
}
243243

244+
auto read_effective_spp(Expr<uint2> p) noexcept {
245+
auto spp = def(0.f);
246+
if (_image) {
247+
auto index = p.y * _resolution.x + p.x;
248+
spp = _image->read(index * 4u + 3u);
249+
}
250+
return spp;
251+
}
252+
244253
void write(Expr<uint2> p, Expr<float3> value, Expr<float> effective_spp = 1.f) noexcept {
245254
if (_image) {
246255
auto index = p.y * _resolution.x + p.x;
@@ -687,6 +696,7 @@ luisa::unique_ptr<Integrator::Instance> GradientPathTracing::build(
687696
};
688697
}
689698
$else {
699+
// TODO: Check if this is correct
690700
shift_successful = false;
691701
};
692702
};
@@ -916,6 +926,7 @@ luisa::unique_ptr<Integrator::Instance> GradientPathTracing::build(
916926
};
917927
}
918928
$else {
929+
// TODO: Check if this is correct
919930
shifted.alive = false;
920931
};
921932
}
@@ -928,16 +939,12 @@ luisa::unique_ptr<Integrator::Instance> GradientPathTracing::build(
928939
// Deny shifts between Dirac and non-Dirac BSDFs. TODO
929940

930941
// TODO check if wo is wo
931-
// Combined closures
932942
auto shifted_bsdf_eta = def(0.f);// eta at previous main it
933-
auto outgoing_direction = shifted.it.shading().local_to_world(tangent_space_outgoing_direction);
934-
auto eval = Surface::Evaluation::zero(swl.dimension());
935943
pipeline().surfaces().dispatch(shifted.it.shape().surface_tag(), [&](auto surface) noexcept {
936944
PolymorphicCall<Surface::Closure> shifted_call;
937945
surface->closure(shifted_call, shifted.it, swl, -shifted.ray->direction(), 1.f, time);
938946
shifted_call.execute([&](auto closure) noexcept {
939947
shifted_bsdf_eta = closure->eta().value_or(1.f);
940-
eval = closure->evaluate(-shifted.ray->direction(), outgoing_direction);
941948
});
942949
});
943950

@@ -963,6 +970,16 @@ luisa::unique_ptr<Integrator::Instance> GradientPathTracing::build(
963970
shift_failed_flag = true;
964971
};
965972

973+
auto outgoing_direction = shifted.it.shading().local_to_world(tangent_space_outgoing_direction);
974+
auto eval = Surface::Evaluation::zero(swl.dimension());
975+
pipeline().surfaces().dispatch(shifted.it.shape().surface_tag(), [&](auto surface) noexcept {
976+
PolymorphicCall<Surface::Closure> shifted_call;
977+
surface->closure(shifted_call, shifted.it, swl, -shifted.ray->direction(), 1.f, time);
978+
shifted_call.execute([&](auto closure) noexcept {
979+
eval = closure->evaluate(-shifted.ray->direction(), outgoing_direction);
980+
});
981+
});
982+
966983
$if (!shift_failed_flag) {
967984
$if (eval.pdf <= 0.f) {
968985
// invalid path
@@ -1107,8 +1124,12 @@ void GradientPathTracingInstance::_render_one_camera(
11071124

11081125
luisa::unordered_map<luisa::string, luisa::unique_ptr<ImageBuffer>> image_buffers;
11091126
if (!node<GradientPathTracing>()->central_radiance()) {
1127+
image_buffers.emplace("gradient_x_single_frame", luisa::make_unique<ImageBuffer>(pipeline(), resolution));
1128+
image_buffers.emplace("gradient_y_single_frame", luisa::make_unique<ImageBuffer>(pipeline(), resolution));
11101129
image_buffers.emplace("gradient_x", luisa::make_unique<ImageBuffer>(pipeline(), resolution));
11111130
image_buffers.emplace("gradient_y", luisa::make_unique<ImageBuffer>(pipeline(), resolution));
1131+
image_buffers.emplace("gradient_x_variance", luisa::make_unique<ImageBuffer>(pipeline(), resolution));
1132+
image_buffers.emplace("gradient_y_variance", luisa::make_unique<ImageBuffer>(pipeline(), resolution));
11121133
}
11131134
// This is sum(x^2)/spp. if Var(mean(x)) is need, it is sum(x^2)/(n(n-1)) - mean(x)^2/(n-1)
11141135
image_buffers.emplace("variance", luisa::make_unique<ImageBuffer>(pipeline(), resolution));
@@ -1161,12 +1182,14 @@ void GradientPathTracingInstance::_render_one_camera(
11611182
for (int i = 0; i < 4; i++) {
11621183
// right/bottom -> center, left/top -> left/top
11631184
auto current_pixel = pixel_id + (i < 2 ? make_uint2(0) : pixel_shifts[i]);
1164-
auto key = i % 2 == 0 ? "gradient_x" : "gradient_y";
1185+
string key = i % 2 == 0 ? "gradient_x" : "gradient_y";
11651186
auto sign = i < 2 ? 1.f : -1.f;
11661187
$if (all(current_pixel >= 0u && current_pixel < resolution)) {
11671188
// Multiplied by 2 because MIS is used here
11681189
auto L = pipeline().spectrum()->srgb(eval.swl, sign * 2.f * (eval.gradients[i] - eval.very_direct));
1169-
image_buffers.at(key)->accumulate(current_pixel, shutter_weight * L, 1.f);
1190+
image_buffers.at(key + "_single_frame")->accumulate(current_pixel, shutter_weight * L, 1.f);
1191+
// image_buffers.at(key)->accumulate(current_pixel, shutter_weight * L, 1.f);
1192+
// image_buffers.at(key + "_variance")->accumulate(current_pixel, shutter_weight * L * L);
11701193
};
11711194
}
11721195
}
@@ -1184,6 +1207,16 @@ void GradientPathTracingInstance::_render_one_camera(
11841207
auto strength = max(max(max(abs_L.x, abs_L.y), abs_L.z), 0.f);
11851208
auto clamp_L = L * (threshold / max(strength, threshold));
11861209
image_buffers.at("variance")->accumulate(pixel_id, clamp_L * clamp_L);
1210+
1211+
// Gradient buffer accumulation
1212+
if (!node<GradientPathTracing>()->central_radiance()) {
1213+
for (int i = 0; i < 2; i++) {
1214+
string key = i == 0 ? "gradient_x" : "gradient_y";
1215+
auto L = image_buffers.at(key + "_single_frame")->read(pixel_id);
1216+
image_buffers.at(key)->accumulate(pixel_id, L);
1217+
image_buffers.at(key + "_variance")->accumulate(pixel_id, L * L);
1218+
}
1219+
}
11871220
};
11881221

11891222
Kernel2D finalize_var_kernel = [&]() noexcept {
@@ -1192,14 +1225,30 @@ void GradientPathTracingInstance::_render_one_camera(
11921225
auto n = static_cast<float>(spp);
11931226
auto mean_x = camera->film()->read(pixel_id).average; // mean(x) = 1/n * sum(x)
11941227
auto mean_x2 = image_buffers.at("variance")->read(pixel_id);// mean(x^2) = 1/n * sum(x^2)
1195-
auto var = (mean_x2 - mean_x * mean_x) / (n - 1.f); // var(x) = 1/(n-1) * (sum(x^2) - n * mean(x)^2)
1228+
auto var = n * (mean_x2 - mean_x * mean_x) / (n - 1.f); // var(x) = 1/(n-1) * (sum(x^2) - n * mean(x)^2)
11961229
image_buffers.at("variance")->write(pixel_id, max(var, 0.f));
11971230
};
11981231

1232+
Kernel2D finalize_gradient_var_kernel = [&]() noexcept {
1233+
set_block_size(16u, 16u, 1u);
1234+
auto pixel_id = dispatch_id().xy();
1235+
if (!node<GradientPathTracing>()->central_radiance()) {
1236+
for (int i = 0; i < 2; i++) {
1237+
string key = i == 0 ? "gradient_x" : "gradient_y";
1238+
auto mean_x = image_buffers.at(key)->read(pixel_id);
1239+
auto mean_x2 = image_buffers.at(key + "_variance")->read(pixel_id);
1240+
auto n = static_cast<float>(spp);
1241+
auto var = n * (mean_x2 - mean_x * mean_x) / (n - 1.f);
1242+
image_buffers.at(key + "_variance")->write(pixel_id, max(var, 0.f));
1243+
}
1244+
}
1245+
};
1246+
11991247
Clock clock_compile;
12001248
auto render = pipeline().device().compile(render_kernel);
12011249
auto accumulate = pipeline().device().compile(accumulate_kernel);
12021250
auto finalize_var = pipeline().device().compile(finalize_var_kernel);
1251+
auto finalize_gradient_var = pipeline().device().compile(finalize_gradient_var_kernel);
12031252
auto integrator_shader_compilation_time = clock_compile.toc();
12041253
LUISA_INFO("Integrator shader compile in {} ms.", integrator_shader_compilation_time);
12051254
auto shutter_samples = camera->node()->shutter_samples();
@@ -1216,6 +1265,10 @@ void GradientPathTracingInstance::_render_one_camera(
12161265
pipeline().update(command_buffer, s.point.time);
12171266
for (auto i = 0u; i < s.spp; i++) {
12181267
current_frame_buffer.clear(command_buffer);
1268+
if (!node<GradientPathTracing>()->central_radiance()) {
1269+
image_buffers.at("gradient_x_single_frame")->clear(command_buffer);
1270+
image_buffers.at("gradient_y_single_frame")->clear(command_buffer);
1271+
}
12191272
command_buffer << render(sample_id++, s.point.time, s.point.weight)
12201273
.dispatch(resolution)
12211274
<< accumulate().dispatch(resolution);
@@ -1232,8 +1285,11 @@ void GradientPathTracingInstance::_render_one_camera(
12321285
auto parent_path = camera->node()->file().parent_path();
12331286
auto filename = camera->node()->file().stem().string();
12341287
auto ext = camera->node()->file().extension().string();
1235-
command_buffer << finalize_var().dispatch(resolution)
1236-
<< synchronize();
1288+
command_buffer << finalize_var().dispatch(resolution);
1289+
if (!node<GradientPathTracing>()->central_radiance()) {
1290+
command_buffer << finalize_gradient_var().dispatch(resolution);
1291+
}
1292+
command_buffer << synchronize();
12371293
for (auto &[key, buffer] : image_buffers) {
12381294
auto path = parent_path / fmt::format("{}_{}{}", filename, key, ext);
12391295
command_buffer << buffer->save(command_buffer, path, key == "effective");

0 commit comments

Comments
 (0)