Blender  V3.3
cycles/kernel/camera/projection.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Parts adapted from Open Shading Language with this license:
3  *
4  * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
5  * All Rights Reserved.
6  *
7  * Modifications Copyright 2011-2022 Blender Foundation. */
8 
9 #pragma once
10 
12 
13 /* Spherical coordinates <-> Cartesian direction. */
14 
16 {
17  float theta = safe_acosf(dir.z);
18  float phi = atan2f(dir.x, dir.y);
19 
20  return make_float2(theta, phi);
21 }
22 
23 ccl_device float3 spherical_to_direction(float theta, float phi)
24 {
25  float sin_theta = sinf(theta);
26  return make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cosf(theta));
27 }
28 
29 /* Equirectangular coordinates <-> Cartesian direction */
30 
32 {
33  if (is_zero(dir))
34  return zero_float2();
35 
36  float u = (atan2f(dir.y, dir.x) - range.y) / range.x;
37  float v = (acosf(dir.z / len(dir)) - range.w) / range.z;
38 
39  return make_float2(u, v);
40 }
41 
43 {
44  float phi = range.x * u + range.y;
45  float theta = range.z * v + range.w;
46  float sin_theta = sinf(theta);
47  return make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cosf(theta));
48 }
49 
51 {
53 }
54 
56 {
58 }
59 
60 /* Fisheye <-> Cartesian direction */
61 
63 {
64  float r = atan2f(sqrtf(dir.y * dir.y + dir.z * dir.z), dir.x) / fov;
65  float phi = atan2f(dir.z, dir.y);
66 
67  float u = r * cosf(phi) + 0.5f;
68  float v = r * sinf(phi) + 0.5f;
69 
70  return make_float2(u, v);
71 }
72 
73 ccl_device float3 fisheye_to_direction(float u, float v, float fov)
74 {
75  u = (u - 0.5f) * 2.0f;
76  v = (v - 0.5f) * 2.0f;
77 
78  float r = sqrtf(u * u + v * v);
79 
80  if (r > 1.0f)
81  return zero_float3();
82 
83  float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
84  float theta = r * fov * 0.5f;
85 
86  if (v < 0.0f)
87  phi = -phi;
88 
89  return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
90 }
91 
93 {
94  float theta = safe_acosf(dir.x);
95  float r = 2.0f * lens * sinf(theta * 0.5f);
96  float phi = atan2f(dir.z, dir.y);
97 
98  float u = r * cosf(phi) / width + 0.5f;
99  float v = r * sinf(phi) / height + 0.5f;
100 
101  return make_float2(u, v);
102 }
103 
105 fisheye_equisolid_to_direction(float u, float v, float lens, float fov, float width, float height)
106 {
107  u = (u - 0.5f) * width;
108  v = (v - 0.5f) * height;
109 
110  float rmax = 2.0f * lens * sinf(fov * 0.25f);
111  float r = sqrtf(u * u + v * v);
112 
113  if (r > rmax)
114  return zero_float3();
115 
116  float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
117  float theta = 2.0f * asinf(r / (2.0f * lens));
118 
119  if (v < 0.0f)
120  phi = -phi;
121 
122  return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
123 }
124 
126  float u, float v, float coeff0, float4 coeffs, float fov, float width, float height)
127 {
128  u = (u - 0.5f) * width;
129  v = (v - 0.5f) * height;
130 
131  float r = sqrtf(u * u + v * v);
132  float r2 = r * r;
133  float4 rr = make_float4(r, r2, r2 * r, r2 * r2);
134  float theta = -(coeff0 + dot(coeffs, rr));
135 
136  if (fabsf(theta) > 0.5f * fov)
137  return zero_float3();
138 
139  float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
140 
141  if (v < 0.0f)
142  phi = -phi;
143 
144  return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
145 }
146 
148  float3 dir, float coeff0, float4 coeffs, float width, float height)
149 {
150  float theta = -safe_acosf(dir.x);
151 
152  float r = (theta - coeff0) / coeffs.x;
153 
154  for (int i = 0; i < 20; i++) {
155  float r2 = r * r;
156  float4 rr = make_float4(r, r2, r2 * r, r2 * r2);
157  r = (theta - (coeff0 + dot(coeffs, rr))) / coeffs.x;
158  }
159 
160  float phi = atan2f(dir.z, dir.y);
161 
162  float u = r * cosf(phi) / width + 0.5f;
163  float v = r * sinf(phi) / height + 0.5f;
164 
165  return make_float2(u, v);
166 }
167 
168 /* Mirror Ball <-> Cartesion direction */
169 
171 {
172  /* point on sphere */
173  float3 dir;
174 
175  dir.x = 2.0f * u - 1.0f;
176  dir.z = 2.0f * v - 1.0f;
177 
178  if (dir.x * dir.x + dir.z * dir.z > 1.0f)
179  return zero_float3();
180 
181  dir.y = -sqrtf(max(1.0f - dir.x * dir.x - dir.z * dir.z, 0.0f));
182 
183  /* reflection */
184  float3 I = make_float3(0.0f, -1.0f, 0.0f);
185 
186  return 2.0f * dot(dir, I) * dir - I;
187 }
188 
190 {
191  /* inverse of mirrorball_to_direction */
192  dir.y -= 1.0f;
193 
194  float div = 2.0f * sqrtf(max(-0.5f * dir.y, 0.0f));
195  if (div > 0.0f)
196  dir /= div;
197 
198  float u = 0.5f * (dir.x + 1.0f);
199  float v = 0.5f * (dir.z + 1.0f);
200 
201  return make_float2(u, v);
202 }
203 
205 {
206  switch (cam->panorama_type) {
208  return equirectangular_range_to_direction(u, v, cam->equirectangular_range);
209  case PANORAMA_MIRRORBALL:
210  return mirrorball_to_direction(u, v);
212  return fisheye_to_direction(u, v, cam->fisheye_fov);
215  v,
216  cam->fisheye_lens_polynomial_bias,
217  cam->fisheye_lens_polynomial_coefficients,
218  cam->fisheye_fov,
219  cam->sensorwidth,
220  cam->sensorheight);
222  default:
224  u, v, cam->fisheye_lens, cam->fisheye_fov, cam->sensorwidth, cam->sensorheight);
225  }
226 }
227 
229 {
230  switch (cam->panorama_type) {
232  return direction_to_equirectangular_range(dir, cam->equirectangular_range);
233  case PANORAMA_MIRRORBALL:
234  return direction_to_mirrorball(dir);
236  return direction_to_fisheye(dir, cam->fisheye_fov);
239  cam->fisheye_lens_polynomial_bias,
240  cam->fisheye_lens_polynomial_coefficients,
241  cam->sensorwidth,
242  cam->sensorheight);
244  default:
246  dir, cam->fisheye_lens, cam->sensorwidth, cam->sensorheight);
247  }
248 }
249 
253 {
254  float interocular_offset = cam->interocular_offset;
255 
256  /* Interocular offset of zero means either non stereo, or stereo without
257  * spherical stereo. */
258  kernel_assert(interocular_offset != 0.0f);
259 
260  if (cam->pole_merge_angle_to > 0.0f) {
261  const float pole_merge_angle_from = cam->pole_merge_angle_from,
262  pole_merge_angle_to = cam->pole_merge_angle_to;
263  float altitude = fabsf(safe_asinf((*D).z));
264  if (altitude > pole_merge_angle_to) {
265  interocular_offset = 0.0f;
266  }
267  else if (altitude > pole_merge_angle_from) {
268  float fac = (altitude - pole_merge_angle_from) /
269  (pole_merge_angle_to - pole_merge_angle_from);
270  float fade = cosf(fac * M_PI_2_F);
271  interocular_offset *= fade;
272  }
273  }
274 
275  float3 up = make_float3(0.0f, 0.0f, 1.0f);
276  float3 side = normalize(cross(*D, up));
277  float3 stereo_offset = side * interocular_offset;
278 
279  *P += stereo_offset;
280 
281  /* Convergence distance is FLT_MAX in the case of parallel convergence mode,
282  * no need to modify direction in this case either. */
283  const float convergence_distance = cam->convergence_distance;
284 
285  if (convergence_distance != FLT_MAX) {
286  float3 screen_offset = convergence_distance * (*D);
287  *D = normalize(screen_offset - stereo_offset);
288  }
289 }
290 
MINLINE float safe_acosf(float a)
MINLINE float safe_asinf(float a)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
float float4[4]
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_constant
Definition: cuda/compat.h:46
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
ccl_device float2 direction_to_fisheye(float3 dir, float fov)
ccl_device float3 fisheye_to_direction(float u, float v, float fov)
ccl_device float2 direction_to_mirrorball(float3 dir)
ccl_device float2 direction_to_fisheye_lens_polynomial(float3 dir, float coeff0, float4 coeffs, float width, float height)
CCL_NAMESPACE_BEGIN ccl_device float2 direction_to_spherical(float3 dir)
ccl_device_inline float3 panorama_to_direction(ccl_constant KernelCamera *cam, float u, float v)
ccl_device float2 direction_to_equirectangular_range(float3 dir, float4 range)
ccl_device_inline void spherical_stereo_transform(ccl_constant KernelCamera *cam, ccl_private float3 *P, ccl_private float3 *D)
ccl_device_inline float2 direction_to_panorama(ccl_constant KernelCamera *cam, float3 dir)
ccl_device float3 equirectangular_to_direction(float u, float v)
ccl_device float2 direction_to_equirectangular(float3 dir)
ccl_device float2 direction_to_fisheye_equisolid(float3 dir, float lens, float width, float height)
ccl_device_inline float3 fisheye_equisolid_to_direction(float u, float v, float lens, float fov, float width, float height)
ccl_device float3 spherical_to_direction(float theta, float phi)
ccl_device float3 equirectangular_range_to_direction(float u, float v, float4 range)
ccl_device float3 mirrorball_to_direction(float u, float v)
ccl_device_inline float3 fisheye_lens_polynomial_to_direction(float u, float v, float coeff0, float4 coeffs, float fov, float width, float height)
int len
Definition: draw_manager.c:108
@ PANORAMA_MIRRORBALL
Definition: kernel/types.h:474
@ PANORAMA_FISHEYE_EQUISOLID
Definition: kernel/types.h:473
@ PANORAMA_FISHEYE_EQUIDISTANT
Definition: kernel/types.h:472
@ PANORAMA_FISHEYE_LENS_POLYNOMIAL
Definition: kernel/types.h:475
@ PANORAMA_EQUIRECTANGULAR
Definition: kernel/types.h:471
ccl_device_inline float2 zero_float2()
Definition: math_float2.h:62
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
static float P(float k)
Definition: math_interp.c:25
#define atan2f(x, y)
Definition: metal/compat.h:227
#define asinf(x)
Definition: metal/compat.h:221
#define make_float2(x, y)
Definition: metal/compat.h:203
#define acosf(x)
Definition: metal/compat.h:222
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
#define make_float3(x, y, z)
Definition: metal/compat.h:204
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
bool is_zero(const T &a)
#define I
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: noise.h:15
float z
float y
float x
float max
#define M_PI_2_F
Definition: util/math.h:37
#define M_2PI_F
Definition: util/math.h:60
#define M_PI_F
Definition: util/math.h:34
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:13