kernel_projection.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  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, Blender Foundation.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions are
  11. * met:
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * * Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * * Neither the name of Sony Pictures Imageworks nor the names of its
  18. * contributors may be used to endorse or promote products derived from
  19. * this software without specific prior written permission.
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. #ifndef __KERNEL_PROJECTION_CL__
  33. #define __KERNEL_PROJECTION_CL__
  34. CCL_NAMESPACE_BEGIN
  35. /* Spherical coordinates <-> Cartesian direction */
  36. ccl_device float2 direction_to_spherical(float3 dir)
  37. {
  38. float theta = safe_acosf(dir.z);
  39. float phi = atan2f(dir.x, dir.y);
  40. return make_float2(theta, phi);
  41. }
  42. ccl_device float3 spherical_to_direction(float theta, float phi)
  43. {
  44. float sin_theta = sinf(theta);
  45. return make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cosf(theta));
  46. }
  47. /* Equirectangular coordinates <-> Cartesian direction */
  48. ccl_device float2 direction_to_equirectangular_range(float3 dir, float4 range)
  49. {
  50. if (is_zero(dir))
  51. return make_float2(0.0f, 0.0f);
  52. float u = (atan2f(dir.y, dir.x) - range.y) / range.x;
  53. float v = (acosf(dir.z / len(dir)) - range.w) / range.z;
  54. return make_float2(u, v);
  55. }
  56. ccl_device float3 equirectangular_range_to_direction(float u, float v, float4 range)
  57. {
  58. float phi = range.x * u + range.y;
  59. float theta = range.z * v + range.w;
  60. float sin_theta = sinf(theta);
  61. return make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cosf(theta));
  62. }
  63. ccl_device float2 direction_to_equirectangular(float3 dir)
  64. {
  65. return direction_to_equirectangular_range(dir, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
  66. }
  67. ccl_device float3 equirectangular_to_direction(float u, float v)
  68. {
  69. return equirectangular_range_to_direction(u, v, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
  70. }
  71. /* Fisheye <-> Cartesian direction */
  72. ccl_device float2 direction_to_fisheye(float3 dir, float fov)
  73. {
  74. float r = atan2f(sqrtf(dir.y * dir.y + dir.z * dir.z), dir.x) / fov;
  75. float phi = atan2f(dir.z, dir.y);
  76. float u = r * cosf(phi) + 0.5f;
  77. float v = r * sinf(phi) + 0.5f;
  78. return make_float2(u, v);
  79. }
  80. ccl_device float3 fisheye_to_direction(float u, float v, float fov)
  81. {
  82. u = (u - 0.5f) * 2.0f;
  83. v = (v - 0.5f) * 2.0f;
  84. float r = sqrtf(u * u + v * v);
  85. if (r > 1.0f)
  86. return make_float3(0.0f, 0.0f, 0.0f);
  87. float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
  88. float theta = r * fov * 0.5f;
  89. if (v < 0.0f)
  90. phi = -phi;
  91. return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
  92. }
  93. ccl_device float2 direction_to_fisheye_equisolid(float3 dir, float lens, float width, float height)
  94. {
  95. float theta = safe_acosf(dir.x);
  96. float r = 2.0f * lens * sinf(theta * 0.5f);
  97. float phi = atan2f(dir.z, dir.y);
  98. float u = r * cosf(phi) / width + 0.5f;
  99. float v = r * sinf(phi) / height + 0.5f;
  100. return make_float2(u, v);
  101. }
  102. ccl_device_inline float3
  103. fisheye_equisolid_to_direction(float u, float v, float lens, float fov, float width, float height)
  104. {
  105. u = (u - 0.5f) * width;
  106. v = (v - 0.5f) * height;
  107. float rmax = 2.0f * lens * sinf(fov * 0.25f);
  108. float r = sqrtf(u * u + v * v);
  109. if (r > rmax)
  110. return make_float3(0.0f, 0.0f, 0.0f);
  111. float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
  112. float theta = 2.0f * asinf(r / (2.0f * lens));
  113. if (v < 0.0f)
  114. phi = -phi;
  115. return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
  116. }
  117. /* Mirror Ball <-> Cartesion direction */
  118. ccl_device float3 mirrorball_to_direction(float u, float v)
  119. {
  120. /* point on sphere */
  121. float3 dir;
  122. dir.x = 2.0f * u - 1.0f;
  123. dir.z = 2.0f * v - 1.0f;
  124. if (dir.x * dir.x + dir.z * dir.z > 1.0f)
  125. return make_float3(0.0f, 0.0f, 0.0f);
  126. dir.y = -sqrtf(max(1.0f - dir.x * dir.x - dir.z * dir.z, 0.0f));
  127. /* reflection */
  128. float3 I = make_float3(0.0f, -1.0f, 0.0f);
  129. return 2.0f * dot(dir, I) * dir - I;
  130. }
  131. ccl_device float2 direction_to_mirrorball(float3 dir)
  132. {
  133. /* inverse of mirrorball_to_direction */
  134. dir.y -= 1.0f;
  135. float div = 2.0f * sqrtf(max(-0.5f * dir.y, 0.0f));
  136. if (div > 0.0f)
  137. dir /= div;
  138. float u = 0.5f * (dir.x + 1.0f);
  139. float v = 0.5f * (dir.z + 1.0f);
  140. return make_float2(u, v);
  141. }
  142. ccl_device_inline float3 panorama_to_direction(ccl_constant KernelCamera *cam, float u, float v)
  143. {
  144. switch (cam->panorama_type) {
  145. case PANORAMA_EQUIRECTANGULAR:
  146. return equirectangular_range_to_direction(u, v, cam->equirectangular_range);
  147. case PANORAMA_MIRRORBALL:
  148. return mirrorball_to_direction(u, v);
  149. case PANORAMA_FISHEYE_EQUIDISTANT:
  150. return fisheye_to_direction(u, v, cam->fisheye_fov);
  151. case PANORAMA_FISHEYE_EQUISOLID:
  152. default:
  153. return fisheye_equisolid_to_direction(
  154. u, v, cam->fisheye_lens, cam->fisheye_fov, cam->sensorwidth, cam->sensorheight);
  155. }
  156. }
  157. ccl_device_inline float2 direction_to_panorama(ccl_constant KernelCamera *cam, float3 dir)
  158. {
  159. switch (cam->panorama_type) {
  160. case PANORAMA_EQUIRECTANGULAR:
  161. return direction_to_equirectangular_range(dir, cam->equirectangular_range);
  162. case PANORAMA_MIRRORBALL:
  163. return direction_to_mirrorball(dir);
  164. case PANORAMA_FISHEYE_EQUIDISTANT:
  165. return direction_to_fisheye(dir, cam->fisheye_fov);
  166. case PANORAMA_FISHEYE_EQUISOLID:
  167. default:
  168. return direction_to_fisheye_equisolid(
  169. dir, cam->fisheye_lens, cam->sensorwidth, cam->sensorheight);
  170. }
  171. }
  172. ccl_device_inline void spherical_stereo_transform(ccl_constant KernelCamera *cam,
  173. float3 *P,
  174. float3 *D)
  175. {
  176. float interocular_offset = cam->interocular_offset;
  177. /* Interocular offset of zero means either non stereo, or stereo without
  178. * spherical stereo. */
  179. kernel_assert(interocular_offset != 0.0f);
  180. if (cam->pole_merge_angle_to > 0.0f) {
  181. const float pole_merge_angle_from = cam->pole_merge_angle_from,
  182. pole_merge_angle_to = cam->pole_merge_angle_to;
  183. float altitude = fabsf(safe_asinf((*D).z));
  184. if (altitude > pole_merge_angle_to) {
  185. interocular_offset = 0.0f;
  186. }
  187. else if (altitude > pole_merge_angle_from) {
  188. float fac = (altitude - pole_merge_angle_from) /
  189. (pole_merge_angle_to - pole_merge_angle_from);
  190. float fade = cosf(fac * M_PI_2_F);
  191. interocular_offset *= fade;
  192. }
  193. }
  194. float3 up = make_float3(0.0f, 0.0f, 1.0f);
  195. float3 side = normalize(cross(*D, up));
  196. float3 stereo_offset = side * interocular_offset;
  197. *P += stereo_offset;
  198. /* Convergence distance is FLT_MAX in the case of parallel convergence mode,
  199. * no need to modify direction in this case either. */
  200. const float convergence_distance = cam->convergence_distance;
  201. if (convergence_distance != FLT_MAX) {
  202. float3 screen_offset = convergence_distance * (*D);
  203. *D = normalize(screen_offset - stereo_offset);
  204. }
  205. }
  206. CCL_NAMESPACE_END
  207. #endif /* __KERNEL_PROJECTION_CL__ */