svm_bevel.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright 2011-2013 Blender Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. CCL_NAMESPACE_BEGIN
  17. /* Bevel shader averaging normals from nearby surfaces.
  18. *
  19. * Sampling strategy from: BSSRDF Importance Sampling, SIGGRAPH 2013
  20. * http://library.imageworks.com/pdfs/imageworks-library-BSSRDF-sampling.pdf
  21. */
  22. ccl_device_noinline float3 svm_bevel(KernelGlobals *kg,
  23. ShaderData *sd,
  24. ccl_addr_space PathState *state,
  25. float radius,
  26. int num_samples)
  27. {
  28. /* Early out if no sampling needed. */
  29. if (radius <= 0.0f || num_samples < 1 || sd->object == OBJECT_NONE) {
  30. return sd->N;
  31. }
  32. /* Can't raytrace from shaders like displacement, before BVH exists. */
  33. if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
  34. return sd->N;
  35. }
  36. /* Don't bevel for blurry indirect rays. */
  37. if (state->min_ray_pdf < 8.0f) {
  38. return sd->N;
  39. }
  40. /* Setup for multi intersection. */
  41. LocalIntersection isect;
  42. uint lcg_state = lcg_state_init_addrspace(state, 0x64c6a40e);
  43. /* Sample normals from surrounding points on surface. */
  44. float3 sum_N = make_float3(0.0f, 0.0f, 0.0f);
  45. for (int sample = 0; sample < num_samples; sample++) {
  46. float disk_u, disk_v;
  47. path_branched_rng_2D(
  48. kg, state->rng_hash, state, sample, num_samples, PRNG_BEVEL_U, &disk_u, &disk_v);
  49. /* Pick random axis in local frame and point on disk. */
  50. float3 disk_N, disk_T, disk_B;
  51. float pick_pdf_N, pick_pdf_T, pick_pdf_B;
  52. disk_N = sd->Ng;
  53. make_orthonormals(disk_N, &disk_T, &disk_B);
  54. float axisu = disk_u;
  55. if (axisu < 0.5f) {
  56. pick_pdf_N = 0.5f;
  57. pick_pdf_T = 0.25f;
  58. pick_pdf_B = 0.25f;
  59. disk_u *= 2.0f;
  60. }
  61. else if (axisu < 0.75f) {
  62. float3 tmp = disk_N;
  63. disk_N = disk_T;
  64. disk_T = tmp;
  65. pick_pdf_N = 0.25f;
  66. pick_pdf_T = 0.5f;
  67. pick_pdf_B = 0.25f;
  68. disk_u = (disk_u - 0.5f) * 4.0f;
  69. }
  70. else {
  71. float3 tmp = disk_N;
  72. disk_N = disk_B;
  73. disk_B = tmp;
  74. pick_pdf_N = 0.25f;
  75. pick_pdf_T = 0.25f;
  76. pick_pdf_B = 0.5f;
  77. disk_u = (disk_u - 0.75f) * 4.0f;
  78. }
  79. /* Sample point on disk. */
  80. float phi = M_2PI_F * disk_u;
  81. float disk_r = disk_v;
  82. float disk_height;
  83. /* Perhaps find something better than Cubic BSSRDF, but happens to work well. */
  84. bssrdf_cubic_sample(radius, 0.0f, disk_r, &disk_r, &disk_height);
  85. float3 disk_P = (disk_r * cosf(phi)) * disk_T + (disk_r * sinf(phi)) * disk_B;
  86. /* Create ray. */
  87. Ray *ray = &isect.ray;
  88. ray->P = sd->P + disk_N * disk_height + disk_P;
  89. ray->D = -disk_N;
  90. ray->t = 2.0f * disk_height;
  91. ray->dP = sd->dP;
  92. ray->dD = differential3_zero();
  93. ray->time = sd->time;
  94. /* Intersect with the same object. if multiple intersections are found it
  95. * will use at most LOCAL_MAX_HITS hits, a random subset of all hits. */
  96. scene_intersect_local(kg, *ray, &isect, sd->object, &lcg_state, LOCAL_MAX_HITS);
  97. int num_eval_hits = min(isect.num_hits, LOCAL_MAX_HITS);
  98. for (int hit = 0; hit < num_eval_hits; hit++) {
  99. /* Quickly retrieve P and Ng without setting up ShaderData. */
  100. float3 hit_P;
  101. if (sd->type & PRIMITIVE_TRIANGLE) {
  102. hit_P = triangle_refine_local(kg, sd, &isect.hits[hit], ray);
  103. }
  104. #ifdef __OBJECT_MOTION__
  105. else if (sd->type & PRIMITIVE_MOTION_TRIANGLE) {
  106. float3 verts[3];
  107. motion_triangle_vertices(
  108. kg, sd->object, kernel_tex_fetch(__prim_index, isect.hits[hit].prim), sd->time, verts);
  109. hit_P = motion_triangle_refine_local(kg, sd, &isect.hits[hit], ray, verts);
  110. }
  111. #endif /* __OBJECT_MOTION__ */
  112. /* Get geometric normal. */
  113. float3 hit_Ng = isect.Ng[hit];
  114. int object = (isect.hits[hit].object == OBJECT_NONE) ?
  115. kernel_tex_fetch(__prim_object, isect.hits[hit].prim) :
  116. isect.hits[hit].object;
  117. int object_flag = kernel_tex_fetch(__object_flag, object);
  118. if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
  119. hit_Ng = -hit_Ng;
  120. }
  121. /* Compute smooth normal. */
  122. float3 N = hit_Ng;
  123. int prim = kernel_tex_fetch(__prim_index, isect.hits[hit].prim);
  124. int shader = kernel_tex_fetch(__tri_shader, prim);
  125. if (shader & SHADER_SMOOTH_NORMAL) {
  126. float u = isect.hits[hit].u;
  127. float v = isect.hits[hit].v;
  128. if (sd->type & PRIMITIVE_TRIANGLE) {
  129. N = triangle_smooth_normal(kg, N, prim, u, v);
  130. }
  131. #ifdef __OBJECT_MOTION__
  132. else if (sd->type & PRIMITIVE_MOTION_TRIANGLE) {
  133. N = motion_triangle_smooth_normal(kg, N, sd->object, prim, u, v, sd->time);
  134. }
  135. #endif /* __OBJECT_MOTION__ */
  136. }
  137. /* Transform normals to world space. */
  138. if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
  139. object_normal_transform(kg, sd, &N);
  140. object_normal_transform(kg, sd, &hit_Ng);
  141. }
  142. /* Probability densities for local frame axes. */
  143. float pdf_N = pick_pdf_N * fabsf(dot(disk_N, hit_Ng));
  144. float pdf_T = pick_pdf_T * fabsf(dot(disk_T, hit_Ng));
  145. float pdf_B = pick_pdf_B * fabsf(dot(disk_B, hit_Ng));
  146. /* Multiple importance sample between 3 axes, power heuristic
  147. * found to be slightly better than balance heuristic. pdf_N
  148. * in the MIS weight and denominator cancelled out. */
  149. float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B));
  150. if (isect.num_hits > LOCAL_MAX_HITS) {
  151. w *= isect.num_hits / (float)LOCAL_MAX_HITS;
  152. }
  153. /* Real distance to sampled point. */
  154. float r = len(hit_P - sd->P);
  155. /* Compute weight. */
  156. float pdf = bssrdf_cubic_pdf(radius, 0.0f, r);
  157. float disk_pdf = bssrdf_cubic_pdf(radius, 0.0f, disk_r);
  158. w *= pdf / disk_pdf;
  159. /* Sum normal and weight. */
  160. sum_N += w * N;
  161. }
  162. }
  163. /* Normalize. */
  164. float3 N = safe_normalize(sum_N);
  165. return is_zero(N) ? sd->N : (sd->flag & SD_BACKFACING) ? -N : N;
  166. }
  167. ccl_device void svm_node_bevel(
  168. KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, float *stack, uint4 node)
  169. {
  170. uint num_samples, radius_offset, normal_offset, out_offset;
  171. decode_node_uchar4(node.y, &num_samples, &radius_offset, &normal_offset, &out_offset);
  172. float radius = stack_load_float(stack, radius_offset);
  173. float3 bevel_N = svm_bevel(kg, sd, state, radius, num_samples);
  174. if (stack_valid(normal_offset)) {
  175. /* Preserve input normal. */
  176. float3 ref_N = stack_load_float3(stack, normal_offset);
  177. bevel_N = normalize(ref_N + (bevel_N - sd->N));
  178. }
  179. stack_store_float3(stack, out_offset, bevel_N);
  180. }
  181. CCL_NAMESPACE_END