geom_curve.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Licensed under the Apache License, Version 2.0 (the "License");
  3. * you may not use this file except in compliance with the License.
  4. * You may obtain a copy of the License at
  5. *
  6. * http://www.apache.org/licenses/LICENSE-2.0
  7. *
  8. * Unless required by applicable law or agreed to in writing, software
  9. * distributed under the License is distributed on an "AS IS" BASIS,
  10. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. * See the License for the specific language governing permissions and
  12. * limitations under the License.
  13. */
  14. CCL_NAMESPACE_BEGIN
  15. /* Curve Primitive
  16. *
  17. * Curve primitive for rendering hair and fur. These can be render as flat
  18. * ribbons or curves with actual thickness. The curve can also be rendered as
  19. * line segments rather than curves for better performance.
  20. */
  21. #ifdef __HAIR__
  22. /* Interpolation of curve geometry */
  23. ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
  24. {
  25. float fc = 0.71f;
  26. float data[4];
  27. float t2 = t * t;
  28. data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
  29. data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
  30. data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
  31. data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
  32. return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
  33. }
  34. ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
  35. {
  36. float data[4];
  37. float fc = 0.71f;
  38. float t2 = t * t;
  39. float t3 = t2 * t;
  40. data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
  41. data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
  42. data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
  43. data[3] = fc * t3 - fc * t2;
  44. return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
  45. }
  46. /* Reading attributes on various curve elements */
  47. ccl_device float curve_attribute_float(
  48. KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
  49. {
  50. if (desc.element == ATTR_ELEMENT_CURVE) {
  51. # ifdef __RAY_DIFFERENTIALS__
  52. if (dx)
  53. *dx = 0.0f;
  54. if (dy)
  55. *dy = 0.0f;
  56. # endif
  57. return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
  58. }
  59. else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
  60. desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
  61. float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
  62. int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
  63. int k1 = k0 + 1;
  64. float f0 = kernel_tex_fetch(__attributes_float, desc.offset + k0);
  65. float f1 = kernel_tex_fetch(__attributes_float, desc.offset + k1);
  66. # ifdef __RAY_DIFFERENTIALS__
  67. if (dx)
  68. *dx = sd->du.dx * (f1 - f0);
  69. if (dy)
  70. *dy = 0.0f;
  71. # endif
  72. return (1.0f - sd->u) * f0 + sd->u * f1;
  73. }
  74. else {
  75. # ifdef __RAY_DIFFERENTIALS__
  76. if (dx)
  77. *dx = 0.0f;
  78. if (dy)
  79. *dy = 0.0f;
  80. # endif
  81. return 0.0f;
  82. }
  83. }
  84. ccl_device float2 curve_attribute_float2(KernelGlobals *kg,
  85. const ShaderData *sd,
  86. const AttributeDescriptor desc,
  87. float2 *dx,
  88. float2 *dy)
  89. {
  90. if (desc.element == ATTR_ELEMENT_CURVE) {
  91. /* idea: we can't derive any useful differentials here, but for tiled
  92. * mipmap image caching it would be useful to avoid reading the highest
  93. * detail level always. maybe a derivative based on the hair density
  94. * could be computed somehow? */
  95. # ifdef __RAY_DIFFERENTIALS__
  96. if (dx)
  97. *dx = make_float2(0.0f, 0.0f);
  98. if (dy)
  99. *dy = make_float2(0.0f, 0.0f);
  100. # endif
  101. return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
  102. }
  103. else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
  104. desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
  105. float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
  106. int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
  107. int k1 = k0 + 1;
  108. float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + k0);
  109. float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + k1);
  110. # ifdef __RAY_DIFFERENTIALS__
  111. if (dx)
  112. *dx = sd->du.dx * (f1 - f0);
  113. if (dy)
  114. *dy = make_float2(0.0f, 0.0f);
  115. # endif
  116. return (1.0f - sd->u) * f0 + sd->u * f1;
  117. }
  118. else {
  119. # ifdef __RAY_DIFFERENTIALS__
  120. if (dx)
  121. *dx = make_float2(0.0f, 0.0f);
  122. if (dy)
  123. *dy = make_float2(0.0f, 0.0f);
  124. # endif
  125. return make_float2(0.0f, 0.0f);
  126. }
  127. }
  128. ccl_device float3 curve_attribute_float3(KernelGlobals *kg,
  129. const ShaderData *sd,
  130. const AttributeDescriptor desc,
  131. float3 *dx,
  132. float3 *dy)
  133. {
  134. if (desc.element == ATTR_ELEMENT_CURVE) {
  135. /* idea: we can't derive any useful differentials here, but for tiled
  136. * mipmap image caching it would be useful to avoid reading the highest
  137. * detail level always. maybe a derivative based on the hair density
  138. * could be computed somehow? */
  139. # ifdef __RAY_DIFFERENTIALS__
  140. if (dx)
  141. *dx = make_float3(0.0f, 0.0f, 0.0f);
  142. if (dy)
  143. *dy = make_float3(0.0f, 0.0f, 0.0f);
  144. # endif
  145. return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
  146. }
  147. else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
  148. desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
  149. float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
  150. int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
  151. int k1 = k0 + 1;
  152. float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k0));
  153. float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k1));
  154. # ifdef __RAY_DIFFERENTIALS__
  155. if (dx)
  156. *dx = sd->du.dx * (f1 - f0);
  157. if (dy)
  158. *dy = make_float3(0.0f, 0.0f, 0.0f);
  159. # endif
  160. return (1.0f - sd->u) * f0 + sd->u * f1;
  161. }
  162. else {
  163. # ifdef __RAY_DIFFERENTIALS__
  164. if (dx)
  165. *dx = make_float3(0.0f, 0.0f, 0.0f);
  166. if (dy)
  167. *dy = make_float3(0.0f, 0.0f, 0.0f);
  168. # endif
  169. return make_float3(0.0f, 0.0f, 0.0f);
  170. }
  171. }
  172. /* Curve thickness */
  173. ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
  174. {
  175. float r = 0.0f;
  176. if (sd->type & PRIMITIVE_ALL_CURVE) {
  177. float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
  178. int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
  179. int k1 = k0 + 1;
  180. float4 P_curve[2];
  181. if (sd->type & PRIMITIVE_CURVE) {
  182. P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
  183. P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
  184. }
  185. else {
  186. motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
  187. }
  188. r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
  189. }
  190. return r * 2.0f;
  191. }
  192. /* Curve location for motion pass, linear interpolation between keys and
  193. * ignoring radius because we do the same for the motion keys */
  194. ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd)
  195. {
  196. float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
  197. int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
  198. int k1 = k0 + 1;
  199. float4 P_curve[2];
  200. P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
  201. P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
  202. return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u);
  203. }
  204. /* Curve tangent normal */
  205. ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
  206. {
  207. float3 tgN = make_float3(0.0f, 0.0f, 0.0f);
  208. if (sd->type & PRIMITIVE_ALL_CURVE) {
  209. tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu, -sd->I) / len_squared(sd->dPdu)));
  210. tgN = normalize(tgN);
  211. /* need to find suitable scaled gd for corrected normal */
  212. # if 0
  213. tgN = normalize(tgN - gd * sd->dPdu);
  214. # endif
  215. }
  216. return tgN;
  217. }
  218. /* Curve bounds utility function */
  219. ccl_device_inline void curvebounds(float *lower,
  220. float *upper,
  221. float *extremta,
  222. float *extrema,
  223. float *extremtb,
  224. float *extremb,
  225. float p0,
  226. float p1,
  227. float p2,
  228. float p3)
  229. {
  230. float halfdiscroot = (p2 * p2 - 3 * p3 * p1);
  231. float ta = -1.0f;
  232. float tb = -1.0f;
  233. *extremta = -1.0f;
  234. *extremtb = -1.0f;
  235. *upper = p0;
  236. *lower = (p0 + p1) + (p2 + p3);
  237. *extrema = *upper;
  238. *extremb = *lower;
  239. if (*lower >= *upper) {
  240. *upper = *lower;
  241. *lower = p0;
  242. }
  243. if (halfdiscroot >= 0) {
  244. float inv3p3 = (1.0f / 3.0f) / p3;
  245. halfdiscroot = sqrtf(halfdiscroot);
  246. ta = (-p2 - halfdiscroot) * inv3p3;
  247. tb = (-p2 + halfdiscroot) * inv3p3;
  248. }
  249. float t2;
  250. float t3;
  251. if (ta > 0.0f && ta < 1.0f) {
  252. t2 = ta * ta;
  253. t3 = t2 * ta;
  254. *extremta = ta;
  255. *extrema = p3 * t3 + p2 * t2 + p1 * ta + p0;
  256. *upper = fmaxf(*extrema, *upper);
  257. *lower = fminf(*extrema, *lower);
  258. }
  259. if (tb > 0.0f && tb < 1.0f) {
  260. t2 = tb * tb;
  261. t3 = t2 * tb;
  262. *extremtb = tb;
  263. *extremb = p3 * t3 + p2 * t2 + p1 * tb + p0;
  264. *upper = fmaxf(*extremb, *upper);
  265. *lower = fminf(*extremb, *lower);
  266. }
  267. }
  268. #endif /* __HAIR__ */
  269. CCL_NAMESPACE_END