Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/kernel_film.h
| Show First 20 Lines • Show All 276 Lines • ▼ Show 20 Lines | ccl_device_inline void film_get_pass_pixel_combined(const KernelFilmConvert *ccl_restrict | ||||
| film_get_pass_pixel_float4(kfilm_convert, buffer, pixel); | film_get_pass_pixel_float4(kfilm_convert, buffer, pixel); | ||||
| pixel[3] = film_transparency_to_alpha(pixel[3]); | pixel[3] = film_transparency_to_alpha(pixel[3]); | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- | /* -------------------------------------------------------------------- | ||||
| * Shadow catcher. | * Shadow catcher. | ||||
| */ | */ | ||||
| ccl_device_inline float4 | ccl_device_inline float3 | ||||
| film_calculate_shadow_catcher_denoised(const KernelFilmConvert *ccl_restrict kfilm_convert, | film_calculate_shadow_catcher_denoised(const KernelFilmConvert *ccl_restrict kfilm_convert, | ||||
| ccl_global const float *ccl_restrict buffer) | ccl_global const float *ccl_restrict buffer) | ||||
| { | { | ||||
| kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); | kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); | ||||
| float scale, scale_exposure; | float scale, scale_exposure; | ||||
| film_get_scale_and_scale_exposure(kfilm_convert, buffer, &scale, &scale_exposure); | film_get_scale_and_scale_exposure(kfilm_convert, buffer, &scale, &scale_exposure); | ||||
| ccl_global const float *in_catcher = buffer + kfilm_convert->pass_shadow_catcher; | ccl_global const float *in_catcher = buffer + kfilm_convert->pass_shadow_catcher; | ||||
| const float3 pixel = make_float3(in_catcher[0], in_catcher[1], in_catcher[2]) * scale_exposure; | const float3 pixel = make_float3(in_catcher[0], in_catcher[1], in_catcher[2]) * scale_exposure; | ||||
| return make_float4(pixel.x, pixel.y, pixel.z, 1.0f); | return pixel; | ||||
| } | } | ||||
| ccl_device_inline float4 | ccl_device_inline float3 | ||||
| film_calculate_shadow_catcher(const KernelFilmConvert *ccl_restrict kfilm_convert, | film_calculate_shadow_catcher(const KernelFilmConvert *ccl_restrict kfilm_convert, | ||||
| ccl_global const float *ccl_restrict buffer) | ccl_global const float *ccl_restrict buffer) | ||||
| { | { | ||||
| /* For the shadow catcher pass we divide combined pass by the shadow catcher. | /* For the shadow catcher pass we divide combined pass by the shadow catcher. | ||||
| * Note that denoised shadow catcher pass contains value which only needs ot be scaled (but not | * Note that denoised shadow catcher pass contains value which only needs ot be scaled (but not | ||||
| * to be calculated as division). */ | * to be calculated as division). */ | ||||
| if (kfilm_convert->is_denoised) { | if (kfilm_convert->is_denoised) { | ||||
| return film_calculate_shadow_catcher_denoised(kfilm_convert, buffer); | return film_calculate_shadow_catcher_denoised(kfilm_convert, buffer); | ||||
| } | } | ||||
| kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); | kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); | ||||
| ccl_global const float *in_catcher = buffer + kfilm_convert->pass_shadow_catcher; | ccl_global const float *in_catcher = buffer + kfilm_convert->pass_shadow_catcher; | ||||
| /* If there is no shadow catcher object in this pixel, there is no modification of the light | /* If there is no shadow catcher object in this pixel, there is no modification of the light | ||||
| * needed, so return one. */ | * needed, so return one. */ | ||||
| const float num_samples = in_catcher[3]; | const float num_samples = in_catcher[3]; | ||||
| if (num_samples == 0.0f) { | if (num_samples == 0.0f) { | ||||
| return one_float4(); | return one_float3(); | ||||
| } | } | ||||
| /* NOTE: It is possible that the Shadow Catcher pass is requested as an output without actual | /* NOTE: It is possible that the Shadow Catcher pass is requested as an output without actual | ||||
| * shadow catcher objects in the scene. In this case there will be no auxillary passes required | * shadow catcher objects in the scene. In this case there will be no auxillary passes required | ||||
| * for the devision (to save up memory). So delay the asserts to this point so that the number of | * for the devision (to save up memory). So delay the asserts to this point so that the number of | ||||
| * samples check handles such configuration. */ | * samples check handles such configuration. */ | ||||
| kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); | kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); | ||||
| kernel_assert(kfilm_convert->pass_combined != PASS_UNUSED); | kernel_assert(kfilm_convert->pass_combined != PASS_UNUSED); | ||||
| Show All 21 Lines | film_calculate_shadow_catcher(const KernelFilmConvert *ccl_restrict kfilm_convert, | ||||
| const float alpha = film_transparency_to_alpha(transparency); | const float alpha = film_transparency_to_alpha(transparency); | ||||
| /* Alpha-over on white using transparency of the combined pass. This allows to eliminate | /* Alpha-over on white using transparency of the combined pass. This allows to eliminate | ||||
| * artifacts which are happenning on an edge of a shadow catcher when using transparent film. | * artifacts which are happenning on an edge of a shadow catcher when using transparent film. | ||||
| * Note that we treat shadow catcher as straight alpha here because alpha got cancelled out | * Note that we treat shadow catcher as straight alpha here because alpha got cancelled out | ||||
| * during the division. */ | * during the division. */ | ||||
| const float3 pixel = (1.0f - alpha) * one_float3() + alpha * shadow_catcher; | const float3 pixel = (1.0f - alpha) * one_float3() + alpha * shadow_catcher; | ||||
| return make_float4(pixel.x, pixel.y, pixel.z, 1.0f); | return pixel; | ||||
| } | } | ||||
| ccl_device_inline float4 film_calculate_shadow_catcher_matte_with_shadow( | ccl_device_inline float4 film_calculate_shadow_catcher_matte_with_shadow( | ||||
| const KernelFilmConvert *ccl_restrict kfilm_convert, | const KernelFilmConvert *ccl_restrict kfilm_convert, | ||||
| ccl_global const float *ccl_restrict buffer) | ccl_global const float *ccl_restrict buffer) | ||||
| { | { | ||||
| /* The approximation of the shadow is 1 - average(shadow_catcher_pass). A better approximation | /* The approximation of the shadow is 1 - average(shadow_catcher_pass). A better approximation | ||||
| * is possible. | * is possible. | ||||
| * | * | ||||
| * The matte is alpha-overed onto the shadow (which is kind of alpha-overing shadow onto footage, | * The matte is alpha-overed onto the shadow (which is kind of alpha-overing shadow onto footage, | ||||
| * and then alpha-overing synthetic objects on top). */ | * and then alpha-overing synthetic objects on top). */ | ||||
| kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); | kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); | ||||
| kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); | kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); | ||||
| kernel_assert(kfilm_convert->pass_shadow_catcher_matte != PASS_UNUSED); | kernel_assert(kfilm_convert->pass_shadow_catcher_matte != PASS_UNUSED); | ||||
| float scale, scale_exposure; | float scale, scale_exposure; | ||||
| film_get_scale_and_scale_exposure(kfilm_convert, buffer, &scale, &scale_exposure); | film_get_scale_and_scale_exposure(kfilm_convert, buffer, &scale, &scale_exposure); | ||||
| ccl_global const float *in_matte = buffer + kfilm_convert->pass_shadow_catcher_matte; | ccl_global const float *in_matte = buffer + kfilm_convert->pass_shadow_catcher_matte; | ||||
| const float4 shadow_catcher = film_calculate_shadow_catcher(kfilm_convert, buffer); | const float3 shadow_catcher = film_calculate_shadow_catcher(kfilm_convert, buffer); | ||||
| const float3 color_matte = make_float3(in_matte[0], in_matte[1], in_matte[2]) * scale_exposure; | const float3 color_matte = make_float3(in_matte[0], in_matte[1], in_matte[2]) * scale_exposure; | ||||
| const float transparency = in_matte[3] * scale; | const float transparency = in_matte[3] * scale; | ||||
| const float alpha = saturate(1.0f - transparency); | const float alpha = saturate(1.0f - transparency); | ||||
| const float alpha_matte = (1.0f - alpha) * (1.0f - average(float4_to_float3(shadow_catcher))) + | const float alpha_matte = (1.0f - alpha) * (1.0f - average(shadow_catcher)) + alpha; | ||||
| alpha; | |||||
| if (kfilm_convert->use_approximate_shadow_catcher_background) { | if (kfilm_convert->use_approximate_shadow_catcher_background) { | ||||
| kernel_assert(kfilm_convert->pass_background != PASS_UNUSED); | kernel_assert(kfilm_convert->pass_background != PASS_UNUSED); | ||||
| ccl_global const float *in_background = buffer + kfilm_convert->pass_background; | ccl_global const float *in_background = buffer + kfilm_convert->pass_background; | ||||
| const float3 color_background = make_float3( | const float3 color_background = make_float3( | ||||
| in_background[0], in_background[1], in_background[2]) * | in_background[0], in_background[1], in_background[2]) * | ||||
| scale_exposure; | scale_exposure; | ||||
| const float3 alpha_over = color_matte + color_background * (1.0f - alpha_matte); | const float3 alpha_over = color_matte + color_background * (1.0f - alpha_matte); | ||||
| return make_float4(alpha_over.x, alpha_over.y, alpha_over.z, 1.0f); | return make_float4(alpha_over.x, alpha_over.y, alpha_over.z, 1.0f); | ||||
| } | } | ||||
| return make_float4(color_matte.x, color_matte.y, color_matte.z, alpha_matte); | return make_float4(color_matte.x, color_matte.y, color_matte.z, alpha_matte); | ||||
| } | } | ||||
| ccl_device_inline void film_get_pass_pixel_shadow_catcher( | ccl_device_inline void film_get_pass_pixel_shadow_catcher( | ||||
| const KernelFilmConvert *ccl_restrict kfilm_convert, | const KernelFilmConvert *ccl_restrict kfilm_convert, | ||||
| ccl_global const float *ccl_restrict buffer, | ccl_global const float *ccl_restrict buffer, | ||||
| float *ccl_restrict pixel) | float *ccl_restrict pixel) | ||||
| { | { | ||||
| const float4 pixel_value = film_calculate_shadow_catcher(kfilm_convert, buffer); | const float3 pixel_value = film_calculate_shadow_catcher(kfilm_convert, buffer); | ||||
| pixel[0] = pixel_value.x; | pixel[0] = pixel_value.x; | ||||
| pixel[1] = pixel_value.y; | pixel[1] = pixel_value.y; | ||||
| pixel[2] = pixel_value.z; | pixel[2] = pixel_value.z; | ||||
| if (kfilm_convert->num_components == 4) { | if (kfilm_convert->num_components == 4) { | ||||
| pixel[3] = pixel_value.w; | pixel[3] = 1.0f; | ||||
| } | } | ||||
| } | } | ||||
| ccl_device_inline void film_get_pass_pixel_shadow_catcher_matte_with_shadow( | ccl_device_inline void film_get_pass_pixel_shadow_catcher_matte_with_shadow( | ||||
| const KernelFilmConvert *ccl_restrict kfilm_convert, | const KernelFilmConvert *ccl_restrict kfilm_convert, | ||||
| ccl_global const float *ccl_restrict buffer, | ccl_global const float *ccl_restrict buffer, | ||||
| float *ccl_restrict pixel) | float *ccl_restrict pixel) | ||||
| { | { | ||||
| Show All 31 Lines | |||||