Fix T100537: gaps in Cycles depth pass with transparency

For some pixels with transparent surfaces, no depth value would be written
when sampling chooses a reflection/refraction BSDF instead of transparent
BSDF. Now ensure we always write at some some depth value to the pass.

This is still not ideal as the resulting depth values are noisy same as they
are for depth of field and motion blur, but at least there should be no gaps.
This commit is contained in:
Brecht Van Lommel 2022-11-18 15:52:34 +01:00
parent c94583cd64
commit 3d41d0b1b5
Notes: blender-bot 2023-02-14 11:00:17 +01:00
Referenced by issue #100537, artefacts in transparent area in depth pass
2 changed files with 41 additions and 20 deletions

View File

@ -42,27 +42,27 @@ ccl_device_inline void film_write_data_passes(KernelGlobals kg,
ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer);
if (!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
if (INTEGRATOR_STATE(state, path, sample) == 0) {
if (flag & PASSMASK(DEPTH)) {
const float depth = camera_z_depth(kg, sd->P);
film_overwrite_pass_float(buffer + kernel_data.film.pass_depth, depth);
}
if (flag & PASSMASK(OBJECT_ID)) {
const float id = object_pass_id(kg, sd->object);
film_overwrite_pass_float(buffer + kernel_data.film.pass_object_id, id);
}
if (flag & PASSMASK(MATERIAL_ID)) {
const float id = shader_pass_id(kg, sd);
film_overwrite_pass_float(buffer + kernel_data.film.pass_material_id, id);
}
if (flag & PASSMASK(POSITION)) {
const float3 position = sd->P;
film_overwrite_pass_float3(buffer + kernel_data.film.pass_position, position);
}
}
if (!(sd->flag & SD_TRANSPARENT) || kernel_data.film.pass_alpha_threshold == 0.0f ||
average(surface_shader_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) {
if (INTEGRATOR_STATE(state, path, sample) == 0) {
if (flag & PASSMASK(DEPTH)) {
const float depth = camera_z_depth(kg, sd->P);
film_write_pass_float(buffer + kernel_data.film.pass_depth, depth);
}
if (flag & PASSMASK(OBJECT_ID)) {
const float id = object_pass_id(kg, sd->object);
film_write_pass_float(buffer + kernel_data.film.pass_object_id, id);
}
if (flag & PASSMASK(MATERIAL_ID)) {
const float id = shader_pass_id(kg, sd);
film_write_pass_float(buffer + kernel_data.film.pass_material_id, id);
}
if (flag & PASSMASK(POSITION)) {
const float3 position = sd->P;
film_write_pass_float3(buffer + kernel_data.film.pass_position, position);
}
}
if (flag & PASSMASK(NORMAL)) {
const float3 normal = surface_shader_average_normal(kg, sd);
film_write_pass_float3(buffer + kernel_data.film.pass_normal, normal);

View File

@ -12,6 +12,7 @@
CCL_NAMESPACE_BEGIN
/* Get pointer to pixel in render buffer. */
ccl_device_forceinline ccl_global float *film_pass_pixel_render_buffer(
KernelGlobals kg, ConstIntegratorState state, ccl_global float *ccl_restrict render_buffer)
{
@ -21,7 +22,8 @@ ccl_device_forceinline ccl_global float *film_pass_pixel_render_buffer(
return render_buffer + render_buffer_offset;
}
/* Write to pixel. */
/* Accumulate in passes. */
ccl_device_inline void film_write_pass_float(ccl_global float *ccl_restrict buffer, float value)
{
#ifdef __ATOMIC_PASS_WRITE__
@ -74,6 +76,25 @@ ccl_device_inline void film_write_pass_float4(ccl_global float *ccl_restrict buf
#endif
}
/* Overwrite for passes that only write on sample 0. This assumes only a single thread will write
* to this pixel and no atomics are needed. */
ccl_device_inline void film_overwrite_pass_float(ccl_global float *ccl_restrict buffer,
float value)
{
*buffer = value;
}
ccl_device_inline void film_overwrite_pass_float3(ccl_global float *ccl_restrict buffer,
float3 value)
{
buffer[0] = value.x;
buffer[1] = value.y;
buffer[2] = value.z;
}
/* Read back from passes. */
ccl_device_inline float kernel_read_pass_float(ccl_global float *ccl_restrict buffer)
{
return *buffer;