Disk and Cylinder stored the phimax parameter raw. It arrives in degrees, while PBRT does radians. This one is embarassing, was causing 50x exposure

This commit is contained in:
Wito Wiala 2026-09-02 21:59:38 +01:00
parent 4faa3cdc95
commit 1b1344c393
2 changed files with 12 additions and 6 deletions

View file

@ -14,7 +14,7 @@ use crate::{gamma, Float, PI};
use crate::core::geometry::{SqrtExt, Tuple}; use crate::core::geometry::{SqrtExt, Tuple};
use crate::utils::interval::Interval; use crate::utils::interval::Interval;
use crate::utils::math::{clamp, difference_of_products, lerp, square}; use crate::utils::math::{clamp, difference_of_products, lerp, radians, square};
use core::mem; use core::mem;
use num_traits::Float as NumFloat; use num_traits::Float as NumFloat;
@ -43,9 +43,11 @@ impl CylinderShape {
) -> Self { ) -> Self {
Self { Self {
radius, radius,
z_min, // pbrt: `zMin(std::min(zMin, zMax)), zMax(std::max(zMin, zMax)),
z_max, // phiMax(Radians(Clamp(phiMax, 0, 360)))`. phiMax arrives in DEGREES.
phi_max, z_min: z_min.min(z_max),
z_max: z_min.max(z_max),
phi_max: radians(clamp(phi_max, 0., 360.)),
render_from_object, render_from_object,
object_from_render, object_from_render,
reverse_orientation, reverse_orientation,

View file

@ -7,7 +7,7 @@ use crate::core::shape::{
QuadricIntersection, ShapeIntersection, ShapeSample, ShapeSampleContext, ShapeTrait, QuadricIntersection, ShapeIntersection, ShapeSample, ShapeSampleContext, ShapeTrait,
}; };
use crate::utils::interval::Interval; use crate::utils::interval::Interval;
use crate::utils::math::square; use crate::utils::math::{clamp, radians, square};
use crate::utils::sampling::sample_uniform_disk_concentric; use crate::utils::sampling::sample_uniform_disk_concentric;
use crate::utils::Transform; use crate::utils::Transform;
use crate::{Float, PI}; use crate::{Float, PI};
@ -40,7 +40,11 @@ impl DiskShape {
radius, radius,
inner_radius, inner_radius,
height, height,
phi_max, // pbrt: `phiMax(Radians(Clamp(phiMax, 0, 360)))`. The parameter arrives in
// DEGREES (default 360); storing it raw made `area()` 360/2pi = 57.3x too
// large, so the sampling pdf was 57.3x too small and every direct-lighting
// contribution from a disk area light was 57.3x too bright.
phi_max: radians(clamp(phi_max, 0., 360.)),
render_from_object: render_from_object.clone(), render_from_object: render_from_object.clone(),
object_from_render, object_from_render,
reverse_orientation, reverse_orientation,