Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2016-10-22 16:59:23 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2016-10-22 17:37:26 +0300
commit9d0ac94d52268ff34ce645035d4315d6018d02b9 (patch)
tree407595f970a244fd186cc2de176f8897bf315da3 /intern/cycles/kernel/kernel_camera.h
parentb5d527ff6c7e01b73c14d8e01b7e33a697d30b12 (diff)
Fix T49750: Cycles wrong ray differentials for perspective and stereo cameras.
Diffstat (limited to 'intern/cycles/kernel/kernel_camera.h')
-rw-r--r--intern/cycles/kernel/kernel_camera.h145
1 files changed, 94 insertions, 51 deletions
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index ed9726e1b51..de3d70bc774 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -105,39 +105,61 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo
}
#endif
- float3 tP = transform_point(&cameratoworld, ray->P);
- float3 tD = transform_direction(&cameratoworld, ray->D);
- ray->P = spherical_stereo_position(kg, tD, tP);
- ray->D = spherical_stereo_direction(kg, tD, tP, ray->P);
+ ray->P = transform_point(&cameratoworld, ray->P);
+ ray->D = normalize(transform_direction(&cameratoworld, ray->D));
+ bool use_stereo = kernel_data.cam.interocular_offset != 0.0f;
+ if (!use_stereo) {
+ /* No stereo */
#ifdef __RAY_DIFFERENTIALS__
- /* ray differential */
- ray->dP = differential3_zero();
-
- float3 tD_diff = transform_direction(&cameratoworld, Pcamera);
- float3 Pdiff = spherical_stereo_position(kg, tD_diff, Pcamera);
- float3 Ddiff = spherical_stereo_direction(kg, tD_diff, Pcamera, Pdiff);
-
- tP = transform_perspective(&rastertocamera,
- make_float3(raster_x + 1.0f, raster_y, 0.0f));
- tD = tD_diff + float4_to_float3(kernel_data.cam.dx);
- Pcamera = spherical_stereo_position(kg, tD, tP);
- ray->dD.dx = spherical_stereo_direction(kg, tD, tP, Pcamera) - Ddiff;
- ray->dP.dx = Pcamera - Pdiff;
-
- tP = transform_perspective(&rastertocamera,
- make_float3(raster_x, raster_y + 1.0f, 0.0f));
- tD = tD_diff + float4_to_float3(kernel_data.cam.dy);
- Pcamera = spherical_stereo_position(kg, tD, tP);
- ray->dD.dy = spherical_stereo_direction(kg, tD, tP, Pcamera) - Ddiff;
- /* dP.dy is zero, since the omnidirectional panorama only shift the eyes horizontally */
+ float3 Dcenter = transform_direction(&cameratoworld, Pcamera);
+
+ ray->dP = differential3_zero();
+ ray->dD.dx = normalize(Dcenter + float4_to_float3(kernel_data.cam.dx)) - normalize(Dcenter);
+ ray->dD.dy = normalize(Dcenter + float4_to_float3(kernel_data.cam.dy)) - normalize(Dcenter);
+#endif
+ }
+ else {
+ /* Spherical stereo */
+ spherical_stereo_transform(kg, &ray->P, &ray->D);
+
+#ifdef __RAY_DIFFERENTIALS__
+ /* Ray differentials, computed from scratch using the raster coordinates
+ * because we don't want to be affected by depth of field. We compute
+ * ray origin and direction for the center and two neighbouring pixels
+ * and simply take their differences. */
+ float3 Pnostereo = transform_point(&cameratoworld, make_float3(0.0f, 0.0f, 0.0f));
+
+ float3 Pcenter = Pnostereo;
+ float3 Dcenter = Pcamera;
+ Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
+ spherical_stereo_transform(kg, &Pcenter, &Dcenter);
+
+ float3 Px = Pnostereo;
+ float3 Dx = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
+ Dx = normalize(transform_direction(&cameratoworld, Dx));
+ spherical_stereo_transform(kg, &Px, &Dx);
+
+ ray->dP.dx = Px - Pcenter;
+ ray->dD.dx = Dx - Dcenter;
+
+ float3 Py = Pnostereo;
+ float3 Dy = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
+ Dy = normalize(transform_direction(&cameratoworld, Dy));
+ spherical_stereo_transform(kg, &Py, &Dy);
+
+ ray->dP.dy = Py - Pcenter;
+ ray->dD.dy = Dy - Dcenter;
#endif
+ }
#ifdef __CAMERA_CLIPPING__
/* clipping */
- float3 Pclip = normalize(Pcamera);
- float z_inv = 1.0f / Pclip.z;
- ray->P += kernel_data.cam.nearclip*ray->D * z_inv;
+ float z_inv = 1.0f / normalize(Pcamera).z;
+ float nearclip = kernel_data.cam.nearclip * z_inv;
+ ray->P += nearclip * ray->D;
+ ray->dP.dx += nearclip * ray->dD.dx;
+ ray->dP.dy += nearclip * ray->dD.dy;
ray->t = kernel_data.cam.cliplength * z_inv;
#else
ray->t = FLT_MAX;
@@ -268,36 +290,57 @@ ccl_device_inline void camera_sample_panorama(KernelGlobals *kg,
}
#endif
- float3 tP = transform_point(&cameratoworld, ray->P);
- float3 tD = transform_direction(&cameratoworld, ray->D);
- ray->P = spherical_stereo_position(kg, tD, tP);
- ray->D = spherical_stereo_direction(kg, tD, tP, ray->P);
+ ray->P = transform_point(&cameratoworld, ray->P);
+ ray->D = normalize(transform_direction(&cameratoworld, ray->D));
+
+ /* Stereo transform */
+ bool use_stereo = kernel_data.cam.interocular_offset != 0.0f;
+ if (use_stereo) {
+ spherical_stereo_transform(kg, &ray->P, &ray->D);
+ }
#ifdef __RAY_DIFFERENTIALS__
- /* ray differential */
- ray->dP = differential3_zero();
-
- tP = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
- tD = transform_direction(&cameratoworld, panorama_to_direction(kg, tP.x, tP.y));
- float3 Pdiff = spherical_stereo_position(kg, tD, tP);
- float3 Ddiff = spherical_stereo_direction(kg, tD, tP, Pdiff);
-
- tP = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
- tD = transform_direction(&cameratoworld, panorama_to_direction(kg, tP.x, tP.y));
- Pcamera = spherical_stereo_position(kg, tD, tP);
- ray->dD.dx = spherical_stereo_direction(kg, tD, tP, Pcamera) - Ddiff;
- ray->dP.dx = Pcamera - Pdiff;
-
- tP = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
- tD = transform_direction(&cameratoworld, panorama_to_direction(kg, tP.x, tP.y));
- Pcamera = spherical_stereo_position(kg, tD, tP);
- ray->dD.dy = spherical_stereo_direction(kg, tD, tP, Pcamera) - Ddiff;
- /* dP.dy is zero, since the omnidirectional panorama only shift the eyes horizontally */
+ /* Ray differentials, computed from scratch using the raster coordinates
+ * because we don't want to be affected by depth of field. We compute
+ * ray origin and direction for the center and two neighbouring pixels
+ * and simply take their differences. */
+ float3 Pcenter = Pcamera;
+ float3 Dcenter = panorama_to_direction(kg, Pcenter.x, Pcenter.y);
+ Pcenter = transform_point(&cameratoworld, Pcenter);
+ Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
+ if (use_stereo) {
+ spherical_stereo_transform(kg, &Pcenter, &Dcenter);
+ }
+
+ float3 Px = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
+ float3 Dx = panorama_to_direction(kg, Px.x, Px.y);
+ Px = transform_point(&cameratoworld, Px);
+ Dx = normalize(transform_direction(&cameratoworld, Dx));
+ if (use_stereo) {
+ spherical_stereo_transform(kg, &Px, &Dx);
+ }
+
+ ray->dP.dx = Px - Pcenter;
+ ray->dD.dx = Dx - Dcenter;
+
+ float3 Py = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
+ float3 Dy = panorama_to_direction(kg, Py.x, Py.y);
+ Py = transform_point(&cameratoworld, Py);
+ Dy = normalize(transform_direction(&cameratoworld, Dy));
+ if (use_stereo) {
+ spherical_stereo_transform(kg, &Py, &Dy);
+ }
+
+ ray->dP.dy = Py - Pcenter;
+ ray->dD.dy = Dy - Dcenter;
#endif
#ifdef __CAMERA_CLIPPING__
/* clipping */
- ray->P += kernel_data.cam.nearclip*ray->D;
+ float nearclip = kernel_data.cam.nearclip;
+ ray->P += nearclip * ray->D;
+ ray->dP.dx += nearclip * ray->dD.dx;
+ ray->dP.dy += nearclip * ray->dD.dy;
ray->t = kernel_data.cam.cliplength;
#else
ray->t = FLT_MAX;