Blender  V2.93
svm_bevel.h
Go to the documentation of this file.
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 
18 
19 #ifdef __SHADER_RAYTRACE__
20 
21 /* Bevel shader averaging normals from nearby surfaces.
22  *
23  * Sampling strategy from: BSSRDF Importance Sampling, SIGGRAPH 2013
24  * http://library.imageworks.com/pdfs/imageworks-library-BSSRDF-sampling.pdf
25  */
26 
27 ccl_device_noinline float3 svm_bevel(KernelGlobals *kg,
28  ShaderData *sd,
30  float radius,
31  int num_samples)
32 {
33  /* Early out if no sampling needed. */
34  if (radius <= 0.0f || num_samples < 1 || sd->object == OBJECT_NONE) {
35  return sd->N;
36  }
37 
38  /* Can't raytrace from shaders like displacement, before BVH exists. */
39  if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
40  return sd->N;
41  }
42 
43  /* Don't bevel for blurry indirect rays. */
44  if (state->min_ray_pdf < 8.0f) {
45  return sd->N;
46  }
47 
48  /* Setup for multi intersection. */
49  LocalIntersection isect;
50  uint lcg_state = lcg_state_init_addrspace(state, 0x64c6a40e);
51 
52  /* Sample normals from surrounding points on surface. */
53  float3 sum_N = make_float3(0.0f, 0.0f, 0.0f);
54 
55  for (int sample = 0; sample < num_samples; sample++) {
56  float disk_u, disk_v;
58  kg, state->rng_hash, state, sample, num_samples, PRNG_BEVEL_U, &disk_u, &disk_v);
59 
60  /* Pick random axis in local frame and point on disk. */
61  float3 disk_N, disk_T, disk_B;
62  float pick_pdf_N, pick_pdf_T, pick_pdf_B;
63 
64  disk_N = sd->Ng;
65  make_orthonormals(disk_N, &disk_T, &disk_B);
66 
67  float axisu = disk_u;
68 
69  if (axisu < 0.5f) {
70  pick_pdf_N = 0.5f;
71  pick_pdf_T = 0.25f;
72  pick_pdf_B = 0.25f;
73  disk_u *= 2.0f;
74  }
75  else if (axisu < 0.75f) {
76  float3 tmp = disk_N;
77  disk_N = disk_T;
78  disk_T = tmp;
79  pick_pdf_N = 0.25f;
80  pick_pdf_T = 0.5f;
81  pick_pdf_B = 0.25f;
82  disk_u = (disk_u - 0.5f) * 4.0f;
83  }
84  else {
85  float3 tmp = disk_N;
86  disk_N = disk_B;
87  disk_B = tmp;
88  pick_pdf_N = 0.25f;
89  pick_pdf_T = 0.25f;
90  pick_pdf_B = 0.5f;
91  disk_u = (disk_u - 0.75f) * 4.0f;
92  }
93 
94  /* Sample point on disk. */
95  float phi = M_2PI_F * disk_u;
96  float disk_r = disk_v;
97  float disk_height;
98 
99  /* Perhaps find something better than Cubic BSSRDF, but happens to work well. */
100  bssrdf_cubic_sample(radius, 0.0f, disk_r, &disk_r, &disk_height);
101 
102  float3 disk_P = (disk_r * cosf(phi)) * disk_T + (disk_r * sinf(phi)) * disk_B;
103 
104  /* Create ray. */
105  Ray *ray = &isect.ray;
106  ray->P = sd->P + disk_N * disk_height + disk_P;
107  ray->D = -disk_N;
108  ray->t = 2.0f * disk_height;
109  ray->dP = sd->dP;
110  ray->dD = differential3_zero();
111  ray->time = sd->time;
112 
113  /* Intersect with the same object. if multiple intersections are found it
114  * will use at most LOCAL_MAX_HITS hits, a random subset of all hits. */
115  scene_intersect_local(kg, ray, &isect, sd->object, &lcg_state, LOCAL_MAX_HITS);
116 
117  int num_eval_hits = min(isect.num_hits, LOCAL_MAX_HITS);
118 
119  for (int hit = 0; hit < num_eval_hits; hit++) {
120  /* Quickly retrieve P and Ng without setting up ShaderData. */
121  float3 hit_P;
122  if (sd->type & PRIMITIVE_TRIANGLE) {
123  hit_P = triangle_refine_local(kg, sd, &isect.hits[hit], ray);
124  }
125 # ifdef __OBJECT_MOTION__
126  else if (sd->type & PRIMITIVE_MOTION_TRIANGLE) {
127  float3 verts[3];
129  kg, sd->object, kernel_tex_fetch(__prim_index, isect.hits[hit].prim), sd->time, verts);
130  hit_P = motion_triangle_refine_local(kg, sd, &isect.hits[hit], ray, verts);
131  }
132 # endif /* __OBJECT_MOTION__ */
133 
134  /* Get geometric normal. */
135  float3 hit_Ng = isect.Ng[hit];
136  int object = (isect.hits[hit].object == OBJECT_NONE) ?
137  kernel_tex_fetch(__prim_object, isect.hits[hit].prim) :
138  isect.hits[hit].object;
139  int object_flag = kernel_tex_fetch(__object_flag, object);
140  if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
141  hit_Ng = -hit_Ng;
142  }
143 
144  /* Compute smooth normal. */
145  float3 N = hit_Ng;
146  int prim = kernel_tex_fetch(__prim_index, isect.hits[hit].prim);
147  int shader = kernel_tex_fetch(__tri_shader, prim);
148 
150  float u = isect.hits[hit].u;
151  float v = isect.hits[hit].v;
152 
153  if (sd->type & PRIMITIVE_TRIANGLE) {
154  N = triangle_smooth_normal(kg, N, prim, u, v);
155  }
156 # ifdef __OBJECT_MOTION__
157  else if (sd->type & PRIMITIVE_MOTION_TRIANGLE) {
158  N = motion_triangle_smooth_normal(kg, N, sd->object, prim, u, v, sd->time);
159  }
160 # endif /* __OBJECT_MOTION__ */
161  }
162 
163  /* Transform normals to world space. */
164  if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
166  object_normal_transform(kg, sd, &hit_Ng);
167  }
168 
169  /* Probability densities for local frame axes. */
170  float pdf_N = pick_pdf_N * fabsf(dot(disk_N, hit_Ng));
171  float pdf_T = pick_pdf_T * fabsf(dot(disk_T, hit_Ng));
172  float pdf_B = pick_pdf_B * fabsf(dot(disk_B, hit_Ng));
173 
174  /* Multiple importance sample between 3 axes, power heuristic
175  * found to be slightly better than balance heuristic. pdf_N
176  * in the MIS weight and denominator cancelled out. */
177  float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B));
178  if (isect.num_hits > LOCAL_MAX_HITS) {
179  w *= isect.num_hits / (float)LOCAL_MAX_HITS;
180  }
181 
182  /* Real distance to sampled point. */
183  float r = len(hit_P - sd->P);
184 
185  /* Compute weight. */
186  float pdf = bssrdf_cubic_pdf(radius, 0.0f, r);
187  float disk_pdf = bssrdf_cubic_pdf(radius, 0.0f, disk_r);
188 
189  w *= pdf / disk_pdf;
190 
191  /* Sum normal and weight. */
192  sum_N += w * N;
193  }
194  }
195 
196  /* Normalize. */
197  float3 N = safe_normalize(sum_N);
198  return is_zero(N) ? sd->N : (sd->flag & SD_BACKFACING) ? -N : N;
199 }
200 
201 ccl_device void svm_node_bevel(
202  KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, float *stack, uint4 node)
203 {
204  uint num_samples, radius_offset, normal_offset, out_offset;
205  svm_unpack_node_uchar4(node.y, &num_samples, &radius_offset, &normal_offset, &out_offset);
206 
207  float radius = stack_load_float(stack, radius_offset);
208  float3 bevel_N = svm_bevel(kg, sd, state, radius, num_samples);
209 
210  if (stack_valid(normal_offset)) {
211  /* Preserve input normal. */
212  float3 ref_N = stack_load_float3(stack, normal_offset);
213  bevel_N = normalize(ref_N + (bevel_N - sd->N));
214  }
215 
216  stack_store_float3(stack, out_offset, bevel_N);
217 }
218 
219 #endif /* __SHADER_RAYTRACE__ */
220 
typedef float(TangentPoint)[2]
unsigned int uint
Definition: BLI_sys_types.h:83
_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
ATTR_WARN_UNUSED_RESULT const BMVert * v
ccl_device float bssrdf_cubic_pdf(const float radius, const float sharpness, float r)
Definition: bssrdf.h:134
ccl_device void bssrdf_cubic_sample(const float radius, const float sharpness, float xi, float *r, float *h)
Definition: bssrdf.h:167
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
OperationNode * node
static float verts[][3]
ccl_device_inline void motion_triangle_vertices(KernelGlobals *kg, int object, int prim, float time, float3 verts[3])
ccl_device_inline float3 motion_triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int object, int prim, float u, float v, float time)
ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
Definition: geom_object.h:166
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
Definition: geom_triangle.h:81
ccl_device_inline float3 triangle_refine_local(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 stack_load_float3(float *stack, uint a)
ccl_device_inline float stack_load_float(float *stack, uint a)
ccl_device_inline void stack_store_float3(float *stack, uint a, float3 f)
ccl_device_forceinline void svm_unpack_node_uchar4(uint i, uint *x, uint *y, uint *z, uint *w)
ccl_device_inline bool stack_valid(uint a)
#define kernel_data
#define ccl_addr_space
#define kernel_tex_fetch(tex, index)
#define sinf(x)
#define cosf(x)
#define ccl_device
#define ccl_device_noinline
#define CCL_NAMESPACE_END
#define fabsf(x)
#define make_float3(x, y, z)
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
ccl_device differential3 differential3_zero()
ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space PathState *state, uint scramble)
ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, uint rng_hash, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
@ SD_BACKFACING
Definition: kernel_types.h:843
@ PRIMITIVE_MOTION_TRIANGLE
Definition: kernel_types.h:687
@ PRIMITIVE_TRIANGLE
Definition: kernel_types.h:686
@ PRNG_BEVEL_U
Definition: kernel_types.h:250
#define OBJECT_NONE
Definition: kernel_types.h:59
#define LOCAL_MAX_HITS
Definition: kernel_types.h:52
ShaderData
@ SHADER_SMOOTH_NORMAL
Definition: kernel_types.h:581
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel_types.h:908
@ SD_OBJECT_NEGATIVE_SCALE_APPLIED
Definition: kernel_types.h:910
@ BVH_LAYOUT_NONE
static ulong state[N]
static void sample(SocketReader *reader, int x, int y, float color[4])
params N
#define min(a, b)
Definition: sort.c:51
struct Intersection hits[LOCAL_MAX_HITS]
float3 Ng[LOCAL_MAX_HITS]
float t
Definition: kernel_types.h:649
differential3 dD
Definition: kernel_types.h:660
float3 P
Definition: kernel_types.h:647
float time
Definition: kernel_types.h:650
differential3 dP
Definition: kernel_types.h:659
float3 D
Definition: kernel_types.h:648
ccl_device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
Definition: util_math.h:477
ccl_device_inline float sqr(float a)
Definition: util_math.h:651
#define M_2PI_F
Definition: util_math.h:69
ccl_device_inline float2 normalize(const float2 &a)
ccl_device_inline float dot(const float2 &a, const float2 &b)
ccl_device_inline float2 safe_normalize(const float2 &a)
ccl_device_inline bool is_zero(const float2 &a)
uint len