Merge branch 'blender-v3.1-release'
This commit is contained in:
commit
9de720f31a
|
@ -5,27 +5,6 @@
|
|||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Ray offset to avoid self intersection.
|
||||
*
|
||||
* This function should be used to compute a modified ray start position for
|
||||
* rays leaving from a surface. This is from "A Fast and Robust Method for Avoiding
|
||||
* Self-Intersection" see https://research.nvidia.com/publication/2019-03_A-Fast-and
|
||||
*/
|
||||
ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
|
||||
{
|
||||
const float int_scale = 256.0f;
|
||||
int3 of_i = make_int3((int)(int_scale * Ng.x), (int)(int_scale * Ng.y), (int)(int_scale * Ng.z));
|
||||
|
||||
float3 p_i = make_float3(__int_as_float(__float_as_int(P.x) + ((P.x < 0) ? -of_i.x : of_i.x)),
|
||||
__int_as_float(__float_as_int(P.y) + ((P.y < 0) ? -of_i.y : of_i.y)),
|
||||
__int_as_float(__float_as_int(P.z) + ((P.z < 0) ? -of_i.z : of_i.z)));
|
||||
const float origin = 1.0f / 32.0f;
|
||||
const float float_scale = 1.0f / 65536.0f;
|
||||
return make_float3(fabsf(P.x) < origin ? P.x + float_scale * Ng.x : p_i.x,
|
||||
fabsf(P.y) < origin ? P.y + float_scale * Ng.y : p_i.y,
|
||||
fabsf(P.z) < origin ? P.z + float_scale * Ng.z : p_i.z);
|
||||
}
|
||||
|
||||
#if defined(__KERNEL_CPU__)
|
||||
ccl_device int intersections_compare(const void *a, const void *b)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,50 @@ ccl_device_inline float bake_clamp_mirror_repeat(float u, float max)
|
|||
return ((((int)fu) & 1) ? 1.0f - u : u) * max;
|
||||
}
|
||||
|
||||
/* Offset towards center of triangle to avoid ray-tracing precision issues. */
|
||||
ccl_device const float2 bake_offset_towards_center(KernelGlobals kg,
|
||||
const int prim,
|
||||
const float u,
|
||||
const float v)
|
||||
{
|
||||
float3 tri_verts[3];
|
||||
triangle_vertices(kg, prim, tri_verts);
|
||||
|
||||
/* Empirically determined values, by no means perfect. */
|
||||
const float position_offset = 1e-4f;
|
||||
const float uv_offset = 1e-5f;
|
||||
|
||||
/* Offset position towards center, amount relative to absolute size of position coordinates. */
|
||||
const float3 P = u * tri_verts[0] + v * tri_verts[1] + (1.0f - u - v) * tri_verts[2];
|
||||
const float3 center = (tri_verts[0] + tri_verts[1] + tri_verts[2]) / 3.0f;
|
||||
const float3 to_center = center - P;
|
||||
|
||||
const float3 offset_P = P + normalize(to_center) *
|
||||
min(len(to_center), max(max3(fabs(P)), 1.0f) * position_offset);
|
||||
|
||||
/* Compute barycentric coordinates at new position. */
|
||||
const float3 v1 = tri_verts[1] - tri_verts[0];
|
||||
const float3 v2 = tri_verts[2] - tri_verts[0];
|
||||
const float3 vP = offset_P - tri_verts[0];
|
||||
|
||||
const float d11 = dot(v1, v1);
|
||||
const float d12 = dot(v1, v2);
|
||||
const float d22 = dot(v2, v2);
|
||||
const float dP1 = dot(vP, v1);
|
||||
const float dP2 = dot(vP, v2);
|
||||
|
||||
const float denom = d11 * d22 - d12 * d12;
|
||||
if (denom == 0.0f) {
|
||||
return make_float2(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
const float offset_v = clamp((d22 * dP1 - d12 * dP2) / denom, uv_offset, 1.0f - uv_offset);
|
||||
const float offset_w = clamp((d11 * dP2 - d12 * dP1) / denom, uv_offset, 1.0f - uv_offset);
|
||||
const float offset_u = clamp(1.0f - offset_v - offset_w, uv_offset, 1.0f - uv_offset);
|
||||
|
||||
return make_float2(offset_u, offset_v);
|
||||
}
|
||||
|
||||
/* Return false to indicate that this pixel is finished.
|
||||
* Used by CPU implementation to not attempt to sample pixel for multiple samples once its known
|
||||
* that the pixel did converge. */
|
||||
|
@ -87,7 +131,7 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
|
|||
/* Initialize path state for path integration. */
|
||||
path_state_init_integrator(kg, state, sample, rng_hash);
|
||||
|
||||
/* Barycentric UV with sub-pixel offset. */
|
||||
/* Barycentric UV. */
|
||||
float u = primitive[2];
|
||||
float v = primitive[3];
|
||||
|
||||
|
@ -96,6 +140,14 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
|
|||
float dvdx = differential[2];
|
||||
float dvdy = differential[3];
|
||||
|
||||
/* Exactly at vertex? Nudge inwards to avoid self-intersection. */
|
||||
if ((u == 0.0f || u == 1.0f) && (v == 0.0f || v == 1.0f)) {
|
||||
const float2 uv = bake_offset_towards_center(kg, prim, u, v);
|
||||
u = uv.x;
|
||||
v = uv.y;
|
||||
}
|
||||
|
||||
/* Sub-pixel offset. */
|
||||
if (sample > 0) {
|
||||
u = bake_clamp_mirror_repeat(u + dudx * (filter_x - 0.5f) + dudy * (filter_y - 0.5f), 1.0f);
|
||||
v = bake_clamp_mirror_repeat(v + dvdx * (filter_x - 0.5f) + dvdy * (filter_y - 0.5f),
|
||||
|
|
|
@ -352,12 +352,8 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
|
|||
float ao_pdf;
|
||||
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
|
||||
|
||||
if (!(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ray ray ccl_optional_struct_init;
|
||||
ray.P = sd->P;
|
||||
ray.P = shadow_ray_offset(kg, sd, ao_D);
|
||||
ray.D = ao_D;
|
||||
ray.t = kernel_data.integrator.ao_bounces_distance;
|
||||
ray.time = sd->time;
|
||||
|
|
|
@ -1038,19 +1038,18 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets,
|
|||
* materials and UVs. */
|
||||
pixel->seed = v;
|
||||
|
||||
/* Barycentric coordinates, nudged a bit to avoid precision issues that
|
||||
* may happen when exactly at the vertex coordinate. */
|
||||
/* Barycentric coordinates. */
|
||||
if (j == 0) {
|
||||
pixel->uv[0] = 1.0f - FLT_EPSILON;
|
||||
pixel->uv[1] = FLT_EPSILON / 2.0f;
|
||||
pixel->uv[0] = 1.0f;
|
||||
pixel->uv[1] = 0.0f;
|
||||
}
|
||||
else if (j == 1) {
|
||||
pixel->uv[0] = FLT_EPSILON / 2.0f;
|
||||
pixel->uv[1] = 1.0f - FLT_EPSILON;
|
||||
pixel->uv[0] = 0.0f;
|
||||
pixel->uv[1] = 1.0f;
|
||||
}
|
||||
else if (j == 2) {
|
||||
pixel->uv[0] = FLT_EPSILON / 2.0f;
|
||||
pixel->uv[1] = FLT_EPSILON / 2.0f;
|
||||
pixel->uv[0] = 0.0f;
|
||||
pixel->uv[1] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue