Blender  V3.3
differential.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #pragma once
5 
7 
8 /* See "Tracing Ray Differentials", Homan Igehy, 1999. */
9 
11  const differential3 ray_dP,
12  float3 ray_D,
13  const differential3 ray_dD,
14  float3 surface_Ng,
15  float ray_t)
16 {
17  /* ray differential transfer through homogeneous medium, to
18  * compute dPdx/dy at a shading point from the incoming ray */
19 
20  float3 tmp = ray_D / dot(ray_D, surface_Ng);
21  float3 tmpx = ray_dP.dx + ray_t * ray_dD.dx;
22  float3 tmpy = ray_dP.dy + ray_t * ray_dD.dy;
23 
24  surface_dP->dx = tmpx - dot(tmpx, surface_Ng) * tmp;
25  surface_dP->dy = tmpy - dot(tmpy, surface_Ng) * tmp;
26 }
27 
29 {
30  /* compute dIdx/dy at a shading point, we just need to negate the
31  * differential of the ray direction */
32 
33  dI->dx = -dD.dx;
34  dI->dy = -dD.dy;
35 }
36 
39  float3 dPdu,
40  float3 dPdv,
41  differential3 dP,
42  float3 Ng)
43 {
44  /* now we have dPdx/dy from the ray differential transfer, and dPdu/dv
45  * from the primitive, we can compute dudx/dy and dvdx/dy. these are
46  * mainly used for differentials of arbitrary mesh attributes. */
47 
48  /* find most stable axis to project to 2D */
49  float xn = fabsf(Ng.x);
50  float yn = fabsf(Ng.y);
51  float zn = fabsf(Ng.z);
52 
53  if (zn < xn || zn < yn) {
54  if (yn < xn || yn < zn) {
55  dPdu.x = dPdu.y;
56  dPdv.x = dPdv.y;
57  dP.dx.x = dP.dx.y;
58  dP.dy.x = dP.dy.y;
59  }
60 
61  dPdu.y = dPdu.z;
62  dPdv.y = dPdv.z;
63  dP.dx.y = dP.dx.z;
64  dP.dy.y = dP.dy.z;
65  }
66 
67  /* using Cramer's rule, we solve for dudx and dvdx in a 2x2 linear system,
68  * and the same for dudy and dvdy. the denominator is the same for both
69  * solutions, so we compute it only once.
70  *
71  * dP.dx = dPdu * dudx + dPdv * dvdx;
72  * dP.dy = dPdu * dudy + dPdv * dvdy; */
73 
74  float det = (dPdu.x * dPdv.y - dPdv.x * dPdu.y);
75 
76  if (det != 0.0f)
77  det = 1.0f / det;
78 
79  du->dx = (dP.dx.x * dPdv.y - dP.dx.y * dPdv.x) * det;
80  dv->dx = (dP.dx.y * dPdu.x - dP.dx.x * dPdu.y) * det;
81 
82  du->dy = (dP.dy.x * dPdv.y - dP.dy.y * dPdv.x) * det;
83  dv->dy = (dP.dy.y * dPdu.x - dP.dy.x * dPdu.y) * det;
84 }
85 
87 {
88  differential d;
89  d.dx = 0.0f;
90  d.dy = 0.0f;
91 
92  return d;
93 }
94 
96 {
97  differential3 d;
98  d.dx = zero_float3();
99  d.dy = zero_float3();
100 
101  return d;
102 }
103 
104 /* Compact ray differentials that are just a scale to reduce memory usage and
105  * access cost in GPU.
106  *
107  * See above for more accurate reference implementations.
108  *
109  * TODO: also store the more compact version in ShaderData and recompute where
110  * needed? */
111 
113 {
114  return 0.0f;
115 }
116 
118 {
119  return 0.5f * (len(D.dx) + len(D.dy));
120 }
121 
123  const float ray_dP,
124  const float3 /* ray_D */,
125  const float ray_dD,
126  const float3 surface_Ng,
127  const float ray_t)
128 {
129  /* ray differential transfer through homogeneous medium, to
130  * compute dPdx/dy at a shading point from the incoming ray */
131  float scale = ray_dP + ray_t * ray_dD;
132 
133  float3 dx, dy;
134  make_orthonormals(surface_Ng, &dx, &dy);
135  surface_dP->dx = dx * scale;
136  surface_dP->dy = dy * scale;
137 }
138 
140  const float3 D,
141  const float dD)
142 {
143  /* compute dIdx/dy at a shading point, we just need to negate the
144  * differential of the ray direction */
145 
146  float3 dx, dy;
147  make_orthonormals(D, &dx, &dy);
148 
149  dI->dx = dD * dx;
150  dI->dy = dD * dy;
151 }
152 
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
ccl_device void differential_dudv(ccl_private differential *du, ccl_private differential *dv, float3 dPdu, float3 dPdv, differential3 dP, float3 Ng)
Definition: differential.h:37
ccl_device_forceinline void differential_incoming_compact(ccl_private differential3 *dI, const float3 D, const float dD)
Definition: differential.h:139
ccl_device_forceinline void differential_transfer_compact(ccl_private differential3 *surface_dP, const float ray_dP, const float3, const float ray_dD, const float3 surface_Ng, const float ray_t)
Definition: differential.h:122
ccl_device differential differential_zero()
Definition: differential.h:86
ccl_device_forceinline float differential_make_compact(const differential3 D)
Definition: differential.h:117
ccl_device differential3 differential3_zero()
Definition: differential.h:95
CCL_NAMESPACE_BEGIN ccl_device void differential_transfer(ccl_private differential3 *surface_dP, const differential3 ray_dP, float3 ray_D, const differential3 ray_dD, float3 surface_Ng, float ray_t)
Definition: differential.h:10
ccl_device_forceinline float differential_zero_compact()
Definition: differential.h:112
ccl_device void differential_incoming(ccl_private differential3 *dI, const differential3 dD)
Definition: differential.h:28
int len
Definition: draw_manager.c:108
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
#define fabsf(x)
Definition: metal/compat.h:219
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
float z
float y
float x
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
Definition: util/math.h:566
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:13