Blender V4.3
init_from_bake.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
8
11
14
16
17#include "kernel/geom/geom.h"
18
20
21/* In order to perform anti-aliasing during baking, we jitter the input barycentric coordinates
22 * (which are for the center of the texel) within the texel.
23 * However, the baking code currently doesn't support going to neighboring triangle, so if the
24 * jittered location falls outside of the input triangle, we need to bring it back in somehow.
25 * Clamping is a bad choice here since it can produce noticeable artifacts at triangle edges,
26 * but properly uniformly sampling the intersection of triangle and texel would be very
27 * performance-heavy, so cheat by just trying different jittering until we end up inside the
28 * triangle.
29 * For triangles that are smaller than a texel, this might take too many attempts, so eventually
30 * we just give up and don't jitter in that case.
31 * This is not a particularly elegant solution, but it's probably the best we can do. */
33 ccl_private float &v,
34 float2 rand_filter,
35 const float dudx,
36 const float dudy,
37 const float dvdx,
38 const float dvdy)
39{
40 for (int i = 0; i < 10; i++) {
41 /* Offset UV according to differentials. */
42 float jitterU = u + (rand_filter.x - 0.5f) * dudx + (rand_filter.y - 0.5f) * dudy;
43 float jitterV = v + (rand_filter.x - 0.5f) * dvdx + (rand_filter.y - 0.5f) * dvdy;
44 /* If this location is inside the triangle, return. */
45 if (jitterU > 0.0f && jitterV > 0.0f && jitterU + jitterV < 1.0f) {
46 u = jitterU;
47 v = jitterV;
48 return;
49 }
50 /* Retry with new jitter value. */
51 rand_filter = hash_float2_to_float2(rand_filter);
52 }
53 /* Retries exceeded, give up and just use center value. */
54 return;
55}
56
57/* Offset towards center of triangle to avoid ray-tracing precision issues. */
59 const int prim,
60 const float u,
61 const float v)
62{
63 float3 tri_verts[3];
64 triangle_vertices(kg, prim, tri_verts);
65
66 /* Empirically determined values, by no means perfect. */
67 const float position_offset = 1e-4f;
68 const float uv_offset = 1e-5f;
69
70 /* Offset position towards center, amount relative to absolute size of position coordinates. */
71 const float3 P = u * tri_verts[0] + v * tri_verts[1] + (1.0f - u - v) * tri_verts[2];
72 const float3 center = (tri_verts[0] + tri_verts[1] + tri_verts[2]) / 3.0f;
73 const float3 to_center = center - P;
74
75 const float3 offset_P = P + normalize(to_center) *
76 min(len(to_center),
77 max(reduce_max(fabs(P)), 1.0f) * position_offset);
78
79 /* Compute barycentric coordinates at new position. */
80 const float3 v1 = tri_verts[1] - tri_verts[0];
81 const float3 v2 = tri_verts[2] - tri_verts[0];
82 const float3 vP = offset_P - tri_verts[0];
83
84 const float d11 = dot(v1, v1);
85 const float d12 = dot(v1, v2);
86 const float d22 = dot(v2, v2);
87 const float dP1 = dot(vP, v1);
88 const float dP2 = dot(vP, v2);
89
90 const float denom = d11 * d22 - d12 * d12;
91 if (denom == 0.0f) {
92 return make_float2(0.0f, 0.0f);
93 }
94
95 const float offset_v = clamp((d22 * dP1 - d12 * dP2) / denom, uv_offset, 1.0f - uv_offset);
96 const float offset_w = clamp((d11 * dP2 - d12 * dP1) / denom, uv_offset, 1.0f - uv_offset);
97 const float offset_u = clamp(1.0f - offset_v - offset_w, uv_offset, 1.0f - uv_offset);
98
99 return make_float2(offset_u, offset_v);
100}
101
102/* Return false to indicate that this pixel is finished.
103 * Used by CPU implementation to not attempt to sample pixel for multiple samples once its known
104 * that the pixel did converge. */
109 const int x,
110 const int y,
111 const int scheduled_sample)
112{
114
115 /* Initialize path state to give basic buffer access and allow early outputs. */
116 path_state_init(state, tile, x, y);
117
118 /* Check whether the pixel has converged and should not be sampled anymore. */
120 return false;
121 }
122
123 /* Always count the sample, even if the camera sample will reject the ray. */
124 const int sample = film_write_sample(
125 kg, state, render_buffer, scheduled_sample, tile->sample_offset);
126
127 /* Setup render buffers. */
129
130 ccl_global float *primitive = buffer + kernel_data.film.pass_bake_primitive;
131 ccl_global float *differential = buffer + kernel_data.film.pass_bake_differential;
132
133 int prim = __float_as_uint(primitive[2]);
134 if (prim == -1) {
135 /* Accumulate transparency for empty pixels. */
136 film_write_transparent(kg, state, 0, 1.0f, buffer);
137 return true;
138 }
139
140 prim += kernel_data.bake.tri_offset;
141
142 /* Random number generator. */
143 uint rng_pixel = 0;
144 if (kernel_data.film.pass_bake_seed != 0) {
145 const uint seed = __float_as_uint(buffer[kernel_data.film.pass_bake_seed]);
146 rng_pixel = hash_uint(seed) ^ kernel_data.integrator.seed;
147 }
148 else {
149 rng_pixel = path_rng_pixel_init(kg, sample, x, y);
150 }
151
152 const float2 rand_filter = (sample == 0) ? make_float2(0.5f, 0.5f) :
153 path_rng_2D(kg, rng_pixel, sample, PRNG_FILTER);
154
155 /* Initialize path state for path integration. */
156 path_state_init_integrator(kg, state, sample, rng_pixel);
157
158 /* Barycentric UV. */
159 float u = primitive[0];
160 float v = primitive[1];
161
162 float dudx = differential[0];
163 float dudy = differential[1];
164 float dvdx = differential[2];
165 float dvdy = differential[3];
166
167 /* Exactly at vertex? Nudge inwards to avoid self-intersection. */
168 if ((u == 0.0f || u == 1.0f) && (v == 0.0f || v == 1.0f)) {
169 const float2 uv = bake_offset_towards_center(kg, prim, u, v);
170 u = uv.x;
171 v = uv.y;
172 }
173
174 /* Sub-pixel offset. */
175 bake_jitter_barycentric(u, v, rand_filter, dudx, dudy, dvdx, dvdy);
176
177 /* Convert from Blender to Cycles/Embree/OptiX barycentric convention. */
178 const float tmp = u;
179 u = v;
180 v = 1.0f - tmp - v;
181
182 const float tmpdx = dudx;
183 const float tmpdy = dudy;
184 dudx = dvdx;
185 dudy = dvdy;
186 dvdx = -tmpdx - dvdx;
187 dvdy = -tmpdy - dvdy;
188
189 /* Position and normal on triangle. */
190 const int object = kernel_data.bake.object_index;
191 float3 P, Ng;
192 int shader;
193 triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
194
195 const int object_flag = kernel_data_fetch(object_flag, object);
196 if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
198 P = transform_point_auto(&tfm, P);
199 }
200
201 if (kernel_data.film.pass_background != PASS_UNUSED) {
202 /* Environment baking. */
203
204 /* Setup and write ray. */
206 ray.P = zero_float3();
207 ray.D = normalize(P);
208 ray.tmin = 0.0f;
209 ray.tmax = FLT_MAX;
210 ray.time = 0.5f;
211 ray.dP = differential_zero_compact();
212 ray.dD = differential_zero_compact();
214
215 /* Setup next kernel to execute. */
217 }
218 else {
219 /* Surface baking. */
220 float3 N = (shader & SHADER_SMOOTH_NORMAL) ? triangle_smooth_normal(kg, Ng, prim, u, v) : Ng;
221
222 if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
226 }
227
228 const int shader_index = shader & SHADER_MASK;
229 const int shader_flags = kernel_data_fetch(shaders, shader_index).flags;
230
231 /* Fast path for position and normal passes not affected by shaders. */
232 if (kernel_data.film.pass_position != PASS_UNUSED) {
233 film_write_pass_float3(buffer + kernel_data.film.pass_position, P);
234 return true;
235 }
236 else if (kernel_data.film.pass_normal != PASS_UNUSED && !(shader_flags & SD_HAS_BUMP)) {
237 film_write_pass_float3(buffer + kernel_data.film.pass_normal, N);
238 return true;
239 }
240
241 /* Setup ray. */
243
244 if (kernel_data.bake.use_camera) {
246
247 const float DN = dot(D, N);
248
249 /* Nudge camera direction, so that the faces facing away from the camera still have
250 * somewhat usable shading. (Otherwise, glossy faces would be simply black.)
251 *
252 * The surface normal offset affects smooth surfaces. Lower values will make
253 * smooth surfaces more faceted, but higher values may show up from the camera
254 * at grazing angles.
255 *
256 * This value can actually be pretty high before it's noticeably wrong. */
257 const float surface_normal_offset = 0.2f;
258
259 /* Keep the ray direction at least `surface_normal_offset` "above" the smooth normal. */
260 if (DN <= surface_normal_offset) {
261 D -= N * (DN - surface_normal_offset);
262 D = normalize(D);
263 }
264
265 /* On the backside, just lerp towards the surface normal for the ray direction,
266 * as DN goes from 0.0 to -1.0. */
267 if (DN <= 0.0f) {
268 D = normalize(mix(D, N, -DN));
269 }
270
271 /* We don't want to bake the back face, so make sure the ray direction never
272 * goes behind the geometry (flat) normal. This is a fail-safe, and should rarely happen. */
273 const float true_normal_epsilon = 0.00001f;
274
275 if (dot(D, Ng) <= true_normal_epsilon) {
276 D -= Ng * (dot(D, Ng) - true_normal_epsilon);
277 D = normalize(D);
278 }
279
280 ray.P = P + D;
281 ray.D = -D;
282 }
283 else {
284 ray.P = P + N;
285 ray.D = -N;
286 }
287
288 ray.tmin = 0.0f;
289 ray.tmax = FLT_MAX;
290 ray.time = 0.5f;
291
292 /* Setup differentials. */
293 float3 dPdu, dPdv;
294 triangle_dPdudv(kg, prim, &dPdu, &dPdv);
295 if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
297 dPdu = transform_direction(&tfm, dPdu);
298 dPdv = transform_direction(&tfm, dPdv);
299 }
300
301 differential3 dP;
302 dP.dx = dPdu * dudx + dPdv * dvdx;
303 dP.dy = dPdu * dudy + dPdv * dvdy;
304 ray.dP = differential_make_compact(dP);
305 ray.dD = differential_zero_compact();
306
307 /* Write ray. */
309
310 /* Setup and write intersection. */
312 isect.object = kernel_data.bake.object_index;
313 isect.prim = prim;
314 isect.u = u;
315 isect.v = v;
316 isect.t = 1.0f;
317 isect.type = PRIMITIVE_TRIANGLE;
319
320 /* Setup next kernel to execute. */
321 const bool use_caustics = kernel_data.integrator.use_caustics &&
322 (object_flag & SD_OBJECT_CAUSTICS);
323 const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE);
324
325 if (use_caustics) {
328 }
329 else if (use_raytrace_kernel) {
332 }
333 else {
335 }
336
337#ifdef __SHADOW_CATCHER__
338 integrator_split_shadow_catcher(kg, state, &isect, render_buffer);
339#endif
340 }
341
342 return true;
343}
344
#define D
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static unsigned long seed
Definition btSoftBody.h:39
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_restrict
#define ccl_optional_struct_init
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define ccl_global
#define CCL_NAMESPACE_END
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define __float_as_uint(x)
ccl_device_forceinline float differential_make_compact(const float dD)
ccl_device_forceinline float differential_zero_compact()
int len
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg, float3 Ng, int prim, float u, float v)
ccl_device_inline void triangle_point_normal(KernelGlobals kg, int object, int prim, float u, float v, ccl_private float3 *P, ccl_private float3 *Ng, ccl_private int *shader)
ccl_device_inline void triangle_vertices(KernelGlobals kg, int prim, float3 P[3])
ccl_device_inline void triangle_dPdudv(KernelGlobals kg, int prim, ccl_private float3 *dPdu, ccl_private float3 *dPdv)
ccl_device_inline float2 hash_float2_to_float2(float2 k)
Definition hash.h:181
ccl_device_inline uint hash_uint(uint kx)
Definition hash.h:78
#define mix(a, b, c)
Definition hash.h:36
ccl_device const float2 bake_offset_towards_center(KernelGlobals kg, const int prim, const float u, const float v)
CCL_NAMESPACE_BEGIN ccl_device_inline void bake_jitter_barycentric(ccl_private float &u, ccl_private float &v, float2 rand_filter, const float dudx, const float dudy, const float dvdx, const float dvdy)
ccl_device bool integrator_init_from_bake(KernelGlobals kg, IntegratorState state, ccl_global const KernelWorkTile *ccl_restrict tile, ccl_global float *render_buffer, const int x, const int y, const int scheduled_sample)
ccl_device_inline float3 camera_direction_from_point(KernelGlobals kg, float3 P)
ccl_global const KernelWorkTile * tile
ccl_gpu_kernel_postfix ccl_global KernelWorkTile const int ccl_global float * render_buffer
CCL_NAMESPACE_BEGIN ccl_device_forceinline bool film_need_sample_pixel(KernelGlobals kg, ConstIntegratorState state, ccl_global float *render_buffer)
@ OBJECT_INVERSE_TRANSFORM
@ OBJECT_TRANSFORM
ccl_device_inline Transform object_fetch_transform(KernelGlobals kg, int object, enum ObjectTransform type)
@ SD_HAS_BUMP
@ SD_HAS_RAYTRACE
#define PASS_UNUSED
@ PRIMITIVE_TRIANGLE
@ PRNG_FILTER
@ SHADER_SMOOTH_NORMAL
@ SHADER_MASK
@ SD_OBJECT_CAUSTICS
@ SD_OBJECT_TRANSFORM_APPLIED
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE
@ DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND
#define PROFILING_INIT(kg, event)
ccl_device_inline void film_write_transparent(KernelGlobals kg, ConstIntegratorState state, const uint32_t path_flag, const float transparent, ccl_global float *ccl_restrict buffer)
ccl_device_inline int film_write_sample(KernelGlobals kg, ConstIntegratorState state, ccl_global float *ccl_restrict render_buffer, int sample, int sample_offset)
ccl_device_inline float reduce_max(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:15
static ulong state[N]
#define N
ccl_device_inline void path_state_init(IntegratorState state, ccl_global const KernelWorkTile *ccl_restrict tile, const int x, const int y)
Definition path_state.h:25
ccl_device_inline void path_state_init_integrator(KernelGlobals kg, IntegratorState state, const int sample, const uint rng_pixel)
Definition path_state.h:38
ccl_device_inline uint path_rng_pixel_init(KernelGlobals kg, const int sample, const int x, const int y)
Definition pattern.h:133
ccl_device_forceinline float2 path_rng_2D(KernelGlobals kg, uint rng_pixel, int sample, int dimension)
Definition pattern.h:82
#define min(a, b)
Definition sort.c:32
IntegratorStateCPU *ccl_restrict IntegratorState
Definition state.h:228
ccl_device_forceinline void integrator_path_init_sorted(KernelGlobals kg, IntegratorState state, const DeviceKernel next_kernel, const uint32_t key)
Definition state_flow.h:160
ccl_device_forceinline void integrator_path_init(KernelGlobals kg, IntegratorState state, const DeviceKernel next_kernel)
Definition state_flow.h:153
ccl_device_forceinline void integrator_state_write_isect(IntegratorState state, ccl_private const Intersection *ccl_restrict isect)
Definition state_util.h:128
CCL_NAMESPACE_BEGIN ccl_device_forceinline void integrator_state_write_ray(IntegratorState state, ccl_private const Ray *ccl_restrict ray)
Definition state_util.h:15
#define FLT_MAX
Definition stdcycles.h:14
float3 P
float x
float y
#define transform_point_auto
Definition transform.h:535
ccl_device_inline float3 transform_direction(ccl_private const Transform *t, const float3 a)
Definition transform.h:94
ccl_device_inline float3 transform_direction_transposed(ccl_private const Transform *t, const float3 a)
Definition transform.h:123
float max
ccl_device_inline int clamp(int a, int mn, int mx)
Definition util/math.h:379
@ PROFILING_RAY_SETUP
ccl_device_inline void film_write_pass_float3(ccl_global float *ccl_restrict buffer, float3 value)
Definition write.h:48
CCL_NAMESPACE_BEGIN ccl_device_forceinline ccl_global float * film_pass_pixel_render_buffer(KernelGlobals kg, ConstIntegratorState state, ccl_global float *ccl_restrict render_buffer)
Definition write.h:17