Fix #56355: Cycles: Wrong differentials for panoramic camera

The code to compute differentials mixed up the camera-space locations
of the raster coordinate and the camera itself, which caused the dP
differential to be set even when the ray origin is always the same.

This commit fixes that, reorganizes the code so that the Px/Py are
no longer used for both values to avoid future confusion, and skips
some unnecessary calculations stereo rendering isn't being used.
This commit is contained in:
Lukas Stockner 2024-03-24 17:20:16 +01:00
parent aa87b747c5
commit 1f44be97e6
2 changed files with 35 additions and 31 deletions

View File

@ -224,18 +224,23 @@ ccl_device void camera_sample_orthographic(KernelGlobals kg,
/* Panorama Camera */
ccl_device_inline float3 camera_panorama_direction(ccl_constant KernelCamera *cam,
float x,
float y)
{
float3 Pcamera = transform_perspective(&cam->rastertocamera, make_float3(x, y, 0.0f));
return panorama_to_direction(cam, Pcamera.x, Pcamera.y);
}
ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
ccl_global const DecomposedTransform *cam_motion,
const float2 raster,
const float2 rand_lens,
ccl_private Ray *ray)
{
ProjectionTransform rastertocamera = cam->rastertocamera;
float3 Pcamera = transform_perspective(&rastertocamera, float2_to_float3(raster));
/* create ray form raster position */
float3 P = zero_float3();
float3 D = panorama_to_direction(cam, Pcamera.x, Pcamera.y);
float3 D = camera_panorama_direction(cam, raster.x, raster.y);
/* indicates ray should not receive any light, outside of the lens */
if (is_zero(D)) {
@ -246,6 +251,11 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
/* modify ray for depth of field */
float aperturesize = cam->aperturesize;
#ifdef __RAY_DIFFERENTIALS__
/* keep pre-DoF value for differentials later */
float3 Dcenter = D;
#endif
if (aperturesize > 0.0f) {
/* sample point on aperture */
float2 lens_uv = camera_sample_aperture(cam, rand_lens) * aperturesize;
@ -289,38 +299,32 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
* because we don't want to be affected by depth of field. We compute
* ray origin and direction for the center and two neighboring pixels
* and simply take their differences. */
float3 Pcenter = Pcamera;
float3 Dcenter = panorama_to_direction(cam, Pcenter.x, Pcenter.y);
float3 Dx = camera_panorama_direction(cam, raster.x + 1.0f, raster.y);
float3 Dy = camera_panorama_direction(cam, raster.x, raster.y + 1.0f);
if (use_stereo) {
float3 Pcenter = zero_float3();
float3 Px = zero_float3();
float3 Py = zero_float3();
spherical_stereo_transform(cam, &Pcenter, &Dcenter);
}
Pcenter = transform_point(&cameratoworld, Pcenter);
Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
float3 Px = transform_perspective(&rastertocamera, make_float3(raster.x + 1.0f, raster.y, 0.0f));
float3 Dx = panorama_to_direction(cam, Px.x, Px.y);
if (use_stereo) {
spherical_stereo_transform(cam, &Px, &Dx);
}
Px = transform_point(&cameratoworld, Px);
Dx = normalize(transform_direction(&cameratoworld, Dx));
differential3 dP, dD;
dP.dx = Px - Pcenter;
dD.dx = Dx - Dcenter;
float3 Py = transform_perspective(&rastertocamera, make_float3(raster.x, raster.y + 1.0f, 0.0f));
float3 Dy = panorama_to_direction(cam, Py.x, Py.y);
if (use_stereo) {
spherical_stereo_transform(cam, &Py, &Dy);
}
Py = transform_point(&cameratoworld, Py);
Dy = normalize(transform_direction(&cameratoworld, Dy));
dP.dy = Py - Pcenter;
dD.dy = Dy - Dcenter;
differential3 dP;
Pcenter = transform_point(&cameratoworld, Pcenter);
dP.dx = transform_point(&cameratoworld, Px) - Pcenter;
dP.dy = transform_point(&cameratoworld, Py) - Pcenter;
ray->dP = differential_make_compact(dP);
}
else {
ray->dP = differential_zero_compact();
}
differential3 dD;
Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
dD.dx = normalize(transform_direction(&cameratoworld, Dx)) - Dcenter;
dD.dy = normalize(transform_direction(&cameratoworld, Dy)) - Dcenter;
ray->dD = differential_make_compact(dD);
ray->dP = differential_make_compact(dP);
#endif
/* clipping */

@ -1 +1 @@
Subproject commit 5e21b8c590ae0375da698df2ec4319055acd438d
Subproject commit b9accb676b11fdf7b99253fa82b475b58c98d73e